Scripting Lua: Zonas y Objetivos

Las funciones Lua de EliteMobs ofrecen dos enfoques complementarios para definir áreas espaciales y resolver objetivos:
- Zonas nativas (
context.zones) -- simples y directas. Se construye una definición de zona como una tabla Lua simple y se consulta para obtener entidades o ubicaciones. Ideal para verificaciones directas de "¿hay algo en esta área?".
- Utilidades de script (
context.script) -- selección de objetivos más completa, handles de zona con métodos watch/contains/entities, generación de partículas, daño y acciones de empuje. Usa los mismos nombres de campo que las Zonas de EliteScript y los Objetivos de EliteScript para mayor familiaridad.
Ambos enfoques son APIs nativas de Lua. Elija el que se ajuste a la complejidad de su poder.
Zonas nativas: context.zones
Las zonas nativas permiten definir zonas como tablas Lua simples y consultarlas directamente. Sin handles, sin abstracción adicional -- solo una tabla que describe una forma y una llamada a método para consultarla.
Métodos
| Método | Notas |
|---|
zones:get_entities_in_zone(zoneDef, options) | Devuelve un array de wrappers de entidad dentro de la zona |
zones:get_locations_in_zone(zoneDef, options) | Devuelve un array de tablas de ubicación dentro de la zona |
zones:zone_contains(zoneDef, location[, "full"|"border"]) | Devuelve true si la ubicación está dentro de la zona |
zones:watch_zone(zoneDef, callbacks, options) | Registra un observador de zona persistente que se ejecuta cada tick |
Campos de definición de zona
| Campo | Tipo | Notas |
|---|
kind | string | "sphere", "dome", "cylinder", "cuboid", "cone", "static_ray", "rotating_ray", "translating_ray" |
radius | number | Radio de la zona (sphere, dome, cylinder, cone) |
height | number | Altura del cilindro |
origin | location | Ubicación central (por defecto la ubicación del boss si se omite) |
destination | location | Punto final para rayos y conos |
x, y, z | number | Semi-extensiones del cuboide |
length | number | Longitud para conos y rayos |
thickness / point_radius | number | Grosor del rayo |
border_radius | number | Ancho del borde (por defecto 1) |
x_border, y_border, z_border | number | Anchos de borde del cuboide (por defecto 1) |
animation_duration | int | Duración de la animación en ticks para rayos animados |
pitch_pre_rotation, yaw_pre_rotation | number | Ángulos de pre-rotación (rayo rotatorio) |
pitch_rotation, yaw_rotation | number | Ángulos de rotación por tick (rayo rotatorio) |
origin_end, destination_end | location | Posiciones finales para rayo en traslación |
ignores_solid_blocks | boolean | Si los rayos atraviesan bloques sólidos (por defecto true) |
Opciones de consulta
| Clave | Notas |
|---|
filter | "player" / "players", "elite" / "elites", "mob" / "mobs", "living" (por defecto) |
mode | "full" (por defecto) o "border" |
coverage | 0.0 a 1.0 -- fracción de ubicaciones a muestrear (por defecto 1.0) |
Callbacks de observación
| Clave | Notas |
|---|
on_enter | function(entity) -- se llama cuando una entidad entra en la zona |
on_leave | function(entity) -- se llama cuando una entidad sale de la zona |
Ejemplo: consulta básica de esfera
Ejemplo
return {
api_version = 1,
on_spawn = function(context)
-- Store a zone definition for reuse
context.state.danger_zone = {
kind = "sphere",
origin = context.boss:get_location(),
radius = 10
}
end,
on_boss_damaged_by_player = function(context)
-- Update the origin to the boss's current position
context.state.danger_zone.origin = context.boss:get_location()
local players = context.zones:get_entities_in_zone(
context.state.danger_zone,
{ filter = "players" }
)
for _, player in ipairs(players) do
player:send_message("&cYou are in the danger zone!")
end
end
}
Ejemplo: observación de zona con entrada/salida
Ejemplo
return {
api_version = 1,
on_spawn = function(context)
context.zones:watch_zone(
{
kind = "sphere",
origin = context.boss:get_location(),
radius = 8
},
{
on_enter = function(entity)
entity:apply_potion_effect("SLOWNESS", 40, 1)
entity:send_message("&7You feel sluggish near the boss...")
end,
on_leave = function(entity)
entity:send_message("&aYou escape the slowing aura.")
end
},
{ filter = "players", mode = "full" }
)
end
}
Notas sobre observadores:
- Los callbacks de observadores reciben directamente un wrapper de entidad individual, no a través de
context.event
- Los observadores se limpian automáticamente cuando el boss es eliminado
- Cada observador se ejecuta cada tick, así que mantenga la lógica del callback ligera
- La entidad del boss está excluida de las consultas de zona
Utilidades de script: context.script
Las utilidades de script proporcionan resolución de objetivos, handles de zona, vectores relativos, generación de partículas y acciones de combate. Usan los mismos nombres de campo que las Zonas de EliteScript y los Objetivos de EliteScript para mayor familiaridad -- los nombres de enum (como "NEARBY_PLAYERS", "SPHERE", "ZONE_FULL") son idénticos para que los autores que ya están familiarizados con EliteScript puedan transferir ese conocimiento directamente.
context.script es una API nativa de Lua. No es un puente hacia YAML o hacia el runtime de EliteScript. Simplemente reutiliza las mismas convenciones de nombres para que no tenga que aprender un segundo conjunto de nombres de enum.
Métodos
| Método | Notas |
|---|
script:target(spec) | Crea un handle de objetivo a partir de una tabla de especificación de objetivo |
script:zone(spec) | Crea un handle de zona a partir de una tabla de especificación de zona |
script:relative_vector(spec[, actionLocation][, zoneHandle]) | Crea un handle de vector relativo |
script:damage(targetHandle, amount[, multiplier]) | Inflige daño a los objetivos resueltos |
script:push(targetHandle, vectorOrHandle[, additive]) | Empuja los objetivos resueltos |
script:set_facing(targetHandle, vectorOrHandle) | Establece la dirección de orientación de los objetivos |
script:spawn_particles(targetHandle, particleSpec) | Genera partículas en las ubicaciones de los objetivos resueltos |
Métodos del handle de objetivo
| Método | Notas |
|---|
handle:entities() | Devuelve array de wrappers de entidad |
handle:locations() | Devuelve array de tablas de ubicación |
handle:first_entity() | Devuelve la primera entidad o nil |
handle:first_location() | Devuelve la primera ubicación o nil |
Claves de especificación de objetivo
| Clave | Notas |
|---|
targetType | "SELF", "DIRECT_TARGET", "NEARBY_PLAYERS", "NEARBY_MOBS", "NEARBY_ELITES", "ZONE_FULL", "ZONE_BORDER", "ALL_PLAYERS", "WORLD_PLAYERS", "SELF_SPAWN", "LOCATION" |
range | Alcance para tipos de objetivo cercanos |
coverage | 0.0 a 1.0 para objetivos de zona |
offset | Cadena "x,y,z" o tabla { x = n, y = n, z = n } |
track | Si se deben volver a resolver los objetivos en movimiento |
Ejemplo: crear y usar un objetivo
Ejemplo
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if not context.cooldowns:check_local("roar", 200) then return end
-- Find all players within 20 blocks
local nearby = context.script:target({
targetType = "NEARBY_PLAYERS",
range = 20
})
for _, player in ipairs(nearby:entities()) do
player:send_message("&eThe boss roars in fury!")
end
-- Single-entity access
local closest = nearby:first_entity()
if closest then
closest:show_title("&cRUN!", "&7The boss is targeting you")
end
end
}
Métodos del handle de zona
| Método | Notas |
|---|
handle:full_target([coverage]) | Devuelve un handle de objetivo para el volumen completo de la zona |
handle:border_target([coverage]) | Devuelve un handle de objetivo para el borde de la zona |
handle:full_locations([coverage]) | Devuelve ubicaciones en el volumen completo de la zona |
handle:border_locations([coverage]) | Devuelve ubicaciones en el borde de la zona |
handle:full_entities() | Devuelve entidades en el volumen completo de la zona |
handle:border_entities() | Devuelve entidades en el borde de la zona |
handle:contains(location[, "full"|"border"]) | Devuelve true si la ubicación está dentro de la zona |
handle:watch(callbacks[, mode]) | Observa la zona para eventos de entrada/salida, devuelve ID de tarea |
Claves de especificación de zona
| Clave | Notas |
|---|
shape | "SPHERE", "DOME", "CYLINDER", "CUBOID", "CONE", "STATIC_RAY", "ROTATING_RAY", "TRANSLATING_RAY" |
radius | Radio de la zona |
height | Altura del cilindro |
x, y, z | Semi-extensiones del cuboide |
borderRadius | Ancho del borde |
pointRadius | Grosor del rayo |
animationDuration | Duración de la animación en ticks para rayos animados |
Target | Especificación de objetivo central (tabla) -- usa el mismo formato de especificación de objetivo |
Target2 | Segundo punto para rayos y conos |
filter | Filtro de entidad |
ignoresSolidBlocks | boolean |
pitchPreRotation, yawPreRotation | Ángulos de pre-rotación |
pitchRotation, yawRotation | Ángulos de rotación por tick |
Ejemplo: zona con daño y partículas
Ejemplo
return {
api_version = 1,
on_enter_combat = function(context)
-- Create a sphere zone centered on the boss
local zone = context.script:zone({
shape = "SPHERE",
radius = 6,
Target = { targetType = "SELF" }
})
-- Spawn warning particles on the zone border
context.script:spawn_particles(
zone:border_target(0.3),
{ particle = "FLAME", amount = 1, speed = 0.02 }
)
-- Damage all players inside the zone
local targets = zone:full_target()
context.script:damage(targets, 5.0)
-- Repeat every 20 ticks
context.scheduler:run_every(20, function(ctx)
local z = ctx.script:zone({
shape = "SPHERE",
radius = 6,
Target = { targetType = "SELF" }
})
ctx.script:spawn_particles(
z:border_target(0.3),
{ particle = "FLAME", amount = 1, speed = 0.02 }
)
ctx.script:damage(z:full_target(), 5.0)
end)
end
}
Claves de especificación de vector relativo
| Clave | Notas |
|---|
SourceTarget | Especificación del objetivo de origen (tabla) |
DestinationTarget | Especificación del objetivo de destino (tabla) |
normalize | boolean -- si se debe normalizar el vector resultante |
multiplier | Factor de escala aplicado después de la normalización |
offset | Cadena "x,y,z" o tabla { x = n, y = n, z = n } |
Métodos del handle de vector relativo
| Método | Notas |
|---|
handle:resolve() | Devuelve la tabla del vector calculado |
Ejemplo: empujar objetivos con un vector relativo
Ejemplo
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
if not context.cooldowns:check_local("knockback", 100) then return end
-- Build a vector from the boss toward the attacker
local vec = context.script:relative_vector({
SourceTarget = { targetType = "SELF" },
DestinationTarget = { targetType = "DIRECT_TARGET" },
normalize = true,
multiplier = 2.5
})
-- Push the attacker away
local target = context.script:target({
targetType = "DIRECT_TARGET"
})
context.script:push(target, vec)
end
}
Las especificaciones de partículas pueden ser una cadena, una tabla individual o un array de tablas:
| Clave | Notas |
|---|
particle | Nombre de partícula (ej. "FLAME", "DUST", "SMOKE") |
amount | Número de partículas |
x, y, z | Valores de offset/dispersión |
speed | Velocidad de partículas |
red, green, blue | Color para DUST / DUST_COLOR_TRANSITION (0-255) |
toRed, toGreen, toBlue | Color de destino de transición para DUST_COLOR_TRANSITION |
Para la lista completa de nombres de partículas, consulte la Referencia de Enums.
Advertencias importantes
- Los handles de utilidades de script están vinculados al contexto del evento en el que fueron creados. No los almacene en
context.state para usarlos en una llamada posterior a un hook.
watch() de zona devuelve un ID de tarea que puede cancelar con context.scheduler:cancel_task().
- Los valores de coverage solo se aplican a la resolución basada en ubicaciones, no a consultas de entidades.
- Todos los valores de cadena usan los mismos nombres de enum en UPPER_SNAKE_CASE que EliteScript YAML (ej.
"SELF", "NEARBY_PLAYERS", "SPHERE").
Espacio de nombres auxiliar em
El espacio de nombres em está disponible globalmente en todos los archivos de poder Lua. Proporciona constructores convenientes para ubicaciones, vectores y definiciones de zona.
Constructores de ubicación y vector
| Función | Notas |
|---|
em.create_location(x, y, z[, world][, yaw][, pitch]) | Devuelve una tabla de ubicación con un método add(dx, dy, dz) |
em.create_vector(x, y, z) | Devuelve una tabla de vector |
Helpers de constructor de zonas
La sub-tabla em.zone proporciona funciones constructoras que devuelven tablas de definición de zona compatibles con context.zones. Cada constructor devuelve una tabla con métodos mutadores encadenables.
| Función | Parámetros | Mutadores |
|---|
em.zone.create_sphere_zone(radius) | radius | :set_center(location) |
em.zone.create_dome_zone(radius) | radius | :set_center(location) |
em.zone.create_cylinder_zone(radius, height) | radius, height | :set_center(location) |
em.zone.create_cuboid_zone(x, y, z) | x, y, z (semi-extensiones) | :set_center(location) |
em.zone.create_cone_zone(length, radius) | length, radius | :set_origin(location), :set_destination(location) |
em.zone.create_static_ray_zone(length, thickness) | length, thickness | :set_origin(location), :set_destination(location) |
em.zone.create_rotating_ray_zone(length, point_radius, animation_duration) | length, point_radius, animation_duration | :set_origin(location), :set_destination(location) |
em.zone.create_translating_ray_zone(length, point_radius, animation_duration) | length, point_radius, animation_duration | :set_origin(location), :set_destination(location) |
Ejemplo
Ejemplo
return {
api_version = 1,
on_spawn = function(context)
-- Create a location offset from the boss
local boss_loc = context.boss:get_location()
local above = em.create_location(boss_loc.x, boss_loc.y + 5, boss_loc.z)
-- Create a sphere zone using the builder
local zone = em.zone.create_sphere_zone(10):set_center(boss_loc)
-- Use with native zone queries
local players = context.zones:get_entities_in_zone(zone, { filter = "players" })
for _, p in ipairs(players) do
p:send_message("&cYou are within the boss's aura!")
end
-- Create a directional vector
local push_vec = em.create_vector(0, 1.5, 0)
context.boss:set_velocity_vector(push_vec)
end
}
El espacio de nombres em no es por instancia -- todas las instancias de poder Lua comparten las mismas funciones auxiliares de em. Las funciones son constructores puros y no mantienen ningún estado.
Zonas nativas vs. Utilidades de script
Ambos sistemas trabajan con la misma geometría de zona subyacente. Aquí se indica cuándo usar cada uno:
| Caso de uso | Enfoque recomendado |
|---|
| Verificación simple de "¿hay algo en esta área?" | Zonas nativas (context.zones) |
| Consulta rápida de entidades con una forma | Zonas nativas |
NEARBY_PLAYERS, ZONE_FULL con coverage | Utilidades de script (context.script) |
| Zonas animadas (rayos rotatorios/en traslación) | Ambos -- las zonas nativas también soportan estas formas |
Handles de zona con métodos watch/contains/entities | Utilidades de script |
| Generación de partículas en ubicaciones de zona | Utilidades de script (spawn_particles) |
| Acciones de daño y empuje vinculadas a objetivos | Utilidades de script (damage, push) |
| Vectores relativos para efectos direccionales | Utilidades de script (relative_vector) |
| Combinación de flujo de control Lua con selección de objetivos avanzada | Utilidades de script |
En la práctica, muchos poderes usan ambos. Las zonas nativas son excelentes para la verificación inicial de "¿hay jugadores cerca?" en un guard de cooldown, mientras que las utilidades de script manejan la lógica de ataque compleja que sigue.
Próximos pasos