Ignitor Docs ← getignitor.com
🇺🇸 EN 🇪🇸 ES

Editor de Cinemáticas#

El Editor de Cinemáticas arma listas de pasos ordenadas y no interactivas — un NPC que camina hacia una puerta, una línea de diálogo, una espera, una escena cinemática — que se reproducen con el input bloqueado, igual que una cinemática clásica de aventura gráfica. La mayoría de las cinemáticas están delimitadas a una sola sala: viven en el propio archivo de reglas de esa sala, junto a sus reacciones de hotspot, watchers y globalWatchers (el mismo archivo que escribe el Editor de Puzzles). Una cinemática también puede vivir en el bucket 🌐 Global de todo el proyecto (rules/_global.rules.js) para momentos que no están atados a una sola sala. Se dispara desde cualquier lugar — una reacción de hotspot, una opción de diálogo, una regla de puzzle — con el token de efecto CUTSCENE:<id>, que resuelve el id contra las cinemáticas de la sala actual primero y cae al bucket Global si la sala no tiene coincidencia, y luego entrega el arreglo de pasos a startCutscene().

Llegas a él desde el Hub (con el dev server corriendo). La barra de herramientas tiene un desplegable Sala (con una entrada sintética 🌐 Global arriba), un desplegable Cinemática acotado a esa sala o bucket, y botones para Nuevo (un modal que pide el nombre), Renombrar, Duplicar, Copiar y Pegar pasos (los dos últimos funcionan entre salas y el bucket Global), Eliminar, y Guardar. Bajo la barra hay una franja de miniaturas de salas para saltar de una a otra sin volver al desplegable — el bucket 🌐 Global tiene su propia tarjeta también; viene en tres tamaños y se puede plegar, y tu elección queda recordada. El panel central muestra los pasos de la cinemática cargada en una de dos vistas intercambiables — Visual (tarjetas de nodo amigables) o Avanzado (el editor campo por campo) — y el panel derecho tiene Validar, Vista previa, y una pestaña Exportar oculta (muestra el código de reglas generado, útil para depurar un guardado).

La pantalla del Editor de Cutscenes — la lista ordenada de pasos del cutscene de una sala.
Editor de Cutscenes — lista ordenada de pasos de un cutscene.

Anatomía de un paso#

Los pasos son una lista ordenada lineal, no una línea de tiempo multi-pista — pasa exactamente una cosa a la vez, en el orden de la lista, la misma forma que consume core/cutscene.js. Cada fila tiene un selector de tipo, un cuerpo de campos específicos del tipo, una insignia bloquea/instantáneo, y controles de reordenar/eliminar. El editor expone seis tipos de paso tipados más un escape genérico:

  • NPCENTER — un NPC aparece ya dentro de la sala actual en el punto de una región (la puerta por la que "entra"). Tanto NPC como Región son pickers tipados (lista de personajes / las regiones de la sala cargada). Instantáneo.
  • WALKNPCTO — un NPC camina hacia un objetivo, elegido con un grupo de pestañas jugador / hotspot / coords: jugador (donde esté parado el jugador en ese momento), el punto de camino de un hotspot, o X/Y crudas (con un botón "⌖ Elegir X/Y en la sala" que lee un clic sobre la sala). Bloquea hasta que el NPC llega — el runtime lo hace caminar ahí durante los frames que hagan falta. Mirando hacia (opc.) es hacia dónde queda mirando el actor al llegar. Si lo dejas vacío y el objetivo es un hotspot, se usa el facing configurado en ese hotspot desde el editor de salas — así, al llegar a una puerta el personaje se voltea hacia ella, igual que cuando el jugador la clickea. Vacío sobre un objetivo jugador/coords deja el rumbo con el que terminó la caminata, que para una puerta a la que acabas de llegar suele ser al revés. Pon un valor explícito para pisar el del hotspot, o para apuntar un objetivo por coordenadas; están las ocho direcciones canónicas, diagonales incluidas.
  • NPCEXIT — un NPC camina hasta un punto de salida en la sala actual (hotspot o coords, mismo grupo de pestañas de arriba) y sale hacia una sala destino (un picker de sala autowired). Este no es en realidad un verbo de core/cutscene.js — serializa al token de efecto NPCEXIT y cae en el catch-all genérico applyEffects() del runner, así que se comporta como cualquier otro efecto instantáneo una vez despachado, no como la caminata bloqueante cuadro-a-cuadro de WALKNPCTO.
  • WAIT — pausa N segundos. Bloquea.
  • SAY — una línea de diálogo: un desplegable NPC (vacío = narrador) y un campo de texto. Bloquea — pero no hay que autorar ningún tiempo manual; el runtime calcula automáticamente cuánto tiempo queda en pantalla según el largo de la línea (sayDuration() en core/cutscene.js, entre 1 y 6 segundos aproximadamente). Si la línea tiene voz horneada, el hold se extiende mientras el clip sigue sonando (tope de 30 segundos extra, así una fuente trabada nunca puede colgar la cutscene), y se corta en el momento en que el jugador salta, mantiene pulsado para saltar, o la línea termina y el control avanza — un warp de room incluido.
  • PLAYSCENE — reproduce una escena cinemática (un picker de escena autowired, conceptualmente enlazado a los clips del Orquestador de Escenas) y bloquea hasta que termina; el jugador puede mantener pulsado para saltarla igual dentro del juego. (REWINDSCENE también existe a nivel de runtime, para el efecto de rebobinado estilo VHS, pero no se expone como un tipo de paso propio acá — solo alcanzable desde el slot raw.)
  • raw (token de efecto) — cualquier otra cosa, a través del mismo widget de efectos compartido y dirigido por manifiesto que usan las reglas, los diálogos y el Editor de Puzzles (modo de efecto único): un desplegable de verbo más campos de argumento tipados/buscados, nunca texto libre para un argumento que porte un ID. Así es como una cinemática dispara SETFLAG, GIVEITEM:<item>|<char>, SWITCHCHAR, WARPTOROOM, CUTSCENESPEED, o cualquier otra cosa del manifiesto de efectos.

