Aller au contenu principal

Script Lua : Zones et ciblage

webapp_banner.jpg

Les fonctions Lua d'EliteMobs offrent deux approches complémentaires pour définir des zones spatiales et résoudre des cibles :

  • Zones natives (context.zones) -- simples et directes. Vous construisez une définition de zone sous forme de table Lua simple et l'interrogez pour obtenir des entités ou des emplacements. Idéal pour les vérifications simples de type « y a-t-il quelque chose dans cette zone ? ».
  • Utilitaires de script (context.script) -- ciblage plus riche, handles de zone avec les méthodes watch/contains/entities, génération de particules, dégâts et actions de poussée. Utilise les mêmes noms de champs que les Zones EliteScript et les Cibles EliteScript pour une plus grande familiarité.

Les deux approches sont des API Lua natives. Choisissez celle qui correspond à la complexité de votre pouvoir.


Zones natives : context.zones

Les zones natives vous permettent de définir des zones sous forme de tables Lua simples et de les interroger directement. Pas de handles, pas d'abstraction supplémentaire -- juste une table décrivant une forme et un appel de méthode pour l'interroger.

Méthodes

MéthodeNotes
zones:get_entities_in_zone(zoneDef, options)Retourne un tableau de wrappers d'entité à l'intérieur de la zone
zones:get_locations_in_zone(zoneDef, options)Retourne un tableau de tables d'emplacement à l'intérieur de la zone
zones:zone_contains(zoneDef, location[, "full"|"border"])Retourne true si l'emplacement est à l'intérieur de la zone
zones:watch_zone(zoneDef, callbacks, options)Enregistre un observateur de zone persistant qui se déclenche à chaque tick

Champs de définition de zone

ChampTypeDéfautNotes
kind (ou type)string"sphere", "dome", "cylinder", "cuboid", "cone", "static_ray", "rotating_ray", "translating_ray"
radiusnumber0Rayon de la zone (sphere, dome, cylinder, cone)
heightnumber0Hauteur du cylindre
originlocationemplacement du bossEmplacement central
destinationlocationemplacement du bossPoint final pour les rayons et les cônes
x, y, znumber0Demi-extensions du cuboïde
thickness / point_radius / pointRadiusnumber0.5Épaisseur du rayon
border_radius / borderRadiusnumber1Largeur de la bordure
x_border, y_border, z_bordernumber1Largeurs de bordure du cuboïde
animation_durationint0Durée de l'animation en ticks pour les rayons animés
pitch_pre_rotation, yaw_pre_rotationnumber0Angles de pré-rotation (rayon rotatif)
pitch_rotation, yaw_rotationnumber0Angles de rotation par tick (rayon rotatif)
origin_end, destination_endlocationemplacement du bossPositions finales pour le rayon en translation
ignores_solid_blocksbooleantrueSi les rayons traversent les blocs solides
lengthnumber0Lu uniquement lorsque destination est omis ; voir ci-dessous.

Chaque champ composé accepte également le camelCase (borderRadius, xBorder, animationDuration, pitchPreRotation, ignoresSolidBlocks, ...) : une spécification copiée depuis un bloc Zone: EliteScript fonctionne donc en grande partie telle quelle.

kind est sensible à la casse

Contrairement à presque toutes les autres chaînes de l'API Lua, kind est comparé exactement et doit être en minuscules. "SPHERE" ou "Sphere" ne correspondent à rien, et la zone se résout silencieusement à rien — les requêtes renvoient simplement une liste vide, sans avertissement en console.

Les cônes et les rayons ont besoin d'une destination explicite

origin et destination retombent tous deux sur l'emplacement du boss lorsqu'ils sont omis. Pour un cône ou un rayon, cela produit une forme de longueur nulle plutôt qu'une erreur. Définissez toujours destination sur cone, static_ray, rotating_ray et translating_ray. Il n'existe pas de raccourci length — définissez un emplacement de destination explicite.

Les cônes et rayons nécessitent destination ou length

Si origin est omis, la position du boss est utilisée. Si destination est omis, origin est projeté de length blocs selon la direction enregistrée dans la table de position origin.

Vous pouvez donc définir un cône ou un rayon de deux façons :

-- Explicit endpoint
local explicit_ray = { kind = "static_ray", origin = context.boss:get_eye_location(),
destination = context.player:get_eye_location() }

-- Or a length along the origin's own facing
local forward_ray = { kind = "static_ray", origin = context.boss:get_eye_location(), length = 15 }

