Módulos de comportamiento de mascotas
Un módulo de comportamiento de mascota es un archivo Lua que le dice a las mascotas qué hacer: seguir a su dueño, desplazarse a la deriva, rodear una hoguera, picar. Cada archivo de especie de mascota lista los módulos que ejecutan sus mascotas y les da ajustes. Esta página es para los autores de criaturas que quieren cambiar un módulo o escribir uno nuevo. Para usar y ajustar los módulos incluidos, consulta Mascotas.
Los módulos usan el mismo dialecto de Lua que los programas de comportamiento de EliteMobs: ai.module, ai.behavior, ai.sensor, ai.controls, memorias con tipo y el contexto c.memory, c.perception, c.actuator y c.entity. Esa página cubre las reglas compartidas. Esta cubre lo que añaden las mascotas: los archivos de módulo, c.pet, c.settings y los límites bajo los que se ejecutan las mascotas.
Archivos
- Los módulos viven en
plugins/FreeMinecraftModels/pet_behaviors/, en esa carpeta o en cualquier subcarpeta. Todo archivo.luaque haya allí es un módulo. - El nombre de un módulo es el nombre de su archivo sin
.lua, en minúsculas. Solo puede usar letras, dígitos,.,_y-. Los archivos de mascota listan los módulos por este nombre. - El
idde un módulo debe serfmm:pet/seguido de su nombre, así quepet_behaviors/mine/slow_drift.luadeclaraid = 'fmm:pet/slow_drift'. Un módulo cuyo id no coincide con el nombre de su archivo se omite con una advertencia. - Cuando dos archivos comparten nombre, se carga aquel cuya ruta va primero en orden, y la consola avisa con
Duplicate content filenamesobre el otro. Una copia idéntica byte a byte se omite sin avisar. - Un archivo o carpeta que enlaza fuera de
pet_behaviors/se omite. - FreeMinecraftModels escribe cada uno de sus 15 módulos incluidos cuando no existe ningún archivo con ese nombre en ninguna parte de la carpeta. Uno eliminado vuelve en la siguiente carga con la versión incluida actual. Un archivo que ya está allí nunca se sobrescribe, esté editado o no, ni siquiera después de moverlo a una subcarpeta, así que conserva tus cambios, pero también pierde las actualizaciones posteriores del módulo incluido.
/fmm reloadvuelve a leer todos los módulos y archivos de mascota, guarda las mascotas y las devuelve con los módulos nuevos. Sus memorias empiezan vacías. No necesitas subir larevisionde un módulo después de editarlo.
Empieza desde una copia
Los módulos incluidos son los mejores ejemplos: drift.lua mueve a una voladora, wander.lua camina, night_glow.lua es un único sensor y sting.lua tiene dos. Empieza por el más cercano a lo que quieres.
- Cópialo con un nombre nuevo, por ejemplo
pet_behaviors/mine/slow_drift.luaa partir dedrift.lua. - Cambia su
idafmm:pet/slow_drift. - Renombra sus memorias, comportamientos y sensores para que empiecen por el nombre nuevo:
drift_topasa a serslow_drift_to, enmemoriesy en todas las llamadas ac.memory, y elid = 'fmm:pet/drift'del comportamiento pasa a serfmm:pet/slow_drift. Dos módulos de una misma criatura no pueden compartir un nombre de memoria, un id de comportamiento ni un id de sensor; el segundo de la lista se deja fuera con una advertencia. Renombrar permite que la copia se ejecute junto al original. - Lístalo en el archivo de mascota en lugar del original:
- slow_drift, o con ajustes,- slow_drift: { speed: 0.03 }. - Ejecuta
/fmm reloady revisa la consola.
Editar un módulo incluido en su sitio también funciona, pero cambia todas las especies que lo listan.
Un archivo de módulo
Este módulo es pequeño pero completo. Por la noche la mascota se queda en un punto cercano a su ancla en lugar de desplazarse a la deriva, y cada 10 segundos desde el momento en que elige ese punto, reproduce una animación.
-- At night: settles on one spot near its anchor (its owner, or home when wild) and plays an animation now and then.
return ai.module {
id = 'fmm:pet/night_rest', revision = 1,
-- radius: blocks around the anchor. speed: blocks per tick for a flyer, at species speed 1.
settings = { radius = 3, speed = 0.04, animation = 'interact' },
memories = { night_rest_to = 'position', night_rest_retry = 'integer' },
behaviors = {
ai.behavior {
id = 'fmm:pet/night_rest', priority = 12, probe_interval = 10,
controls = { ai.controls.move, ai.controls.look },
can_start = function(c)
return c.pet.night and not c.pet.staying and c.pet.anchor ~= nil
and c.tick >= (c.memory:get('night_rest_retry') or 0)
end,
can_continue = function(c)
return c.pet.night and not c.pet.staying and c.memory:contains('night_rest_to')
end,
start = function(c)
local anchor = c.pet.anchor
local to = anchor and c.pet:rest_point(anchor, c.settings.radius)
if to ~= nil then
c.memory:set('night_rest_to', to)
else
-- Nothing fits here: look again in 5 seconds instead of every tick.
c.memory:set('night_rest_retry', c.tick + 100)
end
end,
tick = function(c)
local to = c.memory:get('night_rest_to')
if to ~= nil then c.pet:steer_to(to, c.settings.speed * c.pet.species.speed) end
end,
stop = function(c)
c.memory:forget('night_rest_to')
c.pet:stop()
end
}
},
sensors = {
ai.sensor {
id = 'fmm:pet/night_rest_animation', interval = 200,
sense = function(c)
if c.memory:contains('night_rest_to') then c.pet:play_animation(c.settings.animation) end
end
}
}
}
Un archivo de mascota lo lista entonces como - night_rest, o - night_rest: { radius: 5, animation: idle }.
| Campo | Notas |
|---|---|
id | Obligatorio. fmm:pet/ y el nombre del archivo |
revision | Obligatorio. Cualquier número entero positivo |
settings | Opcional. Los valores predeterminados que los archivos de mascota pueden cambiar. El tipo de cada valor predeterminado es el tipo que debe dar un archivo de mascota: un número, true/false, texto o una lista de textos. Consulta Valores de los ajustes |
memories | Opcional. Lo que el módulo recuerda para cada mascota, por nombre y tipo: integer, number, boolean, string, uuid o position. Empieza cada nombre con el nombre del módulo. Consulta Memorias |
dependencies | Opcional. Ids de otros módulos de pet_behaviors/ que necesita este. Se ejecutan en todas las criaturas que listan este, con sus ajustes predeterminados salvo que el archivo de mascota también los liste |
behaviors | Opcional. Entradas ai.behavior { ... }, que mueven o giran a la mascota |
sensors | Opcional. Entradas ai.sensor { ... }, que nunca mueven a la mascota |
Se permite código por encima de return, como funciones locales y constantes; wander.lua e idle_look.lua tienen algo.
Qué recibe un callback
| Nombre | Qué es |
|---|---|
c.pet | La mascota, de solo lectura. Consulta c.pet |
c.settings | Los ajustes de este módulo: sus valores predeterminados con los valores del archivo de mascota y de la variante por encima, como en c.settings.radius. Cada mascota tiene su propia copia, así que escribir en ella solo cambia a esa mascota |
c.memory | get(name), set(name, value), forget(name) y contains(name) para los nombres de memories. Cada mascota tiene la suya |
c.tick | El tick actual del juego, para temporizadores |
c.perception, c.actuator, c.entity | El contexto Mind de MagmaCore, como en los programas de comportamiento de EliteMobs. c.entity es el cuerpo oculto, no el modelo. Consulta Contexto de un programa Mind. idle_look.lua usa c.perception:nearest_player(range) y c.actuator:look_at(point) |
c.pet
Un punto es una tabla con x, y y z, y opcionalmente world, como c.pet.position. Un punto sin world está en el mundo de la mascota. Un punto en otro mundo cuenta como nada: los métodos responden nil, false o 0, y distance_to responde math.huge. Los puntos que devuelve c.pet siempre están en el mundo de la mascota, y uno que estaría en otro mundo se lee como nil.
- Los métodos se llaman con dos puntos:
c.pet:distance_to(point). - Los argumentos numéricos deben ser finitos. Los radios, profundidades, alturas, amplificadores, duraciones y demás rangos están limitados como se indica a continuación. Ningún método carga un chunk.
c.petyc.pet.speciesson de solo lectura. Asignarles algo provoca un error; guarda los valores por mascota enc.memory.- Las propiedades y
route_target()son una instantánea: cada una se lee una vez por tick de la mascota y permanece igual durante todos los callbacks de ese tick.c.pet:teleport_near_owneryc.pet:stoplas actualizan. Un movimiento hecho de otra forma, comoc.entity:teleport, se ve en el siguiente tick.speedes la excepción y siempre se lee de nuevo. - Cada lectura de una ubicación da una tabla nueva, que el módulo puede modificar.
Propiedades
| Nombre | Tipo | Valor |
|---|---|---|
wild | bool | true para una mascota salvaje, false para una con dueño |
staying | bool | Con la orden de quedarse |
settled | bool | Sin la orden de quedarse, y salvaje o a menos de follow.distance de su dueño |
baby | bool | Es una cría |
migrating | bool | Volando una ruta de migración nocturna |
model | string | El modelo de su variante. Una cría que lleva babyModel sigue leyendo su variante |
position | point | Dónde está su cuerpo |
home | point/nil | Dónde vive una mascota salvaje; nil para una mascota con dueño |
anchor | point/nil | Aquello alrededor de lo que merodea: su dueño, o en una mascota salvaje su hogar, o el lugar donde está cuando no tiene hogar. nil cuando el dueño está desconectado o en otro mundo |
stay_anchor | point/nil | El punto donde se le ordenó quedarse; nil cuando no tiene la orden de quedarse |
owner_location | point/nil | nil para una mascota salvaje, o cuando el dueño está desconectado, muerto o en otro mundo |
owner_distance | number | Bloques hasta el dueño; math.huge cuando no hay ninguno en este mundo |
night, day | bool | day solo con luz diurna en un mundo normal; el anochecer, el amanecer, el Nether y el End cuentan como night |
raining | bool | La lluvia cae sobre la mascota, comprobado como máximo cada 10 ticks |
speed | number | La velocidad actual de su cuerpo, en bloques por tick |
route_cruise | number | La velocidad de crucero de su bandada en una migración, y 0 en caso contrario |
species | table | Los números del archivo de la mascota, a continuación |
c.pet.species contiene:
| Campo | Clave del archivo de mascota |
|---|---|
id | species |
speed | follow.speed |
hover_height | float.hoverHeight |
hover_variance | float.hoverVariance |
roam_radius | follow.roamRadius |
follow_distance | follow.distance |
leash_distance | follow.leashDistance |
teleport_distance | follow.teleportDistance |
scale | scale |
baby_scale | babyScale |
Movimiento
Llama a estos métodos solo desde start, tick o stop de un comportamiento, en un comportamiento cuyos controls listen lo que necesitan. Desde can_start o desde un sensor, steer_to y stop provocan un error que indica dónde les corresponde estar.
| Método | Devuelve | Qué hace |
|---|---|---|
steer_to(point, cruise) | bool | Avanza un tick hacia el punto, así que llámalo en cada tick. Necesita move y look. Una voladora vuela a cruise bloques por tick (0 a 4), frenando al llegar. Una caminante o nadadora busca una ruta hasta allí con la navegación nativa a 4 × cruise veces la velocidad de movimiento de su tipo de cuerpo, nunca por debajo de una cuarta parte de ella; un cruise de 0 la detiene y devuelve false. false cuando no puede ir allí |
stop() | nil | Deja de moverse. Necesita move |
teleport_near_owner(radius) | bool | Coloca el cuerpo junto a su dueño, a menos de radius bloques (hasta 64), en su propio medio; para una nadadora, el agua se busca en un radio de al menos 6 bloques. Una caminante o nadadora cae al menos a un bloque del dueño. false cuando el dueño está ausente o en otro mundo, no hay ningún punto válido, o el punto no queda al menos un bloque más cerca del dueño de lo que ya está la mascota. No necesita ningún control, pero llámalo desde un comportamiento que tenga move, como hace follow_owner, para que no aparte a la mascota de otro comportamiento |
Puntos y distancias
Estos funcionan desde cualquier callback. Los que devuelven un punto devuelven nil cuando no hay ningún punto válido o el chunk no está cargado. Los radios llegan hasta 64.
| Método | Devuelve | Qué hace |
|---|---|---|
hover_point(center, radius) | point/nil | Un punto de su banda de flotación a menos de radius |
rest_point(center, radius) | point/nil | Un punto de descanso en su propio medio: la banda de flotación para una voladora, suelo firme para una caminante o un cuerpo estacionario, agua para una nadadora (a la altura de center cuando center está en el agua, y si no entre 0,5 y 2 bloques bajo la superficie), y suelo o si no agua para un cuerpo anfibio |
ground_point(center, radius) | point/nil | Un punto de apoyo, desde unos 5 bloques por debajo hasta 4 por encima de center. nil sobre un líquido o una caída larga |
water_point(center, radius, min_depth, max_depth) | point/nil | Un punto de nado entre las dos profundidades bajo la superficie (0 a 16) |
ground_below(point, depth) | number/nil | La altura de la parte superior del suelo a menos de depth bloques hacia abajo (1 a 64). Una superficie de agua o lava cuenta como suelo salvo que la especie sea AQUATIC. Sin suelo al alcance, la altura del punto menos depth |
trail_point(back, height) | point/nil | back bloques por detrás del dueño, según hacia dónde mira, height por encima de sus pies para una especie FLYING y a la altura de sus pies en los demás casos. nil cuando el dueño está ausente o en otro mundo |
distance_to(point) | number | Bloques desde su cuerpo |
route_target() | point/nil | Dónde quiere su ruta de migración que esté en este tick. nil cuando no está migrando o la ruta ha terminado |
find_perch(height, radius) | point/nil | height bloques (0 a 8) por encima de las hojas más cercanas bajo ella, hasta radius bloques (0 a 4) hacia los lados, o por encima del suelo justo debajo. Una mascota con dueño solo recibe una percha a menos de follow.distance de su dueño |
nearest_campfire(radius, keep_ticks, blocks, soul_variants, height) | point/nil | El bloque del fuego encendido más cercano que puede usar a menos de radius (1 a 32). blocks lista los tipos de fuego que acepta, CAMPFIRE, SOUL_CAMPFIRE o ambos, y una lista que no nombra ninguno acepta ambos; soul_variants lista los modelos que aceptan solo hogueras de almas, y todos los demás modelos aceptan entonces solo las normales. Una mascota con dueño solo acepta un fuego cuyo punto situado height bloques por encima esté a menos de follow.distance menos 1 bloques de su dueño. La búsqueda de cada chunk se conserva durante keep_ticks ticks (20 a 1200) y la comparten todas las mascotas |
campfire_usable(fire, blocks, soul_variants, height) | bool | Si un fuego encontrado antes sigue encendido y sigue siendo adecuado |
Efectos
Estos funcionan desde cualquier callback; los sensores son el lugar habitual.
| Método | Devuelve | Qué hace |
|---|---|---|
set_glow(light, lantern_bone, animation) | nil | Ilumina los huesos de display del modelo a light (0 a 15), para jugadores de Java. Un modelo con un hueso llamado lantern_bone también repite animation. Los dos últimos son opcionales |
clear_glow() | nil | Vuelve a la luz del mundo, terminando esa animación |
scale_toward(target, span, ticks, elapsed) | nil | Lleva gradualmente el tamaño del cuerpo hacia target veces su tamaño base. Un cambio completo de 1 a span tarda ticks (al menos 2); elapsed son los ticks desde la última llamada. Multiplicadores de 0.1 a 16 |
sting_contacts(on, effect, duration, amplifier, damage, cooldown) | number | Pica a los jugadores cuyo contacto alcanzó el modelo de una mascota salvaje en el último segundo, nunca a uno en modo Creativo o Espectador, y devuelve cuántos. Borra los contactos incluso cuando on es false. Las mascotas con dueño no registran contactos |
sting_enemies(reach, effect, duration, amplifier, damage, cooldown) | number | Pica a los mobs hostiles a menos de reach bloques (0 a 4) de la hitbox del modelo, nunca a jugadores ni mascotas, y devuelve cuántos |
drizzle(depth, chance) | bool | Cuando la mascota flota quieta sobre un cultivo a menos de depth bloques (1 a 8), muestra partículas de agua y da una probabilidad chance (0 a 1) de que el cultivo crezca una etapa. true cuando está sobre un cultivo |
owner_effect(effect, duration, amplifier, range) | bool | Da al dueño el efecto de poción durante duration ticks (1 a 6000) cuando está a menos de range bloques, sin partículas. Un efecto que el dueño ya tiene, al menos igual de fuerte y de igual o mayor duración, se deja como está. false cuando el dueño está ausente, en otro mundo o fuera de rango, o el efecto no existe |
play_animation(name) | bool | Reproduce una vez una de las animaciones del modelo. false cuando el modelo no la tiene |
Para ambas picaduras, effect es un nombre de efecto de poción o NONE, duration está en ticks (1 a 6000), amplifier 0 es el nivel I (hasta 255), damage está en medios corazones y cooldown son los ticks (al menos 1) antes de que esta mascota pueda picar de nuevo a la misma víctima. Una picadura muestra chispas y reproduce un sonido de picadura de abeja, y un adulto reproduce su animación attack. Un nombre de efecto de poción que no existe genera una advertencia una vez por especie y nombre, y no aplica nada.
Comportamientos y sensores
- Un comportamiento mueve o gira a la mascota. Lista los controles que necesita,
ai.controls.moveyai.controls.lookpara las llamadas de movimiento dec.pet, y solo un comportamiento tiene un control a la vez. Mientras está detenido, MagmaCore pregunta a sucan_start. Cuando devuelvetruey los controles están libres, los toma y ejecutastart, despuésticken cada tick mientrascan_continuedevuelvetrue(sincan_continue, decidecan_start), y por últimostop. Consulta Ciclo de vida. - El número de
prioritymás bajo va primero. Un comportamiento quita los controles a uno en ejecución con un número más alto, cuyostopse ejecuta entonces. El12del ejemplo lo mantiene por detrás de seguir y de quedarse y lo pone por delante de desplazarse y flotar, pero también por delante decampfire, así que una mascota que lista ambos nunca visita una hoguera por la noche. Un número por encima de15dejaría ganar al fuego. - Un comportamiento solo compite por los controles que lista.
idle_looksolo tomalook, así que se ejecuta mientras ningún comportamiento tenga la mirada; todos los comportamientos de movimiento incluidos toman tambiénlook, así que moverse siempre gana a este. - Un archivo de mascota no puede cambiar una prioridad. Para reordenar, copia el módulo y cambia el número.
probe_intervales opcional, en ticks: mientras el comportamiento está detenido,can_startse consulta solo cada esa cantidad de ticks, con una fase propia para cada mascota. Ahorra tiempo de servidor cuando hay muchas mascotas fuera, a costa de que el comportamiento empiece con hasta esa cantidad de ticks de retraso. Su valor por defecto es1y por encima de200cuenta como200. Un comportamiento en ejecución sigue ejecutándose en cada tick.- Un sensor nunca mueve a la mascota. Ejecuta
senseen el primer tick en que se procesa el cuerpo de la mascota, y después cadaintervalticks con una fase propia de la mascota, sea lo que sea lo que estén haciendo los comportamientos. El brillo, el hinchado, las picaduras, la llovizna y los efectos para el dueño son sensores.
Los módulos incluidos usan:
| Módulo | Prioridad | probe_interval | interval del sensor |
|---|---|---|---|
migrate | 1 | 10 | |
stay | 5 | 4 | |
follow_owner | 10 | 4 | |
campfire | 15 | 10 | |
day_perch | 18 | 10 | |
rain_bloom | 19 | 10 | 4 (hinchado) |
drift, wander, swim | 20 | 10 | |
hover | 30 | 4 | |
idle_look | 30 | 10 | |
night_glow | 40 | ||
sting | 4 (jugadores), 10 (mobs) | ||
crop_drizzle | 20 | ||
owner_effect | 20 |
Reglas
- Llama a
steer_toystopsolo desdestart,tickostopde un comportamiento, en un comportamiento que liste los controles que necesitan. - Guarda el estado por mascota en
c.memory, declarado enmemories, con nombres que empiecen por el nombre del módulo. - No escribas en
c.pet; asignarle algo provoca un error. - Mantén los callbacks cortos. Todas las mascotas se ejecutan bajo estos límites fijos, que los módulos y los archivos de mascota no pueden cambiar:
| Límite | Valor |
|---|---|
| Un callback | 1,5 ms |
| Los callbacks de una mascota en un tick | 3 ms, como máximo 32 callbacks |
| Los callbacks de todas las mascotas en un tick | 10 ms |
| Tiempo de CPU de un callback, límite estricto | 20 ms |
| Instrucciones Lua de un callback, límite estricto | 20.000 |
Cuando una mascota alcanza uno de los tres primeros límites, sus callbacks restantes esperan al siguiente tick. Un callback que supera un límite estricto se detiene y falla como un error. Consulta Presupuestos.
Cuando algo va mal
Nada de lo siguiente detiene el servidor ni a las demás criaturas. Busca en la consola pet behavior, pet_behaviors y .pet.yml para encontrar estas advertencias.
- Un módulo no se carga. Un módulo que no compila, cuyo id no coincide con el nombre de su archivo, o cuyo nombre de archivo tiene otros caracteres se omite con una advertencia que nombra el archivo, y la línea en el caso de un error de Lua. Todos los demás módulos se cargan igualmente.
- Un archivo de mascota nombra un módulo que no existe. La advertencia nombra el archivo de mascota y sugiere el nombre de módulo más parecido cuando hay uno a una o dos letras de distancia. La criatura se carga sin él. Cuando el módulo existe pero no se pudo cargar, la advertencia remite a la advertencia sobre su archivo.
- Un ajuste es incorrecto. Un ajuste que el módulo no tiene, o un valor del tipo equivocado, se notifica con el nombre del archivo de mascota, y el valor predeterminado se mantiene. Consulta Valores de los ajustes.
- Dos módulos chocan. Cuando dos módulos de una misma criatura declaran el mismo nombre de memoria, id de comportamiento o id de sensor, la criatura conserva el primero de la lista y se ejecuta sin el otro, con una advertencia.
- Un callback falla mientras las mascotas se ejecutan. Se registra una vez por programa, callback y tipo de fallo hasta la siguiente recarga. Los programas se llaman
fmm:pet/creature/<species>/<variant>, y los callbacks por el id de su comportamiento o sensor, comofmm:pet/drift.tick. Un comportamiento que falla se detiene, o no se inicia, y se reintenta desde el siguiente tick; mientras siga fallando, es posible que no se ejecuten los comportamientos con números de prioridad más altos que mueven o giran a la mascota. Un sensor que falla se ejecuta de nuevo en su siguiente intervalo. - Una llamada a
c.petfalla dentro de FreeMinecraftModels. La causa se registra una vez por especie y llamada, con su traza de pila, y el callback falla conc.pet:<method> failed; the server log has the cause. - Un nombre de efecto de poción no existe. Se avisa una vez por especie y nombre, y la llamada no aplica ningún efecto.
Tras una corrección, ejecuta /fmm reload.