Script (Entity Action Type)

Runs a script against one entity.

Runs a script against one entity. Use it when the behaviour you want has no shape in JSON — picking a target out of a list, remembering something between calls, or branching on state Apoli has no condition for.

Type ID: apoli:script

Fields

FieldTypeDefaultDescription
scriptIdentifierrequiredThe script to run. Either an id registered from KubeJS with ApoliEvents, or the path of a .js file shipped in a data pack at data/<namespace>/apoli/scripts/<path>.js — in which case the .js is part of the id.
paramsNBToptionalValues handed to the script. Read them with event.params from KubeJS, or params inside a data pack script. This is how one script serves several powers.

Examples

Drain the nearest living entity within four blocks and heal for what you took. The whole search-and-pick is one line of JavaScript instead of a nested apoli:selector and apoli:if_else_list:

// kubejs/server_scripts/vampire.js
ApoliEvents.entityAction('vampire:drain', event => {
  const player = event.entity
  const victim = event.level.getEntitiesWithin(player.boundingBox.inflate(4))
    .filter(e => e.living && e !== player)
    .sort((a, b) => a.distanceToSqr(player) - b.distanceToSqr(player))[0]

  if (!victim) return
  victim.attack(event.params.getFloat('damage'))
  player.heal(event.params.getFloat('heal'))
})
{
  "type": "apoli:action_on_key_press",
  "key": { "key": "key.origins.primary_active" },
  "cooldown": 60,
  "entity_action": {
    "type": "apoli:script",
    "script": "vampire:drain",
    "params": { "damage": 4.0, "heal": 2.0 }
  }
}

The same action written as a data pack file instead, so the behaviour ships inside the zip. The file body is the action, and ctx and params are already in scope:

// data/vampire/apoli/scripts/drain.js
ctx.entity.heal(params.getFloat('heal'))
{
  "type": "apoli:script",
  "script": "vampire:drain.js",
  "params": { "heal": 2.0 }
}

Data pack scripts are disabled until an operator enables them — see the KubeJS page for that and for what the sandbox allows.

Needs KubeJS. Without it the type still loads and the pack still works — the call logs once and does nothing. Scripts always run on the server.