Quest Phasing
NPCs appear and disappear as quests progress
The NPC Visibility System enables per-player control of NPC visibility, allowing you to create phased quest content where NPCs appear or disappear based on player progress, flags, or other conditions.
NPC Visibility provides:
Quest Phasing
NPCs appear and disappear as quests progress
Story Progression
Control NPC visibility based on story state
Dynamic World
World changes for each player individually
MoLang Powered
Full scripting control via MoLang
Phase 1: NPC visible, gives questPhase 2: NPC hidden (traveling)Phase 3: NPC visible at new locationGood Path: See friendly NPCsEvil Path: See hostile NPCsLow Level: See tutorial NPCsHigh Level: See endgame NPCsPre-Champion: See gym leadersPost-Champion: See Elite FourNPC visibility is configured directly on NPC entities using commands or MoLang scripts.
Each NPC can have:
The NPC Visibility System provides several MoLang functions for controlling visibility.
q.npc.set_visibility_condition(condition)Set a global visibility condition for all players.
Example:
// Only visible to players with spirit vision flagq.npc.set_visibility_condition("q.player.has_flag('spirit_vision')");Parameters:
condition (String) - MoLang expression returning 1.0 (visible) or 0.0 (hidden)Common Conditions:
// Flag-basedq.npc.set_visibility_condition("q.player.has_flag('quest_started')");
// Task completionq.npc.set_visibility_condition("q.player.has_completed_task('journey:intro_quest')");
// Level-basedq.npc.set_visibility_condition("q.player.levelable_level('trainer_rank') >= 25.0");
// Combinedq.npc.set_visibility_condition("q.player.has_flag('gym_badge_8') && !q.player.has_completed_task('journey:champion_fight')");q.npc.set_player_visibility(playerUuid, condition)Set a visibility condition for a specific player.
Example:
// Hide from specific playerq.npc.set_player_visibility('player-uuid-here', '0.0');
// Show only if player has special flagq.npc.set_player_visibility('player-uuid-here', "q.player.has_flag('chosen_one')");Parameters:
playerUuid (String) - Player’s UUIDcondition (String) - MoLang expression for visibilityUse Cases:
q.npc.force_show_to_player(playerUuid)Force NPC to be visible to a specific player, overriding all conditions.
Example:
q.npc.force_show_to_player('player-uuid-here');Use Cases:
q.npc.force_hide_from_player(playerUuid)Force NPC to be hidden from a specific player, overriding all conditions.
Example:
q.npc.force_hide_from_player('player-uuid-here');Use Cases:
q.npc.is_visible_to_player(playerUuid)Check if NPC is currently visible to a player.
Example:
q.npc.is_visible_to_player('player-uuid-here')Returns:
1.0 if visible0.0 if hiddenUse Cases:
q.npc.update_visibility()Manually trigger visibility update for all players.
Example:
// After changing conditions, force immediate updateq.npc.set_visibility_condition("q.player.has_flag('new_flag')");
q.npc.update_visibility();Use Cases:
NPC appears during specific quest phase.
// In quest script, when phase changes:q.npc.set_visibility_condition("q.player.has_flag('quest_phase_2') && !q.player.has_flag('quest_phase_3')");
q.npc.update_visibility();Result: NPC visible only during phase 2.
NPC visibility changes based on story progression.
// Tutorial NPC - visible only at startq.npc.set_visibility_condition("!q.player.has_completed_task('journey:tutorial')");
// Mentor NPC - visible after tutorialq.npc.set_visibility_condition("q.player.has_completed_task('journey:tutorial') && q.player.levelable_level('trainer_rank') < 50.0");
// Master NPC - visible at high levelq.npc.set_visibility_condition("q.player.levelable_level('trainer_rank') >= 50.0");Different NPCs based on player choices.
// Good path NPCsq.npc.set_visibility_condition("q.player.has_flag('chose_good_path')");
// Evil path NPCsq.npc.set_visibility_condition("q.player.has_flag('chose_evil_path')");
// Neutral NPCs (visible to both)q.npc.set_visibility_condition("1.0");NPC visible only during specific times or events.
// Event NPC - visible only during eventq.npc.set_visibility_condition("q.player.has_flag('halloween_event_active')");
// Daily NPC - visible once per dayq.npc.set_visibility_condition("q.player.has_flag('daily_npc_available')");Control how often visibility conditions are evaluated.
Default: 20 ticks (1 second)
Setting via script:
// Check every 5 seconds (100 ticks)q.npc.set_check_interval(100);Performance Considerations:
Control whether dialogue should sync with visibility.
When enabled:
When disabled:
Setting via script:
q.npc.set_dialogue_sync(true);Make NPCs appear/disappear based on task state.
Example Task:
{ "name": "Find the Lost Merchant", "sequential": "sequential", "tasks": [ { "id": "search_for_merchant", "name": "Search the Forest", "event": "ENTER_ZONE", "target": 1, "script": "q.npc.set_visibility_condition('1.0'); q.npc.update_visibility();" }, { "id": "talk_to_merchant", "name": "Talk to the Merchant", "event": "ENTITY_INTERACT", "target": 1 } ]}Flow:
Combine with quest markers for guided NPC discovery.
{ "id": "hidden_npc_marker", "name": "Mysterious Presence", "position": {"x": 100, "y": 64, "z": 200}, "visibilityCondition": "q.player.has_flag('can_see_spirits')", "onActivate": { "scripts": [ "q.npc.force_show_to_player(q.player.uuid());" ] }}Flow:
NPC visible only during tutorial, disappears after.
// Set visibility conditionq.npc.set_visibility_condition("!q.player.has_completed_task('journey:tutorial_complete')");
// When tutorial completes (in task script)q.player.add_flag('tutorial_complete');// NPC automatically becomes hidden for this playerGym leaders appear as you progress.
// Brock - Always visibleq.npc.set_visibility_condition("1.0");
// Misty - Visible after defeating Brockq.npc.set_visibility_condition("q.player.has_flag('gym_badge_boulder')");
// Lt. Surge - Visible after defeating Mistyq.npc.set_visibility_condition("q.player.has_flag('gym_badge_cascade')");
// And so on...Different NPCs for different story paths.
// Professor Oak's Lab
// Assistant (always visible)q.npc.set_visibility_condition("1.0");
// Good Path Researcherq.npc.set_visibility_condition("q.player.has_flag('helped_townspeople')");
// Evil Path Gruntq.npc.set_visibility_condition("q.player.has_flag('joined_team_rocket')");NPCs from different time periods.
// Present Day NPCsq.npc.set_visibility_condition("!q.player.has_flag('time_traveled')");
// Past NPCsq.npc.set_visibility_condition("q.player.has_flag('time_traveled') && q.player.has_flag('in_past')");
// Future NPCsq.npc.set_visibility_condition("q.player.has_flag('time_traveled') && q.player.has_flag('in_future')");Note: The <npc> argument in all commands is an entity selector (e.g., @e[type=cobblemon:npc,limit=1]). You can target NPCs by looking at them or using entity selectors.
/journey npcvisibility <player> show <npc>Force NPC to be visible to a specific player.
Permission: journey.command.npcvisibility
Arguments:
<player> - Target player name<npc> - Entity selector for the NPCExample:
# Target nearest NPC/journey npcvisibility Notch show @e[type=cobblemon:npc,limit=1,sort=nearest]
# Target specific NPC by name/journey npcvisibility Notch show @e[type=cobblemon:npc,name="Elder"]/journey npcvisibility <player> hide <npc>Force NPC to be hidden from a specific player.
Permission: journey.command.npcvisibility
Example:
/journey npcvisibility Notch hide @e[type=cobblemon:npc,limit=1,sort=nearest]/journey npcvisibility <player> check <npc>Check if NPC is currently visible to a player.
Permission: journey.command.npcvisibility
Example:
/journey npcvisibility Notch check @e[type=cobblemon:npc,limit=1,sort=nearest]Output:
NPC Elder is visible to Notch/journey npcvisibility <player> setcondition <npc> <condition>Set a player-specific visibility condition for an NPC.
Permission: journey.command.npcvisibility
Arguments:
<player> - Target player name<npc> - Entity selector for the NPC<condition> - MoLang condition expressionExample:
/journey npcvisibility Notch setcondition @e[type=cobblemon:npc,name="Elder"] q.player.has_flag('spirit_vision')/journey npcvisibility register <npc> [condition]Register an NPC with the visibility system. Optionally provide a global condition.
Permission: journey.command.npcvisibility
Arguments:
<npc> - Entity selector for the NPC[condition] - Optional MoLang condition (defaults to always visible)Example:
# Register with always visible/journey npcvisibility register @e[type=cobblemon:npc,name="Elder"]
# Register with condition/journey npcvisibility register @e[type=cobblemon:npc,name="Spirit"] q.player.has_flag('spirit_vision')/journey npcvisibility update <npc>Manually trigger visibility update for all players for a specific NPC.
Permission: journey.command.npcvisibility
Example:
/journey npcvisibility update @e[type=cobblemon:npc,name="Elder"]/journey npcvisibility listList all registered NPC visibility configurations.
Permission: journey.command.npcvisibility
✅ Keep It Simple - Complex conditions are harder to debug
✅ Use Flags - Flags are fast and easy to track
✅ Cache Results - Don’t recalculate complex conditions every tick
✅ Test Thoroughly - Verify conditions work as expected
✅ Reasonable Check Intervals - 20-60 ticks is usually sufficient
✅ Avoid Heavy Conditions - Complex MoLang impacts performance
✅ Batch Updates - Use manual updates when changing many NPCs
✅ Gradual Changes - Don’t have NPCs pop in/out suddenly
✅ Visual Feedback - Use particles or sounds when NPCs appear
✅ Clear Triggers - Players should understand why NPCs appear
✅ Consistent Logic - Similar NPCs should use similar conditions
Check:
/journey npcvisibility <player> check <npc> commandCheck:
update_visibility() after condition changeCheck:
Check: