Lua-Scripting: Zonen & Zielerfassung

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
| Methode | Hinweise |
|---|
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
| Feld | Typ | Hinweise |
|---|
kind | string | "sphere", "dome", "cylinder", "cuboid", "cone", "static_ray", "rotating_ray", "translating_ray" |
radius | number | Zonenradius (sphere, dome, cylinder, cone) |
height | number | Zylinderhöhe |
origin | location | Mittelpunktposition (standardmäßig Boss-Position, wenn weggelassen) |
destination | location | Endpunkt für Strahlen und Kegel |
x, y, z | number | Halbe Quader-Ausdehnungen |
length | number | Länge für Kegel und Strahlen |
thickness / point_radius | number | Strahldicke |
border_radius | number | Randbreite (Standard 1) |
x_border, y_border, z_border | number | Quader-Randbreiten (Standard 1) |
animation_duration | int | Animationslänge in Ticks für animierte Strahlen |
pitch_pre_rotation, yaw_pre_rotation | number | Vorrotationswinkel (rotierender Strahl) |
pitch_rotation, yaw_rotation | number | Pro-Tick-Rotationswinkel (rotierender Strahl) |
origin_end, destination_end | location | Endpositionen für translierenden Strahl |
ignores_solid_blocks | boolean | Ob Strahlen durch solide Blöcke hindurchgehen (Standard true) |
Abfrageoptionen
| Schlüssel | Hinweise |
|---|
filter | "player" / "players", "elite" / "elites", "mob" / "mobs", "living" (Standard) |
mode | "full" (Standard) oder "border" |
coverage | 0.0 bis 1.0 -- Anteil der abgetasteten Positionen (Standard 1.0) |
Watch-Callbacks
| Schlüssel | Hinweise |
|---|
on_enter | function(entity) -- wird aufgerufen, wenn eine Entität die Zone betritt |
on_leave | function(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.
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
| Methode | Hinweise |
|---|
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
| Methode | Hinweise |
|---|
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üssel | Hinweise |
|---|
targetType | "SELF", "DIRECT_TARGET", "NEARBY_PLAYERS", "NEARBY_MOBS", "NEARBY_ELITES", "ZONE_FULL", "ZONE_BORDER", "ALL_PLAYERS", "WORLD_PLAYERS", "SELF_SPAWN", "LOCATION" |
range | Reichweite für Nearby-Zieltypen |
coverage | 0.0 bis 1.0 für Zonenziele |
offset | "x,y,z" String oder { x = n, y = n, z = n } Tabelle |
track | Ob 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
| Methode | Hinweise |
|---|
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üssel | Hinweise |
|---|
shape | "SPHERE", "DOME", "CYLINDER", "CUBOID", "CONE", "STATIC_RAY", "ROTATING_RAY", "TRANSLATING_RAY" |
radius | Zonenradius |
height | Zylinderhöhe |
x, y, z | Halbe Quader-Ausdehnungen |
borderRadius | Randbreite |
pointRadius | Strahldicke |
animationDuration | Animationslänge in Ticks für animierte Strahlen |
Target | Ziel-Spezifikation für Zentrum (Tabelle) -- verwendet das gleiche Ziel-Spezifikationsformat |
Target2 | Zweiter Punkt für Strahlen und Kegel |
filter | Entitätsfilter |
ignoresSolidBlocks | boolean |
pitchPreRotation, yawPreRotation | Vorrotationswinkel |
pitchRotation, yawRotation | Pro-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
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
}
Schlüssel für relative Vektoren
| Schlüssel | Hinweise |
|---|
SourceTarget | Quellziel-Spezifikation (Tabelle) |
DestinationTarget | Zielziel-Spezifikation (Tabelle) |
normalize | boolean -- ob der resultierende Vektor normalisiert werden soll |
multiplier | Skalierungsfaktor, 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
| Methode | Hinweise |
|---|
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
}
Partikelspezifikationen können ein String, eine einzelne Tabelle oder ein Array von Tabellen sein:
| Schlüssel | Hinweise |
|---|
particle | Partikelname (z.B. "FLAME", "DUST", "SMOKE") |
amount | Anzahl der Partikel |
x, y, z | Offset-/Streuungswerte |
speed | Partikelgeschwindigkeit |
red, green, blue | Farbe für DUST / DUST_COLOR_TRANSITION (0-255) |
toRed, toGreen, toBlue | Zielfarbe 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
| Funktion | Hinweise |
|---|
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.
| Funktion | Parameter | Mutatoren |
|---|
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
}
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:
| Anwendungsfall | Empfohlener Ansatz |
|---|
| Einfache „Ist irgendetwas in diesem Bereich?"-Prüfung | Native Zonen (context.zones) |
| Schnelle Entitätsabfrage mit einer Form | Native Zonen |
NEARBY_PLAYERS, ZONE_FULL mit Coverage | Script-Utilities (context.script) |
| Animierte Zonen (rotierende/translierende Strahlen) | Beides -- native Zonen unterstützen diese Formen ebenfalls |
Zonen-Handles mit watch/contains/entities-Methoden | Script-Utilities |
| Partikel-Spawning an Zonenpositionen | Script-Utilities (spawn_particles) |
| Schadens- und Push-Aktionen mit Zielerfassung | Script-Utilities (damage, push) |
| Relative Vektoren für Richtungseffekte | Script-Utilities (relative_vector) |
| Kombination von Lua-Kontrollfluss mit umfangreicher Zielerfassung | Script-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