Skip to content

NPC Visibility System

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:

  • Per-Player Control - Each player sees different NPCs
  • MoLang Conditions - Show/hide based on complex logic
  • Global Conditions - Apply rules to all players
  • Per-Player Overrides - Specific rules for individual players
  • Periodic Checks - Configurable update intervals
  • Quest Phasing - NPCs appear/disappear during quest progression

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 quest
Phase 2: NPC hidden (traveling)
Phase 3: NPC visible at new location
Good Path: See friendly NPCs
Evil Path: See hostile NPCs
Low Level: See tutorial NPCs
High Level: See endgame NPCs
Pre-Champion: See gym leaders
Post-Champion: See Elite Four

NPC visibility is configured directly on NPC entities using commands or MoLang scripts.

Each NPC can have:

  • Default Visibility - Visible or hidden by default
  • Global Condition - MoLang condition applied to all players
  • Per-Player Conditions - Specific conditions for individual players
  • Check Interval - How often to update visibility (ticks)
  • Dialogue Sync - Whether to sync dialogue with visibility

The NPC Visibility System provides several MoLang functions for controlling visibility.

Set a global visibility condition for all players.

Example:

// Only visible to players with spirit vision flag
q.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-based
q.npc.set_visibility_condition("q.player.has_flag('quest_started')");
// Task completion
q.npc.set_visibility_condition("q.player.has_completed_task('journey:intro_quest')");
// Level-based
q.npc.set_visibility_condition("q.player.levelable_level('trainer_rank') >= 25.0");
// Combined
q.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)

Section titled “q.npc.set_player_visibility(playerUuid, condition)”

Set a visibility condition for a specific player.

Example:

// Hide from specific player
q.npc.set_player_visibility('player-uuid-here', '0.0');
// Show only if player has special flag
q.npc.set_player_visibility('player-uuid-here', "q.player.has_flag('chosen_one')");

Parameters:

  • playerUuid (String) - Player’s UUID
  • condition (String) - MoLang expression for visibility

Use Cases:

  • Player-specific quest NPCs
  • Personalized story branches
  • One-time NPC interactions

Force NPC to be visible to a specific player, overriding all conditions.

Example:

q.npc.force_show_to_player('player-uuid-here');

Use Cases:

  • Debug/testing
  • Admin commands
  • Special event triggers

Force NPC to be hidden from a specific player, overriding all conditions.

Example:

q.npc.force_hide_from_player('player-uuid-here');

Use Cases:

  • Punishment mechanics
  • Story-driven removals
  • Phasing transitions

Check if NPC is currently visible to a player.

Example:

q.npc.is_visible_to_player('player-uuid-here')

Returns:

  • 1.0 if visible
  • 0.0 if hidden

Use Cases:

  • Conditional dialogue
  • Quest validation
  • Event triggers

Manually trigger visibility update for all players.

Example:

// After changing conditions, force immediate update
q.npc.set_visibility_condition("q.player.has_flag('new_flag')");
q.npc.update_visibility();

Use Cases:

  • Immediate visibility changes
  • After flag updates
  • Event-driven updates

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 start
q.npc.set_visibility_condition("!q.player.has_completed_task('journey:tutorial')");
// Mentor NPC - visible after tutorial
q.npc.set_visibility_condition("q.player.has_completed_task('journey:tutorial') && q.player.levelable_level('trainer_rank') < 50.0");
// Master NPC - visible at high level
q.npc.set_visibility_condition("q.player.levelable_level('trainer_rank') >= 50.0");

Different NPCs based on player choices.

// Good path NPCs
q.npc.set_visibility_condition("q.player.has_flag('chose_good_path')");
// Evil path NPCs
q.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 event
q.npc.set_visibility_condition("q.player.has_flag('halloween_event_active')");
// Daily NPC - visible once per day
q.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:

  • Lower interval = more responsive but higher CPU usage
  • Higher interval = less responsive but better performance
  • Recommended: 20-60 ticks for most use cases

Control whether dialogue should sync with visibility.

When enabled:

  • Hidden NPCs cannot be talked to
  • Dialogue trees respect visibility state
  • Prevents interaction with “invisible” NPCs

When disabled:

  • NPCs can be talked to even if hidden (for testing)

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:

  1. Player starts task, merchant is hidden
  2. Player enters zone, script reveals merchant
  3. Player talks to merchant, task completes
  4. Merchant can be hidden again in next task

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:

  1. Marker appears to players with spirit vision
  2. Player reaches marker location
  3. NPC becomes visible via force_show
  4. Player can interact with previously hidden NPC

NPC visible only during tutorial, disappears after.

// Set visibility condition
q.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 player

Gym leaders appear as you progress.

// Brock - Always visible
q.npc.set_visibility_condition("1.0");
// Misty - Visible after defeating Brock
q.npc.set_visibility_condition("q.player.has_flag('gym_badge_boulder')");
// Lt. Surge - Visible after defeating Misty
q.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 Researcher
q.npc.set_visibility_condition("q.player.has_flag('helped_townspeople')");
// Evil Path Grunt
q.npc.set_visibility_condition("q.player.has_flag('joined_team_rocket')");

NPCs from different time periods.

// Present Day NPCs
q.npc.set_visibility_condition("!q.player.has_flag('time_traveled')");
// Past NPCs
q.npc.set_visibility_condition("q.player.has_flag('time_traveled') && q.player.has_flag('in_past')");
// Future NPCs
q.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>

Section titled “/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 NPC

Example:

Terminal window
# 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>

Section titled “/journey npcvisibility <player> hide <npc>”

Force NPC to be hidden from a specific player.

Permission: journey.command.npcvisibility

Example:

Terminal window
/journey npcvisibility Notch hide @e[type=cobblemon:npc,limit=1,sort=nearest]

/journey npcvisibility <player> check <npc>

Section titled “/journey npcvisibility <player> check <npc>”

Check if NPC is currently visible to a player.

Permission: journey.command.npcvisibility

Example:

Terminal window
/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>

Section titled “/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 expression

Example:

Terminal window
/journey npcvisibility Notch setcondition @e[type=cobblemon:npc,name="Elder"] q.player.has_flag('spirit_vision')

/journey npcvisibility register <npc> [condition]

Section titled “/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:

Terminal window
# 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')

Manually trigger visibility update for all players for a specific NPC.

Permission: journey.command.npcvisibility

Example:

Terminal window
/journey npcvisibility update @e[type=cobblemon:npc,name="Elder"]

List 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:

  1. Visibility condition evaluates to true
  2. No per-player override hiding NPC
  3. Check interval has passed
  4. Use /journey npcvisibility <player> check <npc> command

Check:

  1. Visibility condition changed correctly
  2. Called update_visibility() after condition change
  3. No force_show override
  4. Check interval allows updates

Check:

  1. MoLang syntax is correct
  2. Functions used are available
  3. Flag/task names are correct
  4. Check server logs for MoLang errors

Check:

  1. Check interval not too low (less than 10 ticks)
  2. Condition complexity (avoid nested queries)
  3. Number of NPCs with visibility checks
  4. Consider disabling for non-critical NPCs

  • NPC System - Create and configure NPCs
  • Task System - Trigger visibility changes via tasks
  • Flags - Track player progress for conditions
  • MoLang - Write complex visibility conditions
  • Markers - Combine with NPC visibility