Zum Hauptinhalt springen

Lua-Scripting: Erste Schritte

webapp_banner.jpg

Was Sie lernen werden

Diese Seite zeigt Ihnen, wie Sie Ihre erste Lua-Power für EliteMobs schreiben, von einer leeren Datei bis hin zu einer funktionierenden Boss-Fähigkeit. Am Ende werden Sie Hooks, Context, Abklingzeiten und die allgemeine Struktur jeder Lua-Power-Datei verstehen.

Sobald Sie mit den Grundlagen vertraut sind, fahren Sie mit den Begleitseiten fort:

  • Hooks & Lebenszyklus -- Hook-Namen, Ausführungsreihenfolge und Context-Verfügbarkeit
  • Boss & Entitäten -- die APIs context.boss, context.player, context.players und context.entities
  • Welt & Umgebung -- Partikel, Sounds, Blitze, Spawning und die context.world-API
  • Zonen & Zielerfassung -- native Lua-Zonen, Script-Utilities-Zielerfassung und die APIs context.zones / context.script
  • Beispiele & Muster -- vollständige, funktionierende Powers zum Studieren und Anpassen
  • Enums & Werte -- Links zu den Spigot-Javadocs für Particle, Material, PotionEffectType und andere String-Konstanten
  • Fehlerbehebung -- häufige Fehler, Debugging-Tipps und die QC-Checkliste
Experimentelles Feature

Lua-Power-Dateien sind derzeit experimentell. Hook-Namen, Hilfsmethoden und Verhaltensweisen können sich noch ändern, während EliteMobs weiterentwickelt wird. Testen Sie daher sorgfältig, bevor Sie sie auf einem Produktionsserver verwenden.

Beziehung zu EliteScript

Lua ersetzt nicht das bestehende eliteScript:-YAML-System.

  • Verwenden Sie EliteScript, wenn Sie deklaratives, YAML-gesteuertes Scripting mit den bestehenden Seiten für Aktionen, Ziele, Zonen, Bedingungen, Abklingzeiten und Relative Vektoren wünschen.
  • Verwenden Sie Lua-Power-Dateien, wenn Sie Variablen, Schleifen, zufällige Auswahl, wiederverwendbare Hilfsfunktionen, persistenten Zustand pro Boss und einen traditionelleren Programmierablauf benötigen.

Lua hat sein eigenes Zielerfassungs- und Zonensystem, das dieselben bekannten Enum-Namen und Konzepte verwendet, die Sie bereits aus EliteScript kennen. Die Script-Utilities-API (context.script) ermöglicht es Ihnen, Zonen, Ziele und relative Vektoren mit denselben Feldnamen zu erstellen, die in den EliteScript-Seiten dokumentiert sind.


Was Lua-Powers sind

Lua-Powers sind eigenständige .lua-Dateien, die im normalen EliteMobs-powers-Verzeichnisbaum liegen und genau wie normale Power-Dateien referenziert werden.

Wofür Lua-Powers gut geeignet sind

Lua-Powers glänzen, wenn Sie Folgendes benötigen:

  • Angriffsrotationen und zufällige Fähigkeitsauswahl
  • Persistenter Zustand zwischen Hooks mit context.state
  • Verzögerte und wiederholte Aktionen, ohne alles mit YAML-Wartezeiten aufzubauen
  • Benutzerdefinierte Hilfsfunktionen innerhalb einer Datei
  • Komplexe Verzweigungen, die in reinem EliteScript umständlich wären
  • Boss-Logik, die dennoch EliteScript-ähnliche Zielerfassung und Zonendefinitionen wiederverwenden möchte

Wenn Ihre Power hauptsächlich „Ereignis auslösen, ein paar geskriptete Aktionen ausführen" ist, sind die bestehenden EliteScript-Dokumente nach wie vor der schnellste und klarste Weg, sie zu erstellen. Wenn Ihre Power echten Programmfluss benötigt, ist Lua das richtige Werkzeug dafür.


Für wen diese Seite gedacht ist

Diese Seite ist für drei Arten von Lesern geschrieben:

  • Jemand, der bereits EliteScript kennt und Lua lernen möchte, ohne gleich „echtes Programmieren" komplett zu erlernen
  • Jemand, der neu im EliteMobs-Scripting ist und eine vollständige Referenz mit exakten Namen benötigt
  • Jemand, der KI zum Entwerfen von Powers nutzt und genug Details braucht, um zu erkennen, wenn die KI etwas Falsches erfunden hat

