Módulos de comportamento de mascotes
Um módulo de comportamento de mascote é um ficheiro Lua que diz às mascotes o que fazer: seguir o dono, flutuar, rodear uma fogueira, picar. Cada ficheiro de espécie de mascote lista os módulos que as suas mascotes executam e dá-lhes definições. Esta página destina-se aos autores de criaturas que querem alterar um módulo ou escrever um novo. Para usar e ajustar os módulos incluídos, consulte Mascotes.
Os módulos usam o mesmo dialeto Lua dos programas de comportamento do EliteMobs: ai.module, ai.behavior, ai.sensor, ai.controls, memórias tipadas e o contexto c.memory, c.perception, c.actuator e c.entity. Essa página descreve as regras partilhadas. Esta descreve o que as mascotes acrescentam: os ficheiros dos módulos, c.pet, c.settings e os limites em que as mascotes são executadas.
Ficheiros
- Os módulos ficam em
plugins/FreeMinecraftModels/pet_behaviors/, nessa pasta ou em qualquer subpasta. Todos os ficheiros.luaaí são módulos. - O nome de um módulo é o nome do seu ficheiro sem
.lua, em minúsculas. Só pode usar letras, dígitos,.,_e-. Os ficheiros de mascotes listam os módulos por este nome. - O
idde um módulo tem de serfmm:pet/seguido do seu nome, pelo quepet_behaviors/mine/slow_drift.luadeclaraid = 'fmm:pet/slow_drift'. Um módulo cujo id não corresponda ao nome do ficheiro é ignorado com um aviso. - Quando dois ficheiros têm o mesmo nome, carrega aquele cujo caminho vem primeiro por ordem, e a consola avisa
Duplicate content filenamesobre o outro. Uma cópia idêntica byte a byte é ignorada sem aviso. - Um ficheiro ou pasta que aponte para fora de
pet_behaviors/é ignorado. - O FreeMinecraftModels escreve cada um dos seus 15 módulos incluídos quando não existe em lado nenhum da pasta um ficheiro com esse nome. Um módulo eliminado volta no carregamento seguinte, com a versão incluída atual. Um ficheiro que já lá esteja nunca é substituído, editado ou não, mesmo depois de o mover para uma subpasta, pelo que mantém as suas alterações e também não recebe as atualizações posteriores do módulo incluído.
/fmm reloadvolta a ler todos os módulos e ficheiros de mascotes, recolhe as mascotes e trá-las de volta com os novos módulos. As suas memórias começam vazias. Não é preciso aumentar arevisionde um módulo depois de o editar.
Comece por uma cópia
Os módulos incluídos são os melhores exemplos: drift.lua move uma voadora, wander.lua anda, night_glow.lua é um único sensor e sting.lua tem dois. Comece pelo que estiver mais perto do que pretende.
- Copie-o com um novo nome, por exemplo
pet_behaviors/mine/slow_drift.luaa partir dedrift.lua. - Altere o seu
idparafmm:pet/slow_drift. - Mude o nome das suas memórias, comportamentos e sensores para que comecem pelo novo nome:
drift_topassa aslow_drift_to, emmemoriese em todas as chamadasc.memory, e oid = 'fmm:pet/drift'do comportamento passa afmm:pet/slow_drift. Dois módulos na mesma criatura não podem partilhar um nome de memória, um id de comportamento nem um id de sensor; o segundo listado fica de fora com um aviso. Mudar os nomes permite que a cópia seja executada ao lado do original. - Liste-o no ficheiro da mascote no lugar do original:
- slow_drift, ou com definições,- slow_drift: { speed: 0.03 }. - Execute
/fmm reloade verifique a consola.
Editar um módulo incluído no próprio sítio também funciona, mas altera todas as espécies que o listam.
Um ficheiro de módulo
Este módulo é pequeno mas completo. À noite, a mascote assenta num sítio perto da sua âncora em vez de flutuar e, a cada 10 segundos desde o momento em que escolhe esse sítio, reproduz uma animação.
-- 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
}
}
}
Um ficheiro de mascote lista-o então como - night_rest, ou - night_rest: { radius: 5, animation: idle }.
| Campo | Notas |
|---|---|
id | Obrigatório. fmm:pet/ e o nome do ficheiro |
revision | Obrigatório. Qualquer número inteiro positivo |
settings | Opcional. As predefinições que os ficheiros de mascotes podem alterar. O tipo de cada predefinição é o tipo que um ficheiro de mascote tem de dar: um número, true/false, texto ou uma lista de textos. Consulte Valores das definições |
memories | Opcional. O que o módulo recorda para cada mascote, por nome e tipo: integer, number, boolean, string, uuid ou position. Comece cada nome pelo nome do módulo. Consulte Memórias |
dependencies | Opcional. IDs de outros módulos de pet_behaviors/ de que este precisa. São executados em todas as criaturas que listam este, com as suas definições predefinidas, a menos que o ficheiro da mascote também os liste |
behaviors | Opcional. Entradas ai.behavior { ... }, que movem ou viram a mascote |
sensors | Opcional. Entradas ai.sensor { ... }, que nunca movem a mascote |
O código acima de return, como funções locais e constantes, é permitido; wander.lua e idle_look.lua têm alguns.
O que recebe um callback
| Nome | O que é |
|---|---|
c.pet | A mascote, só de leitura. Consulte c.pet |
c.settings | As definições deste módulo: as suas predefinições com os valores do ficheiro da mascote e da variante por cima, como em c.settings.radius. Cada mascote tem a sua própria cópia, pelo que escrever nela altera apenas essa mascote |
c.memory | get(name), set(name, value), forget(name) e contains(name) para os nomes em memories. Cada mascote tem a sua |
c.tick | O tick atual do jogo, para temporizadores |
c.perception, c.actuator, c.entity | O contexto Mind do MagmaCore, como nos programas de comportamento do EliteMobs. c.entity é o corpo oculto, não o modelo. Consulte Contexto de um programa Mind. idle_look.lua usa c.perception:nearest_player(range) e c.actuator:look_at(point) |
c.pet
Um ponto é uma tabela com x, y e z, e opcionalmente world, como c.pet.position. Um ponto sem world está no mundo da mascote. Um ponto noutro mundo conta como nada: os métodos respondem nil, false ou 0, e distance_to responde math.huge. Os pontos que c.pet devolve estão sempre no mundo da mascote, e um que ficasse noutro lado é lido como nil.
- Os métodos são chamados com dois pontos:
c.pet:distance_to(point). - Os argumentos numéricos têm de ser finitos. Os raios, profundidades, alturas, amplificadores, durações e os outros intervalos têm os limites indicados abaixo. Nenhum método carrega um chunk.
c.petec.pet.speciessão só de leitura. Atribuir-lhes gera um erro; guarde os valores por mascote emc.memory.- As propriedades e
route_target()são um instantâneo: cada uma é lida uma vez por tick da mascote e mantém-se igual em todos os callbacks desse tick.c.pet:teleport_near_ownerec.pet:stopatualizam-nas. Um movimento feito de outra forma, comoc.entity:teleport, aparece no tick seguinte.speedé a exceção e é sempre lida de novo. - Cada leitura de uma posição dá uma tabela nova, que o módulo pode alterar.
Propriedades
| Nome | Tipo | Valor |
|---|---|---|
wild | bool | true numa mascote selvagem, false numa com dono |
staying | bool | Tem ordem para ficar quieta |
settled | bool | Não está a ficar quieta, e é selvagem ou está a menos de follow.distance do dono |
baby | bool | É uma cria |
migrating | bool | Está a voar um percurso de migração noturna |
model | string | O modelo da sua variante. Uma cria que veste babyModel continua a ler a sua variante |
position | point | Onde está o seu corpo |
home | point/nil | Onde vive uma mascote selvagem; nil numa mascote com dono |
anchor | point/nil | Aquilo à volta do qual vagueia: o dono ou, numa mascote selvagem, a sua casa, ou o sítio onde está se não tem nenhuma. nil quando o dono está offline ou noutro mundo |
stay_anchor | point/nil | O sítio onde lhe mandaram ficar; nil quando não está a ficar quieta |
owner_location | point/nil | nil numa mascote selvagem, ou quando o dono está offline, morto ou noutro mundo |
owner_distance | number | Blocos até ao dono; math.huge quando não há nenhum neste mundo |
night, day | bool | day só à luz do dia num mundo normal; o anoitecer, o amanhecer, o Nether e o End contam como night |
raining | bool | A chuva cai sobre a mascote, verificado no máximo a cada 10 ticks |
speed | number | A velocidade atual do seu corpo, em blocos por tick |
route_cruise | number | A velocidade de cruzeiro do seu bando numa migração, caso contrário 0 |
species | table | Os números do ficheiro da mascote, abaixo |
c.pet.species contém:
| Campo | Chave do ficheiro da mascote |
|---|---|
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 |
Movimento
Chame-os apenas a partir de start, tick ou stop de um comportamento, num comportamento cujo controls liste o que precisam. A partir de can_start ou de um sensor, steer_to e stop geram um erro que indica onde pertencem.
| Método | Devolve | O que faz |
|---|---|---|
steer_to(point, cruise) | bool | Um tick em direção ao ponto, por isso chame-o a cada tick. Precisa de move e look. Uma voadora voa a cruise blocos por tick (0 a 4), abrandando à chegada. Uma caminhante ou nadadora segue até lá nativamente a 4 × cruise vezes a velocidade de movimento do seu tipo de corpo, nunca abaixo de um quarto dela; um cruise de 0 imobiliza-a e devolve false. false quando não pode ir para lá |
stop() | nil | Para de se mover. Precisa de move |
teleport_near_owner(radius) | bool | Coloca o corpo junto do dono, a até radius blocos (até 64), no meio em que se desloca; uma nadadora procura água num raio de radius ou de 6 blocos, o que for maior. Uma caminhante ou nadadora aterra a pelo menos um bloco do dono. false quando o dono está longe ou noutro mundo, nada serve, ou o sítio não fica pelo menos um bloco mais perto do dono do que a mascote está. Não precisa de nenhum controlo, mas chame-o a partir de um comportamento que detenha move, como follow_owner faz, para não afastar a mascote de outro comportamento |
Sítios e distâncias
Funcionam a partir de qualquer callback. Os que devolvem um ponto devolvem nil quando nada serve ou o chunk não está carregado. Os raios vão até 64.
| Método | Devolve | O que faz |
|---|---|---|
hover_point(center, radius) | point/nil | Um ponto na sua faixa de pairar a até radius |
rest_point(center, radius) | point/nil | Um sítio onde descansar no meio em que se desloca: a faixa de pairar numa voadora, chão onde se possa estar de pé numa caminhante ou num corpo estacionário, água numa nadadora (à altura de center quando center está na água, caso contrário 0,5 a 2 blocos abaixo da superfície), e chão ou, na falta dele, água num corpo anfíbio |
ground_point(center, radius) | point/nil | Um sítio onde estar de pé, desde cerca de 5 blocos abaixo até 4 acima de center. nil sobre líquido ou uma queda longa |
water_point(center, radius, min_depth, max_depth) | point/nil | Um sítio de nado entre as duas profundidades abaixo da superfície (0 a 16) |
ground_below(point, depth) | number/nil | A altura do topo do chão a até depth blocos abaixo (1 a 64). Uma superfície de água ou lava conta como chão, a menos que a espécie seja AQUATIC. Sem chão ao alcance, a altura do ponto menos depth |
trail_point(back, height) | point/nil | back blocos atrás de onde o dono está virado, height acima dos seus pés numa espécie FLYING e aos seus pés nas outras. nil quando o dono está longe ou noutro mundo |
distance_to(point) | number | Blocos desde o seu corpo |
route_target() | point/nil | Onde o seu percurso de migração a quer neste tick. nil quando não está a migrar ou o percurso terminou |
find_perch(height, radius) | point/nil | height blocos (0 a 8) acima da folhagem mais próxima por baixo dela, até radius blocos (0 a 4) para o lado, ou acima do chão mesmo por baixo. Uma mascote com dono só obtém um poiso a menos de follow.distance do dono |
nearest_campfire(radius, keep_ticks, blocks, soul_variants, height) | point/nil | O bloco da fogueira acesa mais próxima que pode usar a até radius (1 a 32). blocks lista os tipos de fogueira que aceita, CAMPFIRE, SOUL_CAMPFIRE ou ambos, e uma lista que não nomeie nenhum aceita ambos; soul_variants lista os modelos que aceitam apenas fogueiras de almas, e todos os outros modelos aceitam então apenas as normais. Uma mascote com dono só aceita uma fogueira cujo sítio, height acima dela, esteja a menos de follow.distance menos 1 do dono. A procura de cada chunk é mantida durante keep_ticks (20 a 1200) e partilhada por todas as mascotes |
campfire_usable(fire, blocks, soul_variants, height) | bool | Se uma fogueira encontrada antes continua acesa e continua a servir |
Efeitos
Funcionam a partir de qualquer callback; os sensores são o sítio habitual.
| Método | Devolve | O que faz |
|---|---|---|
set_glow(light, lantern_bone, animation) | nil | Ilumina os ossos de apresentação do modelo a light (0 a 15), para jogadores Java. Um modelo com um osso chamado lantern_bone repete também animation. Os dois últimos são opcionais |
clear_glow() | nil | Volta à luz do mundo, terminando essa animação |
scale_toward(target, span, ticks, elapsed) | nil | Aproxima suavemente o tamanho do corpo de target vezes o seu tamanho base. Uma mudança completa de 1 para span demora ticks (no mínimo 2); elapsed são os ticks desde a última chamada. Multiplicadores de 0.1 a 16 |
sting_contacts(on, effect, duration, amplifier, damage, cooldown) | number | Pica os jogadores cujo toque atingiu o modelo de uma mascote selvagem no último segundo, nunca um em modo Criativo ou Espectador, e devolve quantos. Limpa os toques mesmo quando on é false. As mascotes com dono não registam toques |
sting_enemies(reach, effect, duration, amplifier, damage, cooldown) | number | Pica os mobs hostis a até reach blocos (0 a 4) da hitbox do modelo, nunca jogadores nem mascotes, e devolve quantos |
drizzle(depth, chance) | bool | Quando a mascote paira imóvel sobre uma cultura a até depth blocos (1 a 8), partículas de água e uma probabilidade chance (0 a 1) de a cultura crescer uma fase. true quando está sobre uma cultura |
owner_effect(effect, duration, amplifier, range) | bool | Dá ao dono o efeito de poção durante duration ticks (1 a 6000) quando ele está a até range blocos, sem partículas. Um efeito que o dono já tenha com pelo menos a mesma força e duração é deixado em paz. false quando o dono está longe, noutro mundo ou fora do alcance, ou o efeito não existe |
play_animation(name) | bool | Reproduz uma vez uma das animações do modelo. false quando o modelo não a tem |
Em ambas as picadas, effect é um nome de efeito de poção ou NONE, duration é em ticks (1 a 6000), amplifier 0 é o nível I (até 255), damage é em meios corações, e cooldown são os ticks (no mínimo 1) até esta mascote poder picar de novo a mesma vítima. Uma picada mostra faíscas e reproduz um som de picada de abelha, e um adulto reproduz a sua animação attack. Um nome de efeito de poção que não exista gera um aviso uma vez por espécie e nome, e não aplica nada.
Comportamentos e sensores
- Um comportamento move ou vira a mascote. Lista os controlos de que precisa,
ai.controls.moveeai.controls.lookpara as chamadas de movimento dec.pet, e só um comportamento detém um controlo de cada vez. Enquanto está parado, o MagmaCore pergunta o seucan_start. Quando devolvetruee os controlos estão livres, assume-os e executastart, depoisticka cada tick enquantocan_continuedevolvertrue(semcan_continue, decidecan_start), depoisstop. Consulte Ciclo de vida. - O número de
prioritymais baixo vai primeiro. Um comportamento tira os controlos a um comportamento em execução com um número mais alto, cujostopé então executado. O12do exemplo mantém seguir e ficar quieta à sua frente e coloca-o à frente de flutuar e pairar, mas também à frente decampfire, pelo que uma mascote que liste ambos nunca visita uma fogueira à noite. Um número acima de15deixaria a fogueira vencer. - Um comportamento só compete pelos controlos que lista.
idle_lookocupa apenaslook, pelo que é executado enquanto nenhum comportamento detiver o olhar; todos os comportamentos de movimento incluídos ocupam tambémlook, pelo que mover-se vence sempre. - Um ficheiro de mascote não pode alterar uma prioridade. Para reordenar, copie o módulo e altere o número.
probe_intervalé opcional, em ticks: enquanto o comportamento está parado,can_startsó é perguntado a cada esse número de ticks, na fase própria de cada mascote. Poupa tempo do servidor quando há muitas mascotes fora, à custa de o comportamento arrancar até esse número de ticks mais tarde. Por predefinição é1e conta como200acima disso. Um comportamento em execução continua a ser executado a cada tick.- Um sensor nunca move a mascote. Executa
senseno primeiro tick em que o corpo da mascote é processado e depois a cadaintervalticks na fase própria da mascote, seja o que for que os comportamentos estejam a fazer. O brilho, o inchaço, as picadas, o chuvisco e os efeitos no dono são sensores.
Os módulos incluídos usam:
| Módulo | Prioridade | probe_interval | interval do sensor |
|---|---|---|---|
migrate | 1 | 10 | |
stay | 5 | 4 | |
follow_owner | 10 | 4 | |
campfire | 15 | 10 | |
day_perch | 18 | 10 | |
rain_bloom | 19 | 10 | 4 (inchaço) |
drift, wander, swim | 20 | 10 | |
hover | 30 | 4 | |
idle_look | 30 | 10 | |
night_glow | 40 | ||
sting | 4 (jogadores), 10 (mobs) | ||
crop_drizzle | 20 | ||
owner_effect | 20 |
Regras
- Chame
steer_toestopapenas a partir destart,tickoustopde um comportamento, num comportamento que liste os controlos de que precisam. - Guarde o estado por mascote em
c.memory, declarado emmemories, com nomes que comecem pelo nome do módulo. - Não escreva em
c.pet; atribuir-lhe gera um erro. - Mantenha os callbacks curtos. Todas as mascotes são executadas com estes limites fixos, que os módulos e os ficheiros de mascotes não podem alterar:
| Limite | Valor |
|---|---|
| Um callback | 1,5 ms |
| Os callbacks de uma mascote num tick | 3 ms, no máximo 32 callbacks |
| Os callbacks de todas as mascotes num tick | 10 ms |
| Tempo de CPU de um callback, limite rígido | 20 ms |
| Instruções Lua de um callback, limite rígido | 20.000 |
Quando uma mascote atinge um dos três primeiros limites, os seus callbacks restantes esperam pelo tick seguinte. Um callback que ultrapasse um limite rígido é interrompido e falha como um erro. Consulte Orçamentos.
Quando algo está errado
Nenhum destes problemas para o servidor nem as outras criaturas. Procure na consola por pet behavior, pet_behaviors e .pet.yml para encontrar estes avisos.
- Um módulo não carrega. Um módulo que não compila, cujo id não corresponde ao nome do ficheiro, ou cujo nome de ficheiro tem outros caracteres, é ignorado com um aviso que indica o ficheiro e, num erro Lua, a linha. Todos os outros módulos continuam a carregar.
- Um ficheiro de mascote indica um módulo que não existe. O aviso indica o ficheiro da mascote e sugere o nome de módulo mais próximo quando há um com uma ou duas letras de diferença. A criatura carrega sem ele. Quando o módulo existe mas falhou ao carregar, o aviso remete para o aviso sobre o seu ficheiro.
- Uma definição está errada. Uma definição que o módulo não tem, ou um valor do tipo errado, é comunicada com o nome do ficheiro da mascote, e a predefinição mantém-se. Consulte Valores das definições.
- Dois módulos entram em conflito. Quando dois módulos na mesma criatura declaram o mesmo nome de memória, id de comportamento ou id de sensor, a criatura mantém o primeiro da lista e é executada sem o outro, com um aviso.
- Um callback falha enquanto as mascotes são executadas. É registado uma vez por programa, callback e tipo de falha até ao recarregamento seguinte. Os programas chamam-se
fmm:pet/creature/<species>/<variant>, e os callbacks pelo id do seu comportamento ou sensor, comofmm:pet/drift.tick. Um comportamento que falhou é parado, ou não arranca, e é tentado de novo a partir do tick seguinte; enquanto continuar a falhar, os comportamentos com números de prioridade mais altos que movem ou viram a mascote podem não ser executados. Um sensor que falhou é executado de novo no seu intervalo seguinte. - Uma chamada
c.petfalha dentro do FreeMinecraftModels. A causa é registada uma vez por espécie e chamada, com o respetivo stack trace, e o callback falha comc.pet:<method> failed; the server log has the cause. - Um nome de efeito de poção não existe. É avisado uma vez por espécie e nome, e a chamada não aplica nenhum efeito.
Depois de uma correção, execute /fmm reload.