La forme abrégée avec length n’est correctement orientée que si origin contient yaw/pitch. Les positions renvoyées par l’API (get_location(), get_eye_location(), current_location) les contiennent. Une table écrite à la main { x = .., y = .., z = .. } ne les contient pas, pas plus que em.create_location(x, y, z) sans ses arguments facultatifs yaw et pitch.

Si les deux sont omis, length vaut 0 par défaut : la forme a une longueur nulle et toutes les requêtes renvoient un résultat vide sans avertissement.

Options de requête

CléNotes
filter"player" / "players", "elite" / "elites", "mob" / "mobs", "living" (par défaut)
mode"full" (par défaut) ou "border"
coverage0.0 à 1.0 -- fraction des emplacements à échantillonner (par défaut 1.0)

Callbacks d'observation

CléNotes
on_enterfunction(entity) -- appelée quand une entité entre dans la zone
on_leavefunction(entity) -- appelée quand une entité quitte la zone

Exemple : requête de sphère basique

Exemple
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
}

Exemple : observation de zone avec entrée/sortie

Exemple
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
}

Notes sur les observateurs :

  • Les callbacks d'observateurs reçoivent directement un seul wrapper d'entité, pas via context.event
  • Les observateurs appellent leurs propres callbacks on_enter / on_leave ; ils n'invoquent pas les hooks de premier niveau on_zone_enter / on_zone_leave du pouvoir
  • Les observateurs sont nettoyés automatiquement lorsque le boss est supprimé
  • Chaque observateur s'exécute à chaque tick, donc gardez la logique du callback légère
  • L'entité du boss elle-même est exclue des requêtes de zone

Utilitaires de script : context.script

Les utilitaires de script fournissent la résolution de cibles, les handles de zone, les vecteurs relatifs, la génération de particules et les actions de combat.

context.script exécute le moteur EliteScript

context.script n'est pas un simple « nommage à la sauce EliteScript » — la table de spécification que vous transmettez est convertie en une map Java brute et remise directement aux mêmes classes de cibles, de zones, de vecteurs relatifs et de particules qui font fonctionner les EliteScripts YAML. Il n'existe pas d'implémentation distincte.

Ce que cela signifie en pratique :

  • Tous les champs documentés dans Cibles EliteScript, Zones EliteScript et Vecteurs relatifs EliteScript fonctionnent dans ces tables de spécification, y compris ceux que cette page ne liste pas.
  • Les valeurs d'enum sont en UPPER_SNAKE_CASE exact ("NEARBY_PLAYERS", "SPHERE", "ZONE_FULL"), comme en YAML.
  • Les noms de champs sont les noms YAML : Target et Target2 portent donc une majuscule, tandis que targetType et borderRadius sont en camelCase.
  • Le comportement de chargement YAML s'applique aussi : une valeur non analysable journalise un avertissement EliteScript et vide le champ au lieu de retomber sur sa valeur par défaut.

C'est l'inverse de context.zones, qui est une implémentation légère véritablement distincte utilisant des noms de kind en minuscules.

Méthodes

MéthodeNotes
script:target(spec)Crée un handle de cible à partir d'une table de spécification de cible
script:zone(spec)Crée un handle de zone à partir d'une table de spécification de zone
script:relative_vector(spec[, actionLocation][, zoneHandle])Crée un handle de vecteur relatif
script:damage(targetHandle, amount[, multiplier])Inflige des dégâts aux cibles résolues
script:push(targetHandle, vectorOrHandle[, additive])Pousse les cibles résolues
script:set_facing(targetHandle, vectorOrHandle)Définit la direction d'orientation des cibles
script:spawn_particles(targetHandle, particleSpec)Génère des particules aux emplacements des cibles résolues

Méthodes du handle de cible

MéthodeNotes
handle:entities()Retourne un tableau de wrappers d'entité
handle:locations()Retourne un tableau de tables d'emplacement
handle:first_entity()Retourne la première entité ou nil
handle:first_location()Retourne le premier emplacement ou nil

Clés de spécification de cible

CléDéfautNotes
targetType"SELF"Tout type de cible EliteScript
range20Portée pour les types de cible à proximité
coverage1.00.0 à 1.0. Honoré uniquement pour les types de cible de zone ; sur tout autre type il est remis à 1.0 avec un avertissement en console
offset0,0,0Chaîne "x,y,z" ou table { x = n, y = n, z = n }
relativeOffsetaucunUne table de spécification de vecteur relatif, pour un décalage relatif à l'orientation du boss
locationaucunEmplacement unique, pour "LOCATION"
locationsaucunListe d'emplacements, pour "LOCATIONS"
tracktrueIndique s'il faut ré-résoudre les cibles en mouvement