Los pasos se reordenan de dos formas: arrastrando la fila por su encabezado, o con los botones ▲/▼ — ambos llaman a la misma ruta de reordenamiento. Eliminar es un solo × por fila, sin confirmación.

Targeting de party y foco#

Para juegos con party, una cinemática no siempre puede nombrar de forma fija a un personaje — el jugador quizá no lo reclutó. Dos mecanismos cubren eso, y ambos aparecen como pickers, nunca texto libre:

  • {partySlotN} — una opción de slot 🧑‍🤝‍🧑 en cualquier campo de personaje (y en el desplegable de hablante de SAY/NPCSAY) que resuelve al N-ésimo miembro comprometido del party en runtime. Un slot vacío deja el token en no-op; para una línea de SAY/NPCSAY, un hablante vacío simplemente salta la línea en vez de sacar un globo fantasma.
  • IFINPARTY:<charId> — un guard por-paso, un select en el encabezado de cada paso. El paso corre solo cuando ese personaje está en el party activo; de lo contrario se salta de forma transparente. (Sin sistema de party en juego, el guard queda simplemente inerte.)

Un tercer sentinel, {_prevChar}, se ofrece en los pickers de personaje para el patrón SWITCHCHAR de abajo — representa a quien tenía el control cuando arrancó la cinemática.

Vistas Visual y Avanzado#

El panel central alterna entre dos vistas de la misma lista de pasos — las ediciones en una aparecen en la otra al instante.

  • Avanzado es el editor campo por campo descrito arriba: cada campo tipado, select de guard y picker desplegado en detalle. Úsalo cuando estés cableando argumentos exactos.
  • Visual renderiza la secuencia como una cadena de tarjetas de nodo amigables — "Dice", "Mueve", "Entra", "Sale", "Espera", "Escena", "Token" — cada una con una insignia BLOQUEA cuando retiene la secuencia. Puedes hacer pan/zoom del diagrama, agregar un nodo soltándolo en la cadena, reordenar, eliminar, y editar una línea de SAY en línea; hacer clic en otra parte del nodo abre el editor completo. Es la vista de leer-de-un-vistazo para ver forma y flujo antes de meterte en los argumentos.

Modelo de secuenciación#

