Aller au contenu principal

Script Lua : Dépannage

webapp_banner.jpg

Cette page couvre les problèmes courants que vous pouvez rencontrer en écrivant ou en déboguant des pouvoirs Lua, ainsi que des conseils de migration pour les auteurs venant d'EliteScript. Si vous déboguez des scripts de PNJ, consultez Scripts de PNJ. Si vous cherchez des exemples fonctionnels, consultez Exemples & Modèles. Si vous débutez tout juste, consultez Premiers pas.

Moteur Lua partagé

EliteMobs utilise le moteur de script Lua MagmaCore partagé entre les plugins Nightbreak. Pour la documentation sur les concepts partagés tels que le bac à sable (sandbox), le planificateur (scheduler), les zones, l'API de monde, les tables d'entités et les méthodes d'interface joueur, consultez la page Moteur de Script Lua MagmaCore.


Problèmes courants

1. Le pouvoir ne se charge pas du tout

Vérifiez la console du serveur à la recherche d'erreurs au démarrage du serveur. La cause la plus fréquente est une erreur de syntaxe Lua (end manquant, parenthèses non appariées, etc.). Vérifiez également que le fichier se termine par .lua et qu'il est placé dans le bon répertoire powers.

2. Le hook ne se déclenche jamais

Vérifiez que le nom du hook est orthographié exactement comme indiqué dans la liste des hooks. Erreurs courantes : on_boss_hit (faux) vs on_boss_damaged_by_player (correct), ou on_tick (faux) vs on_game_tick (correct).

3. context.player est nil

Seuls les hooks dont l'événement sous-jacent porte un joueur renseignent context.player. Il vaut toujours nil dans on_spawn, on_game_tick, on_boss_damaged, on_boss_damaged_by_elite, on_exit_combat, on_heal, on_death et on_phase_switch.

Il est renseigné dans on_boss_damaged_by_player, on_player_damaged_by_boss, on_enter_combat et on_boss_target_changed, ainsi que dans on_zone_enter / on_zone_leave lorsque l'entité concernée se trouve être un joueur. Ajoutez toujours une protection contre nil avant de l'utiliser. Voir Hooks et Cycle de Vie pour le tableau complet.

4. Délai dépassé / budget d'exécution dépassé

Chaque hook, callback planifié et évaluation de fichier partage avec ses appels imbriqués un budget de 250 000 instructions Lua et de 50 ms de temps CPU du thread. Si la JVM ne peut pas mesurer ce temps CPU, une limite de secours de 250 ms de temps écoulé s'applique. L'erreur indique la limite dépassée :

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)

La VM interrompt les boucles Lua incontrôlées pendant leur exécution. Elle ne peut pas interrompre un appel Java en cours, et aucun second seuil de 50 ms ne s'applique après son retour. Utilisez des cooldowns, moins de points d'échantillonnage ou context.scheduler:run_every(...) pour répartir le travail entre les ticks.

5. Le callback du planificateur utilise des données obsolètes

Vous utilisez probablement le context extérieur au lieu du paramètre du callback. Remplacez function() ... context.boss ... end par function(tick_context) ... tick_context.boss ... end.

6. La requête de zone ne renvoie aucune entité

Vérifiez bien la définition de la zone. Pour les zones natives, assurez-vous que kind est en minuscules ("sphere", pas "SPHERE"). Pour les utilitaires de script, assurez-vous que shape est en majuscules ("CONE", pas "cone"). Vérifiez aussi que origin ou Target se résout réellement vers un emplacement valide.

7. Les particules n'apparaissent pas

Utilisez un nom valide de l'énumération Bukkit Particle ; "FLAME" et "flame" sont normalisés en majuscules. Vérifiez la position, la quantité et les données requises. BLOCK exige des données de bloc que cet utilitaire du monde ne fournit pas : utilisez une particule prise en charge ou l'API de particules de script avec son option de matériau.

8. Le délai de récupération ne semble pas fonctionner

Assurez-vous d'utiliser check_local(key, duration) (qui vérifie ET définit en un seul appel), et non local_ready(key) suivi d'un set_local(duration, key) séparé. Si vous utilisez local_ready seul, vous ne faites que vérifier sans jamais définir le délai de récupération.

9. Le boss continue d'utiliser un pouvoir après sa mort

Ajoutez une logique de nettoyage dans on_exit_combat et/ou on_death pour annuler les tâches du planificateur. Si le boss meurt, on_exit_combat devrait se déclencher, mais ajouter un nettoyage explicite dans les deux hooks est plus sûr.


Lire les messages d'erreur

Lorsqu'un problème survient dans un pouvoir Lua, la console affiche un bloc d'erreur convivial préfixé par [Lua]. Ces messages vous indiquent exactement quel fichier, quelle ligne, quel hook et ce qui s'est mal passé — en clair. Lisez toujours le message complet avant de déboguer.

Une erreur typique ressemble à ceci :

