Advanced Patterns¶
This guide covers advanced scripting techniques for creating complex gameplay sequences, quest chains, and dynamic NPC behaviors.
Sequential Cutscenes¶
Chain multiple scripts using script_complete to create multi-part cutscenes.
{
"cutscene_part1": {
"scene": "temple",
"trigger": {
"event": "npc_interacted",
"npc": "elder"
},
"run_once": true,
"actions": [
{
"type": "dialog",
"speaker": "Elder",
"text": ["Behold the ancient altar!"]
},
{
"type": "wait_for_dialog_close"
}
]
},
"cutscene_part2": {
"scene": "temple",
"trigger": {
"event": "script_complete",
"script_name": "cutscene_part1"
},
"actions": [
{
"type": "move_npc",
"npcs": ["elder"],
"waypoint": "altar"
},
{
"type": "wait_for_movement",
"npc": "elder"
},
{
"type": "reveal_npcs",
"npcs": ["spirit"]
}
]
},
"cutscene_part3": {
"scene": "temple",
"trigger": {
"event": "script_complete",
"script_name": "cutscene_part2"
},
"actions": [
{
"type": "dialog",
"speaker": "Spirit",
"text": ["I have been summoned..."]
},
{
"type": "wait_for_dialog_close"
},
{
"type": "play_music",
"file": "mysterious.ogg"
}
]
}
}
Key Techniques:
- Each part triggers when the previous completes
- Use
run_onceon the first script to prevent replaying the sequence - Break long sequences into manageable chunks
- Each part can have different timing and actions
Conditional Progression¶
Create branching paths based on player actions and game state.
{
"talk_with_seal": {
"scene": "castle",
"trigger": {
"event": "npc_interacted",
"npc": "guard",
"dialog_level": 0
},
"conditions": [
{
"check": "object_interacted",
"object": "royal_seal",
"equals": true
}
],
"actions": [
{
"type": "set_dialog_level",
"npc": "guard",
"dialog_level": 2
},
{
"type": "dialog",
"speaker": "Guard",
"text": ["You have the royal seal! Enter."]
},
{
"type": "reveal_npcs",
"npcs": ["king"]
}
]
},
"talk_without_seal": {
"scene": "castle",
"trigger": {
"event": "npc_interacted",
"npc": "guard",
"dialog_level": 0
},
"actions": [
{
"type": "dialog",
"speaker": "Guard",
"text": ["You need the royal seal to enter."]
}
]
}
}
Key Techniques:
- First script has conditions, second is fallback
- Both trigger on same event
- First script changes dialog level to prevent future triggers
- Creates "gated" progression requiring specific actions
NPC Patrol Routes¶
Create looping movement patterns for guards, merchants, or other NPCs.
{
"guard_patrol_1": {
"scene": "castle",
"trigger": {
"event": "npc_movement_complete",
"npc": "guard",
"waypoint": "point_a"
},
"actions": [
{
"type": "move_npc",
"npcs": ["guard"],
"waypoint": "point_b"
}
]
},
"guard_patrol_2": {
"scene": "castle",
"trigger": {
"event": "npc_movement_complete",
"npc": "guard",
"waypoint": "point_b"
},
"actions": [
{
"type": "move_npc",
"npcs": ["guard"],
"waypoint": "point_c"
}
]
},
"guard_patrol_3": {
"scene": "castle",
"trigger": {
"event": "npc_movement_complete",
"npc": "guard",
"waypoint": "point_c"
},
"actions": [
{
"type": "move_npc",
"npcs": ["guard"],
"waypoint": "point_a"
}
]
}
}
Key Techniques:
- Each waypoint arrival triggers next movement
- Forms a continuous loop
- Add delays or dialog at specific waypoints
- Can have multiple NPCs with different routes
Enhanced Version with Pauses:
{
"guard_patrol_1": {
"scene": "castle",
"trigger": {
"event": "npc_movement_complete",
"npc": "guard",
"waypoint": "point_a"
},
"actions": [
{
"type": "dialog",
"speaker": "Guard",
"text": ["Hmm, all quiet here..."]
},
{
"type": "wait_for_dialog_close"
},
{
"type": "move_npc",
"npcs": ["guard"],
"waypoint": "point_b"
}
]
}
}
Multi-Stage Quests¶
Track quest progress through dialog levels and object interactions.
{
"quest_start": {
"scene": "temple",
"trigger": {
"event": "npc_interacted",
"npc": "elder",
"dialog_level": 0
},
"run_once": true,
"actions": [
{
"type": "dialog",
"speaker": "Elder",
"text": ["Bring me the ancient artifact..."]
},
{
"type": "wait_for_dialog_close"
},
{
"type": "advance_dialog",
"npc": "elder"
}
]
},
"quest_progress": {
"scene": "temple",
"trigger": {
"event": "object_interacted",
"object_name": "ancient_artifact"
},
"run_once": true,
"actions": [
{
"type": "set_dialog_level",
"npc": "elder",
"dialog_level": 2
}
]
},
"quest_complete": {
"scene": "temple",
"trigger": {
"event": "npc_interacted",
"npc": "elder",
"dialog_level": 2
},
"run_once": true,
"actions": [
{
"type": "dialog",
"speaker": "Elder",
"text": ["You found it! The quest is complete!"]
},
{
"type": "wait_for_dialog_close"
},
{
"type": "play_sfx",
"file": "quest_complete.wav"
},
{
"type": "emit_particles",
"particle_type": "burst",
"npc": "elder"
}
]
}
}
Quest State Tracking:
- Level 0: Quest not started
- Level 1: Quest given, in progress
- Level 2: Objective completed, ready to turn in
Key Techniques:
- Use dialog levels to track quest state
- Object interaction advances quest
- Different scripts for each quest stage
- Audio and visual feedback on completion
Timed Sequences¶
Create dramatic timing with coordinated movement, dialog, and effects.
{
"dramatic_entrance": {
"scene": "throne_room",
"trigger": {
"event": "object_interacted",
"object_name": "throne"
},
"run_once": true,
"actions": [
{
"type": "play_music",
"file": "ominous.ogg"
},
{
"type": "reveal_npcs",
"npcs": ["villain"]
},
{
"type": "wait_for_npcs_appear",
"npcs": ["villain"]
},
{
"type": "move_npc",
"npcs": ["villain"],
"waypoint": "throne"
},
{
"type": "wait_for_movement",
"npc": "villain"
},
{
"type": "dialog",
"speaker": "Villain",
"text": ["You dare approach my throne?!"]
},
{
"type": "wait_for_dialog_close"
},
{
"type": "reveal_npcs",
"npcs": ["minion_1", "minion_2"]
}
]
}
}
Timing Elements:
- Music sets mood immediately
- Villain appears with animation
- Wait for appearance to complete
- Villain walks to throne
- Wait for movement to complete
- Dialog plays at dramatic moment
- Minions appear as reinforcements
Complex Multi-NPC Choreography¶
Coordinate multiple NPCs with precise timing.
{
"council_meeting": {
"scene": "village",
"trigger": {
"event": "npc_interacted",
"npc": "elder"
},
"run_once": true,
"actions": [
{
"type": "dialog",
"speaker": "Elder",
"text": ["Let me call the council."]
},
{
"type": "wait_for_dialog_close"
},
{
"type": "reveal_npcs",
"npcs": ["guard", "merchant", "healer"]
},
{
"type": "wait_for_npcs_appear",
"npcs": ["guard", "merchant", "healer"]
},
{
"type": "move_npc",
"npcs": ["guard"],
"waypoint": "council_spot_1"
},
{
"type": "move_npc",
"npcs": ["merchant"],
"waypoint": "council_spot_2"
},
{
"type": "move_npc",
"npcs": ["healer"],
"waypoint": "council_spot_3"
},
{
"type": "wait_for_movement",
"npc": "guard"
},
{
"type": "wait_for_movement",
"npc": "merchant"
},
{
"type": "wait_for_movement",
"npc": "healer"
},
{
"type": "dialog",
"speaker": "Elder",
"text": ["Now that we're all here..."]
}
]
}
}
Key Techniques:
- Reveal all NPCs simultaneously
- Wait for all appearances to complete
- Move NPCs to positions (parallel movement)
- Wait for all movements to complete
- Continue with scene dialog
Dialog-Driven State Machines¶
Use dialog levels as state machine for complex NPC behaviors.
{
"blacksmith_state_idle": {
"scene": "village",
"trigger": {
"event": "npc_interacted",
"npc": "blacksmith",
"dialog_level": 0
},
"run_once": true,
"actions": [
{
"type": "dialog",
"speaker": "Blacksmith",
"text": ["I need iron ore to work."]
},
{
"type": "wait_for_dialog_close"
},
{
"type": "advance_dialog",
"npc": "blacksmith"
}
]
},
"blacksmith_state_waiting": {
"scene": "village",
"trigger": {
"event": "npc_interacted",
"npc": "blacksmith",
"dialog_level": 1
},
"actions": [
{
"type": "dialog",
"speaker": "Blacksmith",
"text": ["Have you found the iron ore yet?"]
}
]
},
"blacksmith_receive_ore": {
"scene": "village",
"trigger": {
"event": "object_interacted",
"object_name": "iron_ore"
},
"run_once": true,
"actions": [
{
"type": "set_dialog_level",
"npc": "blacksmith",
"dialog_level": 2
}
]
},
"blacksmith_state_working": {
"scene": "village",
"trigger": {
"event": "npc_interacted",
"npc": "blacksmith",
"dialog_level": 2
},
"run_once": true,
"actions": [
{
"type": "dialog",
"speaker": "Blacksmith",
"text": ["Excellent! Let me forge this into a sword."]
},
{
"type": "wait_for_dialog_close"
},
{
"type": "play_sfx",
"file": "hammer.wav"
},
{
"type": "advance_dialog",
"npc": "blacksmith"
}
]
},
"blacksmith_state_complete": {
"scene": "village",
"trigger": {
"event": "npc_interacted",
"npc": "blacksmith",
"dialog_level": 3
},
"actions": [
{
"type": "dialog",
"speaker": "Blacksmith",
"text": ["Your sword is ready!"]
}
]
}
}
States:
- 0: Initial - needs ore
- 1: Waiting - player searching for ore
- 2: Working - received ore, forging
- 3: Complete - sword ready
Dynamic Scene Population¶
Reveal NPCs based on quest progress or conditions.
{
"populate_market": {
"scene": "village",
"trigger": {
"event": "npc_interacted",
"npc": "elder",
"dialog_level": 5
},
"run_once": true,
"actions": [
{
"type": "dialog",
"speaker": "Elder",
"text": ["The market is now open!"]
},
{
"type": "wait_for_dialog_close"
},
{
"type": "reveal_npcs",
"npcs": ["merchant_1", "merchant_2", "merchant_3", "buyer_1", "buyer_2"]
}
]
}
}
Tutorial Sequences¶
Guide players through game mechanics interactively.
{
"tutorial_movement": {
"scene": "tutorial",
"trigger": {
"event": "npc_interacted",
"npc": "guide"
},
"run_once": true,
"actions": [
{
"type": "dialog",
"speaker": "Guide",
"text": ["Use WASD to move around."]
},
{
"type": "wait_for_dialog_close"
},
{
"type": "advance_dialog",
"npc": "guide"
}
]
},
"tutorial_inventory": {
"scene": "tutorial",
"trigger": {
"event": "npc_interacted",
"npc": "guide",
"dialog_level": 1
},
"run_once": true,
"actions": [
{
"type": "dialog",
"speaker": "Guide",
"text": ["Press I to open your inventory."]
},
{
"type": "wait_for_dialog_close"
},
{
"type": "wait_for_inventory_access"
},
{
"type": "dialog",
"speaker": "Guide",
"text": ["Great job! Tutorial complete."]
},
{
"type": "wait_for_dialog_close"
},
{
"type": "advance_dialog",
"npc": "guide"
}
]
}
}
Best Practices for Advanced Scripts¶
1. Plan Your State Machine¶
Draw out dialog levels and transitions before scripting:
Level 0: First meeting → Level 1
Level 1: Quest given → (on item found) → Level 2
Level 2: Quest complete → Level 3
Level 3: Repeating thank you dialog
2. Use Meaningful Names¶
3. Break Complex Sequences¶
Split into 3-5 scripts maximum per sequence:
4. Test Edge Cases¶
- What if player walks away during cutscene?
- What if NPC can't reach waypoint?
- What if player triggers same script twice?
5. Add Audio and Visual Feedback¶
Every major action should have:
- Sound effect
- Particle effect (optional)
- Dialog confirmation
6. Document State Machines¶
{
"quest_state_0": {
// STATE 0: Quest not started
// TRANSITION: Player talks to quest giver → STATE 1
"trigger": {...}
}
}
7. Use Consistent Naming Conventions¶
Performance Considerations¶
Avoid Infinite Loops¶
// Bad - Creates infinite loop
{
"bad_script_1": {
"trigger": {
"event": "script_complete",
"script_name": "bad_script_2"
},
"actions": [...]
},
"bad_script_2": {
"trigger": {
"event": "script_complete",
"script_name": "bad_script_1"
},
"actions": [...]
}
}
Limit Concurrent Scripts¶
- Don't trigger too many scripts simultaneously
- Use
wait_for_*actions to sequence properly - Consider performance with many NPCs moving
Clean Up After Cutscenes¶
Remove NPCs that are no longer needed: