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
Nicht alle Hooks stellen einen Spieler bereit. on_spawn, on_game_tick und on_exit_combat haben keinen Spieler. on_enter_combat stellt context.player bereit (den Spieler, der den Kampf ausgelöst hat). In on_boss_damaged (generischer Schaden) ist der Angreifer möglicherweise kein Spieler. Füge immer einen Nil-Schutz hinzu, bevor du context.player verwendest.
4. Timeout / Ausführungsbudget überschritten
Wenn ein Hook oder Callback zu lange dauert, wird die Fähigkeit automatisch deaktiviert, um Lag zu vermeiden. Die Konsolenmeldung sieht so aus:
[Lua] my_power.lua took 73ms in 'on_game_tick' (limit: 50ms) — script disabled to prevent lag.
Häufige Ursachen: zu viele Entitäten durchlaufen, zu viele Zonen pro Tick erstellen oder aufwendige String-Operationen in on_game_tick ausführen. Verschiebe aufwendige Arbeit hinter ein Cooldown-Gate oder reduziere die Arbeit pro Aufruf.
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
Überprüfe, ob der Partikelname ein gültiger Bukkit-Particle-Enum-Wert in GROSSBUCHSTABEN ist. Häufiger Fehler: "flame" (falsch) vs. "FLAME" (richtig). Prüfe auch, ob amount mindestens 1 ist und sich die Position in einem geladenen Chunk befindet.
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). |
| Timeout | <filename> benötigte Xms in 'hook_name' (Limit: 50ms) – Skript deaktiviert, um Lag zu verhindern. |
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. Die Script-Utilities akzeptieren die gleichen Feldnamen wie EliteScript (targetType,shape,Target,Target2,range,offset,coverage), sodass du weiterhin die vorhandene EliteScript-Dokumentation als Referenz für diese Spezifikationen verwenden kannst. So kannst du vertraute Muster nutzen und gleichzeitig die Flexibilität von Lua für die Logikebene gewinnen.
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