Sie müssen nicht ein vollwertiger Lua-Entwickler werden, bevor Sie nützliche Powers schreiben können. Für die meisten praktischen EliteMobs-Powers benötigen Sie nur:

  • Wie man einen gültigen Hook in der zurückgegebenen Tabelle platziert
  • Wie man Werte aus context liest
  • Wie man mit if ... then return end frühzeitig abbricht
  • Wie man ein paar Hilfsmethoden korrekt aufruft
  • Wie man die richtigen Ziel- und Zonenspezifikationen aus den bestehenden EliteScript-Docs kopiert

Mentales Modell: EliteScript vs. Lua

Wenn Sie EliteScript kennen, ist dieser Vergleich der schnellste Weg, Lua-Powers zu verstehen:

Wenn Sie in EliteScript-Begriffen denkenIn Lua bedeutet das normalerweise
EventsHook-Namen wie on_spawn oder on_boss_damaged_by_player
Cooldownscontext.cooldowns (siehe context.cooldowns weiter unten)
AktionenDirekte Methodenaufrufe wie context.world:spawn_particle_at_location(...) oder context.script:damage(...)
Zielecontext.script:target({...}) -- verwendet die Feldnamen von EliteScript Target
Zonencontext.script:zone({...}) oder native context.zones-Helfer -- siehe Zonen & Zielerfassung
Relative Vektorencontext.script:relative_vector({...}) oder context.vectors
SkriptflussIhre eigenen Lua-if-Anweisungen, Hilfsfunktionen, Timer und Zustand

Der größte Unterschied ist dieser:

  • EliteScript beschreibt in YAML, was passieren soll.
  • Lua lässt Sie mithilfe von Code entscheiden, wann, warum und welcher Zweig ausgeführt werden soll.

Wenn sich EliteScript also wie „Konfiguration" anfühlt, fühlt sich Lua wie „Konfiguration plus Entscheidungsfindung" an.


Kleiner Lua-Einstieg für EliteMobs-Autoren

Dies ist die minimale Lua-Syntax, die die meisten Power-Autoren benötigen.

Variablen

Verwenden Sie local, um einen Wert zu speichern:

local cooldown_key = "fire_burst"
local damage_multiplier = 1.5

local bedeutet, dass die Variable nur zu dieser Datei oder diesem Block gehört.

Funktionen

Funktionen sind wiederverwendbare Logikblöcke:

local function warn_player(player)
player:send_message("&cMove!")
end

Später können Sie sie aufrufen:

warn_player(context.player)

if-Prüfungen

Verwenden Sie if, wenn etwas nur manchmal passieren soll:

if context.player == nil then
return
end

Das bedeutet: „Wenn es keinen Spieler für diesen Hook gibt, hier anhalten".

nil

nil bedeutet „kein Wert". Es ist Luas Version von „hier ist nichts".

Sie werden oft auf nil prüfen mit:

if context.event ~= nil then
-- etwas mit dem Event machen
end

~= bedeutet „ist nicht gleich".

Tabellen

Lua verwendet Tabellen für verschiedene Aufgaben:

  • Listen
  • Objekte mit benannten Schlüsseln
  • Die zurückgegebene Power-Definition

Beispiel einer Tabelle mit benannten Schlüsseln:

local particle = {
particle = "FLAME",
amount = 1,
speed = 0.05
}

Die Power-Definition zurückgeben

Am Ende der Datei geben Sie eine Tabelle zurück:

return {
api_version = 1,

on_spawn = function(context)
end
}

Diese zurückgegebene Tabelle ist die Power-Datei.

Kommentare

Verwenden Sie --, um eine Notiz für Menschen zu schreiben:

-- Dieser Cooldown verhindert, dass der Angriff bei jedem Treffer ausgelöst wird
context.cooldowns:set_local(60, "fire_burst")

Ihre erste funktionierende Power, Schritt für Schritt

Wenn Sie komplett neu sind, ist dies die beste Progression für den „ersten Erfolg".

Vor Schritt 1: Speichern und an einen Boss anhängen

Speichern Sie die Lua-Datei im normalen EliteMobs-Powers-Ordner, zum Beispiel:

plugins/
EliteMobs/
powers/
first_test.lua

