Zum Hauptinhalt springen

Lua-Scripting: Zonen & Zielerfassung

webapp_banner.jpg

Die Lua-Funktionen von EliteMobs bieten zwei sich ergänzende Ansätze zur Definition räumlicher Bereiche und zur Zielauflösung:

  • Native Zonen (context.zones) -- einfach und direkt. Sie erstellen eine Zonendefinition als einfache Lua-Tabelle und fragen sie nach Entitäten oder Positionen ab. Am besten geeignet für einfache „Ist irgendetwas in diesem Bereich?"-Prüfungen.
  • Script-Utilities (context.script) -- umfangreichere Zielerfassung, Zonen-Handles mit watch/contains/entities-Methoden, Partikel-Spawning, Schaden und Push-Aktionen. Verwendet die gleichen Feldnamen wie EliteScript-Zonen und EliteScript-Ziele zur besseren Vertrautheit.

Beide Ansätze sind native Lua-APIs. Wählen Sie den, der zur Komplexität Ihrer Fähigkeit passt.


Native Zonen: context.zones

Native Zonen ermöglichen es Ihnen, Zonen als einfache Lua-Tabellen zu definieren und sie direkt abzufragen. Keine Handles, keine zusätzliche Abstraktion -- einfach eine Tabelle, die eine Form beschreibt, und ein Methodenaufruf, um sie abzufragen.

Methoden

MethodeHinweise
zones:get_entities_in_zone(zoneDef, options)Gibt ein Array von Entity-Wrappern innerhalb der Zone zurück
zones:get_locations_in_zone(zoneDef, options)Gibt ein Array von Positions-Tabellen innerhalb der Zone zurück
zones:zone_contains(zoneDef, location[, "full"|"border"])Gibt true zurück, wenn sich die Position innerhalb der Zone befindet
zones:watch_zone(zoneDef, callbacks, options)Registriert einen persistenten Zonen-Watcher, der pro Tick feuert

Zonendefinitionsfelder

FeldTypHinweise
kindstring"sphere", "dome", "cylinder", "cuboid", "cone", "static_ray", "rotating_ray", "translating_ray"
radiusnumberZonenradius (sphere, dome, cylinder, cone)
heightnumberZylinderhöhe
originlocationMittelpunktposition (standardmäßig Boss-Position, wenn weggelassen)
destinationlocationEndpunkt für Strahlen und Kegel
x, y, znumberHalbe Quader-Ausdehnungen
lengthnumberWird nur gelesen, wenn destination fehlt; siehe unten.
thickness / point_radiusnumberStrahldicke
border_radiusnumberRandbreite (Standard 1)
x_border, y_border, z_bordernumberQuader-Randbreiten (Standard 1)
animation_durationintAnimationslänge in Ticks für animierte Strahlen
pitch_pre_rotation, yaw_pre_rotationnumberVorrotationswinkel (rotierender Strahl)
pitch_rotation, yaw_rotationnumberPro-Tick-Rotationswinkel (rotierender Strahl)
origin_end, destination_endlocationEndpositionen für translierenden Strahl
ignores_solid_blocksbooleanOb Strahlen durch solide Blöcke hindurchgehen (Standard true)

Alle mehrteiligen Feldnamen akzeptieren auch camelCase (borderRadius, xBorder, animationDuration, pitchPreRotation, ignoresSolidBlocks, ...).

Bei kind ist Groß-/Kleinschreibung relevant

kind wird exakt verglichen und muss kleingeschrieben sein. "SPHERE" oder "Sphere" passen zu keiner Form; Abfragen liefern ohne Konsolenwarnung eine leere Liste.

Kegel und Strahlen benötigen destination oder length

Fehlt origin, wird die Position des Bosses verwendet. Fehlt destination, wird origin um length Blöcke entlang der in der origin-Position gespeicherten Blickrichtung verschoben.

Damit gibt es zwei Möglichkeiten, einen Kegel oder Strahl zu definieren:

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

Die Kurzform mit length ist nur sinnvoll ausgerichtet, wenn origin Yaw/Pitch enthält. Die API liefert diese Werte mit get_location(), get_eye_location() und current_location. Eine selbst geschriebene Tabelle { x = .., y = .., z = .. } enthält sie nicht; auch em.create_location(x, y, z) benötigt dazu die optionalen Argumente yaw und pitch.

Fehlen beide Angaben, ist length standardmäßig 0. Die Form hat dann keine Länge und alle Abfragen liefern ohne Warnung keine Ergebnisse.

Abfrageoptionen

SchlüsselHinweise
filter"player" / "players", "elite" / "elites", "mob" / "mobs", "living" (Standard)
mode"full" (Standard) oder "border"
coverage0.0 bis 1.0 -- Anteil der abgetasteten Positionen (Standard 1.0)

Watch-Callbacks

