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. Du erstellst eine Zonendefinition als einfache Lua-Tabelle und fragst 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ähle den, der zur Komplexität deiner Fähigkeit passt.


Native Zonen: context.zones​

Native Zonen akzeptieren einfache Lua-Tabellen. Jede Abfrage erzeugt eine neue Form; ein Watcher behält eine Form. Wiederholte Abfragen eines animierten Strahls starten daher die Animation neu, statt den aktuellen Zustand des Watchers zu lesen. Verwende ein Script-Zonen-Handle, wenn mehrere Operationen dieselbe animierte Form benötigen.

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 dauerhaften Zonen-Watcher, der jeden Tick prüft

Zonendefinitionsfelder​

FeldTypStandardHinweise
kind (oder type)string—"sphere", "dome", "cylinder", "cuboid", "cone", "static_ray", "rotating_ray", "translating_ray"
radiusnumber0Radius für Kugel, Kuppel, Zylinder und Kegel
heightnumber0Zylinderhöhe
originlocationBoss-PositionUrsprung: Zylinderboden, Kegelspitze oder Strahlanfang
destinationlocationBoss-PositionEndpunkt für Strahlen und Kegel
x, y, znumber0Quaderabmessungen; siehe unterschiedliche Punkt- und Entitätsgeometrie
thickness / point_radius / pointRadiusnumber0.5Radius und Abstand der Strahlproben; muss positiv sein
border_radius / borderRadiusnumber1Innenradius, der aus der äußeren Form ausgeschlossen wird
x_border, y_border, z_bordernumber1Innere Quaderabmessungen
animation_durationint0Animationsdauer in Ticks für animierte Strahlen
pitch_pre_rotation, yaw_pre_rotationnumber0Vorrotationswinkel für rotierende Strahlen
pitch_rotation, yaw_rotationnumber0Gesamtdrehung während der Animation; derzeit werden nur positive Schritte angewendet
origin_end, destination_endlocationBoss-PositionEndpositionen für verschobene Strahlen
ignores_solid_blocksbooleantrueOb Strahlen feste Blöcke durchdringen
lengthnumber0Vom Builder gespeichert; eine fehlende destination wird jedoch vor diesem Rückfall durch die Boss-Position ersetzt. Ziel explizit angeben

Die numerischen und booleschen Felder mit Unterstrichen akzeptieren auch camelCase (borderRadius, xBorder, animationDuration, pitchPreRotation, ignoresSolidBlocks). origin_end und destination_end verlangen die Namen mit Unterstrichen. EliteScript-Tabellen vom Typ Target ersetzen keine nativen Positionsfelder.

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.

Endpunkte für Kegel und Strahlen explizit angeben

Fehlt origin oder destination, wird die aktuelle Boss-Position verwendet. Der Positionsleser verhindert derzeit, dass length eine fehlende Zielposition ersetzt. Gib unterschiedliche Endpunkte an:

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

Für die Animation eines verschobenen Strahls sind origin_end, destination_end und eine positive animation_duration nötig. Ein weggelassener Endpunkt bleibt an seiner Ausgangsposition. Eine Dauer von null erzeugt den statischen Anfangsstrahl; eine negative Dauer wird abgelehnt. Das letzte Animationsbild endet genau an den angeforderten Endpunkten.

Alle Endpunkte und abgefragten Positionen sollten in der aktuellen Welt des Bosses liegen: Dort suchen native Entitätsabfragen. In Positionstabellen sind fehlende Koordinaten 0; ohne Weltangabe wird die Boss-Welt verwendet, ein expliziter Weltname muss aber bereits geladen sein. Abmessungen müssen endlich und positiv sein. Punktprüfungen, Partikelproben und Entitätsprüfungen sind nicht austauschbar. Zu den gemeinsamen Geometrieeinschränkungen gehören kugelförmige Entitätsprüfungen für volle Kuppeln, die Prüfung der gesamten Entitätshöhe bei Zylindern und unterschiedliche Quadergrenzen.

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)

filter ignoriert Groß-/Kleinschreibung; unbekannte Werte verwenden living. mobs umfasst lebende Nichtspieler, einschließlich Elites. Der Boss wird ausgeschlossen, Spieler werden aber nicht nach Spielmodus gefiltert. mode erkennt border unabhängig von der Schreibweise; andere Werte verwenden full. Coverage wählt zufällig Positionen aus, keine Entitäten, und begrenzt keine Watcher-Mitglieder. Verwende bei Strahlen full: Randpositionen werden nicht unterstützt und können Positionsabfragen fehlschlagen lassen.

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 rufen ihre eigenen on_enter-/on_leave-Callbacks auf, nicht die übergeordneten Hooks on_zone_enter / on_zone_leave der Fähigkeit
  • Watcher werden automatisch bereinigt, wenn der Boss entfernt wird
  • Ein nativer Watcher baut seine Form einmal auf. Ihr Zentrum folgt dem Boss nicht; Änderungen der ursprünglichen Tabelle bewegen einen bestehenden Watcher nicht. Verwende neue Abfragen oder eine Script-Zone mit verfolgtem Ziel für einen beweglichen Bereich.
  • Jeder Watcher läuft jeden Tick, daher sollte die Callback-Logik leichtgewichtig sein
  • Die Boss-Entität selbst wird von Zonenabfragen ausgeschlossen