Fügen Sie dann diesen Dateinamen zur Boss-Konfiguration in der normalen powers:-Liste hinzu:

powers:
- first_test.lua

Der vollständige Anfänger-Ablauf ist also:

  1. Datei in plugins/EliteMobs/powers/ speichern
  2. Den .lua-Dateinamen zur powers:-Liste des Bosses hinzufügen
  3. Den Boss spawnen oder neu laden
  4. Den Hook testen, den Sie gerade bauen

Wenn Sie mehr Hintergrundwissen zu Boss-Dateien, Power-Listen oder der Struktur benutzerdefinierter Bosse benötigen, sehen Sie sich Benutzerdefinierte Bosse erstellen an. Diese Seite behandelt die Boss-Einrichtung im Detail, einschließlich der Funktionsweise der powers:-Liste.

Schritt 1: Die Datei laden lassen

return {
api_version = 1,

on_spawn = function(context)
end
}

Wenn dies ohne Fehler geladen wird, haben Sie bereits bewiesen:

  • Die Datei ist gültiges Lua
  • EliteMobs hat sie gefunden
  • Die Struktur der zurückgegebenen Tabelle ist korrekt
  • on_spawn ist ein gültiger Hook-Name

Schritt 2: Den Boss eine sichtbare Aktion ausführen lassen

return {
api_version = 1,

on_spawn = function(context)
context.boss:play_sound_at_self("entity.blaze.ambient", 1.0, 1.0)
end
}

Jetzt haben Sie den wichtigsten Anfängerbeweis: Ihr Hook wird ausgelöst.

Schritt 3: Auf einen Spielertreffer reagieren

return {
api_version = 1,

on_boss_damaged_by_player = function(context)
if context.player == nil then
return
end

context.player:send_message("&eYou hit the boss.")
end
}

Dies vermittelt drei Kernideen:

  • on_boss_damaged_by_player ist der Hook-Name
  • context.player ist der Spieler, der an diesem Hook beteiligt ist
  • return bricht frühzeitig ab, wenn die benötigten Daten fehlen

Schritt 4: Spam mit einer Abklingzeit verhindern

return {
api_version = 1,

on_boss_damaged_by_player = function(context)
if context.player == nil then
return
end

if not context.cooldowns:local_ready("hello_message") then
return
end

context.player:send_message("&eYou woke up the boss.")
context.cooldowns:set_local(60, "hello_message")
end
}

Dies ist das erste wirklich nützliche Muster, das die meisten Autoren benötigen. Wenn Sie dieses Muster verstehen, können Sie bereits viele praktische Powers erstellen.

Schritt 5: Einen echten Effekt hinzufügen

return {
api_version = 1,

on_boss_damaged_by_player = function(context)
if context.player == nil then
return
end

if not context.cooldowns:local_ready("shock") then
return
end

context.player:send_message("&cStatic jumps from the boss into your armor!")
context.world:strike_lightning_at_location(context.player.current_location)
context.cooldowns:set_local(100, "shock")
end
}

Ab diesem Punkt schreiben Sie bereits eine echte Power.


Erster echter Arbeitsablauf

Wenn Sie eine brandneue Lua-Power erstellen, verwenden Sie diese Reihenfolge:

  1. Die Datei erstellen und on_spawn zum Laufen bringen.
  2. Zum gewünschten Hook wechseln.
  3. Bestätigen, dass der Hook die erwarteten Daten hat, wie context.player oder context.event.
  4. Zuerst eine Nachricht oder einen Sound hinzufügen, bevor Schaden oder Partikel.
  5. Abklingzeiten hinzufügen.
  6. Einen Gameplay-Effekt hinzufügen.
  7. Erst danach Helfer, Zustand, Scheduler-Logik oder Zonen hinzufügen.

Diese Reihenfolge macht das Debugging erheblich einfacher, da sich immer nur eine Sache ändert.


Wo Lua-Dateien liegen

Platzieren Sie .lua-Dateien im selben Ordnerbaum wie normale Power-.yml-Dateien:

plugins/
EliteMobs/
powers/
mycoolpower.lua
attack_push.yml
subfolder/
myotherpower.lua

Lua-Powers werden automatisch aus den Power-Verzeichnissen erkannt, die EliteMobs bereits lädt.

Wie Bosse Lua-Powers referenzieren

Boss-Dateien verwenden weiterhin die normale powers:-Liste:

