Scripting Lua: Zonas e Alvos
As funcionalidades Lua do EliteMobs oferecem duas abordagens complementares para definir áreas espaciais e resolver alvos:
- Zonas nativas (
context.zones) -- simples e diretas. Constrói uma definição de zona como uma tabela Lua simples e consulta-a para obter entidades ou localizações. Ideal para verificações diretas de "há algo nesta área?". - Utilitários de script (
context.script) -- segmentação mais rica, handles de zona com métodos watch/contains/entities, geração de partículas, dano e ações de empurrão. Usa os mesmos nomes de campo que as Zonas do EliteScript e os Alvos do EliteScript para maior familiaridade.
Ambas as abordagens são APIs Lua nativas. Escolha a que se adequa à complexidade do seu poder.
Zonas nativas: context.zones
As zonas nativas aceitam tabelas Lua simples. Cada consulta cria uma forma nova; um observador conserva uma forma. Consultas repetidas de um raio animado reiniciam a animação em vez de ler a forma atual do observador. Use um handle de zona de script quando várias operações precisarem da mesma forma animada.
Métodos
| Método | Notas |
|---|---|
zones:get_entities_in_zone(zoneDef[, options]) | Devolve um array de wrappers de entidade dentro da zona |
zones:get_locations_in_zone(zoneDef[, options]) | Devolve um array de tabelas de localização dentro da zona |
zones:zone_contains(zoneDef, location[, "full"|"border"]) | Devolve true se a localização está dentro da zona |
zones:watch_zone(zoneDef, callbacks[, options]) | Regista um observador de zona persistente que verifica a cada tick |
Campos de definição de zona
| Campo | Tipo | Predefinição | Notas |
|---|---|---|---|
kind (ou type) | string | — | "sphere", "dome", "cylinder", "cuboid", "cone", "static_ray", "rotating_ray", "translating_ray" |
radius | number | 0 | Raio da zona (sphere, dome, cylinder, cone) |
height | number | 0 | Altura do cilindro |
origin | location | localização do boss | Origem: base do cilindro, ponta do cone ou início do raio |
destination | location | localização do boss | Ponto final para raios e cones |
x, y, z | number | 0 | Dimensões do cuboide; consulte a limitação geométrica de pontos e entidades |
thickness / point_radius / pointRadius | number | 0.5 | Raio e espaçamento das amostras do raio; use um valor positivo |
border_radius / borderRadius | number | 1 | Raio interior excluído da forma exterior |
x_border, y_border, z_border | number | 1 | Dimensões interiores do cuboide |
animation_duration | int | 0 | Duração da animação em ticks para raios animados |
pitch_pre_rotation, yaw_pre_rotation | number | 0 | Ângulos de pré-rotação (raio rotativo) |
pitch_rotation, yaw_rotation | number | 0 | Rotação total durante a animação; atualmente só são aplicados incrementos positivos |
origin_end, destination_end | location | localização do boss | Posições finais para raio em translação |
ignores_solid_blocks | boolean | true | Se os raios passam através de blocos sólidos |
length | number | 0 | Guardado pelos construtores, mas omitir destination usa a posição do boss antes deste recurso; forneça um destino explícito |
Os campos numéricos e booleanos com sublinhados também aceitam camelCase (borderRadius, xBorder, animationDuration, pitchPreRotation, ignoresSolidBlocks). Os campos de localização origin_end e destination_end exigem os nomes com sublinhados. Tabelas Target de EliteScript não substituem campos de localização nativos.
kind diferencia maiúsculas de minúsculaskind é comparado exatamente e deve estar em minúsculas. "SPHERE" ou "Sphere" não correspondem a nenhuma forma: as consultas devolvem uma lista vazia sem aviso na consola.
Omitir origin ou destination usa a posição atual do boss. O leitor de localizações impede que length substitua um destino omitido. Forneça extremos distintos:
local explicit_ray = { kind = "static_ray", origin = context.boss:get_eye_location(),
destination = context.player:get_eye_location() }
Para animar um raio em translação, forneça origin_end, destination_end e um animation_duration positivo. Um extremo final omitido fica na sua posição inicial. Uma duração de zero cria o raio inicial estático; uma duração negativa é rejeitada. O último fotograma da animação termina exatamente nos extremos pedidos.
Mantenha os extremos e localizações consultadas no mundo atual do boss: as consultas nativas de entidades pesquisam esse mundo. Numa tabela de localização, coordenadas omitidas valem 0; omitir o mundo usa o do boss, mas um nome explícito deve indicar um mundo já carregado. As dimensões devem ser finitas e positivas. Testes de pontos, amostras de partículas e testes de entidades não são equivalentes; as limitações das formas incluem testes esféricos de entidades em domos completos, verificação da altura completa da entidade em cilindros e limites diferentes em cuboides.
Opções de consulta
| Chave | Notas |
|---|---|
filter | "player" / "players", "elite" / "elites", "mob" / "mobs", "living" (predefinição) |
mode | "full" (predefinição) ou "border" |
coverage | 0.0 a 1.0 -- fração de localizações a amostrar (predefinição 1.0) |
filter ignora maiúsculas/minúsculas; valores desconhecidos usam living. mobs inclui entidades vivas que não sejam jogadores, incluindo elites. O boss é excluído, mas os jogadores não são filtrados pelo modo de jogo. mode reconhece border sem distinguir maiúsculas; outros valores usam full. Coverage amostra localizações aleatoriamente, não entidades, e não limita os membros de um observador. Use full para raios: as localizações de borda não são suportadas e podem fazer falhar uma consulta de localizações.
Callbacks de observação
| Chave | Notas |
|---|---|
on_enter | function(entity) -- chamada quando uma entidade entra na zona |
on_leave | function(entity) -- chamada quando uma entidade sai da zona |
Exemplo: consulta básica de esfera
Exemplo
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
}
Exemplo: observação de zona com entrada/saída
Exemplo
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:
- Os callbacks de observadores recebem diretamente um único wrapper de entidade, não via
context.event - Os observadores chamam os próprios callbacks
on_enter/on_leave, não os hooks principaison_zone_enter/on_zone_leavedo poder - Os observadores são limpos automaticamente quando o boss é removido
- Um observador nativo constrói a forma uma vez. O centro não segue o boss, e alterar a tabela original não move um observador existente. Use consultas novas ou uma zona de script com um alvo acompanhado para áreas móveis.
- Cada observador é executado a cada tick, portanto mantenha a lógica do callback leve
- A entidade do boss é excluída das consultas de zona
A primeira verificação ocorre um tick depois; entidades já presentes ativam on_enter. Cancelar ou limpar não envia on_leave aos membros restantes. Neste exemplo, a esfera fica na posição de aparecimento. A lentidão dura 40 ticks desde a entrada; permanecer dentro não a renova, e sair não a remove antecipadamente.
Utilitários de script: context.script
Os utilitários de script fornecem resolução de alvos, handles de zona, vetores relativos, geração de partículas e ações de combate.
context.script executa o motor do EliteScriptA tabela de especificação é convertida num mapa Java e passada às classes de alvos, zonas, vetores relativos e partículas usadas pelos EliteScripts YAML.
O que isto significa na prática:
- As tabelas usam os leitores documentados em Alvos do EliteScript, Zonas do EliteScript e Vetores Relativos do EliteScript, com as suas limitações. Aceitar um campo não garante que o handle Lua tenha o ciclo de vida de ação ou o contexto herdado necessário.
- Os valores de enum são exatamente em UPPER_SNAKE_CASE (
"NEARBY_PLAYERS","SPHERE","ZONE_FULL"), tal como no YAML. - Use os nomes YAML canónicos mostrados aqui:
Target,Target2,targetType,borderRadius. Os leitores internos ignoram maiúsculas/minúsculas. - Valores inválidos podem produzir avisos, valores alternativos ou campos ausentes que falham depois. Aceitar a tabela não valida a operação completa.
context.zones tem um leitor separado com nomes kind em minúsculas, mas usa as mesmas classes geométricas. Forneça tabelas não vazias com campos nomeados: um {} Lua vazio converte-se numa lista Java, pelo que até script:target({}) falha. Use script:target({targetType = "SELF"}).
Métodos
| Método | Notas |
|---|---|
script:target(spec) | Cria um handle de alvo a partir de uma tabela de especificação de alvo |
script:zone(spec) | Cria um handle de zona a partir de uma tabela de especificação de zona |
script:relative_vector(spec[, actionLocation][, zoneHandle]) | Cria um handle de vetor relativo |
script:damage(targetHandle, amount[, multiplier]) | Causa dano aos alvos resolvidos |
script:push(targetHandle, vectorOrHandle[, additive]) | Empurra os alvos resolvidos |
script:set_facing(targetHandle, vectorOrHandle) | Define a direção de orientação dos alvos |
script:spawn_particles(targetHandle, particleSpec) | Gera partículas nas localizações dos alvos resolvidos |
damage, push, set_facing e spawn_particles exigem um handle de alvo, não um array de entidades, e não devolvem resultado. Não aplicam condições, esperas ou filtros de ações YAML. damage envia o valor ao Bukkit com o boss como atacante; o multiplicador opcional aplica-se ao combate contra jogadores, e a perda final de vida depende do processamento do combate. push resolve agora os alvos e um vetor, aplicando esse vetor a todos no tick seguinte. Substitui a velocidade, exceto com additive = true, que soma à velocidade desse tick. set_facing aplica imediatamente uma direção a todos. Evite direções nulas ou não finitas.
Métodos do handle de alvo
| Método | Notas |
|---|---|
handle:entities() | Devolve array de wrappers de entidade |
handle:locations() | Devolve array de tabelas de localização |
handle:first_entity() | Devolve a primeira entidade ou nil |
handle:first_location() | Devolve a primeira localização ou nil |
Cada método resolve novamente; first_* não lê uma captura partilhada nem garante o resultado mais próximo. DIRECT_TARGET refere-se ao alvo capturado pelo evento, não ao alvo de combate atual do boss, e não seleciona nada se o evento não fornecer nenhum.
Chaves de especificação de alvo
| Chave | Predefinição | Notas |
|---|---|---|
targetType | "SELF" | Qualquer tipo de alvo do EliteScript |
range | 20 | Meia largura em cada eixo da caixa de pesquisa; resultados não ordenados por distância |
coverage | 1.0 | 0.0 a 1.0. Só para alvos de zona; valores abaixo de 1.0 noutros tipos são repostos a 1.0 com aviso |
offset | 0,0,0 | String "x,y,z" separada por vírgulas; este campo EliteScript não aceita tabelas vetoriais Lua |
relativeOffset | nenhum | Especificação de vetor relativo; os alvos de origem e destino determinam a direção |
location | nenhum | String serializada "world,x,y,z,yaw,pitch", para "LOCATION" |
locations | nenhum | Array de strings de localização serializadas, para "LOCATIONS" |
track | true | Se deve resolver novamente alvos em movimento |
A via Lua não executa a cache de alvos das ações YAML. Por isso, track = false não fixa a localização de um alvo ou zona Lua estáticos. Zonas estáticas resolvem as origens a cada consulta; as animadas guardam as formas ao serem criadas. Para uma área fixa, use LOCATION com coordenadas explícitas ou uma zona nativa com origin capturado. offset e relativeOffset deslocam todas as localizações que um handle resolve, incluindo LOCATION, LOCATIONS, SELF_SPAWN, alvos baseados em entidades e localizações amostradas de zonas; não movem as entidades devolvidas por entities(), e LANDING_LOCATION e INHERIT_SCRIPT_TARGET ignoram-nos. full_target() e border_target() de um handle de zona não aceitam offset, por isso coloque os offsets nas especificações Target e Target2 da zona. Consulte os atributos partilhados.
O leitor aceita os 17 nomes: 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. Handles Lua independentes não fornecem dados de ações herdadas nem localização de aterragem. Evite INHERIT_* e LANDING_LOCATION, que podem falhar ao resolver. ACTION_TARGET só faz sentido num contexto compatível de vetor relativo ou ação. Consulte as limitações de zonas herdadas.
Para ZONE_FULL e ZONE_BORDER, obtenha o alvo de um handle de zona; script:target(...) isolado não tem zona. Os auxiliares Lua de partículas mantêm coverage em 1.0 por predefinição; não aplicam o 0.3 da ação YAML SPAWN_PARTICLE.
Exemplo: criar e usar um alvo
Exemplo
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 along each axis
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
-- First resolved entity; this does not promise the nearest player.
local first = nearby:first_entity()
if first then
first:show_title("&cRUN!", "&7The boss is targeting you")
end
end
}
Métodos do handle de zona
| Método | Notas |
|---|---|
handle:full_target([coverage]) | Devolve um handle de alvo para o volume completo da zona |
handle:border_target([coverage]) | Devolve um handle de alvo para a borda da zona |
handle:full_locations([coverage]) | Devolve localizações no volume completo da zona |
handle:border_locations([coverage]) | Devolve localizações na borda da zona |
handle:full_entities() | Devolve entidades no volume completo da zona |
handle:border_entities() | Devolve entidades na borda da zona |
handle:contains(location[, "full"|"border"]) | Devolve true se a localização está dentro da zona |
handle:watch(callbacks[, mode]) | Observa a zona para eventos de entrada/saída, devolve ID de tarefa |
Chaves de especificação de zona
| Chave | Predefinição | Notas |
|---|---|---|
shape | "CYLINDER" | "SPHERE", "DOME", "CYLINDER", "CUBOID", "CONE", "STATIC_RAY", "ROTATING_RAY", "TRANSLATING_RAY" |
radius | 5 | Esfera, domo, cilindro, cone |
height | 1 | Apenas cilindro; a altura completa da entidade deve caber nas consultas de entidades |
x, y, z | 0 | Dimensões do cuboide; consulte a limitação geométrica de pontos e entidades |
xBorder, yBorder, zBorder | 0 | Dimensões interiores do cuboide |
borderRadius | 1 | Raio interior para esfera, domo, cilindro e cone |
pointRadius | 0.5 | Raio e espaçamento positivos das amostras do raio |
animationDuration | 0 | Duração da animação em ticks para raios animados |
Target | {targetType = "SELF"} | Especificação de alvo central (tabela) -- usa o mesmo formato de especificação de alvo |
Target2 | nenhum | Segundo ponto. Obrigatório para cones e para todas as formas de raio |
FinalTarget, FinalTarget2 | nenhum | Posições finais, apenas para raio em translação |
filter | "PLAYER" | "PLAYER", "ELITE", "LIVING" -- note que aqui são MAIÚSCULAS, ao contrário do context.zones |
ignoresSolidBlocks | true | Apenas raios |
pitchPreRotation, yawPreRotation | 0 | Apenas raio rotativo |
pitchRotation, yawRotation | 0 | Apenas raio rotativo |
As chaves que não se aplicam à shape escolhida são lidas sem qualquer reclamação e depois ignoradas -- um height numa esfera não faz nada.
contains testa um ponto, não a caixa da entidade. watch usa os mesmos callbacks e primeira verificação dos observadores nativos. Cancele o ID devolvido com context.scheduler:cancel_task(id); cancelar não emite callbacks de saída. Uma zona de script estática pode seguir SELF ao resolvê-lo a cada tick; um handle animado conserva as formas. borderRadius é o raio interior, não a espessura da borda. Use alvos completos para raios.
Exemplo: zona com dano e partículas
Exemplo
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)
-- First repeat after 20 ticks, then every 20 ticks.
context.state.zone_task_id = context.scheduler:run_repeating(20, 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
}
Este exemplo causa dano ao mostrar as partículas, sem um atraso de aviso. As repetições começam após 20 ticks e terminam ao sair do combate. O raio interior predefinido de 1 cria uma camada espessa dentro do raio 6, não um anel fino.
Chaves de especificação de vetor relativo
| Chave | Notas |
|---|---|
SourceTarget | Especificação do alvo de origem (tabela) |
DestinationTarget | Especificação do alvo de destino (tabela) |
normalize | Booleano, predefinição false; indica se o vetor é normalizado |
multiplier | Fator aplicado após normalizar, predefinição 1 |
offset | String "x,y,z" separada por vírgulas, predefinição "0,0,0"; não uma tabela vetorial Lua |
Métodos do handle de vetor relativo
| Método | Notas |
|---|---|
handle:resolve() | Devolve a tabela do vetor calculado |
Forneça ambas as especificações de alvo. A resolução usa a primeira localização de cada uma: destino menos origem, normalização opcional, multiplicação e depois offset nos eixos do mundo. Resultados vazios ou mundos diferentes devolvem zero antes do offset; normalizar pontos coincidentes pode produzir um vetor não finito. ACTION_TARGET usa actionLocation, por predefinição a posição do boss capturada ao criar o handle. Não é substituído para cada entidade empurrada. Passe um handle de zona como terceiro argumento se os alvos do vetor precisarem dessa zona.
Exemplo: empurrar alvos com um vetor relativo
Exemplo
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
}
Formato de especificação de partículas
As especificações de partículas podem ser uma string, uma tabela individual ou um array de tabelas. Como este caminho executa o motor de partículas do EliteScript, as chaves são as do EliteScript documentadas em SPAWN_PARTICLE:
| Chave | Predefinição | Notas |
|---|---|---|
particle | "FLAME" | Nome da partícula (ex. "FLAME", "DUST", "SMOKE") |
amount | 1 | Número de partículas. Com 0, o comportamento direcional depende do tipo de partícula |
x, y, z | 0.01 | Valores de offset/dispersão, ou velocidade quando o amount é 0 |
speed | 0.01 | Velocidade das partículas |
red, green, blue | 255 | Cor para DUST, DUST_COLOR_TRANSITION e partículas que exigem dados Color (0-255); WITCH não usa estes valores |
toRed, toGreen, toBlue | 255 | Cor de destino de transição para DUST_COLOR_TRANSITION |
material | "STONE" | Bloco ou item mostrado por partículas que transportam dados de bloco/item (BLOCK, ITEM, FALLING_DUST, ...) |
relativeVector | nenhum | Uma especificação de vetor relativo. Defini-la força o amount a 0 e substitui x/y/z pela direção resolvida |
O tamanho da poeira é fixo em 1. moveToTarget é lido, mas não move partículas. Tipos de dados não suportados são ignorados com aviso. O auxiliar desloca partículas de zonas e LOCATION / LOCATIONS em +0.5 nos eixos X e Z; as localizações devolvidas pelos handles não recebem esse deslocamento.
Estas chaves do EliteScript não são as mesmas que o context.world:spawn_particle_at_location(loc, spec) aceita. A tabela world tem o seu próprio leitor, mais pequeno e com valores predefinidos diferentes (amount 1, x/y/z/speed 0), sem material e sem relativeVector, e aceita adicionalmente to_red / to_green / to_blue em snake_case. Consulte Mundo e Ambiente.
Para a lista completa de nomes de partículas, consulte a Referência de Enums.
Avisos importantes
- Os handles de utilitários de script estão vinculados ao contexto do evento em que foram criados. Não os armazene em
context.statepara uso numa chamada de hook posterior. context.script:zone(...):watch(...)devolve um ID cancelável comcontext.scheduler:cancel_task().context.zones:watch_zone(...)não devolve nada e é limpo automaticamente com o poder.- Os valores de coverage aplicam-se apenas à resolução baseada em localização, não a consultas de entidades.
- Os enums de alvos, formas e filtros usam os nomes UPPER_SNAKE_CASE do YAML EliteScript (ex.
"SELF","NEARBY_PLAYERS","SPHERE"). Os modos de watch/contains continuam a ser"full"ou"border".
Namespace auxiliar em
O namespace em está disponível globalmente em todos os ficheiros de poder Lua. Fornece construtores convenientes para localizações, vetores e definições de zona.
Construtores de localização e vetor
| Função | Notas |
|---|---|
em.create_location(x, y, z[, world][, yaw][, pitch]) | Devolve uma tabela de localização com um método add(dx, dy, dz) |
em.create_vector(x, y, z) | Devolve uma tabela de vetor |
Helpers de construtor de zonas
A sub-tabela em.zone fornece funções construtoras que devolvem tabelas de definição de zona compatíveis com context.zones. Cada construtor devolve uma tabela com métodos mutadores encadeáveis.
| Função | 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 (dimensões do cuboide) | :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) |
Os construtores de cones e raios guardam length, mas o leitor nativo usa a posição do boss quando falta o destino. Encadeie :set_origin(...) e :set_destination(...); não dependa de length para orientar a forma. Raios em translação também precisam de origin_end, destination_end e um animation_duration positivo na tabela devolvida.
Exemplo
Exemplo
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, boss_loc.world)
-- 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
}
Cada instância de script tem o seu próprio ambiente Lua e namespace em. Estes construtores devolvem tabelas novas; add(...) e os setters de zona modificam a tabela em que são chamados.
Zonas nativas vs. Utilitários de script
Ambos os sistemas trabalham com a mesma geometria de zona subjacente. Aqui está quando usar cada um:
| Caso de uso | Abordagem recomendada |
|---|---|
| Verificação simples de "há algo nesta área?" | Zonas nativas (context.zones) |
| Consulta rápida de entidades com uma forma | Zonas nativas |
NEARBY_PLAYERS, ZONE_FULL com coverage | Utilitários de script (context.script) |
| Zonas animadas (raios rotativos/em translação) | Handles de zona de script para consultas repetidas; observadores nativos também podem conservar uma forma animada |
Handles de zona com métodos watch/contains/entities | Utilitários de script |
| Geração de partículas em localizações de zona | Utilitários de script (spawn_particles) |
| Ações de dano e empurrão vinculadas a alvos | Utilitários de script (damage, push) |
| Vetores relativos para efeitos direcionais | Utilitários de script (relative_vector) |
| Combinar fluxo de controle Lua com segmentação avançada | Utilitários de script |
As duas APIs podem ser usadas no mesmo poder. Escolha conforme os alvos e ciclo de vida necessários: consultas nativas selecionam por predefinição entidades vivas exceto o boss; zonas de script selecionam jogadores.
Próximos passos
- Exemplos e padrões -- poderes funcionais completos que pode estudar e adaptar
- Scripts de NPC -- hooks de proximidade de NPC para comportamentos simples de aproximação/afastamento
- Referência de Enums -- valores válidos para Particle, Sound, Material e outras constantes de string
