Docs / Animaciones

Animaciones y Emotes

Animorph usa un sistema de controladores de animación por layers. Cada emote tiene su propio YAML en animations/.

Configuración de emotes

Cada emote es un archivo .yml en animations/. El nombre del archivo (sin extensión) es el namespace del emote. Cada animación dentro del archivo se registra como namespace:nombre_animacion.

Ejemplo simple

yaml plugins/Animorph/animations/greet.yml
animation: greet.animation.json

Si greet.animation.json contiene una animación llamada "wave", el emote se invoca con /animorph emote greet:wave @a.

Ejemplo con propiedades

yaml plugins/Animorph/animations/dance.yml
animation: dance.animation.json
properties:
  freeze: true
  stop:
    on_death: true
    on_hurt: false
  controller_exceptions:
    - arm_right
    - arm_left
  layer_emotes:
    pompompurin: dance

Referencia de campos

CampoTipoDescripción
animationstringArchivo .animation.json en animations/. Obligatorio.
properties.freezebooleanCongela el movimiento del jugador durante el emote.
properties.stop.on_deathbooleanDetiene el emote al morir.
properties.stop.on_hurtbooleanDetiene el emote al recibir daño.
properties.controller_exceptionslistaControladores que NO se desactivan durante el emote (ej: brazos).
properties.layer_emotesmapEmotes que se reproducen automáticamente en layers junto con el emote principal. Clave: ID de layer, valor: ID de emote.

Emotes por layer

Además de emotes a nivel de modelo, Animorph soporta emotes por layer. Esto permite reproducir animaciones independientes en cada layer del modelo.

Desde el servidor (API o comandos), puedes reproducir emotes en layers específicos:

java
// Reproducir emote solo en un layer
api.playEmote(player, "dance:spin", Set.of("pompompurin"));

// Detener emote en layers específicos
api.clearEmote(player, Set.of("pompompurin"));

O definir emotes de layer automáticos en el YAML con layer_emotes, para que al reproducir el emote principal, los layers indicados reproduzcan su propio emote simultáneamente.

Nota
Después de añadir o modificar un YAML, ejecuta /animorph reload.

Controladores de animación

Los controladores se evalúan en orden de prioridad. El primero que tenga una animación activa gana para ese ciclo de renderizado.

IDCuándo actúa
emoteCuando hay un emote activo (máxima prioridad).
extended_posePoses avanzadas: idle/walk/sprint/jump/fall/climb/backwards y más.
simple_posePoses básicas: idle, caminar, agacharse, nadar, volar, dormir, montar.
mount_posePoses al montar entidades: horse, boat (con giros) y generic.
turn_overlayOverlay que se activa al girar el cuerpo (normal y giro rápido).
idleAnimación base siempre activa (breathing, idle, etc.).
arm_right / arm_leftPose de cada brazo según el ítem en mano.
arms / fp_armsAmbos brazos a la vez (hold, swing, por ítem).
fp_emoteEmotes en primera persona.
fp_arm_right / fp_arm_leftBrazos en primera persona.
*.animation.jsonAnimation controllers custom (máquina de estados con Molang). Se referencian por nombre de archivo completo.

Regístralos en el YAML del modelo:

yaml
properties:
  animation_controllers:
    idle:
      transition_time: 0
    simple_pose:
      transition_time: 0
    extended_pose:
      transition_time: 5          # blend entre animaciones (en ticks)
      animation_transitions:
        standing.jump: 0          # override: sin blend al saltar
        standing.fall: 2          # override: blend rápido al caer
    emote:
      transition_time: 2
    mount_pose:
      transition_time: 0
    turn_overlay:
      transition_time: 0
    arm_right:
      transition_time: 0
    arm_left:
      transition_time: 0

animation_transitions permite sobrescribir el transition_time para animaciones específicas. La clave es el nombre de la animación sin el prefijo del controlador (ej. standing.jump, no extended_pose.standing.jump).

Nombres de animación por controlador

Cada controlador busca animaciones con nombres exactos en tu .animation.json. Si la animación no existe, el controlador simplemente no la reproduce.

Consejo
En Blockbench, el nombre de la animación es el campo Name del panel de animaciones. Debe coincidir exactamente (case-sensitive).

idle

Controla la orientación de la cabeza del modelo. Siempre está activo si el modelo lo tiene registrado.

Nombre en BlockbenchCuándo se usa
idleSiempre activo. Maneja la rotación de la cabeza según la vista del jugador.

simple_pose

NombreEstado
pose.standingDe pie, sin moverse.
pose.idleIdle genérico.
pose.crouchingAgachado (Shift).
pose.swimmingNadando.
pose.flyingVolando (creativo).
pose.fall_flyingPlaneando con elytra.
pose.sleepingDurmiendo.
pose.sittingMontando un vehículo.
pose.spin_attackAtaque giratorio con tridente.
pose.dyingMuriendo.

extended_pose

Variantes más detalladas de cada estado:

NombreEstado
extended_pose.standing.idleDe pie, sin moverse.
extended_pose.standing.walkCaminando.
extended_pose.standing.sprintCorriendo.
extended_pose.standing.backwardsCaminando hacia atrás.
extended_pose.standing.jumpSaltando (idle, walk o sprint según el movimiento).
extended_pose.standing.jump.idleSalto sin moverse horizontalmente.
extended_pose.standing.jump.walkSalto caminando.
extended_pose.standing.jump.sprintSalto corriendo.
extended_pose.standing.jump.backwardsSalto hacia atrás.
extended_pose.standing.fallCayendo.
extended_pose.standing.step_upSubiendo un bloque.
extended_pose.on_edge.idleDe pie en el borde de un bloque.
extended_pose.on_fence.idleParado sobre una valla, quieto.
extended_pose.on_fence.walkCaminando sobre una valla.
extended_pose.crouching.idleAgachado, quieto.
extended_pose.crouching.walkCaminando agachado.
extended_pose.crouching.backwardsCaminando agachado hacia atrás.
extended_pose.flying.idleVolando, quieto.
extended_pose.flying.walkVolando y moviéndose.
extended_pose.flying.sprintVolando a máxima velocidad.
extended_pose.climbing.upTrepando hacia arriba.
extended_pose.climbing.downBajando por una escalera.
extended_pose.climbing.idleAgarrado a la escalera, quieto.
extended_pose.climbing.crouching.upTrepando agachado.
extended_pose.climbing.crouching.idleAgarrado agachado, quieto.
extended_pose.climbing.backwardsBajando de espaldas.
extended_pose.in_water.idleEn agua/lava, quieto.
extended_pose.in_water.walkMoviéndose en agua/lava.
extended_pose.in_water.upNadando hacia arriba.
extended_pose.in_water.downHundiéndose (shift en agua).
extended_pose.in_water.backwardsNadando hacia atrás.
extended_pose.swimming.idleEn pose de natación, quieto.
extended_pose.swimming.walkNadando despacio.
extended_pose.swimming.sprintNadando rápido (sprint).
extended_pose.fall_flyingPlaneando con elytra.
extended_pose.sleepingDurmiendo.
extended_pose.sittingMontando (genérico).
extended_pose.spin_attackAtaque giratorio.
extended_pose.dyingMuriendo.

mount_pose

Animaciones específicas según el tipo de montura:

NombreEstado
mount_pose.generic.idleMontando cualquier entidad, quieto.
mount_pose.generic.walkMontando cualquier entidad, moviéndose.
mount_pose.horse.idleMontando un caballo (u otra entidad viva), quieto.
mount_pose.horse.walkMontando un caballo, moviéndose.
mount_pose.boat.idleEn barco, quieto.
mount_pose.boat.walkEn barco, moviéndose.
mount_pose.boat.turn_leftGirando a la izquierda en barco.
mount_pose.boat.turn_rightGirando a la derecha en barco.

turn_overlay

Overlay que se activa al girar el cuerpo del jugador:

NombreCuándo
turn_overlay.leftGirando a la izquierda (>8° por tick).
turn_overlay.rightGirando a la derecha.
turn_overlay.fast_leftGiro rápido a la izquierda (>35° por tick). Fallback a left si no existe.
turn_overlay.fast_rightGiro rápido a la derecha. Fallback a right si no existe.
Advertencia
Prioridad por ítem en extended_pose y simple_pose
Si tu modelo tiene una animación con el sufijo .hold.<item_id>, esta toma prioridad sobre la animación genérica del mismo estado.
Por ejemplo, si existe extended_pose.standing.idle.hold.minecraft:diamond_sword, se usará esa en lugar de extended_pose.standing.idle cuando el jugador sostenga una espada de diamante.
Lo mismo aplica para simple_pose: pose.standing.hold.minecraft:bow sobreescribe pose.standing.

arm_right / arm_left

Poses del brazo según la acción. En primera persona se usa el prefijo fp..

3a persona1a personaAcción
arm_right.holdfp.arm_right.holdSosteniendo un objeto.
arm_right.emptyfp.arm_right.emptyMano vacía.
arm_right.swingfp.arm_right.swingAtacando.
arm_right.eatfp.arm_right.eatComiendo.
arm_right.drinkfp.arm_right.drinkBebiendo.
arm_right.blockfp.arm_right.blockBloqueando con escudo.
arm_right.bowfp.arm_right.bowTensando arco.
arm_right.crossbowfp.arm_right.crossbowCargando ballesta.
arm_right.tridentfp.arm_right.tridentLanzando tridente.
arm_right.spyglassfp.arm_right.spyglassUsando catalejo.

Para el brazo izquierdo, sustituye arm_right por arm_left.

Animaciones por ítem específico

Podés definir una animación de hold para un ítem concreto de Minecraft. Si existe, toma prioridad sobre la animación genérica de hold:

plaintext
arm_right.hold.<item_id>
arm_right.hold.minecraft:diamond_sword
arm_right.hold.minecraft:bow
Advertencia
Prioridad del controlador arms sobre arm_right / arm_left
Si el controlador arms tiene definida la animación arms.hold.<item_id> para el ítem que el jugador sostiene, los controladores individuales arm_right y arm_left se detienen y ceden el control a arms.

Lo mismo aplica para el swing: si arms tiene arms.swing o arms.hold.<item_id>.swing, el swing individual de arm_right / arm_left no se ejecuta.

arms / fp_arms

Ambos brazos a la vez. Se usan principalmente en primera persona (fp.arms.*).

3a persona1a personaAcción
arms.nonefp.arms.noneSin acción.
arms.swingfp.arms.swingAtacando (todos los ítems).
arms.hold.<item_id>fp.arms.hold.<item_id>Sosteniendo un ítem específico.
arms.hold.<item_id>.swingfp.arms.hold.<item_id>.swingSwing con un ítem específico.
arms.eatfp.arms.eatComiendo.
arms.drinkfp.arms.drinkBebiendo.
arms.blockfp.arms.blockBloqueando.
arms.bowfp.arms.bowTensando arco.
arms.crossbowfp.arms.crossbowCargando ballesta.
arms.tridentfp.arms.tridentLanzando tridente.
arms.spyglassfp.arms.spyglassCatalejo.
Consejo
Ejemplos de ítem ID válidos: minecraft:diamond_sword, minecraft:bow, minecraft:shield. Usá el namespace completo, incluyendo minecraft: o el mod correspondiente.

emote

No usa nombres fijos. Reproduce la animación declarada en el .animation.json que referencia el YAML del emote.

Animation Controllers custom

Los animation controllers custom son máquinas de estados exportadas desde Blockbench que usan condiciones Molang para determinar qué animación reproducir.

Uso

  1. En Blockbench, crea un Animation Controller en la pestaña de animaciones.
  2. Exporta como JSON y colócalo en animations/ (la misma carpeta de animaciones).
  3. Añádelo a animation_controllers en el modelo con una clave libre y el campo file apuntando al archivo.
yaml Referencia en el modelo
properties:
  animation_controllers:
    idle:
      transition_time: 0
    simple_pose:
      transition_time: 0
    mi_controlador:
      file: mi_controlador.animation_controller.json

Coloca el archivo en:

plaintext
plugins/Animorph/animations/mi_controlador.animation_controller.json
Nota
A diferencia de los controladores nativos (idle, simple_pose, etc.), los custom usan una clave arbitraria y referencian el archivo mediante file. El transition_time se define dentro del propio controlador.

Estructura del JSON

json animations/mi_controlador.animation.json
{
  "format_version": "1.10.0",
  "animation_controllers": {
    "controller.animation.mi_controlador": {
      "initial_state": "idle",
      "states": {
        "idle": {
          "animations": ["idle"],
          "transitions": [
            { "walking": "query.limb_swing_amount > 0.1" }
          ]
        },
        "walking": {
          "animations": ["pose.standing"],
          "transitions": [
            { "idle": "query.limb_swing_amount < 0.1" }
          ]
        }
      }
    }
  }
}

Queries Molang

Queries personalizadas disponibles en condiciones de transición y propiedades de animación:

QueryTipoDescripción
query.limb_swingfloatCiclo de balanceo de extremidades (0 .. 2π).
query.limb_swing_amountfloatIntensidad del balanceo: 0 = parado, 1 = corriendo.
query.ground_speedfloatVelocidad horizontal normalizada.
query.pitchfloatInclinación de la cabeza (-1..1).
query.yawfloatRotación horizontal de la vista.
query.body_yawfloatRotación del cuerpo respecto a la vista.
query.left_hand_swingfloatSwing del brazo izquierdo al atacar (0..1).
query.right_hand_swingfloatSwing del brazo derecho al atacar (0..1).
query.is_flyingboolEl jugador está en modo vuelo.
query.can_flyboolEl jugador tiene permiso de vuelo.
query.death_timefloatTicks desde la muerte (0 si vivo).
query.use_actionenumAcción del ítem: BOW, TRIDENT, SPYGLASS, EAT...
query.use_timefloatTicks usando el ítem activo.
query.use_time_leftfloatTicks restantes de uso.

Ejemplos de uso

javascript
// Transición cuando el jugador vuela y se mueve
"query.is_flying && query.limb_swing_amount > 0.05"

// Peso de animación de arco ponderado por carga
"query.use_action == 'BOW' ? math.min(query.use_time / 20.0, 1.0) : 0.0"

// Detectar que el jugador acaba de morir
"query.death_time > 0"

Conversión desde EmoteCraft

Si tienes animaciones en formato EmoteCraft:

  1. Asegúrate de que EmoteCraft está instalado y la animación registrada.
  2. Ejecuta: /animorph emote-parser <id_emote>
  3. El archivo convertido se guarda en plugins/Animorph/animations/parser/.
  4. Crea un YAML referenciando el archivo y recarga con /animorph reload.