Skip to content

Native Script System ​

The native script system covers the global settings, how to write a skill's script block, which phases exist, which actions you can write, and how targets and conditions work

Besides handing effects to MythicMobs, EmakiSkills ships its own native script system. The benefit: no external plugin is required, and you define effect logic directly in skill configuration

Global script engine configuration ​

The global settings live in config.yml under script_engine:

yaml
script_engine:
  enabled: true
  # Mode used when a skill does not declare one
  default_mode: "native"
  # Whether a failed action stops the current phase
  stop_on_failure: true
  # Maximum lines per phase; values below 1 are treated as 1
  max_lines_per_phase: 64
  # Maximum targets per action; values below 1 are treated as 1
  max_targets_per_action: 16
  debug: false
FieldTypeRequiredDefaultValuesDescription
script_engine.enabledbooleanNotruetrue / falseWhether native skill scripts are enabled. When off, every skill's script block is ignored and only the MythicMobs flow remains
script_engine.default_modestringNo"native"native / mythic / hybridMode used when a skill declares no script.mode; blank falls back to native
script_engine.stop_on_failurebooleanNotruetrue / falseWhether later actions in the same phase stop after a failed action; a skill may override it with script.stop_on_failure
script_engine.max_lines_per_phaseintegerNo64≥ 1, values below 1 become 1Maximum action lines in one phase
script_engine.max_targets_per_actionintegerNo16≥ 1, values below 1 become 1Maximum targets one action may process
script_engine.debugbooleanNofalsetrue / falseWhether script debug output is enabled

These limits exist to keep a single cast from processing too many actions or targets. For large area skills, cap the target count and test visuals, damage, and messages separately

The script block inside a skill ​

yaml
script:
  enabled: true
  mode: native
  stop_on_failure: true
  actions:
    cast:
      - 'self | play_sound sound=ENTITY_BLAZE_SHOOT volume=1 pitch=1.5'
    hit:
      - 'trigger | ignite duration=3s'
  conditions:
    hit:
      - "%level% >= 3"
FieldTypeRequiredDefaultValuesDescription
script.enabledbooleanNotrue when actions has any phase, otherwise falsetrue / falseWhen explicitly disabled, the skill's script is not compiled or executed
script.modestringNoscript_engine.default_modenative, mythic (alias mythicmobs), hybrid (alias both)How the skill runs. An unrecognized value falls back to native
script.stop_on_failurebooleanNoscript_engine.stop_on_failuretrue / falseWhether later actions in the same phase stop after a failed action
script.actions.<phase>list<\string>No[]Action pipeline linesAction lines run in that phase
script.conditions.<phase>list<\string>No[]Condition expressionsPreconditions for that phase; the phase only runs when all pass, otherwise it reports skill.script_phase_condition_failed and counts as skipped

Script modes ​

ModeAliasDescription
native—Run only built-in script actions
mythicmythicmobsRun only the MythicMobs skill from mythic_skill
hybridbothRun both the native script and the MythicMobs skill; a failed native phase skips the MythicMobs part

If you write no script block, or the script is disabled, the skill goes straight down the MythicMobs path; if there is no mythic_skill either, the cast fails with skill.mythic_not_configured

Phases ​

Each phase has its own conditions and actions lists:

PhaseWhen it runs
castWhen the skill is cast
hitWhen the skill hits a target
missWhen the skill misses
failWhen casting fails (conditions unmet, resources short, and so on)

Keep to the names above for phase keys; prefixed forms such as on_cast are not supported. hit and miss are chosen by whether the target flow forwarded from the previous phase is empty

Example ​

yaml
id: flame_strike
trigger_type: active
display_name: '<red>Flame Strike'
script:
  mode: native
  stop_on_failure: true
  actions:
    cast:
      - 'self | play_sound sound=ENTITY_BLAZE_SHOOT volume=1 pitch=1.5'
      - 'trigger | spawn_particle particle=FLAME count=20'
      - 'trigger | damage amount=%var.fire_damage%'
    hit:
      - 'trigger | ignite duration=3s'
      - 'self | send_message text="<red>Burning!"'
    fail:
      - 'self | send_message text="<gray>Skill failed."'

Context variables ​

Script execution injects the variables below; you reference them in action lines, phase conditions, and text as %var.<name>%:

VariableDescription
%var.level%Current skill level
%var.skill_id%Skill id
%var.trigger_id%Trigger id
%var.has_target%Whether there is a target (0 or 1)
%var.<skill variable>%Variables defined in the skill's variables, see Variable types

Five synonyms for MythicMobs are injected as well, visible in scripts as %var.emaki_skill_id% and so on: emaki_skill_id, emaki_skill_level, emaki_trigger_id, emaki_is_passive, and emaki_has_target