Die erste Prüfung erfolgt einen Tick später; bereits enthaltene Entitäten lösen on_enter aus. Abbruch oder Bereinigung sendet kein on_leave für verbleibende Mitglieder. In diesem Beispiel bleibt die Kugel am Spawnort. Die Verlangsamung hält ab Eintritt 40 Ticks; Verbleiben erneuert sie nicht und Verlassen entfernt sie nicht vorzeitig.


Script-Utilities: context.script​

Die Script-Utilities bieten Zielauflösung, Zonen-Handles, relative Vektoren, Partikel und Kampfaktionen.

context.script verwendet die EliteScript-Engine

Die Spezifikationstabelle wird in eine Java-Map umgewandelt und an die Ziel-, Zonen-, Vektor- und Partikelklassen der YAML-EliteScripts übergeben.

Das bedeutet:

  • Die Tabellen verwenden die Leser aus EliteScript-Ziele, EliteScript-Zonen und Relative EliteScript-Vektoren, einschließlich ihrer Einschränkungen. Ein akzeptiertes Feld garantiert nicht, dass das Lua-Handle den nötigen Aktionsablauf oder vererbten Kontext hat.
  • Enum-Werte sind exakt UPPER_SNAKE_CASE ("NEARBY_PLAYERS", "SPHERE", "ZONE_FULL"), wie in YAML.
  • Nutze die kanonischen YAML-Namen Target, Target2, targetType, borderRadius. Die internen Leser ignorieren Groß-/Kleinschreibung.
  • Ungültige Werte können Warnungen, Ersatzwerte oder fehlende Felder mit späteren Fehlern erzeugen. Eine akzeptierte Tabelle validiert nicht die gesamte Operation.

context.zones besitzt einen eigenen Tabellenleser mit kleingeschriebenen kind-Namen, verwendet aber dieselben Geometrieklassen. Gib nichtleere Tabellen mit benannten Feldern an: Ein leeres Lua-{} wird zu einer Java-Liste, weshalb selbst script:target({}) scheitert. Nutze script:target({targetType = "SELF"}).

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

damage, push, set_facing und spawn_particles benötigen ein Ziel-Handle, kein Entitätsarray, und liefern keinen Rückgabewert. Sie wenden keine YAML-Aktionsbedingungen, Wartezeiten oder Filter an. damage übergibt den Betrag an Bukkit mit dem Boss als Angreifer; der optionale Multiplikator gilt für den Spieler-Kampfpfad, und der endgültige Gesundheitsverlust hängt von der Kampfverarbeitung ab. push ermittelt Ziele und einen Vektor sofort und wendet denselben Vektor im nächsten Tick auf alle Ziele an. Er ersetzt die Geschwindigkeit, außer bei additive = true: Dann wird er zur Geschwindigkeit dieses Ticks addiert. set_facing richtet alle Ziele sofort in dieselbe Richtung aus. Prüfe Richtungen auf Null und nichtendliche Werte.

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

Jede Methode löst erneut auf; first_* liest keinen gemeinsamen Schnappschuss und garantiert nicht das nächste Ergebnis. DIRECT_TARGET ist das vom Ereignis erfasste Ziel, nicht das aktuelle Kampfziel des Bosses, und wählt nichts aus, wenn das Ereignis keines liefert.

Ziel-Spezifikationsschlüssel​

SchlüsselStandardHinweise
targetType"SELF"Jeder EliteScript-Zieltyp
range20Halbe Breite je Achse des Suchquaders; keine Sortierung nach Entfernung
coverage1.00.0 bis 1.0; nur für Zonenziele. Werte unter 1.0 werden bei anderen Typen mit Warnung auf 1.0 gesetzt
offset0,0,0Kommagetrennter String "x,y,z"; keine Lua-Vektortabelle
relativeOffsetkeinerRelative Vektorspezifikation; Quell- und Zielpunkt bestimmen die Richtung
locationkeinerSerialisierter String "world,x,y,z,yaw,pitch" für "LOCATION"
locationskeineArray serialisierter Positionsstrings für "LOCATIONS"
tracktrueOb bewegliche Ziele erneut aufgelöst werden