Les 17 types de cible EliteScript sont acceptés, pas seulement les plus courants : SELF, SELF_SPAWN, DIRECT_TARGET, NEARBY_PLAYERS, NEARBY_MOBS, NEARBY_ELITES, WORLD_PLAYERS, ALL_PLAYERS, LOCATION, LOCATIONS, ZONE_FULL, ZONE_BORDER, LANDING_LOCATION, ACTION_TARGET, INHERIT_SCRIPT_TARGET, INHERIT_SCRIPT_ZONE_FULL, INHERIT_SCRIPT_ZONE_BORDER. Les types ACTION_TARGET et INHERIT_* ne se résolvent à quelque chose que si le contexte EliteScript environnant existe ; ils sont donc de peu d'utilité depuis Lua.

Exemple : créer et utiliser une cible

Exemple
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éthodes du handle de zone

MéthodeNotes
handle:full_target([coverage])Retourne un handle de cible pour le volume complet de la zone
handle:border_target([coverage])Retourne un handle de cible pour la bordure de la zone
handle:full_locations([coverage])Retourne les emplacements dans le volume complet de la zone
handle:border_locations([coverage])Retourne les emplacements sur la bordure de la zone
handle:full_entities()Retourne les entités dans le volume complet de la zone
handle:border_entities()Retourne les entités sur la bordure de la zone
handle:contains(location[, "full"|"border"])Retourne true si l'emplacement est à l'intérieur de la zone
handle:watch(callbacks[, mode])Surveille la zone pour les événements d'entrée/sortie, retourne un ID de tâche

Clés de spécification de zone

CléDéfautNotes
shape"CYLINDER""SPHERE", "DOME", "CYLINDER", "CUBOID", "CONE", "STATIC_RAY", "ROTATING_RAY", "TRANSLATING_RAY"
radius5Sphère, dôme, cylindre, cône
height1Cylindre uniquement
x, y, z0Demi-extensions du cuboïde
xBorder, yBorder, zBorder0Largeurs de bordure du cuboïde
borderRadius1Largeur de bordure pour sphère / dôme / cylindre / cône
pointRadius0.5Épaisseur du rayon
animationDuration0Durée de l'animation en ticks pour les rayons animés
Target{targetType = "SELF"}Spécification de cible centrale (table) -- utilise le même format de spécification de cible
Target2aucunSecond point. Requis pour les cônes et toutes les formes de rayon
FinalTarget, FinalTarget2aucunPositions finales, rayon en translation uniquement
filter"PLAYER""PLAYER", "ELITE", "LIVING" — notez qu'ils sont en MAJUSCULES ici, contrairement à context.zones
ignoresSolidBlockstrueRayons uniquement
pitchPreRotation, yawPreRotation0Rayon rotatif uniquement
pitchRotation, yawRotation0Rayon rotatif uniquement

Les clés qui ne s'appliquent pas à la shape choisie sont lues sans protestation puis ignorées — un height sur une sphère ne fait rien.

Exemple : zone avec dégâts et particules

Exemple
return {
api_version = 1,
on_enter_combat = function(context)
-- Create a sphere zone centered on the boss
if context.state.zone_task_id ~= nil then return end
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.state.zone_task_id = 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,
on_exit_combat = function(context)
if context.state.zone_task_id ~= nil then
context.scheduler:cancel_task(context.state.zone_task_id)
context.state.zone_task_id = nil
end
end
}

Clés de spécification de vecteur relatif

CléNotes
SourceTargetSpécification de la cible source (table)
DestinationTargetSpécification de la cible de destination (table)
normalizeboolean -- indique s'il faut normaliser le vecteur résultant
multiplierFacteur d'échelle appliqué après la normalisation
offsetChaîne "x,y,z" ou table { x = n, y = n, z = n }

Méthodes du handle de vecteur relatif

MéthodeNotes
handle:resolve()Retourne la table du vecteur calculé

Exemple : pousser des cibles avec un vecteur relatif

Exemple
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
}

Format de spécification des particules

Les spécifications de particules peuvent être une chaîne, une table unique ou un tableau de tables. Comme ce chemin exécute le moteur de particules d'EliteScript, les clés sont celles d'EliteScript documentées sous SPAWN_PARTICLE :