[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.

Le système traduit les erreurs Lua courantes en langage clair. Voici les plus fréquentes :

Erreur Lua bruteCe que la console vous indique
attempt to call nilVous avez tenté d'appeler une méthode ou une fonction qui n'existe pas. Vérifiez le nom de la méthode pour des fautes de frappe, ou assurez-vous d'utiliser : (deux-points) pour les appels de méthode, et non . (point).
index expected, got nilVous avez tenté d'accéder à un champ sur quelque chose qui est nil. Vérifiez qu'un code antérieur l'a bien initialisé.
attempt to indexVous avez tenté d'accéder à une propriété sur une valeur nil ou invalide.
bad argumentAffiche les détails spécifiques de la non-correspondance d'argument (type attendu vs type réel).
Budget dépasséLe message indique la limite d'instructions, de temps CPU ou de temps écoulé de secours ; voir ci-dessus.
astuce

Lorsque vous voyez une erreur [Lua] dans la console, le message d'erreur vous indique exactement quel fichier, quelle ligne, quel hook et ce qui s'est mal passé, en clair. Lisez le message complet avant de plonger dans le code — il vous oriente généralement directement vers la solution.


Ne supposez pas que des alias non documentés existent

L'API Lua expose un ensemble spécifique de noms de méthodes. Si vous écrivez des pouvoirs à la main ou avec l'aide d'une IA, ne supposez pas que des raccourcis ou des noms alternatifs existent. Voici des exemples de noms qui n'existent pas et qui provoqueront des erreurs :

  • show_temporary_boss_bar() — utilisez plutôt player:show_boss_bar(title, color, style, duration).
  • run_command_as_player() — utilisez plutôt player:run_command(command).
  • em.location(...) — le nom de la méthode est faux. Utilisez plutôt em.create_location(x, y, z), ou context.boss:get_location() / context.player.current_location.
  • em.vector(...) — le nom de la méthode est faux. Utilisez plutôt em.create_vector(x, y, z), ou de simples tables {x=0, y=1, z=0}.
  • em.zone.sphere(...) — le nom de la méthode est faux. Utilisez plutôt em.zone.create_sphere_zone(radius), ou une table de définition de zone comme {kind = "sphere", radius = 5, origin = location}.
  • entity:teleport_to(...) — utilisez entity:teleport_to_location(location).
  • entity:set_velocity(...) — utilisez entity:set_velocity_vector(vector).
  • entity:set_facing(...) — utilisez entity:face_direction_or_location(direction_or_location).

En cas de doute, consultez les pages de Référence de l'API (Boss & Entités, Monde & Environnement, Zones & Ciblage). Si ce n'est pas documenté là, cela n'existe pas.


Conseils de migration pour les auteurs d'EliteScript

Si vous écrivez déjà de bons EliteScripts, la façon la plus simple d'apprendre les pouvoirs Lua est :

  1. Continuez à raisonner en termes d'événements, de cibles, de zones, de vecteurs relatifs et de particules. Les concepts sont les mêmes — seule la syntaxe change. Les événements EliteScript deviennent des noms de hooks comme on_spawn ou on_boss_damaged_by_player. Les cibles et les zones sont passées sous forme de tables à context.script en utilisant les mêmes noms de champs documentés dans les pages Zones EliteScript et Cibles EliteScript.

  2. Déplacez votre flux de contrôle dans Lua. Les tirages aléatoires, les fonctions d'aide partagées, les boucles, l'état persistant (context.state) et la planification de tâches (context.scheduler) sont les choses que Lua ajoute et que l'EliteScript pur ne peut pas faire facilement. Commencez par convertir un pouvoir avec branchement ou condition en Lua tout en gardant tout le reste identique.

  3. Utilisez context.script pour le ciblage et la géométrie des zones. Ce ne sont pas de simples sosies — la table de spécification que vous transmettez est remise au véritable moteur EliteScript, de sorte que chaque champ documenté dans les pages EliteScript (targetType, shape, Target, Target2, FinalTarget, range, offset, relativeOffset, coverage, filter, ...) fonctionne littéralement, avec les mêmes valeurs par défaut et la même casse. Gardez la documentation EliteScript ouverte comme référence de spécification et utilisez Lua uniquement pour la couche logique.

  4. Attention aux deux systèmes de zones. context.script:zone({shape = "SPHERE", ...}) est le moteur EliteScript (enums en MAJUSCULES, tables de spécification Target). context.zones est une implémentation légère distincte (kind en minuscules, emplacements origin/destination simples). Mélanger leurs styles de clés produit silencieusement une zone vide.


Parcours de progression pour débutants

Si vous voulez apprendre ce système à partir de zéro, cette progression fonctionne bien :

  1. Écrivez un fichier avec seulement api_version = 1 et on_spawn.
  2. Faites en sorte que le boss envoie un message ou joue un son.
  3. Ajoutez un délai de récupération avec context.cooldowns.
  4. Ajoutez un hook déclenché par le joueur tel que on_boss_damaged_by_player.
  5. Ajoutez une action différée avec context.scheduler:run_after(...).
  6. Ajoutez une requête de zone Lua native simple ou un simple context.script:target(...).
  7. Ce n'est qu'ensuite que vous passerez aux attaques en rotation, aux machines à états et aux mécaniques en plusieurs étapes.

Chaque étape s'appuie sur la précédente, et vous pouvez tester à chaque stade. N'essayez pas d'écrire un boss multi-phases comme premier pouvoir Lua.


Étapes suivantes

  • Premiers pas — structure des fichiers, hooks, premier pouvoir pas à pas, modèles à copier-coller
  • Scripts de PNJ — scripts de proximité, d'interaction et de cycle de vie des PNJ
  • Exemples & Modèles — pouvoirs complets et fonctionnels que vous pouvez étudier et adapter