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

Tous les hooks ne fournissent pas de joueur. on_spawn, on_game_tick et on_exit_combat n'ont pas de joueur. on_enter_combat fournit bien context.player (le joueur qui a déclenché le combat). Dans on_boss_damaged (dégâts génériques), l'auteur des dégâts peut ne pas être un joueur. Ajoutez toujours une protection contre nil avant d'utiliser context.player.

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

Si un hook ou un callback prend trop de temps, le pouvoir est automatiquement désactivé pour éviter le lag. Le message de la console ressemble à ceci :

[Lua] my_power.lua took 73ms in 'on_game_tick' (limit: 50ms) — script disabled to prevent lag.

Causes courantes : itérer sur trop d'entités, créer trop de zones par tick, ou exécuter des opérations de chaîne coûteuses dans on_game_tick. Placez le travail coûteux derrière une barrière de délai de récupération (cooldown) ou réduisez le travail effectué par appel.

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

Vérifiez que le nom de la particule est une valeur d'énumération Particle Bukkit valide en MAJUSCULES. Erreur courante : "flame" (faux) vs "FLAME" (correct). Vérifiez aussi que amount est au moins de 1 et que l'emplacement se trouve dans un chunk chargé.

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).
Délai dépassé<filename> a pris Xms dans 'hook_name' (limite : 50ms) — script désactivé pour éviter le lag.
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. Les utilitaires de script acceptent les mêmes noms de champs qu'EliteScript (targetType, shape, Target, Target2, range, offset, coverage), vous pouvez donc continuer à utiliser la documentation EliteScript existante comme référence pour ces spécifications. Cela vous permet d'exploiter des modèles familiers tout en gagnant la flexibilité de Lua pour la couche logique.


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