Task System
Task System
Section titled “Task System”Tasks are the heart of Journey. They’re how you create quests, objectives, challenges, and anything else you want players to accomplish. “Catch 5 Pikachu,” “defeat the gym leader,” “explore 3 zones” — they’re all tasks.
A task contains one or more subtasks (individual objectives), and when a player completes all required subtasks, the task is done and rewards are given.
Quick Start
Section titled “Quick Start”Here’s the simplest possible task — catch one Pokemon:
File: config/journey/tasks/first_catch.json
{ "name": "<gold>Catch Your First Pokemon", "description": [ "<gray>Catch any wild Pokemon to begin your adventure!" ], "sequential": "linear", "icon": { "item_id": "cobblemon:poke_ball" }, "repeat_type": "NONE", "rewards": [ { "type": "currency", "data": { "currency_id": "impactor:pokedollars", "amount": 100 } } ], "tasks": [ { "id": "catch_one", "name": "Catch a Pokemon", "description": "Catch any wild Pokemon", "event": "POKEMON_CAPTURE", "filter": "1.0", "target": 1 } ]}That’s it. When a player catches any Pokemon, they get 100 Pokedollars. Let’s break down every piece.
Task Structure
Section titled “Task Structure”Every task file is a JSON object with these fields:
| Field | Type | Required | Description |
|---|---|---|---|
name | String | Yes | Display name (supports MiniMessage formatting) |
description | String[] | Yes | Array of description lines for the quest journal |
sequential | String | Yes | Progression type: "linear", "sequential", or "randomized" |
subtask_count | Number | Only for randomized | How many subtasks to randomly select |
start_requirement | String | No | Molang condition that must be true to start the task |
icon | Object | No | Item icon shown in GUIs ({"item_id": "minecraft:compass"}) |
repeat_type | String | No | How the task repeats (see Repeat Types) |
repeat_interval | Number | No | Interval for repeats (meaning depends on repeat_type) |
repeat_limit | Number | No | Maximum number of times the task can repeat (0 = unlimited) |
party_shared | Boolean | No | Default party sharing for all subtasks (default: false) |
global | Boolean | No | Whether this is a global (server-wide) task |
rewards | Array | No | Rewards given when the entire task is completed |
tasks | Array | Yes | Array of subtask definitions |
available_marker | Object | No | Marker shown when task is available but not started |
area | Object | No | Area restriction for the task (supports Ceremony regions) |
Progression Types
Section titled “Progression Types”The sequential field controls how subtasks are presented to the player.
Linear
Section titled “Linear”"sequential": "linear"All subtasks are active at the same time. The player can complete them in any order.
Best for: Collection challenges, exploration objectives, parallel goals.
{ "name": "<gold>Starter Town Exploration", "sequential": "linear", "tasks": [ { "id": "visit_lab", "name": "Visit the Lab", "event": "ENTER_ZONE", "filter": "q.zone.uuid == 'lab-zone-uuid'", "target": 1 }, { "id": "visit_center", "name": "Visit the Pokemon Center", "event": "ENTER_ZONE", "filter": "q.zone.uuid == 'center-zone-uuid'", "target": 1 }, { "id": "visit_mart", "name": "Visit the Poke Mart", "event": "ENTER_ZONE", "filter": "q.zone.uuid == 'mart-zone-uuid'", "target": 1 } ]}All three objectives appear immediately. The player can visit these locations in any order.
Sequential
Section titled “Sequential”"sequential": "sequential"Subtasks must be completed in order. Only the current subtask is active — the next one unlocks when the current one finishes.
Best for: Story progression, tutorial chains, ordered quest steps.
{ "name": "<gold>Gym Challenge", "sequential": "sequential", "tasks": [ { "id": "enter_gym", "name": "Enter the Gym", "event": "ENTER_ZONE", "filter": "q.zone.uuid == 'pewter-gym-uuid'", "target": 1 }, { "id": "defeat_trainers", "name": "Defeat Gym Trainers", "event": "BATTLE_VICTORY", "filter": "q.battle.is_pvn", "target": 3 }, { "id": "talk_to_leader", "name": "Challenge the Gym Leader", "event": "ENTITY_INTERACT", "filter": "q.entity.uuid == 'brock-npc-uuid'", "target": 1 }, { "id": "defeat_leader", "name": "Defeat Brock", "event": "BATTLE_VICTORY", "filter": "q.battle.is_pvn", "target": 1 } ]}The player must enter the gym first, then defeat 3 trainers, then talk to the leader, then win.
Randomized
Section titled “Randomized”"sequential": "randomized","subtask_count": 3A random subset of subtasks is selected from the pool. You define more subtasks than needed, and Journey picks subtask_count of them randomly.
Best for: Daily quests, bounties, replayable content.
{ "name": "<gold>Daily Challenge", "sequential": "randomized", "subtask_count": 3, "repeat_type": "DAILY", "tasks": [ { "id": "catch_pokemon", "name": "Catch 5 Pokemon", "event": "POKEMON_CAPTURE", "filter": "1.0", "target": 5 }, { "id": "win_battles", "name": "Win 10 Battles", "event": "BATTLE_VICTORY", "filter": "1.0", "target": 10 }, { "id": "harvest_berries", "name": "Harvest 20 Berries", "event": "BERRY_HARVESTED", "filter": "1.0", "target": 20 }, { "id": "evolve_pokemon", "name": "Evolve a Pokemon", "event": "POKEMON_EVOLVE", "filter": "1.0", "target": 1 }, { "id": "explore_zones", "name": "Visit 3 Zones", "event": "ENTER_ZONE", "filter": "1.0", "target": 3 } ]}Each day, 3 of these 5 subtasks are randomly selected. The player completes whichever 3 they’re given.
Subtask Structure
Section titled “Subtask Structure”Subtasks are the individual objectives within a task:
| Field | Type | Required | Description |
|---|---|---|---|
id | String | Yes | Unique identifier within the task |
name | String | Yes | Display name for this objective |
description | String | No | What the player needs to do |
event | String | Yes | Event type that triggers progress (see Events) |
event_data | Object | No | Extra event-specific data |
filter | String | Yes | Molang expression to validate events |
target | Number | Yes | How many times the event must match |
rewards | Array | No | Rewards given when this specific subtask completes |
location | Object | No | Waypoint coordinates ({"x": 100, "y": 64, "z": 200}) |
time_limit | String | No | Time constraint (e.g., "30s", "5m", "1h") |
optional | Boolean | No | If true, not required for task completion |
party_shared | Boolean | No | Override task-level party sharing for this subtask |
script | String | No | Molang script to run when subtask completes |
labels | String[] | No | Tags for categorization |
marker | Object | No | Marker configuration for this subtask |
area | Object | No | Area restriction for this subtask |
The Filter Field
Section titled “The Filter Field”Filters are Molang expressions that decide whether an event counts toward progress. Every time the event fires, Journey evaluates the filter — if it returns a truthy value (non-zero), progress goes up by 1.
"filter": "1.0"Always matches. Every event of this type counts.
"filter": "q.pokemon.species.identifier == 'cobblemon:pikachu'"Only matches when the Pokemon is a Pikachu.
"filter": "q.battle.is_pvw && q.player.is_in_zone('forest-zone-uuid')"Only matches wild battles while the player is in a specific zone.
See the Events page for what data each event provides, and the Molang page for all available functions.
Reward Types
Section titled “Reward Types”Journey supports five reward types. You can use any of them on both tasks and subtasks.
Command Reward
Section titled “Command Reward”Runs a server command. Use {player} as a placeholder for the player’s name:
{ "type": "command", "data": { "command": "give {player} minecraft:diamond 5" }}Currency Reward
Section titled “Currency Reward”Awards economy currency (requires Impactor):
{ "type": "currency", "data": { "currency_id": "impactor:pokedollars", "amount": 500 }}Script Reward
Section titled “Script Reward”Runs Molang scripts with full access to all player functions:
{ "type": "script", "data": { "scripts": [ "q.player.add_flag('gym_badge_boulder');", "q.player.tell_minimessage('<gold>You earned the Boulder Badge!');", "q.player.progress_levelable('trainer_rank', 100);" ] }}Timeline Reward
Section titled “Timeline Reward”Launches a timeline sequence:
{ "type": "timeline", "data": { "timeline": "journey:gym_victory" }}Buff Reward
Section titled “Buff Reward”Applies a buff to the player:
{ "type": "buff", "data": { "buff_id": "speed_boost", "duration": 6000, "amplifier": 0, "source": "gym_reward" }}durationis in ticks (20 ticks = 1 second,-1= permanent)amplifieris 0-based (0 = level 1, 1 = level 2, etc.)sourceis an optional tag for tracking where the buff came from
Start Requirements
Section titled “Start Requirements”Control when a task becomes available using start_requirement. This is a Molang expression that must return true for the player to start the task.
No Requirement (Always Available)
Section titled “No Requirement (Always Available)”{ "start_requirement": ""}Flag-Based
Section titled “Flag-Based”{ "start_requirement": "q.player.has_flag('tutorial_complete')"}Previous Task Completion
Section titled “Previous Task Completion”{ "start_requirement": "q.player.has_completed_task('journey:first_gym')"}Level-Based
Section titled “Level-Based”{ "start_requirement": "q.player.levelable_level('trainer_rank') >= 25"}Multiple Conditions
Section titled “Multiple Conditions”{ "start_requirement": "q.player.has_flag('gym_badge_boulder') && q.player.has_flag('gym_badge_cascade') && q.player.has_flag('gym_badge_thunder')"}Repeat Types
Section titled “Repeat Types”The repeat_type field controls whether and how a task resets after completion:
| Repeat Type | Description |
|---|---|
NONE | One-time task (default) |
MINUTELY | Resets every minute |
HOURLY | Resets every hour |
DAILY | Resets once per day |
WEEKLY | Resets once per week |
MONTHLY | Resets once per month |
YEARLY | Resets once per year |
Use repeat_limit to cap how many times a task can be repeated:
{ "repeat_type": "DAILY", "repeat_interval": 1, "repeat_limit": 30}This daily task can only be completed 30 times total.
Party Sharing
Section titled “Party Sharing”When party_shared is true, progress from any party member counts for all party members who have the task.
{ "name": "<gold>Party Dungeon Quest", "sequential": "linear", "party_shared": true, "tasks": [ { "id": "defeat_bosses", "name": "Defeat Dungeon Bosses", "event": "BATTLE_VICTORY", "filter": "q.battle.is_pvn", "target": 5 }, { "id": "find_treasure", "name": "Find the Hidden Treasure", "event": "ENTER_ZONE", "filter": "q.zone.uuid == 'treasure-room-uuid'", "target": 1, "party_shared": false } ]}party_sharedon the task sets the default for all subtasksparty_sharedon a subtask overrides the task default- In this example, boss defeats are shared but each member must find the treasure themselves
Complete Examples
Section titled “Complete Examples”Story Quest with NPCs and Cutscenes
Section titled “Story Quest with NPCs and Cutscenes”File: config/journey/tasks/rival_battle.json
{ "name": "<red>Rival Showdown", "description": [ "<gray>Your rival has challenged you to a battle!", "<gray>Meet them at the bridge and prove your strength." ], "sequential": "sequential", "start_requirement": "q.player.has_flag('starter_chosen') && q.player.has_completed_task('journey:route_1_exploration')", "icon": { "item_id": "minecraft:iron_sword" }, "repeat_type": "NONE", "rewards": [ { "type": "script", "data": { "scripts": [ "q.player.add_flag('rival_defeated_1');", "q.player.tell_minimessage('<gold>Your rival respects your strength!');" ] } }, { "type": "timeline", "data": { "timeline": "journey:rival_defeated_celebration" } }, { "type": "currency", "data": { "currency_id": "impactor:pokedollars", "amount": 500 } } ], "tasks": [ { "id": "go_to_bridge", "name": "Go to Nugget Bridge", "description": "Meet your rival at Nugget Bridge", "event": "ENTER_ZONE", "filter": "q.zone.uuid == 'nugget-bridge-uuid'", "target": 1, "location": { "x": 500, "y": 64, "z": -200 } }, { "id": "talk_to_rival", "name": "Talk to Your Rival", "event": "ENTITY_INTERACT", "filter": "q.entity.uuid == 'rival-npc-uuid'", "target": 1, "script": "q.player.launch_timeline('journey:rival_pre_battle_dialogue');" }, { "id": "defeat_rival", "name": "Defeat Your Rival", "event": "BATTLE_VICTORY", "filter": "q.battle.is_pvn", "target": 1, "rewards": [ { "type": "command", "data": { "command": "give {player} cobblemon:rare_candy 3" } } ] } ]}Shiny Hunter Challenge with Timer
Section titled “Shiny Hunter Challenge with Timer”File: config/journey/tasks/shiny_sprint.json
{ "name": "<rainbow>Shiny Sprint", "description": [ "<gray>Catch a shiny Pokemon within 30 minutes!", "<yellow>Good luck, trainer!" ], "sequential": "linear", "start_requirement": "q.player.has_flag('unlocked_shiny_sprint')", "icon": { "item_id": "cobblemon:shiny_stone" }, "repeat_type": "WEEKLY", "rewards": [ { "type": "buff", "data": { "buff_id": "shiny_hunter", "duration": -1, "amplifier": 0, "source": "shiny_sprint_reward" } } ], "tasks": [ { "id": "catch_shiny", "name": "Catch a Shiny Pokemon", "event": "POKEMON_CAPTURE", "filter": "q.pokemon.is_shiny", "target": 1, "time_limit": "30m" } ]}Badge Collection (All 8 Gyms)
Section titled “Badge Collection (All 8 Gyms)”File: config/journey/tasks/elite_four_unlock.json
{ "name": "<gold>Road to the Elite Four", "description": [ "<gray>Collect all 8 gym badges to unlock", "<gray>the Elite Four challenge!" ], "sequential": "linear", "start_requirement": "q.player.has_flag('tutorial_complete')", "icon": { "item_id": "minecraft:nether_star" }, "repeat_type": "NONE", "rewards": [ { "type": "script", "data": { "scripts": [ "q.player.add_flag('elite_four_unlocked');", "q.player.tell_minimessage('<gold><bold>The Elite Four awaits you!');" ] } }, { "type": "timeline", "data": { "timeline": "journey:elite_four_unlocked_cutscene" } } ], "tasks": [ { "id": "badge_boulder", "name": "Boulder Badge", "event": "BATTLE_VICTORY", "filter": "q.battle.is_pvn && q.player.is_in_zone('pewter-gym-uuid')", "target": 1, "script": "q.player.add_flag('gym_badge_boulder');" }, { "id": "badge_cascade", "name": "Cascade Badge", "event": "BATTLE_VICTORY", "filter": "q.battle.is_pvn && q.player.is_in_zone('cerulean-gym-uuid')", "target": 1, "script": "q.player.add_flag('gym_badge_cascade');" }, { "id": "badge_thunder", "name": "Thunder Badge", "event": "BATTLE_VICTORY", "filter": "q.battle.is_pvn && q.player.is_in_zone('vermilion-gym-uuid')", "target": 1, "script": "q.player.add_flag('gym_badge_thunder');" }, { "id": "badge_rainbow", "name": "Rainbow Badge", "event": "BATTLE_VICTORY", "filter": "q.battle.is_pvn && q.player.is_in_zone('celadon-gym-uuid')", "target": 1, "script": "q.player.add_flag('gym_badge_rainbow');" }, { "id": "badge_soul", "name": "Soul Badge", "event": "BATTLE_VICTORY", "filter": "q.battle.is_pvn && q.player.is_in_zone('fuchsia-gym-uuid')", "target": 1, "script": "q.player.add_flag('gym_badge_soul');" }, { "id": "badge_marsh", "name": "Marsh Badge", "event": "BATTLE_VICTORY", "filter": "q.battle.is_pvn && q.player.is_in_zone('saffron-gym-uuid')", "target": 1, "script": "q.player.add_flag('gym_badge_marsh');" }, { "id": "badge_volcano", "name": "Volcano Badge", "event": "BATTLE_VICTORY", "filter": "q.battle.is_pvn && q.player.is_in_zone('cinnabar-gym-uuid')", "target": 1, "script": "q.player.add_flag('gym_badge_volcano');" }, { "id": "badge_earth", "name": "Earth Badge", "event": "BATTLE_VICTORY", "filter": "q.battle.is_pvn && q.player.is_in_zone('viridian-gym-uuid')", "target": 1, "script": "q.player.add_flag('gym_badge_earth');" } ]}File Location & Naming
Section titled “File Location & Naming”Task files go in config/journey/tasks/. You can use subdirectories for organization:
config/journey/tasks/├── tutorial/│ ├── choose_starter.json → journey:tutorial/choose_starter│ └── first_catch.json → journey:tutorial/first_catch├── gyms/│ ├── pewter_gym.json → journey:gyms/pewter_gym│ └── cerulean_gym.json → journey:gyms/cerulean_gym└── daily/ └── daily_challenge.json → journey:daily/daily_challengeThe task ID is journey:<path_without_extension>. Use this ID when referencing tasks in commands, Molang, and other configs.
Commands
Section titled “Commands”| Command | Description |
|---|---|
/journey starttask <player> <task_id> | Give a task to a player |
/journey completetask <player> <task_id> | Force-complete a task |
/journey removetask <player> <task_id> | Remove a task from a player |
/journey removecompleted <player> | Clear a player’s completed task history |
/journey completesubtask <player> <task_id> <subtask_id> | Force-complete a specific subtask |
/journey progresssubtask <player> <task_id> <subtask_id> <amount> | Add progress to a subtask |
/track <task_id> | Track a task on your HUD |
/track untrack | Stop tracking |
Tips & Best Practices
Section titled “Tips & Best Practices”Task Design
Section titled “Task Design”- Keep subtask counts reasonable (3-8 per task works well)
- Use descriptive IDs:
defeat_gym_leadernotstep3 - Provide
locationcoordinates for objectives so players know where to go - Set
start_requirementto prevent players from being overwhelmed with quests
Filters
Section titled “Filters”- Start simple with
"1.0"(matches everything), then add conditions - Test filters in-game before deploying to production
- Use
q.player.is_in_zone()to restrict objectives to specific areas - Combine conditions with
&&(AND) and||(OR)
Rewards
Section titled “Rewards”- Use subtask rewards for milestone feedback along the way
- Mix reward types for variety (currency + items + flags)
- Be careful with repeatable tasks — generous rewards add up fast
- Use script rewards to set flags that gate future content
Performance
Section titled “Performance”- Avoid overly complex Molang expressions in filters for high-frequency events
- For daily/weekly tasks, set
repeat_limitto prevent infinite farming