Expressions inside a variables block can additionally read %max_level%, %target_level%, %is_passive%, %player_level%, %player_health%, %player_max_health%, and %sneaking%. These take part in variable evaluation only; they are not injected as script-line placeholders

Script actions ​

Every script line you write is compiled and executed by CoreLib's action engine, so the available action stages are exactly those in the CoreLib registry plus the skill stages EmakiSkills registers. EmakiSkills has no separate private action IDs

  • The full list of CoreLib's own stages and their parameters is in CoreLib Actions
  • The stages EmakiSkills adds (cast_skill, cast_mythic_skill, level/slot/cooldown/unlock) are in CoreLib Actions

Use the registered stage IDs

A stage ID must match its registered name exactly. A line with a wrong ID is dropped at compile time and recorded as a diagnostic; it does not fail at runtime. Common mistakes:

WrongCorrect
messagesend_message
soundplay_sound
particlespawn_particle
mythiccast_mythic_skill

Also note: ray and aoe_damage are not registered stages and have no equivalent

Targets are not written as an action parameter but with the pipeline's source | stage syntax, see CoreLib Actions

Only the stages most commonly used in skill scripts are listed below; the registry is authoritative for parameters

damage ​

Deal damage to a target

ParameterRequiredDefaultDescription
amountYes—Health removed

heal ​

Heal a target

ParameterRequiredDefaultDescription
amountYes—Health restored

ignite ​

Set a target on fire

ParameterRequiredDefaultDescription
durationNo5sBurn duration; accepts ms, s, and t suffixes

send_message ​

Send MiniMessage chat text

ParameterRequiredDefaultDescription
textYes—Message text

play_sound ​

Play a sound

ParameterRequiredDefaultDescription
soundYes—Bukkit Sound name
volumeNo—Volume
pitchNo—Pitch

spawn_particle ​

Spawn particles

ParameterRequiredDefaultDescription
particleYes—Particle type
countNo—Particle count
offset_x / offset_y / offset_zNo—Per-axis spread offsets
extraNo—Extra particle data (speed for most particles)

projectile ​

Launch a custom projectile with tick-by-tick simulation. Sets the context target entity on hit

ParameterRequiredDefaultDescription
speedNo1.5Blocks per tick
gravityNo0.05Gravity per tick
lifetimeNo60Max lifetime in ticks
hit_radiusNo0.5Hit detection radius
pierceNo0Number of entities to pierce through
homingNofalseEnable homing toward the target
homing_strengthNo0.1Homing turn strength
particleNoFLAMETrail particle type
damageNo0Damage on hit (0 = no damage)
directionNolookInitial direction: look (view direction) or target (toward the target)

Target resolution ​

Targets are written in the source stage left of the pipe, not as an action parameter. The sources you will use most in skill scripts:

SourceResolves to
selfThe caster. Also the default when the source is omitted
triggerThe entity named by the trigger context (the crosshair target of an active skill, the event entity of a passive skill)
inherited / keepThe target flow carried across phases; keep records the current targets and inherited reads what the upstream recorded
looking_atThe entity under the caster's crosshair; accepts range= and width=
nearby / nearby_playersNearby entities or players; accepts radius=, limit=, and type=
player_by_nameA player by name

The full source list and parameters are in CoreLib Actions

Conditions, chance, and delay ​

Conditions, chance rolls, and delays are gate stages; they sit between pipes and are not written as line-leading @ prefixes:

yaml
actions:
  cast:
    - 'trigger | where %var.has_target%==1 | damage amount=20'
    - 'trigger | chance 30% | ignite duration=5s'
    - 'self | after 20t | send_message text="<gray>Fires one second later."'
GateDescription
where <condition>Clears the target stream when the condition is false, so later stages do not run
if <condition> [ ... ]Runs the piped stages in brackets when the condition is true
chance <n>%Passes with the given probability
after <time>Delays the following stages. Accepts ms, s, and t suffixes

The @ prefix form is obsolete

The old line-leading @if=, @chance= and @delay= prefixes are no longer parsed; replace them as follows: @chance=25% → chance 25%, @delay=20t → after 20t, and @if=<condition> → an if <condition> [ ... ] branch or where <condition>. @ignore_failure has no equivalent. Full syntax is in CoreLib Actions

Built-in JavaScript stages ​

The native script system also ships three GraalVM JavaScript stages, letting you do lightweight computation or read entity or location state inside a pipeline. Note that their return value only lands in the action result's script_result; it does not write back to variables, does not create placeholders, and does not filter or replace targets. When a value must feed later computation, use an expression variable instead

StageBindingsDescription
js_computecontext (plus player when the current target is a player)Pure computation, no target needed. context can read var.* variables
js_entityplayer, contextOperates on an existing player target; non-player targets are skipped silently
js_locationlocation, context (plus a read-only player when one is associated)Reads a location target

Every stage requires code; timeout is in milliseconds, defaults to 5000, and also falls back to 5000 when <= 0