Skip to content

Buff System

Journey includes a powerful and extensible buff system that allows you to grant temporary or permanent effects to players as rewards, bonuses, or through other gameplay mechanics.

Buffs are effects that modify player attributes, apply status effects, execute scripts, or interact with game systems like Cobblemon. They can be:

  • Temporary (expire after a set duration) or Permanent (last forever)
  • Stackable (multiple instances can exist) or Unique (only one at a time)
  • Visible (shown to player) or Hidden (background effects)
  • Beneficial or Debuffs (negative effects)

Built-in Types

4 Types
  • Attribute modification
  • Potion effects
  • Script execution
  • Shiny chance boost

Extensible

API Available

Third-party mods can add custom buff types through the BuffTypeRegistry

Integration

Buffs can be granted as:

  • Task rewards
  • Levelable rewards
  • Command grants
  • Custom triggers

Persistent

Buffs survive:

  • Server restarts
  • Player logout/login
  • World reloads

Modify player attributes like movement speed, attack damage, health, etc.

Operations:

  • add_value - Adds flat value to attribute
  • add_multiplied_base - Adds percentage of base value
  • add_multiplied_total - Multiplies total value

Example:

{
"id": "speed_boost",
"type": "attribute",
"name": "Speed Boost",
"description": "Increases movement speed by 20%",
"max_stacks": 1,
"is_debuff": false,
"hidden": false,
"attribute": "minecraft:generic.movement_speed",
"operation": "add_multiplied_base",
"value": 0.2
}

Apply Minecraft potion effects with custom settings. Every potion effect can be used.

Example:

{
"id": "regeneration",
"type": "potion",
"name": "Regeneration",
"description": "Slowly restores health",
"max_stacks": 1,
"is_debuff": false,
"hidden": false,
"potion_effect": "minecraft:regeneration",
"show_particles": false,
"show_icon": true,
"ambient": false
}

Execute MoLang scripts when buff is applied, ticked, or removed.

Available Scripts:

  • on_apply_script - Runs once when buff is applied
  • on_tick_script - Runs periodically based on tick_interval
  • on_remove_script - Runs once when buff is removed

Script Context:

  • Full player context (q.player.* functions)
  • Buff properties (query.amplifier(), query.remaining_ticks(), query.buff_duration())
  • MoLang query functions

Example:

{
"id": "explorers_celebration",
"type": "script",
"name": "Explorer's Celebration",
"description": "A burst of energy celebrates your achievement",
"max_stacks": 1,
"is_debuff": false,
"hidden": false,
"on_apply_script": "q.player.tell_minimessage('<gold>✨ You feel a surge of explorer\\'s energy! ✨</gold>')",
"on_tick_script": "query.random(1, 100) > 90 ? q.player.snowstorm_particle('journey:sparkle', query.position_x + query.random(-1, 1), query.position_y + query.random(0, 2), query.position_z + query.random(-1, 1)) : 0",
"on_remove_script": "q.player.tell_minimessage('<gray>The explorer\\'s energy fades...</gray>')",
"tick_interval": 20
}

Increase the chance of encountering shiny Pokémon (Cobblemon integration).

How it Works:

  • Integrates with Cobblemon’s shiny calculation event
  • Multiple shiny buffs stack additively
  • Applies to all Pokémon encounters while buff is active

Example:

{
"id": "shiny_hunter",
"type": "shiny_chance",
"name": "Shiny Hunter",
"description": "Increases your chance of encountering shiny Pokémon",
"max_stacks": 3,
"is_debuff": false,
"hidden": false,
"chance_increase": 100.0
}

Buff definitions are stored as JSON files in:

config/journey/buffs/

Each buff should be in its own .json file. On first run, Journey creates several example buffs.

All buff types share these properties:

