Script Lua : Exemples et modèles
Cette page contient des exemples complets et fonctionnels de pouvoirs Lua EliteMobs, ainsi que des modèles pratiques, des bonnes pratiques et des conseils. Chaque exemple comprend une explication détaillée de ce qu'il fait et pourquoi.
Si vous débutez avec les pouvoirs Lua, commencez par Premiers pas. Pour les détails complets de l'API, consultez la Référence API, Boss et entités, Monde et environnement, Zones et ciblage et Enums.
Exemple : Ciblage par zone avec les utilitaires de script
Ce que cet exemple enseigne : Comment utiliser context.script pour créer une géométrie de zone de style EliteScript depuis Lua, générer des particules et infliger des dégâts aux entités dans la zone.
Fichier de pouvoir complet (cliquez pour développer)
return {
api_version = 1,
on_boss_damaged_by_player = function(context)
local cone = context.script:zone({
shape = "CONE",
Target = {
targetType = "SELF",
offset = "0,1,0"
},
Target2 = {
targetType = "NEARBY_PLAYERS",
range = 20
},
radius = 5
})
context.script:spawn_particles(
cone:full_target(0.4),
{
particle = "FLAME",
amount = 1,
speed = 0.05
}
)
context.script:damage(cone:full_target(), 1.0, 1.5)
end
}
Explication
-
Création de zone --
context.script:zone(...)crée une forme de cône en utilisant les mêmes noms de champs que les Zones EliteScript.Targetdéfinit l'origine du cône (le boss lui-même, décalé de 1 bloc vers le haut), etTarget2définit la destination (les joueurs les plus proches dans un rayon de 20 blocs).radiuscontrôle l'ouverture du cône. -
Génération de particules --
cone:full_target(0.4)retourne un handle de cible qui résout toutes les positions à l'intérieur du cône avec 40% de couverture (échantillonne aléatoirement 40% des points de zone à chaque appel). La spécification de particules utilise les mêmes noms de champs que les particules EliteScript :particle,amountetspeed. -
Dégâts --
context.script:damage(cone:full_target(), 1.0, 1.5)touche toutes les entités vivantes à l'intérieur du cône complet. Le premier nombre (1.0) est le montant de dégâts de base, et le second (1.5) est le multiplicateur de dégâts appliqué aux joueurs.
Les tables de zone et de cible passées à context.script utilisent les noms de champs EliteScript (targetType, shape, Target, Target2, range, offset, coverage). Pour la liste complète, consultez Zones EliteScript et Cibles EliteScript.
Exemple : Boucle d'attaque avec état et planificateur
Ce que cet exemple enseigne : Utilisation de context.state pour suivre l'état d'exécution, context.scheduler pour les tâches répétitives et le cycle de vie approprié d'entrée/sortie de combat.
Fichier de pouvoir complet (cliquez pour développer)
local function pick_action(context)
local roll = math.random(1, 2)
if roll == 1 then
context.boss:play_model_animation("slam")
else
context.boss:play_model_animation("roar")
end
end
return {
api_version = 1,
on_spawn = function(context)
context.state.started = false
context.state.loop_task_id = nil
end,
on_enter_combat = function(context)
if context.state.started then
return
end
context.state.started = true
context.state.loop_task_id = context.scheduler:run_every(100, function(loop_context)
if loop_context.boss.exists then
pick_action(loop_context)
end
end)
end,
on_exit_combat = function(context)
if context.state.loop_task_id ~= nil then
context.scheduler:cancel_task(context.state.loop_task_id)
context.state.loop_task_id = nil
end
context.state.started = false
end
}
Explication
-
Initialisation de l'état --
on_spawninitialisecontext.state.startedàfalseetcontext.state.loop_task_idànil. La tablestatepersiste pendant toute la durée de vie de cette instance de boss, donc les valeurs définies ici survivent entre les hooks. -
Garde de combat --
on_enter_combatvérifiecontext.state.startedavant de démarrer la boucle. Cela empêche les boucles multiples superposées si l'événement se déclenche plus d'une fois. -
Modèle de planificateur --
context.scheduler:run_every(100, callback)exécute le callback toutes les 100 ticks (5 secondes). Le callback reçoit un contexte frais, doncloop_context.bossvous donne le dernier snapshot du boss. Le planificateur retourne un ID de tâche numérique que vous stockez dans l'état. -
Nettoyage à la sortie --
on_exit_combatannule la tâche répétitive en utilisant l'ID de tâche stocké et réinitialise l'état. C'est essentiel : sans nettoyage, le planificateur continue de s'exécuter même après la fin du combat.
Si vous démarrez une tâche répétitive dans on_enter_combat, annulez-la toujours dans on_exit_combat. Oublier d'annuler laisse une tâche en arrière-plan qui s'exécute jusqu'au despawn du boss, ce qui gaspille des performances et peut causer un comportement inattendu.
Exemple : Effet de feu au toucher
Ce que cet exemple enseigne : Un simple pouvoir « appliquer un effet au toucher » -- le modèle le plus courant pour les pouvoirs de combat.
Fichier de pouvoir complet (cliquez pour développer)
return {
api_version = 1,
on_player_damaged_by_boss = function(context)
-- Garde : le joueur peut être nil dans des cas limites
if context.player == nil then
return
end
-- Vérifie et définit un cooldown local de 60 ticks (3 secondes) en un seul appel
if not context.cooldowns:check_local("fire_touch", 60) then
return
end
-- Met le joueur en feu pendant 60 ticks (3 secondes)
context.player:set_fire_ticks(60)
-- Retour visuel : génère des particules de flamme à la position du joueur
context.world:spawn_particle_at_location(
context.player.current_location,
{ particle = "FLAME", amount = 20, speed = 0.1 }
)
-- Indique au joueur ce qui s'est passé
context.player:send_message("&cThe boss's touch burns!")
-- Définit le cooldown global des pouvoirs pour que les autres pouvoirs
-- de ce boss ne se déclenchent pas tous au même instant
context.cooldowns:set_global(40)
end
}
Explication
-
Garde nil --
context.playerest une clé paresseuse qui résout le joueur impliqué dans l'événement. Dans de rares cas limites (par ex., le joueur s'est déconnecté entre le déclenchement de l'événement et l'exécution du hook), il peut êtrenil. Vérifiez toujours avant d'utiliser. -
Cooldown local --
context.cooldowns:check_local("fire_touch", 60)fait deux choses de manière atomique : il vérifie si la clé de cooldown"fire_touch"est prête, et si c'est le cas, il définit immédiatement le cooldown à 60 ticks. Si le cooldown n'est pas prêt, il retournefalseet la fonction se termine prématurément. La clé"fire_touch"est limitée à cette instance de boss -- les autres boss avec le même pouvoir ont des cooldowns indépendants. -
Ticks de feu --
context.player:set_fire_ticks(60)met le joueur en feu pendant 60 ticks de jeu (3 secondes). Cela appelle directement la méthode Bukkit sous-jacente. -
Particules --
context.world:spawn_particle_at_location(location, spec)génère des particules à un emplacement spécifique. La table spec accepteparticle(nom de l'enum de particules Bukkit),amountetspeed. -
Message --
context.player:send_message(text)envoie un message avec codes couleur dans le chat. Les codes couleur Minecraft standard comme&c(rouge) fonctionnent automatiquement. -
Cooldown global --
context.cooldowns:set_global(40)met tous les pouvoirs de ce boss en cooldown de 40 ticks (2 secondes). Cela empêche plusieurs pouvoirs de se déclencher simultanément.
Exemple : Pouvoir AoE par zone avec zones natives Lua
Ce que cet exemple enseigne : Créer et interroger des zones Lua natives pour infliger des dégâts aux joueurs dans une zone.
Fichier de pouvoir complet (cliquez pour développer)
return {
api_version = 1,
on_spawn = function(context)
context.state.aoe_task_id = nil
end,
on_enter_combat = function(context)
-- Empêcher les boucles en double
if context.state.aoe_task_id ~= nil then
return
end
context.state.aoe_task_id = context.scheduler:run_every(60, function(tick_context)
-- S'assurer que le boss est toujours en vie
if not tick_context.boss.exists then
return
end
-- Vérifier un cooldown local pour éviter l'empilement avec d'autres effets
if not tick_context.cooldowns:check_local("pulse_aoe", 60) then
return
end
-- Construire une zone sphérique centrée sur la position actuelle du boss
local zone_def = {
kind = "sphere",
radius = 8,
origin = tick_context.boss:get_location()
}
-- Trouver tous les joueurs à l'intérieur de la sphère
local victims = tick_context.zones:get_entities_in_zone(zone_def, { filter = "players" })
-- Infliger des dégâts et afficher des particules sur chaque joueur trouvé
for i = 1, #victims do
local victim = victims[i]
victim:deal_custom_damage(4.0)
tick_context.world:spawn_particle_at_location(
victim.current_location,
{ particle = "DUST", amount = 15, speed = 0, red = 128, green = 0, blue = 255 }
)
end
-- Générer des particules visuelles en anneau au boss
tick_context.world:spawn_particle_at_location(
tick_context.boss:get_location(),
{ particle = "WITCH", amount = 40, speed = 0.1 }
)
-- Définir le cooldown global
tick_context.cooldowns:set_global(60)
end)
end,
on_exit_combat = function(context)
if context.state.aoe_task_id ~= nil then
context.scheduler:cancel_task(context.state.aoe_task_id)
context.state.aoe_task_id = nil
end
end
}
Explication
-
Configuration de l'état --
on_spawninitialiseaoe_task_idànil. Cet ID de tâche conservera la référence du planificateur répétitif. -
Attaque répétitive --
on_enter_combatdémarre une tâche répétitive toutes les 60 ticks (3 secondes). La garde au début empêche de démarrer une seconde boucle si le combat reprend. -
Définition de zone -- La table
zone_defutilise la syntaxe de zone Lua native. Le champkindspécifie la forme ("sphere"),radiusdéfinit la taille, etoriginest défini sur la position actuelle du boss au moment où le callback s'exécute. Cela signifie que la zone suit le boss lorsqu'il se déplace. -
Requête d'entités --
tick_context.zones:get_entities_in_zone(zone_def, { filter = "players" })retourne un tableau Lua de toutes les tables de joueurs à l'intérieur de la sphère. L'optionfilteraccepte"players","elites","mobs"ou"living"(par défaut). -
Infliger des dégâts --
victim:deal_custom_damage(4.0)inflige 4 points de dégâts attribués au boss. Cela utilise le système de dégâts personnalisé d'EliteMobs, qui respecte l'armure et les autres modificateurs de combat. -
Retour visuel par particules -- Des particules de poussière violette apparaissent sur chaque victime, et des particules ambiantes apparaissent à la position du boss pour signaler visuellement l'impulsion.
-
Nettoyage --
on_exit_combatannule la tâche répétitive et efface l'état, suivant le même modèle que l'exemple précédent.
Cet exemple utilise les zones Lua natives (context.zones:get_entities_in_zone()), qui prennent une table simple avec kind, radius, origin, etc. Les utilitaires de script (context.script:zone(...)) utilisent les noms de champs EliteScript comme shape, Target et Target2. Les deux fonctionnent -- utilisez les zones natives pour les formes simples et context.script lorsque vous avez besoin de la résolution avancée de cibles d'EliteScript.
Exemple : Mécanique de boss multi-phases
Ce que cet exemple enseigne : Utilisation de l'état pour suivre les phases du boss et changer de comportement aux seuils de santé.
Fichier de pouvoir complet (cliquez pour développer)
local function phase_one_attack(context)
-- Frappe lente et lourde
context.boss:play_model_animation("slam")
local zone_def = {
kind = "sphere",
radius = 5,
origin = context.boss:get_location()
}
local targets = context.zones:get_entities_in_zone(zone_def, { filter = "players" })
for i = 1, #targets do
targets[i]:deal_custom_damage(3.0)
end
context.world:spawn_particle_at_location(
context.boss:get_location(),
{ particle = "EXPLOSION", amount = 3, speed = 0 }
)
end
local function phase_two_attack(context)
-- Multi-coups rapides et frénétiques
context.boss:play_model_animation("frenzy")
local zone_def = {
kind = "sphere",
radius = 8,
origin = context.boss:get_location()
}
local targets = context.zones:get_entities_in_zone(zone_def, { filter = "players" })
for i = 1, #targets do
targets[i]:deal_custom_damage(2.0)
targets[i]:apply_potion_effect("SLOWNESS", 40, 1)
end
context.world:spawn_particle_at_location(
context.boss:get_location(),
{ particle = "DUST", amount = 30, speed = 0.2, red = 255, green = 0, blue = 0 }
)
context.world:play_sound_at_location(
context.boss:get_location(),
"entity.wither.ambient",
1.0, 1.5
)
end
return {
api_version = 1,
on_spawn = function(context)
context.state.phase = 1
context.state.attack_task_id = nil
context.state.phase_switched = false
end,
on_enter_combat = function(context)
if context.state.attack_task_id ~= nil then
return
end
-- Démarrer la boucle d'attaque phase 1 : toutes les 100 ticks (5 secondes)
context.state.attack_task_id = context.scheduler:run_every(100, function(tick_context)
if not tick_context.boss.exists then
return
end
if not tick_context.cooldowns:check_local("phase_attack", 100) then
return
end
phase_one_attack(tick_context)
end)
end,
on_game_tick = function(context)
-- Ne vérifier la transition de phase que toutes les 20 ticks (1 seconde) pour rester léger
if not context.cooldowns:check_local("phase_check", 20) then
return
end
-- Ignorer si déjà en phase 2
if context.state.phase ~= 1 then
return
end
-- Vérifier le ratio de santé
local health_ratio = context.boss.health / context.boss.maximum_health
if health_ratio <= 0.5 then
-- Transition vers la phase 2
context.state.phase = 2
context.state.phase_switched = true
context.log:info("Boss entering phase 2 at " .. tostring(math.floor(health_ratio * 100)) .. "% health")
-- Annuler l'ancienne boucle d'attaque
if context.state.attack_task_id ~= nil then
context.scheduler:cancel_task(context.state.attack_task_id)
context.state.attack_task_id = nil
end
-- Jouer les effets de transition
context.boss:play_model_animation("transform")
-- Annoncer le changement de phase aux joueurs proches
local nearby = context.players.nearby_players(40)
for i = 1, #nearby do
nearby[i]:send_message("&4&lThe boss enters a frenzy!")
nearby[i]:show_title("&4Phase 2", "&cThe boss is enraged!", 10, 40, 10)
end
-- Démarrer une boucle d'attaque phase 2 plus rapide : toutes les 40 ticks (2 secondes)
context.state.attack_task_id = context.scheduler:run_every(40, function(tick_context)
if not tick_context.boss.exists then
return
end
if not tick_context.cooldowns:check_local("phase_attack", 40) then
return
end
phase_two_attack(tick_context)
end)
end
end,
on_exit_combat = function(context)
if context.state.attack_task_id ~= nil then
context.scheduler:cancel_task(context.state.attack_task_id)
context.state.attack_task_id = nil
end
end
}
Explication
-
Initialisation de l'état --
on_spawndéfinitphaseà1,attack_task_idàniletphase_switchedàfalse. Ces valeurs persistent entre tous les hooks pour cette instance de boss. -
Boucle d'attaque phase 1 --
on_enter_combatdémarre une tâche répétitive qui exécutephase_one_attacktoutes les 100 ticks. L'attaque crée une sphère de 5 blocs, inflige des dégâts aux joueurs à l'intérieur et joue une animation de frappe avec des particules d'explosion. -
Vérification de phase dans on_game_tick --
on_game_tickse déclenche à chaque tick serveur, donc la première chose qu'il fait est de vérifier un cooldown de 20 ticks ("phase_check") pour éviter d'exécuter une logique coûteuse à chaque tick. Si le boss est déjà en phase 2, il retourne immédiatement. -
Seuil de santé --
context.boss.health / context.boss.maximum_healthdonne la santé actuelle sous forme de fraction. Lorsqu'elle descend à 50% ou en dessous, la transition commence. -
Transition de phase -- L'ancienne boucle d'attaque est annulée, une animation de transformation est jouée, les joueurs proches reçoivent un message et un titre, et une nouvelle boucle d'attaque plus rapide démarre (toutes les 40 ticks au lieu de 100).
-
Attaques phase 2 --
phase_two_attackutilise une sphère plus grande (8 blocs), inflige un peu moins de dégâts par coup mais se déclenche beaucoup plus fréquemment, applique un effet de potion de lenteur et utilise des particules de poussière rouge et un son de wither pour une ambiance différente. -
Journalisation --
context.log:info(...)écrit dans la console du serveur, ce qui est inestimable pour déboguer les transitions de phase pendant le développement. -
Nettoyage --
on_exit_combatannule la boucle d'attaque active, quelle que soit la phase du boss.
on_game_tick s'exécute à chaque tick serveur (20 fois par seconde). Protégez toujours le travail coûteux derrière une vérification de cooldown, comme montré avec check_local("phase_check", 20). Si votre hook dépasse 50ms, EliteMobs désactivera automatiquement le pouvoir.
Conseils pour la génération par IA
Si vous souhaitez que l'IA génère des pouvoirs Lua de manière fiable, assurez-vous que le prompt inclut :
- Nom de hook exact -- par ex.,
on_player_damaged_by_boss, pas « quand le boss frappe un joueur ». - Zones Lua natives ou utilitaires de script -- précisez lequel. Les zones natives utilisent
context.zones:get_entities_in_zone(zone_def, opts)aveckind,radius,origin. Les utilitaires de script utilisentcontext.script:zone(...)avec les noms de champs EliteScript commeshape,Target,Target2. - Cooldowns locaux et globaux -- précisez le nom de clé de cooldown et la durée en ticks.
context.cooldowns:check_local(key, ticks)pour les cooldowns par boss,context.cooldowns:set_global(ticks)pour le cooldown de pouvoir partagé. - Noms d'animation de modèle personnalisé -- par ex.,
context.boss:play_model_animation("slam"). L'IA ne peut pas deviner les noms d'animation ; fournissez-les. - Sélection de cible -- précisez si le pouvoir cible
context.player(le joueur de l'événement),context.players.nearby_players(range)ou une requête de zone. - Type d'effet -- dégâts (
deal_custom_damage), potion (apply_potion_effect), feu (set_fire_ticks), vélocité (set_velocity_vector,apply_push_vector), etc. - N'utilisez que des noms de méthodes documentés -- si ce n'est pas sur la page de Référence API, cela n'existe pas.
- Les spécifications d'utilitaires de script utilisent les noms de champs EliteScript --
targetType,shape,Target,Target2,range,offset,coverage, pas des noms de style Lua. - Les callbacks du planificateur acceptent un contexte frais -- le paramètre du callback est un nouveau contexte, pas le contexte externe. Utilisez toujours
tick_context(ou le nom que vous donnez au paramètre) à l'intérieur des callbacks.
Bon exemple de prompt
Écrivez un pouvoir Lua qui utilise
on_enter_combatpour démarrer une tâche répétitive toutes les 80 ticks. À chaque tick, créez une zone de sphère Lua native (rayon 6) centrée sur le boss, interrogez les joueurs à l'intérieur et infligez 2.0 de dégâts personnalisés à chacun. Utilisez une clé de cooldown locale"pulse"avec une durée de 80. Annulez la tâche danson_exit_combat. Générez des particules DUST (red=0, green=255, blue=100) sur chaque victime.
Contraintes supplémentaires à inclure
- « Retournez une seule table avec
api_version = 1. » - « Initialisez tous les champs d'état dans
on_spawn. » - « Protégez les callbacks du planificateur avec
if not tick_context.boss.exists then return end. » - « Annulez toutes les tâches répétitives dans
on_exit_combat. » - « N'inventez pas de noms de méthodes -- n'utilisez que les méthodes de la page de Référence API. »
- « Utilisez
context.cooldowns:check_local(key, ticks)pour une vérification-et-définition combinée. »
Liste de vérification QC pour révision humaine ou IA
Utilisez cette liste de vérification pour valider un pouvoir Lua avant de le déployer :
- Le fichier retourne exactement une table avec
api_version = 1. - Chaque nom de hook correspond exactement à une entrée dans la liste des hooks (par ex.,
on_player_damaged_by_boss, pason_player_hit). context.playerest protégé avec== nilavant utilisation dans les hooks où il peut être nil.- Les champs de
context.statesont initialisés danson_spawn. - Chaque appel
context.scheduler:run_every(...)a uncontext.scheduler:cancel_task(...)correspondant danson_exit_combat. - Les callbacks du planificateur utilisent le paramètre de contexte propre au callback, pas le
contextexterne. - Les clés de cooldown sont des chaînes descriptives (par ex.,
"fire_pulse") et les durées sont en ticks. - Les hooks
on_game_tickprotègent le travail coûteux derrière une vérification de cooldown. - Tous les noms de méthodes existent dans la Référence API -- pas d'alias inventés.
- Les tables d'utilitaires de script utilisent les noms de champs EliteScript (
targetType,shape,Target, etc.), pas des noms de style Lua. - Les définitions de zone natives utilisent
kind,radius,origin,destination, etc. - Le pouvoir n'appelle aucune opération bloquante ou de longue durée à l'intérieur d'un hook ou callback.
- Les spécifications de particules utilisent des noms d'enum de particules Bukkit valides en MAJUSCULES (par ex.,
"FLAME","DUST","EXPLOSION").
Bonnes pratiques
-
Commencez petit et vérifiez. Écrivez un seul
on_spawnqui envoie un message de log. Confirmez qu'il se déclenche. Puis construisez à partir de là. -
Gardez les fonctions auxiliaires locales. Déclarez les helpers comme
local function pick_action(context)au-dessus de la table de retour. Cela les garde hors de la portée globale et évite les collisions avec d'autres pouvoirs Lua chargés dans le même runtime. -
Placez la géométrie dans les utilitaires de script. Si vous avez besoin de cônes, de rayons rotatifs, de rayons en translation ou de zones animées, utilisez
context.script:zone(...)avec les noms de champs EliteScript. Les utilitaires de script réutilisent le moteur de zones éprouvé d'EliteScript. -
Utilisez
context.statepour l'état d'exécution. N'utilisez pas de variables globales Lua.context.stateest limité à une seule instance de boss et persiste entre les hooks pendant toute la durée de vie de ce boss. -
Utilisez des clés de cooldown locales nommées. Au lieu de simples nombres, utilisez des clés descriptives comme
"fire_touch"ou"aoe_pulse". Cela facilite le débogage et empêche les collisions accidentelles entre différents cooldowns dans le même pouvoir. -
Gardez
on_game_tickléger. Protégez-le toujours derrière une vérification de cooldown. Si votre logique s'exécute à chaque tick, elle doit se terminer en bien moins de 50ms ou le pouvoir sera désactivé. -
Annulez les tâches répétitives quand c'est terminé. Chaque
run_everydoit avoir uncancel_taskcorrespondant danson_exit_combat(et éventuellementon_death). Les tâches non annulées gaspillent du CPU et peuvent causer des erreurs de référence nulle après la disparition du boss. -
Utilisez des contextes frais dans les callbacks du planificateur. Les callbacks du planificateur (
run_every,run_after) reçoivent un contexte frais comme paramètre. Utilisez toujours ce paramètre -- pas lecontextexterne -- car le contexte externe peut contenir des snapshots obsolètes. -
Journalisez les transitions d'état avec
context.log:info(). Pendant le développement, ajoutez des logs pour les changements de phase, les débuts de cooldown et les démarrages/arrêts du planificateur. Supprimez ou changez encontext.log:debug()avant le déploiement. -
Réutilisez la documentation EliteScript existante. Les pages Zones, Cibles, Vecteurs relatifs et Conditions documentent les mêmes noms de champs que les utilitaires de script acceptent. Ne dupliquez pas ces informations dans votre pouvoir Lua -- faites simplement référence à celles-ci.
Erreurs courantes de débutant
-
Utiliser le
contextexterne dans un callback du planificateur. Le contexte externe capture un snapshot au moment où le hook s'est exécuté. Dans un callbackrun_everyourun_after, utilisez toujours le paramètre propre du callback (par ex.,tick_context), qui vous donne un snapshot frais. -
Oublier d'annuler les tâches répétitives. Si vous démarrez un
run_everydanson_enter_combatmais ne l'annulez jamais, la tâche continue de s'exécuter jusqu'à ce que le boss soit retiré du serveur, même après la fin du combat. -
Ne pas initialiser l'état dans
on_spawn. Si vous lisezcontext.state.phasedanson_game_tickmais ne le définissez jamais danson_spawn, il seranilet vos comparaisons se comporteront de manière inattendue. -
Vérifier
context.playersans garde nil. Dans les hooks commeon_player_damaged_by_boss, le joueur est presque toujours disponible -- mais « presque toujours » n'est pas « toujours ». Un seul garde nil manquant peut faire planter le pouvoir. -
Utiliser des noms de champs style Lua dans les appels d'utilitaires de script. Les utilitaires de script attendent
targetType,Target,Target2,shape-- pastarget_type,target,target2,zone_shape. Les noms non concordants ne produisent silencieusement aucun résultat. -
Exécuter une logique lourde dans
on_game_ticksans garde de cooldown. Ce hook se déclenche à chaque tick du serveur. Même une arithmétique simple répétée 20 fois par seconde sur de nombreux boss s'accumule. -
Inventer des noms de méthodes. Si une méthode n'est pas listée dans la Référence API, elle n'existe pas. Les erreurs courantes incluent écrire
entity:teleport(loc)au lieu deentity:teleport_to_location(loc), ouplayer:set_velocity(vec)au lieu deplayer:set_velocity_vector(vec). -
Utiliser
context.boss.healthpour définir la santé.context.boss.healthest un snapshot en lecture seule. Pour guérir le boss, utilisezcontext.boss:restore_health(amount). -
Oublier
api_version = 1. La table retournée doit inclure ce champ, sinon EliteMobs ne chargera pas le pouvoir.
Étapes suivantes
- Premiers pas -- structure de fichiers, hooks, premier pouvoir
- Hooks et cycle de vie -- référence complète des hooks et du contexte
- Boss et entités -- méthodes de boss, joueur et entité
- Monde et environnement -- particules, sons, éclairs, blocs
- Zones et ciblage -- zones natives et zones d'utilitaires de script
- Enums -- valeurs valides pour Particle, Sound, Material et autres constantes de type chaîne
- Dépannage -- problèmes courants, conseils de débogage et migration