Lua-Handles führen den Ziel-Cache-Schritt von YAML-Aktionen nicht aus. track = false friert daher statische Lua-Ziele oder Zonen nicht ein. Statische Zonen ermitteln ihre Ursprünge bei jeder Abfrage; animierte Handles speichern ihre Formen bei der Erstellung. Für feste Bereiche verwendest du LOCATION mit expliziten Koordinaten oder eine native Zone mit erfasstem origin. offset und relativeOffset verschieben jede Position, die ein Handle auflöst, einschließlich LOCATION, LOCATIONS, SELF_SPAWN, entitätsbasierter Ziele und abgetasteter Zonenpositionen. Die von entities() zurückgegebenen Entitäten verschieben sie nicht, und LANDING_LOCATION sowie INHERIT_SCRIPT_TARGET ignorieren sie. full_target() und border_target() eines Zonen-Handles nehmen keinen Offset an; Offsets gehören daher in die Spezifikationen Target und Target2 der Zone. Siehe gemeinsame Attribute.

Der Parser akzeptiert alle 17 Namen: 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. Eigenständige Lua-Handles stellen keine geerbten Aktionsdaten und keine Landeposition bereit. Vermeide dort INHERIT_* und LANDING_LOCATION: Die Auflösung kann scheitern. ACTION_TARGET benötigt einen passenden Vektor-/Aktionskontext. Siehe Einschränkungen geerbter Zonen.

Beziehe ZONE_FULL- und ZONE_BORDER-Ziele aus einem Zonen-Handle; ein eigenständiges script:target(...) hat keine Zone. Lua-Partikelhelfer behalten die Standard-Coverage 1.0; der YAML-Standard 0.3 von SPAWN_PARTICLE wird nicht angewendet.

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

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üsselStandardHinweise
shape"CYLINDER""SPHERE", "DOME", "CYLINDER", "CUBOID", "CONE", "STATIC_RAY", "ROTATING_RAY", "TRANSLATING_RAY"
radius5Kugel, Kuppel, Zylinder, Kegel
height1Nur Zylinder; für Entitätsabfragen muss die gesamte Entitätshöhe hineinpassen
x, y, z0Quaderabmessungen; siehe unterschiedliche Punkt- und Entitätsgeometrie
xBorder, yBorder, zBorder0Innere Quaderabmessungen
borderRadius1Innenradius für Kugel, Kuppel, Zylinder und Kegel
pointRadius0.5Positiver Radius und Abstand der Strahlproben
animationDuration0Animationsdauer in Ticks für animierte Strahlen
Target{targetType = "SELF"}Ursprung als Zielspezifikationstabelle im selben Format
Target2keinesZweiter Punkt; erforderlich für Kegel und alle Strahlformen
FinalTarget, FinalTarget2keineEndpositionen, nur für verschobene Strahlen
filter"PLAYER""PLAYER", "ELITE", "LIVING"; anders als bei context.zones hier großgeschrieben
ignoresSolidBlockstrueNur Strahlen
pitchPreRotation, yawPreRotation0Nur rotierende Strahlen
pitchRotation, yawRotation0Nur rotierende Strahlen

Felder, die nicht zur gewählten shape passen, werden gelesen und dann ignoriert; height verändert beispielsweise keine Kugel.

contains prüft einen Punkt, nicht die Entitätsbox. watch verwendet dieselben Callbacks und dieselbe erste Prüfung wie native Watcher. Brich die zurückgegebene ID mit context.scheduler:cancel_task(id) ab; dabei entstehen keine Leave-Callbacks. Eine statische Script-Zone kann SELF folgen, da es jeden Tick neu aufgelöst wird; animierte Handles behalten ihre Formen. borderRadius ist der Innenradius, nicht die Randdicke. Verwende volle Ziele für Strahlen.

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)

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

Das Beispiel verursacht Schaden sofort beim Anzeigen der Partikel, ohne Vorwarnzeit. Wiederholungen beginnen nach 20 Ticks und enden beim Verlassen des Kampfes. Der Standard-Innenradius 1 erzeugt innerhalb von Radius 6 eine dicke Schale, keinen schmalen Ring.

Schlüssel für relative Vektoren​

SchlüsselHinweise
SourceTargetQuellziel-Spezifikation (Tabelle)
DestinationTargetZielziel-Spezifikation (Tabelle)
normalizeBoolescher Wert, Standard false; ob der Vektor normalisiert wird
multiplierFaktor nach der Normalisierung, Standard 1
offsetKommagetrennter String "x,y,z", Standard "0,0,0"; keine Lua-Vektortabelle

Methoden für relative Vektor-Handles​

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