PropertyTypeDefaultDescription
idStringRequiredUnique identifier for the buff
typeStringRequiredBuff type: attribute, potion, script, shiny_chance
nameStringnullDisplay name shown to player
descriptionStringnullDescription shown to player
max_stacksInteger1Maximum number of instances allowed
is_debuffBooleanfalseWhether this is a negative effect
hiddenBooleanfalseWhether to hide from player UI
PropertyTypeRequiredDescription
attributeStringYesMinecraft attribute identifier
operationStringYesadd_value, add_multiplied_base, or add_multiplied_total
valueNumberYesValue to apply (meaning depends on operation)
PropertyTypeDefaultDescription
potion_effectStringRequiredMinecraft potion effect identifier
show_particlesBooleantrueShow particle effects
show_iconBooleantrueShow effect icon in inventory
ambientBooleanfalseAmbient effect (lighter particles)
PropertyTypeDefaultDescription
on_apply_scriptString""MoLang script to run on apply
on_tick_scriptString""MoLang script to run periodically
on_remove_scriptString""MoLang script to run on remove
tick_intervalInteger20Ticks between on_tick_script executions
PropertyTypeRequiredDescription
chance_increaseNumberYesAmount to increase shiny chance by

Buffs can be granted when tasks are completed:

{
"name": "catch_first_pokemon",
"display_name": "Catch Your First Pokémon",
"rewards": [
{
"type": "buff",
"data": {
"buff_id": "shiny_hunter",
"duration": 6000,
"amplifier": 0,
"source": "first_catch_task"
}
}
]
}

Buffs can be granted when players level up a levelable:

{
"name": "Pokemon Breeder",
"description": ["Become an expert at breeding Pokémon!"],
"levels": [
{
"level": 5,
"required_experience": 1000,
"rewards": [
{
"type": "buff",
"data": {
"buff_id": "shiny_hunter",
"duration": -1,
"amplifier": 1,
"source": "breeder_levelable"
}
}
]
}
]
}
PropertyTypeDescription
buff_idStringID of the buff definition to apply
durationIntegerDuration in ticks (20 ticks = 1 second), -1 for permanent
amplifierIntegerBuff level (0-based, 0 = base effect, 1 = enhanced, etc.)
sourceStringOptional source identifier for tracking/removal

Duration is specified in ticks (20 ticks = 1 second):

  • 200 = 10 seconds
  • 600 = 30 seconds
  • 1200 = 1 minute
  • 6000 = 5 minutes
  • -1 = Permanent/infinite

Amplifier is 0-based and affects buffs differently:

Attribute Buffs: Value is multiplied by (amplifier + 1)

  • Amplifier 0: value * 1 (100% of value)
  • Amplifier 1: value * 2 (200% of value)
  • Amplifier 2: value * 3 (300% of value)

Potion Buffs: Passed directly to potion effect

  • Amplifier 0: Potion effect level I
  • Amplifier 1: Potion effect level II
  • Amplifier 2: Potion effect level III

Script Buffs: Available as query.amplifier() in scripts

Shiny Chance Buffs: Chance is multiplied by (amplifier + 1)

  • Amplifier 0: chance_increase * 1
  • Amplifier 1: chance_increase * 2
  • Amplifier 2: chance_increase * 3

Buffs can have multiple instances active based on max_stacks:

  • Only one instance can be active
  • Applying again refreshes duration to new duration
  • Amplifier updates to new amplifier
  • Multiple instances can exist simultaneously
  • Each instance has its own duration and amplifier
  • When max is reached, oldest instance is refreshed

Example: Shiny Hunter with max_stacks: 3

  • Player gets buff with amplifier 0 → 1 instance active (+100 shiny chance)
  • Player gets buff with amplifier 0 → 2 instances active (+200 shiny chance)
  • Player gets buff with amplifier 1 → 3 instances active (+300 shiny chance total)

The source field in buff rewards allows tracking where buffs came from:

  • Bulk removal: Remove all buffs from a specific source
  • Automatic cleanup: Buffs from levelables are removed when levelable is lost
  • Organization: Track which systems granted which buffs

For levelable rewards, use: "{levelable_name}_levelable"

Example:

{
"buff_id": "speed_boost",
"duration": -1,
"source": "explorer_levelable"
}

When the “Explorer” levelable is removed, all buffs with source "explorer_levelable" are automatically removed.

Apply a buff to a player:

/journey buff apply <player> <buff_id> [duration] [amplifier]

Parameters:

  • <player> - Target player
  • <buff_id> - Buff identifier (just the name, e.g., speed_boost not journey:speed_boost)
  • [duration] - Optional duration in ticks (-1 for permanent, defaults to permanent)
  • [amplifier] - Optional amplifier level (defaults to 0)

