Lua Scripting: Boss & Entities
This page covers everything about boss and entity wrappers in EliteMobs Lua powers: context.boss, context.player, context.players, context.entities, and the entity wrapper tables they return. If you are new to Lua powers, start with Getting Started first.
Entity Wrappers
When you access entities through the Lua API -- whether from context.boss, context.player, query results like context.players:nearby_players(), or event fields -- you always receive wrapper tables. These are not raw Bukkit objects. Each wrapper provides a set of fields (snapshot values captured at creation time) and methods (live calls that reach into the server).
This page describes EliteMobs' native boss-power wrappers. Shared MagmaCore helpers, such as context.world:get_entity(uuid), can return a different wrapper with lazy live fields and different signatures; use the shared API reference for those. Native methods accept colon syntax or dot syntax without an explicit self argument. Assigning a wrapper field only changes the Lua table; use a method to change the entity.
Two rules to remember:
- Fields like
health,current_location, andmaximum_healthare snapshots. They reflect the state at the moment the wrapper was created and do not auto-update. - Methods like
get_location(),get_health(), andis_alive()perform a live check every time you call them.
Common Entity Fields
Every living entity wrapper includes these fields.
| Field | Type | Notes |
|---|---|---|
entity.name | string | Display name |
entity.uuid | string | UUID as text |
entity.entity_type | string | Bukkit EntityType name (e.g. "ZOMBIE", "PLAYER") |
entity.is_player | boolean | true for players |
entity.is_elite | boolean | true if EliteMobs tracks it as an elite |
entity.is_mount | boolean | true if this wrapper represents a boss mount |
entity.is_monster | boolean | true for monster-type entities |
entity.health | number | Current health (snapshot) |
entity.maximum_health | number | Max health (snapshot) |
entity.current_location | location table | Position at the time the wrapper was created |
entity.is_valid | boolean | Bukkit validity when the wrapper was created (snapshot) |
is_valid is a field on living entities, not a methodOn living-entity wrappers (including context.player and context.boss) is_valid is a plain boolean captured when the wrapper was built. Calling entity:is_valid() raises attempt to call a boolean value and disables the power.
- Read the snapshot with
entity.is_valid(dot). - For a live check, call
entity:is_alive()instead -- it re-queries the server every time.
is_valid() is a real method on the lighter non-living reference wrappers returned by summon_projectile, spawn_falling_block_at_location and friends. Those are the wrappers you are most likely to store across ticks, which is where the live check matters.
To read elite-specific data such as the boss level, use the context.boss fields and methods described in the context.boss section below. To despawn an elite from a script, call the entity:remove_elite() method.
Example
return {
api_version = 1,
on_enter_combat = function(context)
context.log:info("Boss level: " .. context.boss.level)
end
}
Example
return {
api_version = 1,
on_enter_combat = function(context)
local target = context.players:current_target()
if target ~= nil then
context.log:info("Target: " .. target.name .. " HP: " .. target.health)
end
end
}
Common Entity Methods
The methods below perform live calls to the server. Movement, health, equipment, and effect methods belong to living-entity wrappers. Chat, action bars, titles, boss bars, and player commands require a player wrapper. context.boss:send_message(...) is a separate boss method that broadcasts to nearby players. Unless a return value is documented, mutating methods return nil, not an operation-success flag.
AI, awareness, invulnerability and scale changes belong to the power that made them. Each records the value it replaced: a positive duration restores that value after the given ticks, and closing the script restores any change still active. When several powers change the same property, ending one change restores the most recent remaining change, or the original value when none remain. If another plugin or command changes the property in the meantime, its value is kept. Pausing the script does not undo these changes. Tag durations, delayed pushes and player boss bars use independent game-clock tasks that keep running after the script closes. Other entity changes are not undone.
entity:is_alive()
Returns true if the entity is still valid and not dead.
Example
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if context.player == nil then return end
if context.player:is_alive() then
context.player:send_message("&aYou're still standing!")
end
end
}
entity:get_location()
Returns the current live location as a location table.
Example
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if context.player == nil then return end
local loc = context.player:get_location()
context.world:play_sound_at_location(loc, "entity.experience_orb.pickup")
end
}
entity:get_eye_location()
Returns the eye-level location as a location table.
Example
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if context.player == nil then return end
local eye = context.player:get_eye_location()
context.world:spawn_particle_at_location(eye, "FLAME")
end
}
entity:get_health() / entity:get_maximum_health()
Returns the live current or maximum health.
Example
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if context.player == nil then return end
local pct = context.player:get_health() / context.player:get_maximum_health()
if pct < 0.25 then
context.player:send_message("&cYou're running low!")
end
end
}
entity:get_velocity()
Returns the entity's current velocity as a vector table.
Example
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if context.player == nil then return end
local vel = context.player:get_velocity()
context.log:info("Player speed Y: " .. vel.y)
end
}
entity:send_message(text)
Sends a chat message to a player. Supports EliteMobs color formatting.
| Parameter | Type | Notes |
|---|---|---|
text | string | Message with color codes |
Example
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if context.player == nil then return end
context.player:send_message("&6[Boss] &fPrepare yourself!")
end
}
entity:show_action_bar(message)
Sends an action bar message to a player through EliteMobs' Lua action-bar source. It participates in the action-bar compositor rather than reserving the display for this script.
| Parameter | Type | Notes |
|---|---|---|
message | string | Action bar text with color codes |
Example
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if context.player == nil then return end
context.player:show_action_bar("&c&lDANGER ZONE")
end
}
entity:show_title(title[, subtitle][, fadeIn][, stay][, fadeOut])
Sends a title and optional subtitle to a player, with EliteMobs color formatting. Timing arguments are integer ticks.
| Parameter | Type | Default | Notes |
|---|---|---|---|
title | string | Title text | |
subtitle | string | "" | Subtitle text |
fadeIn | number | 10 | Fade-in ticks |
stay | number | 40 | Stay ticks |
fadeOut | number | 10 | Fade-out ticks |
Example
return {
api_version = 1,
on_enter_combat = function(context)
local nearby = context.players:nearby_players(20)
for _, p in ipairs(nearby) do
p:show_title("&4PHASE 2", "&7The boss is enraged!", 10, 40, 10)
end
end
}
entity:show_boss_bar(title[, color][, style][, duration])
Creates a new boss bar for a player through the boss-bar order manager. Color and style names ignore case; unknown values fall back to WHITE and SOLID. A positive duration schedules independent removal. Nonpositive values add no removal timer, and this method returns no handle or key for later removal. Use a positive duration. This signature differs from the keyed shared MagmaCore boss-bar API.
| Parameter | Type | Default | Notes |
|---|---|---|---|
title | string | Bar title text | |
color | string | "WHITE" | BarColor value |
style | string | "SOLID" | BarStyle value |
duration | number | 40 | Duration in ticks |
Example
return {
api_version = 1,
on_enter_combat = function(context)
local nearby = context.players:nearby_players(20)
for _, p in ipairs(nearby) do
p:show_boss_bar("&cIncoming Attack!", "RED", "SOLID", 100)
end
end
}
entity:teleport_to_location(location)
Requests a Bukkit teleport and returns nil, without exposing whether teleportation succeeded. Native location conversion accepts x, y, z, optional yaw/pitch, a loaded world name, or a nested current_location table. Missing coordinates become 0; an omitted world uses the casting boss's world, not necessarily the target entity's world. An explicitly unknown world fails conversion. nil or a non-table uses the boss's position. No safe-destination or region check is added here.
| Parameter | Type | Notes |
|---|---|---|
location | location table | Destination |
Example
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if context.player == nil then return end
if not context.cooldowns:check_local("teleport_pull", 200) then return end
context.player:teleport_to_location(context.boss:get_location())
context.player:send_message("&cThe boss pulls you in!")
end
}
entity:set_velocity_vector(vector)
Sets the entity's velocity immediately.
| Parameter | Type | Notes |
|---|---|---|
vector | vector table | { x, y, z } or { x = 0, y = 1, z = 0 } |
Example
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if context.player == nil then return end
if not context.cooldowns:check_local("launch", 100) then return end
context.player:set_velocity_vector({ x = 0, y = 1.5, z = 0 })
context.player:send_message("&cYou are launched into the air!")
end
}
entity:apply_push_vector(vector[, additive][, delay])
Applies a captured velocity after a delay of 1 tick by default. The independent timer checks that the entity is still valid. With additive = true, it adds to the velocity at execution time; otherwise it replaces that velocity. Pausing or closing the script does not cancel the push.
| Parameter | Type | Default | Notes |
|---|---|---|---|
vector | vector table | Direction and strength | |
additive | boolean | false | Add to existing velocity instead of replacing |
delay | number | 1 | Delay in ticks before applying |
Example
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if context.player == nil then return end
if not context.cooldowns:check_local("push_up", 100) then return end
context.player:apply_push_vector({ x = 0, y = 2.0, z = 0 })
context.player:send_message("&cUpward blast!")
end
}
entity:face_direction_or_location(directionOrLocation)
Makes the entity face a direction or location by teleporting it to its current position with a new rotation. A table with a string world or nested current_location is interpreted as a destination, which must be in the entity's world. A bare x/y/z table is interpreted as a direction vector. Zero directions do nothing.
| Parameter | Type | Notes |
|---|---|---|
directionOrLocation | vector or location table | Target to face |
Example
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if context.player == nil then return end
context.player:face_direction_or_location(context.boss:get_location())
context.player:send_message("&cThe boss forces you to look at it!")
end
}
entity:set_fire_ticks(ticks)
Sets Bukkit fire ticks to the supplied value. The instance-effect policy rechecks the target when called. Players must be online, alive and in the source world; in an instance they must belong to the active match and participant list. Other living targets must be valid. This does not guarantee that fire will cause damage.
| Parameter | Type | Notes |
|---|---|---|
ticks | number | Fire duration in ticks (20 ticks = 1 second) |
Example
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if context.player == nil then return end
if not context.cooldowns:check_local("ignite", 100) then return end
context.player:set_fire_ticks(60)
context.player:send_message("&cYou catch fire!")
end
}
entity:add_visual_freeze_ticks([ticks])
Adds to Bukkit's actual freeze-tick value, subject to the same instance-effect policy as set_fire_ticks. Despite the method name, this is not a packet-only overlay and does not freeze AI or movement directly; normal Minecraft freezing behavior can apply.
| Parameter | Type | Default | Notes |
|---|---|---|---|
ticks | number | 1 | Freeze tick amount |
Example
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if context.player == nil then return end
if not context.cooldowns:check_local("freeze", 200) then return end
context.player:add_visual_freeze_ticks(100)
context.player:send_message("&bYou feel a chilling frost!")
end
}
entity:apply_potion_effect(effect, duration[, amplifier])
Applies a Bukkit potion effect after the same instance-effect check as set_fire_ticks. Names ignore case; unknown names warn and do nothing. Bukkit's effect replacement rules apply, so this is not a forced overwrite of every existing effect.
| Parameter | Type | Default | Notes |
|---|---|---|---|
effect | string | PotionEffectType name | |
duration | number | Duration in ticks | |
amplifier | number | 0 | Effect level (0 = level I) |
Example
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if context.player == nil then return end
if not context.cooldowns:check_local("slow", 200) then return end
context.player:apply_potion_effect("SLOWNESS", 60, 1)
context.player:send_message("&7You feel sluggish...")
end
}
remove_potion_effect(effect) is not available on EliteMobs boss-power entity wrappers. It exists on shared MagmaCore wrappers. Give effects an appropriate duration when applying them; applying a zero-duration effect is not a reliable way to remove an existing effect.
entity:deal_damage(amount) / entity:deal_custom_damage(amount) / entity:deal_damage_from_boss(amount)
Submits damage to Bukkit. All three methods return nil; the requested amount is not proof of health lost. Combat rules and later listeners can change or cancel the hit.
| Method | Notes |
|---|---|
deal_damage(amount) | Calls Bukkit damage without an explicit damager |
deal_custom_damage(amount) | Uses BossCustomAttackDamage with the casting boss: rejects self-hits, invulnerable/dead targets and players outside Survival/Adventure, submits a custom hit, then clears the native damage cooldown |
deal_damage_from_boss(amount) | Calls Bukkit damage with the casting boss as damager; normal EliteMobs combat processing can apply |
Example
return {
api_version = 1,
on_enter_combat = function(context)
local nearby = context.players:nearby_players(10)
for _, p in ipairs(nearby) do
p:deal_custom_damage(10)
p:send_message("&cThe boss unleashes a shockwave!")
end
end
}
entity:restore_health(amount)
For tracked elites, calls EliteMobs healing and fires the cancellable EliteMobHealEvent. Other living entities are healed directly up to their base maximum-health attribute, which can differ from the effective maximum returned by get_maximum_health(). Supply a nonnegative amount; this helper is not an input-clamping damage API.
| Parameter | Type | Notes |
|---|---|---|
amount | number | Amount to heal |
Example
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if context.player == nil then return end
-- Heal the player slightly when they hit the boss
context.player:restore_health(5)
context.player:send_message("&aYou drain life from the boss!")
end
}
entity:set_invulnerable(enabled[, duration])
Sets invulnerability on the entity and records the value it replaced. A positive duration restores that value after the given ticks; otherwise the change lasts until this power shuts down, which also restores it. Calling it again from the same power replaces that power's earlier change.
| Parameter | Type | Default | Notes |
|---|---|---|---|
enabled | boolean | true to enable invulnerability | |
duration | number | 0 | Restore the replaced value after this many ticks; 0 keeps the change until the power shuts down |
Example
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if context.player == nil then return end
if not context.cooldowns:check_local("shield", 200) then return end
context.player:set_invulnerable(true, 40)
context.player:send_message("&6A brief shield protects you!")
end
}
entity:set_ai_enabled(enabled[, duration])
Sets AI on the entity and records the value it replaced. A positive duration restores that value after the given ticks; otherwise the change lasts until this power shuts down, which also restores it. Calling set_ai_enabled(true) while this power holds an AI change ends that change and restores the replaced value instead of applying a new one.
| Parameter | Type | Default | Notes |
|---|---|---|---|
enabled | boolean | true to enable AI | |
duration | number | 0 | Restore the replaced value after this many ticks; 0 keeps the change until the power shuts down |
Example
return {
api_version = 1,
on_enter_combat = function(context)
-- Disable boss AI for 3 seconds at combat start
context.boss:set_ai_enabled(false, 60)
context.boss:send_message("&7The boss is stunned!")
end
}
entity:add_tag(tag[, duration]) / entity:remove_tag(tag) / entity:has_tag(tag)
Manages case-sensitive EliteMobs tags on tracked elites and players with loaded EliteMobs inventory data. Ordinary untracked mobs do not store these tags. They are not Bukkit scoreboard tags. A positive duration schedules removal independently; adding the same tag again does not cancel its older removal timer.
| Method | Parameter | Notes |
|---|---|---|
add_tag(tag[, duration]) | string, optional number | Adds tag, optionally auto-removes after ticks |
remove_tag(tag) | string | Removes the tag |
has_tag(tag) | string | Returns true if the tag is present |
Example
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if context.player == nil then return end
if not context.player:has_tag("marked") then
context.player:add_tag("marked", 200)
context.player:send_message("&cYou have been marked!")
end
end
}
entity:run_command(command)
Immediately runs a command as the player with that player's permissions. Use text without a leading /. This player-only method returns nil, does not expose command success and does not substitute placeholders.
| Parameter | Type | Notes |
|---|---|---|
command | string | Command text without leading / |
Example
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if context.player == nil then return end
if not context.cooldowns:check_local("curse_cmd", 200) then return end
context.player:run_command("say I have been cursed!")
end
}
entity:set_scale(scale[, duration])
Sets the base value of the entity's scale attribute when available and records the value it replaced. A positive duration restores that value after the given ticks; otherwise the change lasts until this power shuts down, which also restores it. Attribute modifiers may make the effective size differ.
| Parameter | Type | Default | Notes |
|---|---|---|---|
scale | number | Scale multiplier | |
duration | number | 0 | Restore the replaced scale after this many ticks; 0 keeps the change until the power shuts down |
Example
return {
api_version = 1,
on_enter_combat = function(context)
-- Boss grows to double size for 5 seconds
context.boss:set_scale(2.0, 100)
context.boss:send_message("&4The boss grows in size!")
end
}
entity:set_gravity(enabled)
Toggles gravity on the entity. There is no automatic restoration when the script closes. A script-owned delayed callback may never run after closure, so do not rely on it as guaranteed cleanup for surviving entities.
| Parameter | Type | Notes |
|---|---|---|
enabled | boolean | true for normal gravity |
Example
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if context.player == nil then return end
if not context.cooldowns:check_local("levitate", 200) then return end
-- Change the boss's gravity; the callback runs only while this script stays active.
context.boss:set_gravity(false)
context.scheduler:run_after(60, function(tick_context)
if tick_context.boss.exists then
tick_context.boss:set_gravity(true)
end
end)
end
}
entity:play_sound_at_entity(sound[, volume][, pitch])
Plays a sound at the entity's location.
| Parameter | Type | Default | Notes |
|---|---|---|---|
sound | string | Minecraft sound key (for example, "entity.ender_dragon.growl") or a Spigot Sound enum name. Resource-pack keys work too. | |
volume | number | 1.0 | Volume |
pitch | number | 1.0 | Pitch |
Example
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if context.player == nil then return end
context.player:play_sound_at_entity("entity.ender_dragon.growl", 1.0, 0.5)
end
}
entity:play_sound_at_self(sound[, volume][, pitch])
Alias for play_sound_at_entity. Plays a sound at the entity's location.
entity:spawn_particle_at_self(particleOrSpec[, count])
Spawns particles at the entity's current location. It uses the same particle specification as the native world helper. A table's amount overrides the fallback count; names are uppercased, and unsupported data-dependent particles warn instead of spawning.
| Parameter | Type | Default | Notes |
|---|---|---|---|
particleOrSpec | string or table | Particle name or spec table | |
count | number | 1 | Number of particles |
Example
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if context.player == nil then return end
context.player:spawn_particle_at_self("HEART", 5)
end
}
entity:spawn_particles_at_location(location, particle[, count])
Spawns particles at a specific location.
| Parameter | Type | Default | Notes |
|---|---|---|---|
location | location table | Target location | |
particle | string | Particle type name | |
count | number | 1 | Number of particles |
Example
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if context.player == nil then return end
local loc = context.player:get_location()
context.player:spawn_particles_at_location(loc, "FLAME", 10)
end
}
entity:play_model_animation(name)
Requests an animation only when EliteMobs tracks the entity as a custom boss with a custom model. The method returns nil; it does not wait for completion or report whether the animation name exists. A generic modeled entity is not enough for this native helper.
| Parameter | Type | Notes |
|---|---|---|
name | string | Animation name |
Example
return {
api_version = 1,
on_enter_combat = function(context)
context.boss:play_model_animation("attack_swing")
end
}
Vehicle And Passenger Methods
Living entity wrappers also expose Bukkit vehicle/passenger helpers. Wrapper arguments are resolved by Bukkit UUID; bare UUID strings are not accepted here. Mounting rejects missing, identical or invalid entities, temporarily bypasses EliteMobs' mount-exploit guard, and returns Bukkit's acceptance result. These methods do not register a scripted transport route or arrange cleanup when the script closes.
| Method | Returns | Notes |
|---|---|---|
entity:is_inside_vehicle() | boolean | True if the entity is riding another entity. |
entity:has_vehicle() | boolean | True if the entity currently has a vehicle. |
entity:get_vehicle() | entity wrapper or nil | Returns the current vehicle wrapper. |
entity:set_vehicle(vehicle) | boolean | Makes this entity ride vehicle. |
entity:leave_vehicle() | boolean | Makes this entity leave its current vehicle. |
entity:has_passengers() | boolean | True if this entity has passengers. |
entity:get_passenger_count() | number | Number of passengers. |
entity:get_passengers() | table | Array of passenger wrappers. |
entity:add_passenger(passenger) | boolean | Adds a passenger to this entity. |
entity:remove_passenger(passenger) | boolean | Removes a passenger from this entity. |
entity:eject_passengers() | boolean | Ejects all passengers. |
Example
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if context.player == nil then return end
if context.player:has_vehicle() then
context.player:leave_vehicle()
end
end
}
entity:push_relative_to(source[, strength][, xOffset][, yOffset][, zOffset])
Immediately replaces velocity with the normalized displacement from the source to this entity, multiplied by strength, then adds the world-axis offsets. Coincident positions still receive the offsets. A wrapper contributes its saved current_location, not a fresh position; pass source:get_location() when needed. This helper does not compare worlds, so only use positions from the same world.
| Parameter | Type | Default | Notes |
|---|---|---|---|
source | location or wrapper | Push origin | |
strength | number | 1.0 | Push strength multiplier |
xOffset | number | 0 | Extra X offset |
yOffset | number | 0 | Extra Y offset |
zOffset | number | 0 | Extra Z offset |
Example
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if context.player == nil then return end
if not context.cooldowns:check_local("knockback", 60) then return end
context.player:push_relative_to(context.boss:get_location(), 2.0, 0, 0.5, 0)
context.player:send_message("&cThe boss knocks you back!")
end
}
entity:set_custom_name(name) / entity:reset_custom_name()
Sets the Bukkit custom name with color formatting. Reset uses the tracked elite's configured name; for an untracked entity it uses that entity's current getName(), so it does not restore a saved original name. This does not change a player's account name or the wrapper's snapshot field.
Example
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if context.player == nil then return end
if not context.cooldowns:check_local("mark", 200) then return end
context.boss:set_custom_name("&c&lEnraged Boss")
context.boss:send_message("&cThe boss is enraged!")
-- Reset after 5 seconds
context.scheduler:run_after(100, function(tick_context)
if tick_context.boss:is_alive() then
tick_context.boss:reset_custom_name()
end
end)
end
}
entity:place_temporary_block(material[, duration][, requireAir])
Places a temporary block at the entity's current location and returns nil, including when requireAir prevents placement. A positive duration restores the saved block data, not container contents, when the timer ends, when the chunk or world unloads, or when the plugin shuts down, but only while the block still holds the temporary block. Placing again on the same temporary block restarts its timer. Blocks with block entities, such as chests, and blocks held by another temporary-block owner are skipped. Breaking the block drops nothing. A nonpositive duration places the block permanently without tracking. Use a block material and check protection yourself.
| Parameter | Type | Default | Notes |
|---|---|---|---|
material | string | Block material name | |
duration | number | 0 | Positive ticks before restoration; nonpositive values place the block permanently |
requireAir | boolean | false | Only place if the block is currently air |
Example
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if context.player == nil then return end
if not context.cooldowns:check_local("ice_trap", 200) then return end
context.player:place_temporary_block("ICE", 60, true)
context.player:send_message("&bIce forms at your feet!")
end
}
entity:get_height()
Returns the entity's height in blocks.
entity:is_on_ground()
Returns Bukkit's current isOnGround() flag. It does not run a new block or headroom query.
entity.is_valid
On a living-entity wrapper this is a boolean field, not a method: it records Bukkit validity when the wrapper was created. Read it with a dot (entity.is_valid); calling it with a colon errors out.
Because it is a snapshot it goes stale, so it is not a substitute for a live check. Use entity:is_alive() when you need the current state, and is_valid() (the method) on non-living reference wrappers you stored across ticks.
entity:is_frozen()
Returns true if the entity (when tracked as a custom boss) has the frozen flag set.
entity:set_awareness_enabled(aware[, duration])
Sets mob awareness and records the value it replaced. Only affects mob-type entities. A positive duration restores that value after the given ticks; otherwise the change lasts until this power shuts down, which also restores it. Calling it with true while this power holds an awareness change ends that change instead of applying a new one.
| Parameter | Type | Default | Notes |
|---|---|---|---|
aware | boolean | true to enable awareness | |
duration | number | 0 | Restore the replaced value after this many ticks; 0 keeps the change until the power shuts down |
entity:is_healing() / entity:set_healing(enabled)
Checks or sets the tracked elite's healing-state flag. This does not itself restore health or start a healing timer. set_healing(true) marks the elite as healing when it is not already; set_healing(false) clears only healing that this power set. When the power shuts down, it clears any healing flag it still owns. Untracked entities return false from the getter and are unchanged by the setter.
entity:overlaps_box_at_location(center[, halfX][, halfY][, halfZ])
Returns true if the entity's bounding box overlaps the numeric axis-aligned box. It does not compare worlds, so pass a center in the entity's world. An unresolved center returns false.
| Parameter | Type | Default | Notes |
|---|---|---|---|
center | location table | Center of the test box | |
halfX | number | 0.5 | Half-width on X axis |
halfY | number | same as halfX | Half-height on Y axis |
halfZ | number | same as halfX | Half-width on Z axis |
entity:remove_elite()
Removes the elite entity from EliteMobs tracking. If the entity is an elite, this despawns it properly through EliteMobs.
entity:remove()
Removes a plain living entity that a script spawned, such as an armor stand. Returns true when removed. Players and elites are refused with false; despawn elites with remove_elite().
entity:set_invisible(enabled) and entity:set_silent(enabled)
set_invisible hides the entity's body; worn and held items stay visible. set_silent mutes the entity's own sounds.
entity:set_marker(enabled)
Armor stands only. These four methods exist on armor stand wrappers and are absent on every other entity.
| Method | Effect |
|---|---|
set_marker(enabled) | A marker stand has no hitbox and cannot be hit or collided with |
set_small(enabled) | Half-size stand |
set_base_plate(enabled) | Shows or hides the stone base plate |
set_arms(enabled) | Shows or hides the arms |
For a purely visual floating item or block, prefer world:spawn_display_at_location, which needs none of these.
entity:set_custom_name_visible(visible)
Sets whether the entity's custom name is always visible or only when looked at.
| Parameter | Type | Notes |
|---|---|---|
visible | boolean | true for always visible |
entity:set_equipment(slot, material[, options])
Replaces the selected slot with a newly created material item. Slot, material and enchantment names ignore case. Unknown slot/material values do nothing; unknown enchantments are skipped, while recognized enchantments use unsafe levels. This is not a custom-item filename loader and does not preserve the previous item's metadata. It returns nil.
| Parameter | Type | Default | Notes |
|---|---|---|---|
slot | string | Equipment slot: "HEAD", "CHEST", "LEGS", "FEET", "HAND", "OFF_HAND" | |
material | string | Material name (e.g. "DIAMOND_SWORD", "IRON_HELMET") | |
options | table | {} | Optional settings (see below) |
Options table:
| Key | Type | Default | Notes |
|---|---|---|---|
enchantments | array of tables | nil | Each entry: { type = "SHARPNESS", level = 2 } |
unbreakable | boolean | false | Whether the item is unbreakable |
Example
return {
api_version = 1,
on_enter_combat = function(context)
-- Give the boss a glowing diamond sword
context.boss:set_equipment("HAND", "DIAMOND_SWORD", {
unbreakable = true,
enchantments = {
{ type = "SHARPNESS", level = 5 }
}
})
end
}
entity:damage_equipment(slot, amount)
Damages the item in HAND, OFF_HAND, HEAD, CHEST, LEGS, or FEET and returns the durability damage actually applied. Request between 1 and 64 points per call. Missing, non-damageable, or unbreakable items return 0.
For players, the operation fires PlayerItemDamageEvent and respects cancellation or an adjusted amount. A listener may raise that amount above the original 64-point request limit; the result is still bounded by remaining durability. An item that reaches its maximum damage is removed from the slot, including its entire stack, and fires PlayerItemBreakEvent. Custom maximum-damage metadata is respected. This method does not roll Unbreaking reductions itself. Invalid slot names or requests outside 1..64 raise a Lua argument error.
entity:is_ai_enabled()
A method that returns true if the entity currently has AI enabled. For tracked elites, it reads EliteMobs' logical AI state, including native behavior ownership, rather than relying only on Bukkit's underlying AI flag.
Example
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if context.boss:is_ai_enabled() then
context.log:info("Boss AI is active")
else
context.log:info("Boss AI is disabled (stunned?)")
end
end
}
Non-Living Entity Reference Wrappers
When a spawned entity is not a LivingEntity -- for example a falling block, projectile, or fireball -- you receive a lighter reference wrapper. These are returned by methods like context.world:spawn_falling_block_at_location() or context.boss:summon_projectile().
Snapshot fields: name, uuid, entity_type, is_player (always false), is_elite (always false), is_mount (normally false; boss:get_mount() sets it to true), current_location.
Methods:
| Method | Notes |
|---|---|
is_valid() | Live validity check. Unlike living-entity wrappers, this really is a method here |
get_location() | Current live location |
get_velocity() | Current velocity vector |
is_on_ground() | Whether on the ground |
teleport_to_location(location) | Teleports the entity |
set_velocity_vector(vector) | Sets velocity |
set_direction_vector(vector) | Sets direction (Fireball only) |
set_yield(value) | Sets explosion yield (Fireball only) |
set_gravity(enabled) | Toggles gravity |
detonate() | Requests detonation for firework entities; no effect on other types |
remove() | Removes the entity from the world |
unregister([reason]) | Runs EliteMobs tracker removal for recognized tracked entities; an untracked entity is unchanged |
These wrappers also carry the full set of vehicle and passenger methods (is_inside_vehicle(), get_vehicle(), set_vehicle(v), add_passenger(p), eject_passengers(), ...), which is how a boss is put on a non-living mount.
unregister accepts a removal-reason name, ignoring case and defaulting to OTHER; it is not a boolean success query. Wrapper methods retain the backing entity reference, so check is_valid() before using a stored reference. A delayed removal scheduled by the Lua instance is cancelled if that instance closes; use an appropriate native duration or owner tracking where cleanup must outlive the script.
Example
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if context.player == nil then return end
if not context.cooldowns:check_local("fireball", 100) then return end
local fb = context.boss:summon_projectile("FIREBALL",
context.boss:get_eye_location(),
context.player:get_location(),
1.5
)
if fb == nil then return end
-- fb is a non-living reference wrapper; remove it after 5 seconds if still alive
context.scheduler:run_after(100, function()
if fb:is_valid() then
fb:remove()
end
end)
end
}
context.player
Available when the event's direct target or actor resolves to a player, including on_boss_damaged_by_player and on_player_damaged_by_boss. Player wrappers include the common living-entity methods, though methods requiring a tracked elite or custom boss do nothing for an ordinary player. The extras below are player-only.
context.player is nil in hooks that have no associated player, such as on_spawn, scheduled callbacks, and timer hooks. Always nil-guard before use.
Example
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if context.player == nil then return end
context.player:send_message("&cHello!")
end
}
Player-Only Fields
| Field | Type | Notes |
|---|---|---|
game_mode | string | Uppercase game mode snapshot (e.g. "SURVIVAL") |
Player-Only Methods
| Method | Notes |
|---|---|
send_message(message) | Chat message with EliteMobs color formatting |
show_action_bar(message) | Action bar text |
show_title(title[, subtitle][, fadeIn][, stay][, fadeOut]) | Title screen overlay |
show_boss_bar(title[, color][, style][, duration]) | Temporary boss bar |
run_command(command) | Run a command as the player (no leading /) |
Example
return {
api_version = 1,
on_player_damaged_by_boss = function(context)
if context.player == nil then return end
local hp_pct = context.player:get_health() / context.player:get_maximum_health()
if hp_pct < 0.3 then
context.player:show_title("&4LOW HEALTH", "&7Find cover!", 5, 30, 10)
context.player:show_boss_bar("&cBoss Enrage Incoming", "RED", "SEGMENTED_6", 80)
end
end
}
context.boss
The boss wrapper for the elite mob that owns this Lua power. Always available in every hook.
While a backing living entity exists, the boss wrapper inherits the common living-entity methods, including push_relative_to, apply_push_vector, set_gravity, set_scale, set_invulnerable, spawn_particle_at_self and overlaps_box_at_location. It does not inherit player-only UI or player-command methods. The methods below are boss-specific or use the EliteEntity layer. If the backing entity is absent, the table still exists but the full set of inherited methods is not guaranteed.
Boss Fields
| Field | Type | Notes |
|---|---|---|
boss.name | string | Display name |
boss.uuid | string | Boss elite UUID |
boss.entity_type | string | Bukkit EntityType name |
boss.is_monster | boolean | true if the underlying entity is a Monster |
boss.level | number | Elite level |
boss.health | number | Current health (snapshot) |
boss.maximum_health | number | Max health (snapshot) |
boss.damager_count | number | Number of damagers (snapshot) |
boss.is_in_combat | boolean | Combat-state snapshot |
boss.exists | boolean | Whether the elite existed when this table was built |
boss.current_location | location table | Position at wrapper creation (snapshot) |
Example
return {
api_version = 1,
on_spawn = function(context)
context.log:info(context.boss.name .. " level " .. context.boss.level)
end
}
Boss Methods
Patrol movement methods
Bosses with a configured patrol expose patrol_pause(), patrol_resume(), walk_to(x, y, z), hold(x, y, z), and teleport(x, y, z). The coordinates are offsets from the boss's authored spawn location and every method returns a boolean indicating whether the request was accepted. walk_to resumes the normal route on arrival; hold waits for patrol_resume(); long walks use the automatic route solver.
boss:is_alive()
Returns true if the boss entity is valid, not dead, and the elite still exists. Use this instead of the exists field for live checks.
Example
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if not context.boss:is_alive() then return end
context.boss:send_message("&cI still live!")
end
}
boss:get_location()
Returns the boss's current live location as a location table.
Example
return {
api_version = 1,
on_enter_combat = function(context)
local loc = context.boss:get_location()
context.world:spawn_particle_at_location(loc, "FLAME")
end
}
boss:get_eye_location()
Returns the boss's eye-level location.
Example
return {
api_version = 1,
on_enter_combat = function(context)
local eye = context.boss:get_eye_location()
context.world:spawn_particle_at_location(eye, "SMOKE")
end
}
boss:set_ai_enabled(enabled[, duration])
Sets AI on the boss with the same owned-change rules as entity:set_ai_enabled: a positive duration restores the replaced value, and closing the power restores any change still active.
| Parameter | Type | Default | Notes |
|---|---|---|---|
enabled | boolean | true to enable AI | |
duration | number | 0 | Restore the replaced value after this many ticks; 0 keeps the change until the power shuts down |
Example
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if not context.cooldowns:check_local("stun", 200) then return end
context.boss:set_ai_enabled(false, 60)
context.boss:send_message("&7The boss is stunned for 3 seconds!")
end
}
boss:teleport_to_location(location)
Requests a Bukkit teleport using the native location-conversion rules described above. It returns nil, not a success flag. This method does not move the authored spawn location or configure a patrol destination.
| Parameter | Type | Notes |
|---|---|---|
location | location table | Destination |
Example
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if not context.cooldowns:check_local("retreat", 300) then return end
local spawn = context.entities:get_boss_spawn_location()
context.boss:teleport_to_location(spawn)
context.boss:send_message("&7The boss retreats to its lair!")
end
}
boss:set_velocity_vector(vector)
Sets the boss's velocity immediately.
| Parameter | Type | Notes |
|---|---|---|
vector | vector table | { x, y, z } or { x = 0, y = 1, z = 0 } |
Example
return {
api_version = 1,
on_enter_combat = function(context)
-- Boss leaps into the air at combat start
context.boss:set_velocity_vector({ x = 0, y = 2.0, z = 0 })
context.boss:send_message("&cThe boss leaps!")
end
}
boss:restore_health(amount)
Calls EliteMobs healing, which fires the cancellable EliteMobHealEvent and caps health at the smaller of EliteMobs' maximum and the base Bukkit maximum-health attribute. It returns nil; cancellation can prevent healing.
| Parameter | Type | Notes |
|---|---|---|
amount | number | Amount to heal |
Example
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if not context.cooldowns:check_local("heal", 200) then return end
context.boss:restore_health(20)
context.boss:send_message("&aThe boss regenerates!")
context.boss:spawn_particle_at_self("HEART")
end
}
boss:play_sound_at_self(sound[, volume][, pitch])
Plays a sound at the boss's location.
| Parameter | Type | Default | Notes |
|---|---|---|---|
sound | string | Minecraft sound key (for example, "entity.wither.spawn") or a Spigot Sound enum name. Resource-pack keys work too. | |
volume | number | 1.0 | Volume |
pitch | number | 1.0 | Pitch |
Example
return {
api_version = 1,
on_spawn = function(context)
context.boss:play_sound_at_self("entity.wither.spawn", 1.0, 0.8)
end
}
boss:spawn_particle_at_self(particleOrSpec[, count])
Spawns particles at the boss's location.
| Parameter | Type | Default | Notes |
|---|---|---|---|
particleOrSpec | string or table | Particle name or spec table | |
count | number | 1 | Number of particles |
Example
return {
api_version = 1,
on_enter_combat = function(context)
context.boss:spawn_particle_at_self("SMOKE", 20)
context.boss:send_message("&8Smoke billows from the boss!")
end
}
boss:play_model_animation(name)
Plays a custom model animation on the boss if available.
| Parameter | Type | Notes |
|---|---|---|
name | string | Animation name |
Example
return {
api_version = 1,
on_enter_combat = function(context)
context.boss:play_model_animation("slam")
end
}
boss:has_mount() / boss:get_mount()
Checks or returns the entity this boss is currently riding. boss:get_mount() returns nil if the boss has no mount. When a mount is returned, its wrapper has is_mount = true.
Example
return {
api_version = 1,
on_enter_combat = function(context)
local mount = context.boss:get_mount()
if mount ~= nil then
context.log:info("Boss is mounted on " .. mount.entity_type)
end
end
}
boss:set_mount(entity) / boss:clear_mount() / boss:dismount()
Mounts or dismounts the boss. boss:set_mount(entity) makes the boss ride the supplied entity wrapper and returns true if Bukkit accepted the passenger change. boss:clear_mount() and boss:dismount() both make the boss leave its current vehicle.
Example
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if not context.cooldowns:check_local("mount_check", 100) then return end
if context.boss:has_mount() then
context.boss:dismount()
end
end
}
boss:face_direction_or_location(vectorOrLocation)
Makes the boss face a direction or location.
| Parameter | Type | Notes |
|---|---|---|
vectorOrLocation | vector or location table | Direction to face |
Example
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if context.player == nil then return end
context.boss:face_direction_or_location(context.player:get_location())
end
}
boss:navigate_to_location(location[, speed][, forceTeleport][, timeout])
Uses pathfinding to walk the boss to a location. Only works on custom bosses.
| Parameter | Type | Default | Notes |
|---|---|---|---|
location | location table | Destination | |
speed | number | 1.0 | Movement speed multiplier |
forceTeleport | boolean | false | Teleport the boss to the destination if timeout elapses before it arrives |
timeout | number | 0 | Give-up time in ticks. 0 means the built-in default of 100 ticks (5 seconds) |
Navigation also stops on its own when the boss gets within 1 block of the destination, stops existing, or leaves the destination's world. Starting a new navigation cancels any navigation already running on that boss. It uses an independent Bukkit task, so pausing or closing the Lua instance does not cancel it. The method returns nil, not an arrival result; the destination is captured when called.
Example
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if context.player == nil then return end
if not context.cooldowns:check_local("charge", 200) then return end
context.boss:navigate_to_location(context.player:get_location(), 1.5)
context.boss:send_message("&cThe boss charges at you!")
end
}
boss:add_tag(tag[, duration]) / boss:remove_tag(tag) / boss:has_tag(tag)
Manages tags on the boss.
Example
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
local pct = context.boss:get_health() / context.boss:get_maximum_health()
if pct < 0.5 and not context.boss:has_tag("phase2") then
context.boss:add_tag("phase2")
context.boss:send_message("&4Entering Phase 2!")
end
end
}
boss:send_message(message[, range])
Sends a formatted chat message to all players within the spherical 3D range in the boss's world. It does not filter by game mode, line of sight, combat participation or instance membership.
| Parameter | Type | Default | Notes |
|---|---|---|---|
message | string | Message text with color codes | |
range | number | 20 | Radius in blocks |
Example
return {
api_version = 1,
on_enter_combat = function(context)
context.boss:send_message("&4You dare challenge me?!")
end
}
boss:summon_projectile(entityType, origin, destination[, speed][, options])
Creates an entity and returns its native wrapper, or nil for an unresolved position or unknown entity type. Recognized but non-spawnable types can still fail. Normal Bukkit projectile types launch from the boss unless spawn_at_origin = true; the supplied origin still determines the direction toward the destination. Keep both positions in the same world, since this helper does not check that they match. Non-projectile types are spawned at the supplied origin and use the appropriate living or non-living wrapper.
| Parameter | Type | Default | Notes |
|---|---|---|---|
entityType | string | Entity type (e.g. "FIREBALL", "ARROW") | |
origin | location table | Launch position | |
destination | location table | Target position | |
speed | number | 1.0 | Projectile speed |
options | table | {} | See options below |
Options table:
| Key | Type | Notes |
|---|---|---|
duration | number | Positive values schedule independent removal after this many ticks; nonpositive values add no timer |
max_ticks | number | Landing-monitor limit; defaults to 6000 |
custom_damage | number | Custom damage metadata for projectile combat handling, not guaranteed health loss |
detonation_power | string | Power filename used as explosive-projectile metadata, not a numeric blast strength |
yield | number | Explosion yield (Fireball) |
persistent | boolean | Sets Bukkit persistence when supplied; does not override duration, collision, or owner removal |
effect | string | EntityEffect name to play on spawn |
incendiary | boolean | Whether explosion is incendiary |
gravity | boolean | Whether projectile has gravity |
glowing | boolean | Glowing effect |
invulnerable | boolean | Whether projectile is invulnerable |
track | boolean | Defaults to true: registers the projectile with EliteMobs. Does not make it home toward a target. |
spawn_at_origin | boolean | Defaults to false: normal projectiles launch from the boss. Set true to spawn at the supplied origin. |
direction_only | boolean | For fireballs spawned at an explicit origin, set direction without an extra velocity assignment |
on_land | function | Callback (landing_location, spawned_entity) when grounded, invalid, or past max_ticks; this is not exclusively an impact callback |
direction_only affects fireballs spawned explicitly at the supplied origin: it skips the extra velocity assignment after setting direction. The destination still determines that direction. Bukkit projectiles receive the boss as shooter. With track = true, a projectile is registered with EliteMobs and added to the boss's reinforcement lifetime. This tracking does not apply to non-projectile entity types. track = false opts out of that owner cleanup, so arrange another removal path.
The on_land monitor belongs to the Lua instance and stops on closure. It calls (landing_location, spawned_entity) once when grounded, invalid or past its counter limit, without itself removing the entity. The positive duration timer is independent and survives script closure. A callback therefore does not prove a projectile hit anything.
Example
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if context.player == nil then return end
if not context.cooldowns:check_local("fireball", 100) then return end
context.boss:summon_projectile(
"FIREBALL",
context.boss:get_eye_location(),
context.player:get_location(),
1.5,
{
custom_damage = 10,
on_land = function(loc, entity)
context.world:spawn_particle_at_location(loc, "EXPLOSION")
end
}
)
end
}
boss:summon_reinforcement(filename[, zoneOrLocation][, duration])
Summons a reinforcement silently from a custom-boss file, records the summoner and inherits normalized combat when the custom-boss summoner uses it. The reinforcement's own configuration and dynamic-level rules determine its level. A zone selects a random sampled location, or its center if no locations are available; an unresolved result falls back to the boss location. Returns its living-entity wrapper, or nil when no live reinforcement was produced.
| Parameter | Type | Notes |
|---|---|---|
filename | string | Boss config filename |
zoneOrLocation | location table or zone | Optional spawn location or zone definition. Defaults to the boss location. |
duration | number | Optional positive escape time in ticks. Defaults to 0, with no timer added by this helper; this is not a level override. |
Example
return {
api_version = 1,
on_enter_combat = function(context)
context.boss:summon_reinforcement("my_minion.yml", context.boss:get_location(), 0)
context.boss:send_message("&cMinions, come to my aid!")
end
}
boss:despawn()
Removes the boss through EliteMobs with reason OTHER. boss:remove() is an alias using the same lifecycle. This is not a damage hit or normal death-reward request.
Example
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
local pct = context.boss:get_health() / context.boss:get_maximum_health()
if pct < 0.1 then
context.boss:send_message("&7The boss vanishes into thin air!")
context.boss:despawn()
end
end
}
boss:get_nearby_players(range)
Returns an array of player wrappers within spherical 3D range in the boss's world. It does not filter game mode, line of sight or instance participation, and does not sort by distance.
| Parameter | Type | Notes |
|---|---|---|
range | number | Radius in blocks |
Example
return {
api_version = 1,
on_enter_combat = function(context)
local players = context.boss:get_nearby_players(30)
for _, p in ipairs(players) do
p:show_action_bar("&cThe boss sees you!")
end
end
}
boss:get_damager_count()
Returns the current size of the boss's recorded damager map. Unlike the damager_count field, this is a live read; it is not a count of nearby or currently online combat participants.
boss:get_nearby_elites(radius)
Returns up to 32 live, tracked elites in the boss's world, excluding the boss itself. The radius must be finite, greater than 0, and at most 64 blocks. Results use living-entity wrappers and are ordered by distance, with elite UUID as the tie-breaker. This query does not by itself establish that an effect is allowed to target every result.
boss:get_target_player()
Returns the boss's current mob target as a player wrapper, or nil if the target is not a player or is unset.
Zone & Particle Methods
These methods combine zones with particle effects. They require a zone table as input.
boss:get_nearby_players_in_zone(zone)
Returns player wrappers whose entities satisfy the native zone shape in the boss's world. It does not filter game mode or instance participation. The query is fresh, not a persistent watcher.
| Parameter | Type | Notes |
|---|---|---|
zone | zone table | A zone shape definition |
boss:spawn_particles_in_zone(zone, particle[, amount][, x][, y][, z][, speed][, coverage])
Fills the interior of a zone with particles. The arguments are positional -- there is no spec table here.
| Parameter | Type | Default | Notes |
|---|---|---|---|
zone | zone table | Zone shape to fill (native kind style, see Zones & Targeting) | |
particle | string | Particle type name | |
amount | number | 1 | Particles per sampled location |
x, y, z | number | 0 | Spread, or direction when amount is 0 |
speed | number | 0 | Particle speed |
coverage | number | 1.0 | Independent sampling probability per location, clamped to 0.01-1.0; a nonempty location set contributes at least one location |
boss:spawn_particles_in_zone_border(zone, particle[, amount][, x][, y][, z][, speed][, coverage])
Same as above, but samples the zone's border locations instead of its interior.
boss:get_particles_from_self_toward_zone(zone, particle[, speed])
Returns an array of particle spec tables located at sampled zone positions and pointing away from the boss. It does not spawn particles at the boss or animate travel from there. Pass the result to boss:spawn_particles_with_vector(...).
| Parameter | Type | Default | Notes |
|---|---|---|---|
zone | zone table | Target zone | |
particle | string | Particle type name | |
speed | number | 0.1 | Particle travel speed written into each spec |
Each returned entry is { location = ..., particle = ..., amount = 0, x/y/z = <unit direction>, speed = ... }. Each zone position has a 20% sampling probability, with at least one chosen from a nonempty set; positions coincident with the boss are then skipped. Actual directional behavior depends on the particle type.
boss:get_particles_toward_self(zone, particle, speed)
The same, with the direction reversed: each particle points from its zone location back toward the boss. Also returns the array rather than spawning it.
| Parameter | Type | Default | Notes |
|---|---|---|---|
zone | zone table | Source zone | |
particle | string | Particle type name | |
speed | number | Pass an explicit speed such as 0.1; omitting it currently reads the particle argument as a number and fails. |
boss:spawn_particles_with_vector(particles)
Spawns an array of directional particles, each with its own position and velocity vector.
| Parameter | Type | Notes |
|---|---|---|
particles | array of tables | Each entry defines a particle with position and direction |
Ender Dragon Methods
These methods only apply when the boss entity is an Ender Dragon.
boss:get_ender_dragon_phase()
Returns the current EnderDragon.Phase name as a string, or nil if the boss is not an Ender Dragon.
boss:set_ender_dragon_phase(phase)
Sets the Ender Dragon's phase.
| Parameter | Type | Notes |
|---|---|---|
phase | string | EnderDragon.Phase name (e.g. "CIRCLING", "CHARGE_PLAYER") |
Special Power Support Methods
These methods support built-in EliteMobs power mechanics from Lua scripts.
boss:start_tracking_fireball_system(speed?)
Starts one controller for this power on a monster boss. On its first run, on the next tick, and then every 8 seconds, it launches tracking fireballs toward Survival and Adventure players within 20 blocks on each axis while the monster has a target. A run without a target stops the controller, including the first run; another call can restart it. Repeated calls while active do not replace the speed. The controller belongs to the power's script: pausing the script pauses it, and closing the script stops it. When the call starts a controller, the speed must be finite and positive, or the call raises an error.
The fireballs have yield 3 and are incendiary. Each fireball's tracking task is independent of the script. It stops after roughly 3 minutes or an invalid context, but stopping that task does not itself remove the fireball. An uncancelled hit on a tracked fireball switches its pursuit between the player and caster.
| Parameter | Type | Default | Notes |
|---|---|---|---|
speed | number | 0.5 | Fireball speed; must be finite and positive |
boss:handle_spirit_walk_damage(cause)
Feeds a damage cause into the Spirit Walk helper. Fire, fire ticks, poison, wither, thorns, and sweep attacks do not advance its counter. Drowning or suffocation starts an escape immediately; other accepted causes start it on every ninth hit. The helper searches for a nearby valid destination and animates movement there with temporary invulnerability. It does not cancel the supplied damage event or promise a position behind the attacker.
| Parameter | Type | Notes |
|---|---|---|
cause | string | Bukkit DamageCause name (e.g. "ENTITY_ATTACK", "PROJECTILE") |
boss:shield_wall_is_active()
Returns the shield controller's active flag. This is not a guarantee that a particular direction still has a positive shield pool.
boss:initialize_shield_wall(openingDirection?)
Initializes directional shield pools and visuals unless a wall is already active. Each protected direction starts with health equal to the boss level. The argument selects the unprotected opening; it is not a number of charges. The Lua method returns nil and does not install a damage-event handler for you.
| Parameter | Type | Default | Notes |
|---|---|---|---|
openingDirection | number | 1 | 1 = north, 2 = east, 3 = south, 4 = west; other integers leave all four sides protected |
boss:shield_wall_absorb_damage(player, damage)
Checks the attacker's position relative to the boss and subtracts the supplied damage from that direction's shield pool. Returns true if the pool was positive before subtraction, even if this hit exceeds the remaining pool. Returns false for a missing player/state, another world, or a depleted/open direction. It does not cancel the damage event. When it returns true, your damage hook must call context.event.cancel_event() to block the hit. Pass a nonnegative damage amount.
| Parameter | Type | Notes |
|---|---|---|
player | player wrapper | The attacking player |
damage | number | Damage amount to absorb |
boss:deactivate_shield_wall()
Stops the wall's independent visual task and removes its state and shield armor stands. Closing the Lua instance alone does not call this method; explicitly deactivate the wall when the mechanic ends.
boss:start_zombie_necronomicon(target, chant)
Starts the Necronomicon controller using a living target and a scrolling chant. The second argument is display text, not a boss filename. It summons the fixed files necronomicon_zombie.yml with 80% probability and necronomicon_skeleton.yml with 20%, at the caster's level, one every 60 ticks. A new activation is accepted only with at most nine tracked reinforcements and no active controller. The running controller fills up to eleven, enables AI while full, and resumes casting when that count falls.
Casting disables the boss's AI and changes its displayed name; warning visuals obey the warning-effects setting. The target must remain valid, in the same world and within 30 blocks. Invalid context or owner removal stops the controllers, restores presentation and culls their reinforcements. These are independent Bukkit tasks, so Lua closure alone does not stop them. The method returns nil.
| Parameter | Type | Notes |
|---|---|---|
target | entity wrapper | Target entity for the necronomicon |
chant | string | Scrolling display text; blank text falls back to the boss name, and short text is padded |
context.players
Player query helpers centered around the boss. Use these to find players without needing a specific player from the event.
These queries do not filter by game mode, line of sight, survival, combat participation or instance membership, and results are not distance-sorted. current_target() gives the event actor priority, which can differ from context.player's direct-target priority. A fresh scheduled context has no event actor and therefore falls back to the current mob target.
| Method | Returns | Notes |
|---|---|---|
players:current_target() | player wrapper or nil | The event player or boss mob target if it is a player |
players:nearby_players(radius) | array of player wrappers | All players within radius of the boss |
players:all_players_in_world() | array of player wrappers | All players in the boss's world |
Example
return {
api_version = 1,
on_enter_combat = function(context)
local nearby = context.players:nearby_players(20)
for _, player in ipairs(nearby) do
player:send_message("&cThe boss is enraged!")
player:apply_potion_effect("GLOWING", 60, 0)
end
end
}
Example
return {
api_version = 1,
on_spawn = function(context)
-- Warn everyone in the world
local everyone = context.players:all_players_in_world()
for _, p in ipairs(everyone) do
p:show_title("&4WARNING", "&7A world boss has spawned!", 10, 60, 20)
end
end
}
context.entities
General entity query helpers centered around the boss.
| Method | Returns | Notes |
|---|---|---|
entities:get_nearby_entities(radius[, filter]) | array of entity wrappers | Nearby entities around the boss |
entities:get_entities_in_box(center, halfX, halfY, halfZ[, filter]) | array of entity wrappers | Living entities whose feet location is inside inclusive box bounds in the center's world; not a bounding-box overlap test |
entities:get_all_entities([filter]) | array of entity wrappers | All matching entities in the boss world |
entities:get_direct_target_entity() | entity wrapper or nil | Direct target for the current event |
entities:get_boss_spawn_location() | location table | The boss's original spawn location |
Valid filters: living (default), player / players, elite / elites, mob / mobs, all / entities
all / entities is only honoured by get_nearby_entities. It includes non-living entities such as dropped items and projectiles, returned as lighter reference wrappers. Living results still use full living-entity wrappers. This filter searches an axis-aligned box with the supplied radius on each axis; the living filters use spherical distance. On the other query methods, all / entities falls through to living. The boss itself is excluded from every result.
Filters ignore case; unknown filters also fall back to living. mob means any non-player living entity, not only hostile monsters. These queries have no automatic instance-participant filter, result cap or distance ordering. Broad living queries scan the world's loaded living entities; use a bounded radius and avoid unnecessary repeated scans. get_direct_target_entity() uses the event's direct target and can be nil; it does not fall back to the mob's current combat target.
Example
return {
api_version = 1,
on_enter_combat = function(context)
-- Damage all nearby elites
local elites = context.entities:get_nearby_entities(10, "elites")
for _, elite in ipairs(elites) do
elite:deal_damage(5)
end
end
}
Example
return {
api_version = 1,
on_enter_combat = function(context)
-- Find players in a box area
local center = context.boss:get_location()
local players = context.entities:get_entities_in_box(center, 10, 5, 10, "players")
for _, p in ipairs(players) do
p:send_message("&eYou are in the danger zone!")
end
end
}