CléDéfautNotes
particle"FLAME"Nom de la particule (ex. "FLAME", "DUST", "SMOKE")
amount1Nombre de particules. 0 transforme x/y/z en vecteur de vélocité
x, y, z0.01Valeurs d'offset/dispersion, ou vélocité lorsque amount vaut 0
speed0.01Vitesse des particules
red, green, blue255Couleur pour DUST, DUST_COLOR_TRANSITION, WITCH et les autres particules à données de couleur (0-255)
toRed, toGreen, toBlue255Couleur cible de transition pour DUST_COLOR_TRANSITION
material"STONE"Bloc ou objet affiché par les particules portant des données de bloc/objet (BLOCK, ITEM, FALLING_DUST, ...)
relativeVectoraucunUne spécification de vecteur relatif. La définir force amount à 0 et écrase x/y/z par la direction résolue
Deux jeux de clés de particules différents

Ces clés EliteScript ne sont pas les mêmes que celles acceptées par context.world:spawn_particle_at_location(loc, spec). La table world possède son propre lecteur plus réduit, avec des valeurs par défaut différentes (amount 1, x/y/z/speed 0), sans material ni relativeVector, et il accepte en plus to_red / to_green / to_blue en snake_case. Voir Monde et Environnement.

Pour la liste complète des noms de particules, consultez la Référence des enums.

Avertissements importants

  • Les handles des utilitaires de script sont liés au contexte d'événement dans lequel ils ont été créés. Ne les stockez pas dans context.state pour une utilisation dans un appel de hook ultérieur.
  • watch() de zone retourne un ID de tâche que vous pouvez annuler avec context.scheduler:cancel_task().
  • Les valeurs de coverage ne s'appliquent qu'à la résolution basée sur les emplacements, pas aux requêtes d'entités.
  • Toutes les valeurs de chaîne utilisent les mêmes noms d'enum en UPPER_SNAKE_CASE que le YAML EliteScript (ex. "SELF", "NEARBY_PLAYERS", "SPHERE").

Espace de noms auxiliaire em

L'espace de noms em est disponible globalement dans tous les fichiers de pouvoir Lua. Il fournit des constructeurs pratiques pour les emplacements, les vecteurs et les définitions de zone.

Constructeurs d'emplacement et de vecteur

FonctionNotes
em.create_location(x, y, z[, world][, yaw][, pitch])Retourne une table d'emplacement avec une méthode add(dx, dy, dz)
em.create_vector(x, y, z)Retourne une table de vecteur

Helpers de constructeur de zones

La sous-table em.zone fournit des fonctions constructrices qui retournent des tables de définition de zone compatibles avec context.zones. Chaque constructeur retourne une table avec des méthodes de mutation chaînables.

FonctionParamètresMutateurs
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 (demi-extensions):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)
L'argument length n'est pas utilisé

Les constructeurs de cônes et de rayons stockent length dans la table de spécification, mais context.zones ne le lit jamais — la forme va d'origin à destination. Chaînez toujours :set_origin(...) et :set_destination(...) sur ces constructeurs ; sinon les deux retombent sur l'emplacement du boss et la forme a une longueur nulle.

Exemple

Exemple
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
}
info

L'espace de noms em n'est pas spécifique à une instance -- toutes les instances de pouvoir Lua partagent les mêmes fonctions auxiliaires em. Les fonctions sont des constructeurs purs et ne maintiennent aucun état.


Zones natives vs. Utilitaires de script

Les deux systèmes fonctionnent avec la même géométrie de zone sous-jacente. Voici quand utiliser chacun :

Cas d'utilisationApproche recommandée
Vérification simple « y a-t-il quelque chose dans cette zone ? »Zones natives (context.zones)
Requête rapide d'entités avec une formeZones natives
NEARBY_PLAYERS, ZONE_FULL avec coverageUtilitaires de script (context.script)
Zones animées (rayons rotatifs/en translation)Les deux -- les zones natives supportent aussi ces formes
Handles de zone avec méthodes watch/contains/entitiesUtilitaires de script
Génération de particules aux emplacements de zoneUtilitaires de script (spawn_particles)
Actions de dégâts et de poussée liées au ciblageUtilitaires de script (damage, push)
Vecteurs relatifs pour effets directionnelsUtilitaires de script (relative_vector)
Combiner le flux de contrôle Lua avec un ciblage avancéUtilitaires de script

En pratique, beaucoup de pouvoirs utilisent les deux. Les zones natives sont idéales pour la vérification initiale « des joueurs sont-ils à proximité ? » dans un garde de cooldown, tandis que les utilitaires de script gèrent la logique d'attaque complexe qui suit.


Prochaines étapes