core/cutscene.js avanza el paso activo cada frame y solo mueve el cursor una vez que un paso se resuelve — no hay paralelismo entre pasos, aunque un paso bloqueante (una caminata, una espera, una línea de SAY, una escena) no congela el resto del motor; la sala sigue renderizando y otros actores siguen animando alrededor. WARPTOROOM y SWITCHCHAR también bloquean a nivel de runtime: ambos son operaciones asíncronas del shell (una carga de sala, en el caso de SWITCHCHAR posiblemente cruzando de sala), y el runner espera hasta que el shell limpia state.warpPending para que un paso pensado para la sala nueva no dispare mientras la vieja sigue en pantalla. Cualquier otro token no cubierto por un paso tipado (todo lo que viene del slot raw) es instantáneo — se aplica a través del mismo applyEffects() que usan el motor de reglas y los diálogos, así que hay una sola ruta de despacho para los tokens que mutan estado en todo el motor.

SWITCHCHAR también puede apuntar a un NPC para un foco momentáneo — una mini-cinemática que mueve el control a un personaje, reproduce un momento, y devuelve el control. Combínalo con el sentinel {_prevChar} para volver a quien manejaba cuando arrancó la escena, sin nombrarlo de forma fija. El foco es autoral, no control del jugador: el switch es skip-safe (el regreso corre igual con un salto acelerado) y no perturba los saves ni corta la música de fondo si el NPC no tiene tema propio.

Mientras corre una cinemática, el shell oculta la GUI y bloquea el input del jugador; un clic del jugador durante un paso SAY salta directo a la siguiente línea, y mantener el mouse presionado dispara el salto acelerado, adelantando toda la secuencia. El salto colapsa todos los pasos bloqueantes, no solo los de tiempo: los WAIT y los SAY terminan al instante, un WALKNPCTO teletransporta al NPC a su destino (con el facing de llegada que le tocaba), un WARPTOROOM cambia de room sin su fundido, y un PLAYSCENE que todavía no arrancó se saltea — una escena que ya está corriendo conserva su propio hold-to-skip. El mundo en el que caes es el mundo que la cinemática habría construido, solo que sin la espera. El cursor del mouse también se oculta — salvo que un paso SETCURSOR:visible=show lo traiga de vuelta: el input sigue bloqueado igual, así que el cursor se vuelve un prop que la propia cinemática maneja (qué cursor, qué frame, clavado dónde — ver la sección SETCURSOR de la referencia de effect-tokens), y el override se limpia solo al terminar la escena.

Pestaña Validar#

Corre en cada edición, y Guardar se niega a escribir mientras haya un error en pantalla — NPCs faltantes/desconocidos, un WAIT no positivo y (ver abajo) un token raw sin un argumento obligatorio cuentan como error; una región vacía en NPCENTER, un objetivo de hotspot/coords incompleto y texto SAY vacío son avisos, que no bloquean. Un segundo pase asíncrono revisa que las regiones y hotspots referenciados existan de verdad en los datos de la sala cargada. También acepta los sentinels dinámicos ({partySlotN}, {_prevChar}) como objetivos válidos, mientras sigue avisando si un guard de party nombra a un personaje que no reconoce.

El effect token de un paso raw se chequea igual que el Editor de Puzzles chequea los tokens de una reacción. Un SETFLAG: sin nombre de flag, o cualquier otro token al que le falte un argumento obligatorio, es un paso que en runtime no va a hacer nada — ahora se marca como error (bloqueando Guardar) en vez de pasar sin revisión, con el mismo juez (y la misma etiqueta de argumento que muestra el propio widget) que comparten los chequeos de argumento vacío del Editor de Puzzles y el Editor de Reacciones.

Uno de esos hallazgos sí tiene algo que decir al guardar. Un SAY vacío el runtime lo salta: no es una pausa (para eso está WAIT), es un paso que no hace nada. Esa es la conducta segura, y es justamente por eso que el editor pregunta: como el paso desaparece en silencio, jugando nunca vas a ver que falta una línea. Así que guardar una cinemática que todavía tiene uno pregunta primero, nombrando el paso. Es una pregunta y no un rechazo a propósito: un SAY vacío es justo lo que tienes a mitad de una idea, y tienes que poder guardar el trabajo y volver después.

Eliminar o renombrar una cinemática te avisa primero si algo todavía apunta a su id — un token CUTSCENE:<id> en otra regla, diálogo o cinemática — para que no dejes huérfano un disparador en silencio.

Pestaña Vista previa#