powers:
- attack_push.yml
- mycoolpower.lua

Es ist kein spezielles Feld erforderlich. Lua-Powers werden nicht über eliteScript: geladen.

Dateibenennungsregeln

  • Bosse referenzieren Lua-Powers über den Dateinamen, nicht über den Ordnerpfad.
  • EliteMobs registriert entdeckte Lua-Powers derzeit nur über den Basisnamen.
  • Vermeiden Sie doppelte Namen wie powers/fire.lua und powers/bosses/fire.lua, da einer den anderen bei der Erkennung überschreiben kann.

Vorgefertigte Lua-Powers

EliteMobs wird mit Dutzenden vorgefertigter Lua-Powers im powers-Ordner ausgeliefert, wie attack_fire.lua, frost_cone.lua, meteor_shower.lua und viele mehr. Diese sind ausgezeichnete Referenzen zum Studieren — öffnen Sie einfach eine beliebige .lua-Datei in Ihrem plugins/EliteMobs/powers/-Verzeichnis. Aus Gründen der Abwärtskompatibilität werden vorgefertigte Powers auch unter ihren alten .yml-Namen registriert.


Minimaler Dateivertrag

Jede Lua-Power muss eine Tabelle mit return zurückgeben. Diese Tabelle ist absichtlich strikt.

Erforderliche und optionale Top-Level-Felder

FeldErforderlichTypAnmerkungen
api_versionJaNumberMuss derzeit 1 sein
priorityNeinNumberAusführungspriorität. Niedrigere Werte werden zuerst ausgeführt. Standard ist 0
Unterstützte Hook-SchlüsselNeinFunctionMuss einen der exakten Hook-Namen verwenden, die in der Hook-Referenz aufgeführt sind

Validierungsregeln

  • Die Datei muss eine Tabelle zurückgeben.
  • api_version ist erforderlich und muss derzeit 1 sein.
  • priority muss numerisch sein, falls vorhanden.
  • Jeder zusätzliche Top-Level-Schlüssel muss ein unterstützter Hook-Name sein.
  • Jeder Hook-Schlüssel muss auf eine Funktion zeigen.
  • Unbekannte Top-Level-Schlüssel werden abgelehnt.

Das bedeutet, dass Hilfsfunktionen und lokale Konstanten oberhalb des abschließenden return stehen sollten, nicht innerhalb der zurückgegebenen Tabelle, es sei denn, es handelt sich um tatsächliche Hooks.


Kopiervorlagen zum Einfügen

Kleinstmögliche gültige Lua-Power

return {
api_version = 1,

on_spawn = function(context)
end
}

Empfohlene Startvorlage

local ATTACK_COOLDOWN = "my_attack"

local function can_run_attack(context)
return context.cooldowns:local_ready(ATTACK_COOLDOWN)
and context.cooldowns:global_ready()
end

local function run_attack(context)
context.boss:play_sound_at_self("entity.blaze.shoot", 1.0, 1.0)
context.cooldowns:set_local(100, ATTACK_COOLDOWN)
context.cooldowns:set_global(20)
end

return {
api_version = 1,
priority = 0,

on_boss_damaged_by_player = function(context)
if context.player == nil then
return
end

if not can_run_attack(context) then
return
end

run_attack(context)
end
}

Layout für größere Dateien

local CONSTANT_NAME = "value"

local function helper_function(context)
end

local function another_helper(context, value)
end

return {
api_version = 1,
priority = 0,

on_spawn = function(context)
end,

on_enter_combat = function(context)
end,

on_boss_damaged_by_player = function(context)
end,

on_exit_combat = function(context)
end
}

Hooks

Hooks sind speziell benannte Funktionen in der Tabelle, die Sie zurückgeben. EliteMobs ruft sie auf, wenn etwas passiert — der Boss spawnt, nimmt Schaden, tritt in den Kampf ein usw. Sie haben on_spawn und on_boss_damaged_by_player bereits im obigen Tutorial gesehen.

Die häufigsten Hooks zum Einstieg sind on_spawn, on_boss_damaged_by_player, on_enter_combat und on_exit_combat. Für die vollständige Liste aller Hooks, welche Context-Schlüssel in jedem verfügbar sind und wie die Ausführungsreihenfolge funktioniert, siehe Hooks & Lebenszyklus.


Was ist context?

