State Machines
State Machines
Section titled “State Machines”State machines define per-phase AI behavior using states, transitions, and MoLang conditions. Each phase can have completely different AI patterns.
Overview
Section titled “Overview”graph LR
A[patrol_state] -->|target_close| B[aggressive_state]
B -->|time_expired| A
B -->|took_damage| C[retreat_state]
C -->|distance_safe| A
style A fill:#4a9eff
style B fill:#e74c3c
style C fill:#f39c12
A state machine consists of:
- States: AI behaviors with movement controllers
- Transitions: Conditional switches between states
- Global Transitions: Emergency transitions from any state
Basic Structure
Section titled “Basic Structure”{ "stateMachine": { "initialState": "patrol", "states": { "patrol": { "movementController": "titan:ground_patrol", "speedMultiplier": 1.0, "aggressionMultiplier": 1.0, "minDuration": 2000, "maxDuration": 5000, "transitions": [ { "targetState": "aggressive", "condition": "q.titan_distance_to_target < 8.0" } ] }, "aggressive": { "movementController": "titan:ground_berserker", "speedMultiplier": 1.3, "aggressionMultiplier": 1.8, "minDuration": 1500, "maxDuration": 4000, "transitions": [ { "targetState": "patrol", "condition": "q.titan_time_in_state > 3500" } ] } }, "globalTransitions": [ { "targetState": "retreat", "condition": "q.titan_time_since_damage < 1000" } ] }}State Configuration
Section titled “State Configuration”Basic Properties
Section titled “Basic Properties”movementController (Required)
Section titled “movementController (Required)”Defines how the titan moves in this state:
| Controller | Behavior | Best For |
|---|---|---|
titan:ground_patrol | Standard ground movement | Default/neutral state |
titan:ground_berserker | Aggressive ground rush | Melee phase |
titan:aerial_circler | Circle around target in air | Flying bosses |
titan:aerial_bomber | Dive bomb from above | Aggressive flying |
titan:aerial_rush | Fast aerial charges | Flying pursuit |
"movementController": "titan:ground_patrol"speedMultiplier (Optional, default: 1.0)
Section titled “speedMultiplier (Optional, default: 1.0)”Movement speed multiplier for this state:
"speedMultiplier": 1.0 // Normal speed"speedMultiplier": 1.3 // 30% faster"speedMultiplier": 0.7 // 30% sloweraggressionMultiplier (Optional, default: 1.0)
Section titled “aggressionMultiplier (Optional, default: 1.0)”How aggressively titan pursues target:
"aggressionMultiplier": 1.0 // Normal"aggressionMultiplier": 1.5 // More aggressive"aggressionMultiplier": 0.5 // DefensiveHigher values = closer positioning, more frequent attacks.
minDuration / maxDuration (Optional)
Section titled “minDuration / maxDuration (Optional)”Time range in milliseconds before forced transition:
"minDuration": 2000, // At least 2 seconds"maxDuration": 5000 // At most 5 secondsAfter maxDuration, titan MUST transition (first valid transition chosen).
Event Scripts
Section titled “Event Scripts”onEnter (Optional)
Section titled “onEnter (Optional)”MoLang executed when entering state:
"onEnter": "q.particle_effect('minecraft:flame', q.position(0), 50, 2.0); q.play_sound('minecraft:entity.blaze.ambient', 0.6, 1.2)"Common uses:
- Particle effects
- Sound effects
- Temporary buffs
- Visual indicators
onTick (Optional)
Section titled “onTick (Optional)”MoLang executed every tick while in state:
"onTick": "q.particle_effect('minecraft:flame', q.position(0), 2, 1.0)"Common uses:
- Particle trails
- Periodic effects
- Status checks
onExit (Optional)
Section titled “onExit (Optional)”MoLang executed when leaving state:
"onExit": "q.particle_effect('minecraft:large_smoke', q.position(0), 30, 1.5)"Common uses:
- Cleanup effects
- Remove temporary buffs
- Transition particles
Custom Properties
Section titled “Custom Properties”properties (Optional)
Section titled “properties (Optional)”Store custom data accessible in MoLang:
"properties": { "attack_power": 1.5, "is_enraged": true, "custom_flag": "value"}Access with: q.titan_state_property('attack_power')
Transitions
Section titled “Transitions”Basic Transition
Section titled “Basic Transition”{ "targetState": "aggressive", "condition": "q.titan_distance_to_target < 8.0 && q.titan_time_in_state > 2000", "priority": 0, "cooldown": 0, "onTransition": null}Properties
Section titled “Properties”targetState (Required)
Section titled “targetState (Required)”State ID to transition to:
"targetState": "aggressive"Must match a key in the states object.
condition (Required)
Section titled “condition (Required)”MoLang expression that must be true:
// Simple"condition": "q.titan_time_in_state > 3000"
// Complex"condition": "q.titan_distance_to_target < 5.0 && q.titan_health_percent < 0.5"
// Random"condition": "q.titan_random < 0.3 && q.titan_time_in_state > 2000"See MoLang Reference for all functions.
priority (Optional, default: 0)
Section titled “priority (Optional, default: 0)”Higher priority transitions evaluated first:
// Checked first{ "targetState": "enrage", "condition": "q.titan_health_percent < 0.15", "priority": 10}
// Checked second{ "targetState": "aggressive", "condition": "q.titan_distance_to_target < 8.0", "priority": 5}
// Checked last{ "targetState": "patrol", "condition": "q.titan_time_in_state > 5000", "priority": 0}cooldown (Optional, default: 0)
Section titled “cooldown (Optional, default: 0)”Milliseconds before transition can be used again:
"cooldown": 5000 // 5 second cooldownPrevents rapid state switching.
onTransition (Optional)
Section titled “onTransition (Optional)”MoLang executed when transition occurs:
"onTransition": "q.play_sound('minecraft:entity.enderman.scream', 1.0, 1.0); q.particle_effect('minecraft:portal', q.position(0), 40, 2.0)"Global Transitions
Section titled “Global Transitions”Transitions that work from ANY state.
"globalTransitions": [ { "targetState": "retreat", "condition": "q.titan_time_since_damage < 1000", "priority": 100 }, { "targetState": "enrage", "condition": "q.titan_health_percent < 0.1", "priority": 90 }]Use for:
- Emergency behaviors (low HP, took damage)
- Phase-wide mechanics
- Special triggers
Available MoLang Functions
Section titled “Available MoLang Functions”Combat Context
Section titled “Combat Context”| Function | Returns | Description |
|---|---|---|
q.titan_health_percent | 0.0-1.0 | Current HP percentage |
q.titan_distance_to_target | Float | Distance to target (blocks) |
q.titan_time_in_state | Long | Milliseconds in current state |
q.titan_time_since_damage | Long | Milliseconds since last hit |
q.titan_aggression_level | Float | Current aggression level |
Capabilities
Section titled “Capabilities”| Function | Returns | Description |
|---|---|---|
q.titan_can_fly | 0.0/1.0 | 1.0 if Pokemon can fly |
q.titan_melee_move_count | Int | Moves with range ≤ 5 |
q.titan_ranged_move_count | Int | Moves with range > 5 |
Phase & State
Section titled “Phase & State”| Function | Returns | Description |
|---|---|---|
q.titan_current_phase | Int | Phase index (0, 1, 2…) |
q.titan_state_property(key) | Number/Bool | Get custom property |
q.titan_previous_state(state) | 0.0/1.0 | 1.0 if previous state matches |
Utility
Section titled “Utility”| Function | Returns | Description |
|---|---|---|
q.titan_random | 0.0-1.0 | Random value |
Complete Examples
Section titled “Complete Examples”Flying Boss (3 States)
Section titled “Flying Boss (3 States)”{ "stateMachine": { "initialState": "circling", "states": { "circling": { "movementController": "titan:aerial_circler", "speedMultiplier": 1.1, "aggressionMultiplier": 1.0, "minDuration": 2000, "maxDuration": 6000, "onEnter": "q.particle_effect('minecraft:cloud', q.position(0), 30, 1.5)", "onTick": "q.particle_effect('minecraft:cloud', q.position(0), 1, 0.5)", "transitions": [ { "targetState": "dive_bomb", "condition": "q.titan_distance_to_target < 10.0 && q.titan_time_in_state > 2500", "priority": 5 }, { "targetState": "high_altitude", "condition": "q.titan_random < 0.2 && q.titan_time_in_state > 3000", "priority": 3 } ] }, "dive_bomb": { "movementController": "titan:aerial_bomber", "speedMultiplier": 1.4, "aggressionMultiplier": 1.8, "minDuration": 1500, "maxDuration": 4000, "onEnter": "q.play_sound('minecraft:entity.ender_dragon.flap', 0.8, 1.2)", "transitions": [ { "targetState": "circling", "condition": "q.titan_time_in_state > 3000", "priority": 5 }, { "targetState": "retreat", "condition": "q.titan_time_since_damage < 1200", "priority": 10 } ] }, "high_altitude": { "movementController": "titan:aerial_rush", "speedMultiplier": 1.6, "aggressionMultiplier": 0.3, "minDuration": 2000, "maxDuration": 5000, "onEnter": "q.particle_effect('minecraft:firework', q.position(0), 50, 2.0)", "transitions": [ { "targetState": "dive_bomb", "condition": "q.titan_time_in_state > 4000", "priority": 5 } ] }, "retreat": { "movementController": "titan:aerial_rush", "speedMultiplier": 1.8, "aggressionMultiplier": 0.5, "minDuration": 1000, "maxDuration": 3000, "onEnter": "q.particle_effect('minecraft:large_smoke', q.position(0), 60, 2.0)", "transitions": [ { "targetState": "circling", "condition": "q.titan_distance_to_target > 15.0 || q.titan_time_in_state > 2500", "priority": 5 } ] } }, "globalTransitions": [ { "targetState": "retreat", "condition": "q.titan_health_percent < 0.3 && q.titan_time_since_damage < 800", "priority": 100 } ] }}Ground Berserker (2 States)
Section titled “Ground Berserker (2 States)”{ "stateMachine": { "initialState": "patrol", "states": { "patrol": { "movementController": "titan:ground_patrol", "speedMultiplier": 1.0, "aggressionMultiplier": 1.2, "minDuration": 2000, "maxDuration": 5000, "onTick": "q.particle_effect('minecraft:smoke', q.position(0), 1, 0.3)", "transitions": [ { "targetState": "berserk", "condition": "q.titan_distance_to_target < 8.0 && q.titan_time_in_state > 2000", "priority": 5 } ] }, "berserk": { "movementController": "titan:ground_berserker", "speedMultiplier": 1.5, "aggressionMultiplier": 2.5, "minDuration": 1500, "maxDuration": 4500, "onEnter": "q.play_sound('minecraft:entity.ravager.roar', 1.0, 0.8); q.particle_effect('minecraft:angry_villager', q.position(0), 20, 1.5)", "onTick": "q.particle_effect('minecraft:flame', q.position(0), 2, 1.0)", "transitions": [ { "targetState": "patrol", "condition": "q.titan_distance_to_target > 12.0 || q.titan_time_in_state > 4000", "priority": 5 } ] } }, "globalTransitions": [] }}Distance-Based (4 States)
Section titled “Distance-Based (4 States)”{ "stateMachine": { "initialState": "neutral", "states": { "neutral": { "movementController": "titan:ground_patrol", "speedMultiplier": 1.0, "aggressionMultiplier": 1.0, "minDuration": 1000, "maxDuration": 999999, "transitions": [ { "targetState": "ranged", "condition": "q.titan_distance_to_target > 10.0", "priority": 5 }, { "targetState": "melee", "condition": "q.titan_distance_to_target < 6.0", "priority": 5 } ] }, "ranged": { "movementController": "titan:ground_patrol", "speedMultiplier": 1.1, "aggressionMultiplier": 0.8, "minDuration": 2000, "maxDuration": 6000, "transitions": [ { "targetState": "approach", "condition": "q.titan_time_in_state > 4000", "priority": 3 }, { "targetState": "melee", "condition": "q.titan_distance_to_target < 6.0", "priority": 8 } ] }, "approach": { "movementController": "titan:ground_berserker", "speedMultiplier": 1.3, "aggressionMultiplier": 1.5, "minDuration": 1000, "maxDuration": 4000, "transitions": [ { "targetState": "melee", "condition": "q.titan_distance_to_target < 6.0", "priority": 8 }, { "targetState": "neutral", "condition": "q.titan_time_in_state > 3500", "priority": 3 } ] }, "melee": { "movementController": "titan:ground_berserker", "speedMultiplier": 1.2, "aggressionMultiplier": 2.0, "minDuration": 1500, "maxDuration": 5000, "transitions": [ { "targetState": "neutral", "condition": "q.titan_distance_to_target > 10.0 || q.titan_time_in_state > 4500", "priority": 5 } ] } }, "globalTransitions": [] }}Design Patterns
Section titled “Design Patterns”Aggressive/Defensive Cycle
Section titled “Aggressive/Defensive Cycle”Alternate between attack and retreat:
aggressive (2-4s) → defensive (1-3s) → aggressiveGood for melee bosses.
Distance-Based
Section titled “Distance-Based”Change behavior based on range:
ranged (>10 blocks) → approach (6-10) → melee (<6)Good for mixed-range bosses.
Random Variation
Section titled “Random Variation”Add unpredictability:
state_a → (30% chance) state_bstate_a → (70% chance) state_cUse q.titan_random < 0.3 for 30% chance.
Time-Limited Aggression
Section titled “Time-Limited Aggression”Burst then retreat:
neutral → aggressive (max 5s) → cooldown → neutralPrevents endless aggression.
Troubleshooting
Section titled “Troubleshooting”State Not Transitioning
Section titled “State Not Transitioning”- Check condition MoLang syntax
- Verify target state exists
- Check
maxDurationisn’t too short - Test condition independently:
q.titan_distance_to_targetin chat
Stuck in State
Section titled “Stuck in State”- No valid transitions found
- Add fallback transition with
q.titan_time_in_state > X - Check global transitions don’t override everything
Rapid State Switching
Section titled “Rapid State Switching”- Add
cooldownto transitions - Increase
minDuration - Make conditions mutually exclusive
Movement Controller Not Working
Section titled “Movement Controller Not Working”- Verify controller ID is correct
- Check if Pokemon can actually fly (for aerial controllers)
- Ensure movement isn’t stopped by other systems
Next Steps
Section titled “Next Steps”- Phases → - Per-phase configuration
- Fight Config Builder → - Visual state machine editor
- MoLang Reference → - All scripting functions
Build complex boss AI with state machines! 🤖