Gib beide Zielspezifikationen an. Die erste Position jeder Seite wird verwendet: Ziel minus Quelle, optionale Normalisierung, Multiplikation, dann Offset entlang der Weltachsen. Leere Ergebnisse oder verschiedene Welten ergeben null vor Anwendung des Offsets; Normalisierung identischer Punkte kann einen nichtendlichen Vektor erzeugen. ACTION_TARGET verwendet actionLocation, standardmäßig die bei Handle-Erstellung erfasste Boss-Position. Sie wird nicht für jede gestoßene Entität ersetzt. Übergib als drittes Argument ein Zonen-Handle, wenn die Vektorziele diese Zone benötigen.

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 Strings, einzelne Tabellen oder Arrays von Tabellen sein. Dieser Pfad verwendet die EliteScript-Partikelengine mit den unter SPAWN_PARTICLE dokumentierten Schlüsseln:

SchlüsselStandardHinweise
particle"FLAME"Partikelname, z. B. "FLAME", "DUST", "SMOKE"
amount1Partikelanzahl; bei 0 hängt das Richtungsverhalten vom Partikeltyp ab
x, y, z0.01Streuung/Offset oder Geschwindigkeit bei amount = 0
speed0.01Partikelgeschwindigkeit
red, green, blue255Farbe für DUST, DUST_COLOR_TRANSITION und Partikel mit Color-Daten (0–255); WITCH verwendet diese Werte nicht
toRed, toGreen, toBlue255Zielfarbe für DUST_COLOR_TRANSITION
material"STONE"Block/Item für Partikel mit entsprechenden Daten (BLOCK, ITEM, FALLING_DUST, ...)
relativeVectorkeinerRelative Vektorspezifikation; erzwingt amount = 0 und ersetzt x/y/z durch die aufgelöste Richtung

Die Staubgröße ist fest 1. moveToTarget wird gelesen, bewegt aber keine Partikel. Nicht unterstützte Partikeldatentypen werden mit Warnung übersprungen. Bei Zonen sowie LOCATION / LOCATIONS verschiebt der Helfer die Partikelpositionen auf X und Z um +0.5; die von Handles gelieferten Positionen bleiben unverschoben.

Zwei verschiedene Sätze von Partikelfeldern

Diese EliteScript-Felder unterscheiden sich von context.world:spawn_particle_at_location(loc, spec). Die World-Tabelle hat einen kleineren Leser mit anderen Standards (amount 1, x/y/z/speed 0), ohne material oder relativeVector, und akzeptiert zusätzlich to_red / to_green / to_blue. Siehe Welt und Umgebung.

Die vollständige Liste der Partikelnamen findest du in der Enum-Referenz.

Wichtige Hinweise​

  • Script-Utility-Handles sind an den Ereigniskontext gebunden, in dem sie erstellt wurden. Speichere sie nicht in context.state zur Verwendung in einem späteren Hook-Aufruf.
  • context.script:zone(...):watch(...) liefert eine mit context.scheduler:cancel_task() abbrechbare Task-ID. context.zones:watch_zone(...) liefert nichts und wird automatisch mit der Fähigkeit bereinigt.
  • Coverage-Werte gelten nur für positionsbasierte Auflösung, nicht für Entitätsabfragen.
  • Ziel-, Form- und Filter-Enums verwenden dieselben UPPER_SNAKE_CASE-Namen wie EliteScript-YAML (z. B. "SELF", "NEARBY_PLAYERS", "SPHERE"). Watch-/Contains-Modi bleiben "full" oder "border".

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 (Quaderabmessungen):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)
Beide Endpunkte setzen

Kegel- und Strahl-Builder speichern length, aber der native Positionsleser verwendet bei fehlendem Ziel die Boss-Position. Verkette :set_origin(...) und :set_destination(...); verlass dich für die Ausrichtung nicht auf length. Verschobene Strahlen benötigen außerdem origin_end, destination_end und eine positive animation_duration in der zurückgegebenen Tabelle.

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

Jede Script-Instanz besitzt eine eigene Lua-Umgebung und einen eigenen em-Namensraum. Die Konstruktoren liefern neue Tabellen; add(...) und die Zonen-Setter verändern die Tabelle, auf der sie aufgerufen werden.


Native Zonen vs. Script-Utilities​

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

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/verschobene Strahlen)Script-Zonen-Handles für wiederholte Abfragen; native Watcher können ebenfalls eine animierte Form behalten
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

Beide APIs können in einer Fähigkeit verwendet werden. Entscheidend sind Ziele und Lebenszyklus: Native Abfragen wählen standardmäßig lebende Entitäten außer dem Boss, Script-Zonen dagegen Spieler.


Nächste Schritte​

  • Beispiele & Muster -- vollständige funktionierende Fähigkeiten zum Studieren und Anpassen
  • NPC-Scripts -- NPC-Nähe-Hooks für einfaches Betreten und Verlassen
  • Enum-Referenz -- gültige Werte für Particle, Sound, Material und andere String-Konstanten