Examples:

/journey buff apply @p speed_boost 600 0
/journey buff apply AmoAster shiny_hunter -1 2

Remove a specific buff from a player:

/journey buff remove <player> <buff_id>

Example:

/journey buff remove @p speed_boost

Remove all buffs from a player:

/journey buff clear <player>

Example:

/journey buff clear @p

List all active buffs on a player:

/journey buff list <player>

Example:

/journey buff list @p

Reload all buff configurations from disk:

/journey buff reload

Third-party mods can register custom buff types using the BuffTypeRegistry API.

Grant a 30-second speed boost when player completes a task:

Buff Definition (config/journey/buffs/task_speed.json):

{
"id": "task_speed",
"type": "attribute",
"name": "Task Completion Rush",
"description": "Temporary speed boost for completing a task!",
"max_stacks": 1,
"is_debuff": false,
"hidden": false,
"attribute": "minecraft:generic.movement_speed",
"operation": "add_multiplied_base",
"value": 0.3
}

Task Configuration:

{
"name": "explore_village",
"display_name": "Explore the Village",
"rewards": [
{
"type": "buff",
"data": {
"buff_id": "task_speed",
"duration": 600,
"amplifier": 0
}
}
]
}

Grant permanent shiny boost when player reaches Breeder level 10:

Levelable Configuration:

{
"name": "Pokemon Breeder",
"levels": [
{
"level": 10,
"required_experience": 10000,
"rewards": [
{
"type": "buff",
"data": {
"buff_id": "shiny_hunter",
"duration": -1,
"amplifier": 2,
"source": "breeder_levelable"
}
}
]
}
]
}

Create a celebratory buff with particles when player achieves something:

Buff Definition:

{
"id": "celebration",
"type": "script",
"name": "Celebration!",
"description": "You did something amazing!",
"max_stacks": 1,
"is_debuff": false,
"hidden": false,
"on_apply_script": "q.player.tell_minimessage('&lt;rainbow&gt;✨ AMAZING! ✨&lt;/rainbow&gt;'); q.player.play_sound('minecraft:entity.player.levelup', 1.0, 1.0)",
"on_tick_script": "q.player.snowstorm_particle('minecraft:happy_villager', query.position_x + query.random(-1, 1), query.position_y + query.random(0, 2), query.position_z + query.random(-1, 1))",
"on_remove_script": "q.player.tell_minimessage('&lt;gray&gt;Back to normal!&lt;/gray&gt;')",
"tick_interval": 10
}

Use descriptive, lowercase IDs with underscores:

  • shiny_hunter, speed_boost, mining_haste
  • buff1, SpeedBoost, shiny-hunter

For readability, use these common durations:

{
"duration": 200, // 10 seconds
"duration": 600, // 30 seconds
"duration": 1200, // 1 minute
"duration": 6000, // 5 minutes
"duration": 12000, // 10 minutes
"duration": -1 // Permanent
}

Use consistent source naming:

  • Levelables: "{levelable_name}_levelable"
  • Tasks: "{task_name}_task"
  • Custom systems: "{mod_id}_{feature_name}"
  • Use max_stacks: 1 for unique buffs that shouldn’t stack
  • Use higher values when stacking makes sense (shiny buffs, damage buffs)
  • Consider balance: more stacks = more powerful

Use hidden: true for:

  • Background calculations
  • System-level effects
  • Effects that shouldn’t clutter player UI

Check:

  1. JSON syntax is valid (use a JSON validator)
  2. File is in config/journey/buffs/ directory
  3. File has .json extension
  4. Server logs for error messages

Check:

  1. Buff ID matches exactly (case-sensitive)
  2. Player doesn’t already have max_stacks instances
  3. Duration is valid (-1 or positive number)
  4. Server logs for error messages

Check:

  1. Attribute name is valid Minecraft attribute
  2. Operation is one of: add_value, add_multiplied_base, add_multiplied_total
  3. Value is appropriate for the operation
  4. Player has the attribute (not all entities have all attributes)

Check:

  1. MoLang syntax is correct
  2. Script doesn’t have syntax errors (check logs)
  3. For on_tick_script, ensure tick_interval is reasonable
  4. Functions used exist in Journey’s MoLang implementation