Jede Hook-Funktion erhält ein Argument namens context. Stellen Sie es sich als einen Werkzeugkasten vor, den EliteMobs Ihnen jedes Mal übergibt, wenn etwas passiert — er enthält alles, was Sie brauchen, um mit dem Boss, dem Spieler, der Welt, Abklingzeiten und mehr zu interagieren.

on_boss_damaged_by_player = function(context)
-- context.boss = der Boss, der getroffen wurde
-- context.player = der Spieler, der ihn getroffen hat
-- context.world = Werkzeuge zum Spawnen von Partikeln, Sounds usw.
-- context.cooldowns = Abklingzeit-Verwaltung
-- context.state = Ihr eigener persistenter Speicher
end

Sie erstellen context nicht selbst — EliteMobs erstellt es und übergibt es an Ihren Hook. Sie lesen einfach daraus und rufen Methoden darauf auf.

info

context wird für jeden Hook-Aufruf neu erstellt, außer context.state, der für die gesamte Lebensdauer des Bosses bestehen bleibt. Das bedeutet, dass Sie Daten in context.state speichern und sie später in einem anderen Hook wieder lesen können.


Wichtige context-APIs

Hier sind die wichtigsten APIs, die Sie aus context verwenden werden:

  • context.state — Eine einfache Lua-Tabelle, die für die Lebensdauer des Bosses bestehen bleibt. Verwenden Sie sie, um Phasennummern, Task-IDs, Flags und alles, was Sie sich zwischen Hooks merken müssen, zu speichern. Nur context.state bleibt bestehen — alle anderen Context-Tabellen werden bei jedem Aufruf neu erstellt.

  • context.log — Konsolenprotokollierung mit log:info(msg), log:warn(msg) und log:debug(msg). Unverzichtbar während der Entwicklung.

  • context.cooldowns — Lokale Abklingzeiten pro Power und globale Abklingzeiten pro Boss. Die Schlüsselmethode ist cooldowns:check_local(key, ticks), die eine Abklingzeit atomar prüft UND setzt. Siehe die Seite Hooks & Lebenszyklus für die vollständige Cooldown-API.

  • context.scheduler — Verzögerte und wiederholte Aufgaben mit scheduler:run_after(ticks, callback) und scheduler:run_every(ticks, callback). Callbacks erhalten einen frischen Context — verwenden Sie immer den Callback-Parameter, nicht den äußeren context. Brechen Sie wiederholte Aufgaben in on_exit_combat ab. Siehe Hooks & Lebenszyklus für Details.

  • context.boss / context.player — Der Boss und der Spieler, die am aktuellen Ereignis beteiligt sind. Siehe Boss & Entitäten für alle Felder und Methoden.

  • context.world — Partikel, Entitäten, Sounds, Blitze, Blöcke spawnen. Siehe Welt & Umgebung.

  • context.zones / context.script — Zonengeometrie, Zielerfassung, Schaden, Partikel. Siehe Zonen & Zielerfassung.


Methodensyntax: : vs. .

In Lua ist object:method(arg) eine Kurzschreibweise für object.method(object, arg). Die EliteMobs-API akzeptiert beide Formen, daher funktioniert beides:

context.cooldowns:set_local(60, "test")
context.cooldowns.set_local(60, "test") -- dasselbe

In der gesamten Dokumentation wird konsistent : verwendet.


Nächste Schritte

Nachdem Sie nun die Grundlagen kennen, erkunden Sie den Rest der Lua-Scripting-Dokumentation:

  • Hooks & Lebenszyklus -- Hook-Namen, Ausführungsreihenfolge und welche Context-Schlüssel in jedem Hook verfügbar sind
  • Boss & Entitäten -- context.boss, context.player, context.players, context.entities und context.event
  • Welt & Umgebung -- Partikel, Sounds, Blitze, Spawning und context.world
  • Zonen & Zielerfassung -- native Lua-Zonen, Script-Utilities-Zielerfassung/-Zonen/-Partikel und relative Vektoren
  • Beispiele & Muster -- vollständige, funktionierende Powers mit Erklärungen
  • Enums & Werte -- Links zu den Spigot-Javadocs für Particle, Material, PotionEffectType und mehr
  • Fehlerbehebung -- häufige Fehler, Debugging-Tipps und eine QC-Checkliste

Für YAML-basiertes Scripting bleiben die EliteScript-Seiten die maßgebliche Referenz: