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. 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
| 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 dauerhaften Zonen-Watcher, der jeden Tick prüft |
Zonendefinitionsfelder
| Feld | Typ | Standard | Hinweise |
|---|---|---|---|
kind (oder type) | string | — | "sphere", "dome", "cylinder", "cuboid", "cone", "static_ray", "rotating_ray", "translating_ray" |
radius | number | 0 | Radius für Kugel, Kuppel, Zylinder und Kegel |
height | number | 0 | Zylinderhöhe |
origin | location | Boss-Position | Ursprung: Zylinderboden, Kegelspitze oder Strahlanfang |
destination | location | Boss-Position | Endpunkt für Strahlen und Kegel |
x, y, z | number | 0 | Quaderabmessungen; siehe unterschiedliche Punkt- und Entitätsgeometrie |
thickness / point_radius / pointRadius | number | 0.5 | Radius und Abstand der Strahlproben; muss positiv sein |
border_radius / borderRadius | number | 1 | Innenradius, der aus der äußeren Form ausgeschlossen wird |
x_border, y_border, z_border | number | 1 | Innere Quaderabmessungen |
animation_duration | int | 0 | Animationsdauer in Ticks für animierte Strahlen |
pitch_pre_rotation, yaw_pre_rotation | number | 0 | Vorrotationswinkel für rotierende Strahlen |
pitch_rotation, yaw_rotation | number | 0 | Gesamtdrehung während der Animation; derzeit werden nur positive Schritte angewendet |
origin_end, destination_end | location | Boss-Position | Endpositionen für verschobene Strahlen |
ignores_solid_blocks | boolean | true | Ob Strahlen feste Blöcke durchdringen |
length | number | 0 | Vom 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.
kind ist Groß-/Kleinschreibung relevantkind wird exakt verglichen und muss kleingeschrieben sein. "SPHERE" oder "Sphere" passen zu keiner Form; Abfragen liefern ohne Konsolenwarnung eine leere Liste.
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ü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) |
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ü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 rufen ihre eigenen
on_enter-/on_leave-Callbacks auf, nicht die übergeordneten Hookson_zone_enter/on_zone_leaveder 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-EngineDie 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
| 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 |
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
| 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 |
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üssel | Standard | Hinweise |
|---|---|---|
targetType | "SELF" | Jeder EliteScript-Zieltyp |
range | 20 | Halbe Breite je Achse des Suchquaders; keine Sortierung nach Entfernung |
coverage | 1.0 | 0.0 bis 1.0; nur für Zonenziele. Werte unter 1.0 werden bei anderen Typen mit Warnung auf 1.0 gesetzt |
offset | 0,0,0 | Kommagetrennter String "x,y,z"; keine Lua-Vektortabelle |
relativeOffset | keiner | Relative Vektorspezifikation; Quell- und Zielpunkt bestimmen die Richtung |
location | keiner | Serialisierter String "world,x,y,z,yaw,pitch" für "LOCATION" |
locations | keine | Array serialisierter Positionsstrings für "LOCATIONS" |
track | true | Ob 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
| 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 | Standard | Hinweise |
|---|---|---|
shape | "CYLINDER" | "SPHERE", "DOME", "CYLINDER", "CUBOID", "CONE", "STATIC_RAY", "ROTATING_RAY", "TRANSLATING_RAY" |
radius | 5 | Kugel, Kuppel, Zylinder, Kegel |
height | 1 | Nur Zylinder; für Entitätsabfragen muss die gesamte Entitätshöhe hineinpassen |
x, y, z | 0 | Quaderabmessungen; siehe unterschiedliche Punkt- und Entitätsgeometrie |
xBorder, yBorder, zBorder | 0 | Innere Quaderabmessungen |
borderRadius | 1 | Innenradius für Kugel, Kuppel, Zylinder und Kegel |
pointRadius | 0.5 | Positiver Radius und Abstand der Strahlproben |
animationDuration | 0 | Animationsdauer in Ticks für animierte Strahlen |
Target | {targetType = "SELF"} | Ursprung als Zielspezifikationstabelle im selben Format |
Target2 | keines | Zweiter Punkt; erforderlich für Kegel und alle Strahlformen |
FinalTarget, FinalTarget2 | keine | Endpositionen, nur für verschobene Strahlen |
filter | "PLAYER" | "PLAYER", "ELITE", "LIVING"; anders als bei context.zones hier großgeschrieben |
ignoresSolidBlocks | true | Nur Strahlen |
pitchPreRotation, yawPreRotation | 0 | Nur rotierende Strahlen |
pitchRotation, yawRotation | 0 | Nur 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üssel | Hinweise |
|---|---|
SourceTarget | Quellziel-Spezifikation (Tabelle) |
DestinationTarget | Zielziel-Spezifikation (Tabelle) |
normalize | Boolescher Wert, Standard false; ob der Vektor normalisiert wird |
multiplier | Faktor nach der Normalisierung, Standard 1 |
offset | Kommagetrennter String "x,y,z", Standard "0,0,0"; keine Lua-Vektortabelle |
Methoden für relative Vektor-Handles
| Methode | Hinweise |
|---|---|
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üssel | Standard | Hinweise |
|---|---|---|
particle | "FLAME" | Partikelname, z. B. "FLAME", "DUST", "SMOKE" |
amount | 1 | Partikelanzahl; bei 0 hängt das Richtungsverhalten vom Partikeltyp ab |
x, y, z | 0.01 | Streuung/Offset oder Geschwindigkeit bei amount = 0 |
speed | 0.01 | Partikelgeschwindigkeit |
red, green, blue | 255 | Farbe für DUST, DUST_COLOR_TRANSITION und Partikel mit Color-Daten (0–255); WITCH verwendet diese Werte nicht |
toRed, toGreen, toBlue | 255 | Zielfarbe für DUST_COLOR_TRANSITION |
material | "STONE" | Block/Item für Partikel mit entsprechenden Daten (BLOCK, ITEM, FALLING_DUST, ...) |
relativeVector | keiner | Relative 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.
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.statezur Verwendung in einem späteren Hook-Aufruf. context.script:zone(...):watch(...)liefert eine mitcontext.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
| 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 (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) |
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
}
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:
| 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/verschobene Strahlen) | Script-Zonen-Handles für wiederholte Abfragen; native Watcher können ebenfalls eine animierte Form behalten |
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 |
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