Corre el runtime real de core/cutscene.js (startCutscene/tickCutscene) contra un estado de prueba dentro del propio editor — no una simulación. ▶ Reproducir lo avanza a 60fps vía setInterval, ⏭ Paso avanza un tick a la vez, ↺ Reiniciar limpia la ejecución. No hay una mini-escena renderizada; en su lugar, un registro de texto reporta cada paso a medida que se resuelve ([VERBO] arg, inicio/llegada de caminata con coordenadas redondeadas, cuentas regresivas de espera), lo cual alcanza para confirmar el orden y el comportamiento de bloqueo sin tener que cablear la cinemática al juego primero. La nota de la vista previa aclara explícitamente que las caminatas de NPC en preview son en línea recta (sin el polígono transitable), aunque el ritmo coincide con la velocidad real del motor.

Content i18n#

El texto de SAY se autora monolingüe, en el defaultLocale del proyecto, misma regla que el Editor de Diálogos. Al guardar, promoteSaySteps() acuña un lid estable para cada línea nueva (o actualiza el existente en su lugar si el paso ya trae uno) y serializa el paso como SAY:<npc>|#lid (o SAY:#lid para una línea de narrador) — nunca un par {es, en} inline. El Editor de Traducción completa después cada otro locale configurado; al volver a cargar una cinemática se resuelve el lid a su texto en defaultLocale para mostrarlo, así que lo que ves en el campo siempre es la línea autorada, no un id crudo.

Flujo de trabajo#

  1. Elige una Sala — la lista cubre cada sala del proyecto (no solo las que ya tienen un archivo de reglas; uno se crea al primer guardado) más el bucket 🌐 Global para momentos entre salas.
  2. Elige una Cinemática existente del desplegable, o haz clic en Nuevo y nómbrala en el modal.
  3. + Agregar Paso para añadir un paso (por defecto SAY), luego elige su tipo y llena los campos específicos — cada argumento que porta un ID es un picker (personaje, región, hotspot, sala, escena), nunca texto libre.
  4. Reordena arrastrando o con ▲/▼; elimina con ×.
  5. Mantén un ojo en Validar a medida que avanzas.
  6. Recórrela en Vista previaReproducir/Paso/Reiniciar — y lee el registro para confirmar que la secuencia y el bloqueo se comportan como se espera.
  7. Guardar para escribir el archivo de reglas de la sala. Como ese archivo se comparte con el Editor de Puzzles, cualquier comentario // del autor anclado a una reacción o watcher en otro lugar del archivo sobrevive a un guardado desde acá también, aunque este editor no tenga UI para mostrarlos. El punto ciego es un comentario escrito directo dentro de tu propio contenido de cutscene — no tiene nombre al cual anclarse, así que Guardar avisa antes de descartarlo.

CUTSCENE:<id> busca en la sala actual primero, luego en el bucket Global. Una cinemática delimitada a una sala y una Global son dos hogares distintos: el mismo string de id en dos salas distintas son dos cinemáticas sin relación, pero el bucket 🌐 Global es el único espacio de nombres compartido, pensado para momentos que cualquier sala puede disparar. Si una reacción de hotspot o una opción de diálogo dispara CUTSCENE:<id> y no pasa nada, la causa habitual es que el id vive en las reglas de una sala distinta a la que el jugador está pisando — y tampoco está en Global, así que el fallback no encuentra nada. Los momentos entre salas van en Global; los específicos de una sala se quedan con su sala.

Guardar reescribe el archivo de reglas entero — incluidas las reacciones y los vigías que no tocaste. Es a propósito (un archivo por sala, un serializador), y por eso la pestaña de exportación sirve para ojear qué va a escribir un guardado. Las notas del autor escritas en las reacciones y los vigías de la sala — las que el Editor de Puzzles y el Editor de Reacciones editan en un campo — sobreviven intactas a esa reescritura, aunque este editor no muestre ningún campo para ellas: viajan con el archivo, ancladas por nombre, y el bloque de la cabecera se preserva como siempre. Lo que el viaje de ida y vuelta no puede cargar es una nota // escrita adentro de un bloque que se re-emite desde el objeto vivo — cutscenes: es justamente eso, y por eso importa acá —, así que el editor avisa y las lista antes de escribir, y cancelar deja el archivo intacto: no se escribe nada ni se acuña ningún lid.