Lua-Scripting: Fehlerbehebung
Diese Seite behandelt häufige Probleme, die beim Schreiben oder Debuggen von Lua-Fähigkeiten auftreten können, sowie Migrationshinweise für Autoren, die von EliteScript kommen. Wenn du NPC-Skripte debuggst, siehe NPC-Skripte. Wenn du nach funktionierenden Beispielen suchst, siehe Beispiele & Muster. Wenn du gerade erst anfängst, siehe Erste Schritte.
EliteMobs verwendet die MagmaCore-Lua-Scripting-Engine, die von allen Nightbreak-Plugins gemeinsam genutzt wird. Für die Dokumentation zu gemeinsamen Konzepten wie der Sandbox, dem Scheduler, Zonen, der Welt-API, Entitätstabellen und Spieler-UI-Methoden siehe die Seite MagmaCore-Lua-Scripting-Engine.
Häufige Probleme
1. Fähigkeit lädt überhaupt nicht
Überprüfe die Serverkonsole auf Fehler beim Serverstart. Die häufigste Ursache ist ein Lua-Syntaxfehler (fehlendes end, nicht übereinstimmende Klammern usw.). Stelle außerdem sicher, dass die Datei auf .lua endet und im richtigen powers-Verzeichnis liegt.
2. Hook wird nie ausgelöst
Überprüfe, ob der Hook-Name exakt so geschrieben ist, wie er in der Hook-Liste aufgeführt ist. Häufige Fehler: on_boss_hit (falsch) vs. on_boss_damaged_by_player (richtig), oder on_tick (falsch) vs. on_game_tick (richtig).
3. context.player ist nil
Nur Hooks, deren zugrunde liegendes Event einen Spieler mitführt, füllen context.player. Es ist immer nil in on_spawn, on_game_tick, on_boss_damaged, on_boss_damaged_by_elite, on_exit_combat, on_heal, on_death und on_phase_switch.
Gefüllt ist es in on_boss_damaged_by_player, on_player_damaged_by_boss, on_enter_combat und on_boss_target_changed sowie in on_zone_enter / on_zone_leave, wenn die beteiligte Entität zufällig ein Spieler ist. Füge immer einen Nil-Schutz hinzu, bevor du es verwendest. Die vollständige Tabelle findest du unter Hooks & Lebenszyklus.
4. Timeout / Ausführungsbudget überschritten
Jeder Hook, geplante Callback und jede Dateiauswertung teilt sich mit verschachtelten Aufrufen ein Budget von 250.000 Lua-Instruktionen und 50 ms Thread-CPU-Zeit. Kann die JVM diese CPU-Zeit nicht messen, gilt stattdessen eine Grenze von 250 ms verstrichener Zeit. Der Fehler nennt die überschrittene Grenze:
Lua instruction budget exceeded (250000 instruction limit)
Lua CPU-time budget exceeded (50ms current-thread CPU limit)
Lua elapsed-time fallback budget exceeded (250ms fallback; current-thread CPU time unavailable)
Die VM bricht unkontrollierte Lua-Schleifen während der Ausführung ab. Einen laufenden Java-Aufruf kann sie nicht unterbrechen; nach dessen Rückkehr gibt es keine zusätzliche 50-ms-Grenze. Nutze Cooldowns, weniger Abtastpunkte oder context.scheduler:run_every(...), um Arbeit über mehrere Ticks zu verteilen.
5. Scheduler-Callback verwendet veraltete Daten
Du verwendest wahrscheinlich den äußeren context anstelle des Callback-Parameters. Ändere function() ... context.boss ... end zu function(tick_context) ... tick_context.boss ... end.
6. Zonenabfrage gibt keine Entitäten zurück
Überprüfe die Zonendefinition noch einmal genau. Für native Zonen muss kind kleingeschrieben sein ("sphere", nicht "SPHERE"). Für Script-Utilities muss shape großgeschrieben sein ("CONE", nicht "cone"). Überprüfe auch, dass origin oder Target tatsächlich zu einer gültigen Position aufgelöst wird.
7. Partikel erscheinen nicht
Verwende einen gültigen Bukkit-Particle-Namen; "FLAME" und "flame" werden in Großbuchstaben normalisiert. Prüfe Position, Menge und benötigte Daten. BLOCK benötigt Blockdaten, die dieser Welt-Helper nicht liefert. Nutze eine unterstützte Partikelart oder die Skript-Partikel-API mit Materialoption.
8. Cooldown scheint nicht zu funktionieren
Stelle sicher, dass du check_local(key, duration) verwendest (das in einem Aufruf prüft UND setzt), nicht local_ready(key) gefolgt von einem separaten set_local(duration, key). Wenn du local_ready allein verwendest, prüfst du nur, setzt den Cooldown aber nie.
9. Boss führt Fähigkeit nach dem Tod weiter aus
Füge Aufräumlogik in on_exit_combat und/oder on_death hinzu, um Scheduler-Aufgaben abzubrechen. Wenn der Boss stirbt, sollte on_exit_combat ausgelöst werden, aber explizites Aufräumen in beiden Hooks ist sicherer.
Fehlermeldungen lesen
Wenn in einer Lua-Fähigkeit etwas schiefgeht, gibt die Konsole einen verständlichen Fehlerblock mit dem Präfix [Lua] aus. Diese Meldungen sagen dir genau, welche Datei, welche Zeile, welcher Hook und was schiefgegangen ist – in einfacher Sprache. Lies immer die vollständige Meldung, bevor du mit dem Debuggen beginnst.
Ein typischer Fehler sieht so aus:
[Lua] Error in 'push_zone.lua' at line 35 during 'on_boss_damaged_by_player':
[Lua] -> You tried to call a method or function that doesn't exist.
[Lua] -> Check the method name for typos, or make sure you're using ':' (colon) for method calls, not '.' (dot).
[Lua] -> Script has been disabled for this entity to prevent further errors.
Das System übersetzt häufige Lua-Fehler in verständliche Sprache. Hier sind die häufigsten:
| Roher Lua-Fehler | Was die Konsole dir sagt |
|---|---|
attempt to call nil | Du hast versucht, eine Methode oder Funktion aufzurufen, die nicht existiert. Prüfe den Methodennamen auf Tippfehler, oder stelle sicher, dass du : (Doppelpunkt) für Methodenaufrufe verwendest, nicht . (Punkt). |
index expected, got nil | Du hast versucht, auf ein Feld von etwas zuzugreifen, das nil ist. Prüfe, ob vorheriger Code es initialisiert hat. |
attempt to index | Du hast versucht, auf eine Eigenschaft eines nil- oder ungültigen Werts zuzugreifen. |
bad argument | Zeigt die spezifischen Details zur Argument-Abweichung an (erwarteter Typ vs. tatsächlicher Typ). |
| Budget überschritten | Die Meldung nennt das Instruktionslimit, die CPU-Zeit oder die Ersatzgrenze für verstrichene Zeit; siehe oben. |
Wenn du einen [Lua]-Fehler in der Konsole siehst, sagt dir die Fehlermeldung in einfacher Sprache genau, welche Datei, welche Zeile, welcher Hook und was schiefgegangen ist. Lies die vollständige Meldung, bevor du in den Code eintauchst – sie weist dich normalerweise direkt auf die Lösung hin.
Nimm nicht an, dass undokumentierte Aliase existieren
Die Lua-API stellt einen bestimmten Satz von Methodennamen bereit. Wenn du Fähigkeiten von Hand oder mit KI-Unterstützung schreibst, nimm nicht an, dass Kurzformen oder alternative Namen existieren. Die folgenden Namen sind Beispiele für Namen, die nicht existieren und Fehler verursachen:
show_temporary_boss_bar()– verwende stattdessenplayer:show_boss_bar(title, color, style, duration).run_command_as_player()– verwende stattdessenplayer:run_command(command).em.location(...)– der Methodenname ist falsch. Verwende stattdessenem.create_location(x, y, z)odercontext.boss:get_location()/context.player.current_location.em.vector(...)– der Methodenname ist falsch. Verwende stattdessenem.create_vector(x, y, z)oder einfache{x=0, y=1, z=0}-Tabellen.em.zone.sphere(...)– der Methodenname ist falsch. Verwende stattdessenem.zone.create_sphere_zone(radius)oder eine Zonendefinitions-Tabelle wie{kind = "sphere", radius = 5, origin = location}.entity:teleport_to(...)– verwendeentity:teleport_to_location(location).entity:set_velocity(...)– verwendeentity:set_velocity_vector(vector).entity:set_facing(...)– verwendeentity:face_direction_or_location(direction_or_location).
Im Zweifelsfall prüfe die API-Referenzseiten (Boss & Entitäten, Welt & Umgebung, Zonen & Zielerfassung). Wenn es dort nicht dokumentiert ist, existiert es nicht.
Migrationshinweise für EliteScript-Autoren
Wenn du bereits gute EliteScripts schreibst, ist der einfachste Weg, Lua-Fähigkeiten zu lernen:
-
Denke weiterhin in Begriffen von Ereignissen, Zielen, Zonen, relativen Vektoren und Partikeln. Die Konzepte sind dieselben – nur die Syntax ändert sich. EliteScript-Ereignisse werden zu Hook-Namen wie
on_spawnoderon_boss_damaged_by_player. Ziele und Zonen werden als Tabellen ancontext.scriptübergeben, wobei die gleichen Feldnamen verwendet werden, die auf den Seiten EliteScript-Zonen und EliteScript-Ziele dokumentiert sind. -
Verlagere deinen Kontrollfluss nach Lua. Zufallswürfe, gemeinsame Hilfsfunktionen, Schleifen, persistenter Zustand (
context.state) und Aufgabenplanung (context.scheduler) sind die Dinge, die Lua hinzufügt und die reines EliteScript nicht ohne Weiteres leisten kann. Beginne damit, eine verzweigende oder bedingte Fähigkeit nach Lua zu konvertieren, während du alles andere unverändert lässt. -
Verwende
context.scriptfür Zielerfassung und Zonengeometrie. Das sind keine Nachbildungen — die Spezifikationstabelle, die du übergibst, wird an die echte EliteScript-Engine weitergereicht. Jedes auf den EliteScript-Seiten dokumentierte Feld (targetType,shape,Target,Target2,FinalTarget,range,offset,relativeOffset,coverage,filter, …) funktioniert daher wortwörtlich, mit denselben Standardwerten und derselben Groß-/Kleinschreibung. Halte die EliteScript-Doku als Spezifikationsreferenz offen und nutze Lua ausschließlich für die Logikebene. -
Achte auf die zwei Zonensysteme.
context.script:zone({shape = "SPHERE", ...})ist die EliteScript-Engine (Enums in GROSSBUCHSTABEN,Target-Spezifikationstabellen).context.zonesist eine separate, leichtgewichtige Implementierung (kleingeschriebeneskind, einfacheorigin/destination-Positionen). Werden deren Schlüsselstile vermischt, entsteht stillschweigend eine leere Zone.
Lernpfad für Anfänger
Wenn du dieses System von Grund auf lernen möchtest, funktioniert dieser Lernpfad gut:
- Schreibe eine Datei mit nur
api_version = 1undon_spawn. - Lass den Boss eine Nachricht senden oder einen Sound abspielen.
- Füge einen Cooldown mit
context.cooldownshinzu. - Füge einen spielerausgelösten Hook wie
on_boss_damaged_by_playerhinzu. - Füge eine verzögerte Aktion mit
context.scheduler:run_after(...)hinzu. - Füge eine einfache native Lua-Zonenabfrage oder ein einfaches
context.script:target(...)hinzu. - Erst dann gehe zu rotierenden Angriffen, Zustandsmaschinen und mehrstufigen Mechaniken über.
Jeder Schritt baut auf dem vorherigen auf, und du kannst in jeder Phase testen. Versuche nicht, einen mehrphasigen Boss als deine erste Lua-Fähigkeit zu schreiben.
Nächste Schritte
- Erste Schritte – Dateistruktur, Hooks, erste Power-Erklärung, Copy-Paste-Vorlagen
- NPC-Skripte – Skripte für NPC-Nähe, -Interaktion und -Lebenszyklus
- Beispiele & Muster – vollständige funktionierende Fähigkeiten zum Studieren und Anpassen