SchlüsselHinweise
on_enterfunction(entity) -- wird aufgerufen, wenn eine Entität die Zone betritt
on_leavefunction(entity) -- wird aufgerufen, wenn eine Entität die Zone verlässt

Beispiel: Einfache Kugelabfrage

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

Beispiel: Zonenüberwachung mit Betreten/Verlassen

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

Watcher-Hinweise:

  • Watcher-Callbacks erhalten direkt einen einzelnen Entity-Wrapper, nicht über context.event
  • Watcher werden automatisch bereinigt, wenn der Boss entfernt wird
  • Jeder Watcher läuft jeden Tick, daher sollte die Callback-Logik leichtgewichtig sein
  • Die Boss-Entität selbst wird von Zonenabfragen ausgeschlossen

Script-Utilities: context.script

Die Script-Utilities bieten Zielauflösung, Zonen-Handles, relative Vektoren, Partikel-Spawning und Kampfaktionen. Sie verwenden die gleichen Feldnamen wie EliteScript-Zonen und EliteScript-Ziele zur besseren Vertrautheit -- die Enum-Namen (wie "NEARBY_PLAYERS", "SPHERE", "ZONE_FULL") sind identisch, damit Autoren, die bereits mit EliteScript vertraut sind, dieses Wissen direkt übertragen können.

Info

context.script ist eine native Lua-API. Es ist keine Brücke zu YAML oder zur EliteScript-Laufzeit. Es verwendet lediglich die gleichen Namenskonventionen, damit Sie keinen zweiten Satz von Enum-Namen lernen müssen.

Methoden

MethodeHinweise
script:target(spec)Erstellt ein Ziel-Handle aus einer Ziel-Spezifikationstabelle
script:zone(spec)Erstellt ein Zonen-Handle aus einer Zonen-Spezifikationstabelle
script:relative_vector(spec[, actionLocation][, zoneHandle])Erstellt ein Handle für einen relativen Vektor
script:damage(targetHandle, amount[, multiplier])Fügt aufgelösten Zielen Schaden zu
script:push(targetHandle, vectorOrHandle[, additive])Stößt aufgelöste Ziele
script:set_facing(targetHandle, vectorOrHandle)Setzt die Blickrichtung für Ziele
script:spawn_particles(targetHandle, particleSpec)Spawnt Partikel an aufgelösten Zielpositionen

Ziel-Handle-Methoden

MethodeHinweise
handle:entities()Gibt Array von Entity-Wrappern zurück
handle:locations()Gibt Array von Positions-Tabellen zurück
handle:first_entity()Gibt erste Entität oder nil zurück
handle:first_location()Gibt erste Position oder nil zurück

Ziel-Spezifikationsschlüssel

SchlüsselHinweise
targetType"SELF", "DIRECT_TARGET", "NEARBY_PLAYERS", "NEARBY_MOBS", "NEARBY_ELITES", "ZONE_FULL", "ZONE_BORDER", "ALL_PLAYERS", "WORLD_PLAYERS", "SELF_SPAWN", "LOCATION"
rangeReichweite für Nearby-Zieltypen
coverage0.0 bis 1.0 für Zonenziele
offset"x,y,z" String oder { x = n, y = n, z = n } Tabelle
trackOb sich bewegende Ziele neu aufgelöst werden sollen

Beispiel: Ein Ziel erstellen und verwenden

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

Zonen-Handle-Methoden

MethodeHinweise
handle:full_target([coverage])Gibt ein Ziel-Handle für das gesamte Zonenvolumen zurück
handle:border_target([coverage])Gibt ein Ziel-Handle für den Zonenrand zurück
handle:full_locations([coverage])Gibt Positionen im gesamten Zonenvolumen zurück
handle:border_locations([coverage])Gibt Positionen am Zonenrand zurück
handle:full_entities()Gibt Entitäten im gesamten Zonenvolumen zurück
handle:border_entities()Gibt Entitäten am Zonenrand zurück
handle:contains(location[, "full"|"border"])Gibt true zurück, wenn sich die Position innerhalb der Zone befindet
handle:watch(callbacks[, mode])Überwacht Zone auf Betreten/Verlassen-Ereignisse, gibt Task-ID zurück

Zonen-Spezifikationsschlüssel

SchlüsselHinweise
shape"SPHERE", "DOME", "CYLINDER", "CUBOID", "CONE", "STATIC_RAY", "ROTATING_RAY", "TRANSLATING_RAY"
radiusZonenradius
heightZylinderhöhe
x, y, zHalbe Quader-Ausdehnungen
borderRadiusRandbreite
pointRadiusStrahldicke
animationDurationAnimationslänge in Ticks für animierte Strahlen
TargetZiel-Spezifikation für Zentrum (Tabelle) -- verwendet das gleiche Ziel-Spezifikationsformat
Target2Zweiter Punkt für Strahlen und Kegel
filterEntitätsfilter
ignoresSolidBlocksboolean
pitchPreRotation, yawPreRotationVorrotationswinkel
pitchRotation, yawRotationPro-Tick-Rotationswinkel

Beispiel: Zone mit Schaden und Partikeln

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

Schlüssel für relative Vektoren

SchlüsselHinweise
SourceTargetQuellziel-Spezifikation (Tabelle)
DestinationTargetZielziel-Spezifikation (Tabelle)
normalizeboolean -- ob der resultierende Vektor normalisiert werden soll
multiplierSkalierungsfaktor, der nach der Normalisierung angewendet wird
offset"x,y,z" String oder { x = n, y = n, z = n } Tabelle

Methoden für relative Vektor-Handles

MethodeHinweise
handle:resolve()Gibt die berechnete Vektortabelle zurück

Beispiel: Ziele mit einem relativen Vektor stoßen

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

Partikelspezifikationsformat

Partikelspezifikationen können ein String, eine einzelne Tabelle oder ein Array von Tabellen sein:

SchlüsselHinweise
particlePartikelname (z.B. "FLAME", "DUST", "SMOKE")
amountAnzahl der Partikel
x, y, zOffset-/Streuungswerte
speedPartikelgeschwindigkeit
red, green, blueFarbe für DUST / DUST_COLOR_TRANSITION (0-255)
toRed, toGreen, toBlueZielfarbe für Übergang bei DUST_COLOR_TRANSITION

Die vollständige Liste der Partikelnamen finden Sie in der Enum-Referenz.

Wichtige Hinweise

  • Script-Utility-Handles sind an den Ereigniskontext gebunden, in dem sie erstellt wurden. Speichern Sie sie nicht in context.state zur Verwendung in einem späteren Hook-Aufruf.
  • Zone watch() gibt eine Task-ID zurück, die Sie mit context.scheduler:cancel_task() abbrechen können.
  • Coverage-Werte gelten nur für positionsbasierte Auflösung, nicht für Entitätsabfragen.
  • Alle String-Werte verwenden die gleichen UPPER_SNAKE_CASE-Enum-Namen wie EliteScript YAML (z.B. "SELF", "NEARBY_PLAYERS", "SPHERE").

em-Hilfsnamensraum

Der em-Namensraum ist global in allen Lua-Power-Dateien verfügbar. Er bietet praktische Konstruktoren für Positionen, Vektoren und Zonendefinitionen.

Positions- und Vektorkonstruktoren

FunktionHinweise
em.create_location(x, y, z[, world][, yaw][, pitch])Gibt eine Positionstabelle mit einer add(dx, dy, dz)-Methode zurück
em.create_vector(x, y, z)Gibt eine Vektortabelle zurück

Zonen-Builder-Helfer

Die em.zone-Untertabelle bietet Builder-Funktionen, die Zonendefinitions-Tabellen zurückgeben, die mit context.zones kompatibel sind. Jeder Builder gibt eine Tabelle mit verkettbaren Mutator-Methoden zurück.

FunktionParameterMutatoren
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 (halbe Ausdehnungen):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)

Beispiel

Beispiel
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

Der em-Namensraum ist nicht instanzbezogen -- alle Lua-Power-Instanzen teilen sich die gleichen em-Hilfsfunktionen. Die Funktionen sind reine Konstruktoren und tragen keinen Zustand.


Native Zonen vs. Script-Utilities

Beide Systeme arbeiten mit der gleichen zugrunde liegenden Zonengeometrie. Hier ist, wann Sie welches verwenden sollten:

AnwendungsfallEmpfohlener Ansatz
Einfache „Ist irgendetwas in diesem Bereich?"-PrüfungNative Zonen (context.zones)
Schnelle Entitätsabfrage mit einer FormNative Zonen
NEARBY_PLAYERS, ZONE_FULL mit CoverageScript-Utilities (context.script)
Animierte Zonen (rotierende/translierende Strahlen)Beides -- native Zonen unterstützen diese Formen ebenfalls
Zonen-Handles mit watch/contains/entities-MethodenScript-Utilities
Partikel-Spawning an ZonenpositionenScript-Utilities (spawn_particles)
Schadens- und Push-Aktionen mit ZielerfassungScript-Utilities (damage, push)
Relative Vektoren für RichtungseffekteScript-Utilities (relative_vector)
Kombination von Lua-Kontrollfluss mit umfangreicher ZielerfassungScript-Utilities

In der Praxis verwenden viele Fähigkeiten beides. Native Zonen eignen sich hervorragend für die anfängliche „Sind Spieler in der Nähe?"-Prüfung in einem Cooldown-Guard, während Script-Utilities die komplexe Angriffslogik danach übernehmen.


Nächste Schritte

  • Beispiele & Muster -- vollständige funktionierende Fähigkeiten zum Studieren und Anpassen
  • API-Referenz -- die vollständige context.*-Methodenreferenz
  • Enum-Referenz -- gültige Werte für Particle, Sound, Material und andere String-Konstanten