Editor de Puzzles#
El Editor de Puzzles autora la lógica autónoma de la sala — reglas que se disparan solas a
medida que cambia el estado, en vez de responder a un clic de verbo (eso es una reacción de
hotspot, cubierta por el Editor de Salas) o de reproducirse como una secuencia ordenada no
interactiva (eso es una cinemática, cubierta por el Editor de Cinemáticas). Escribe en el mismo
archivo de reglas delimitado a la sala que ambas herramientas — reactions, watchers, y
globalWatchers viven juntos en un solo <roomId>.rules.js, y este es el editor dedicado para
las dos últimas.
Llegas a él desde el Hub (con el dev server corriendo). La barra de herramientas tiene un
desplegable Cuarto — cada cuarto del proyecto, más una entrada sintética 🌐 Global
(cross-room) arriba de todo para el bucket compartido _global.rules.js (el mismo que expone
el Editor de Cutscenes) —, un campo Nombre, Nuevo, 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. Debajo, cinco pestañas:
Reacciones, Vigías de Cuarto, Vigías Globales, GUI Puzzles, y Grafo. El panel
derecho tiene Validar y Vista previa (existe una pestaña Exportar en el markup, oculta,
guardada para una futura vía de escape).
Las tarjetas de reacciones y vigías se muestran colapsadas por defecto, con solo su clave/id visible, para que un cuarto con mucha lógica siga siendo fácil de recorrer — haz clic en el encabezado de una tarjeta (o en la flecha) para abrirla, o usa los botones colapsar todo / expandir todo en la esquina superior derecha de la barra de pestañas para actuar sobre todas las tarjetas de la pestaña actual a la vez. Agregar una reacción o vigía nuevo siempre expande y hace scroll hasta la tarjeta recién creada. El modal + Agregar Vigía pide el id del vigía por adelantado, igual que el modal de reacción — así un vigía queda nombrado e indexado antes de existir, nunca sobre un id placeholder que te olvidas de cambiar.
Watchers ("vigías"): la pieza propia de este editor#
Un watcher (vigía) es { id, when, do } — una condición y una lista de efectos, sin ningún
hotspot ni verbo asociado. Cada cuadro, tickRules() del motor de reglas chequea la condición
when de cada vigía activa contra el estado actual; en el momento en que evalúa verdadero, do
se dispara una sola vez, y el vigía queda marcado en state.firedWatchers para que nunca
vuelva a dispararse por sí solo. Esto es semántica edge-triggered, dispara-una-vez — lo opuesto a
una reacción de hotspot (que solo se evalúa porque el jugador hizo clic con un verbo sobre algo)
y a una cinemática (una lista de pasos ordenada por el autor que se reproduce de principio a fin).
Un vigía en cambio dice "en el momento en que esta condición se vuelva verdadera — cuando sea,
como sea que pase — haz esto", sin ninguna acción del jugador como disparador.
{ p: 'timerExpired', a: 'estufa' } disparando un mensaje de quemado cuando se agota la cuenta
regresiva de una estufa, o { p: 'npcSharesRoomWith', ... } atrapando al jugador fuera de
pantalla, son trabajos típicos de un vigía: cosas que deberían pasar porque cambió el estado, no
porque hubo un clic.
CLEARWATCHER lo rearma#
state.firedWatchers es lo único que se interpone entre un vigía y volver a dispararse. El token
de efecto CLEARWATCHER:<id> (disponible desde el mismo widget de efectos compartido en el resto
del motor, autocableado contra los ids de vigías de cuarto y globales de esta sala) borra el id de
ese set, así que en el siguiente cuadro la condición se vuelve a chequear de cero. Sin un
CLEARWATCHER explícito, un vigía que ya se disparó queda gastado permanentemente por el resto de
esa sesión de juego (o hasta que un guardado/carga reinicie el estado) — esto es intencional, no
un bug, pero es el punto de confusión más común cuando un vigía "deja de funcionar" después de la
primera vez.
Vigías de cuarto vs. vigías globales#
Ambas pestañas editan exactamente la misma forma { id, when, do }; la única diferencia es dónde
se registran en runtime:
- Vigías de Cuarto (
rules.watchers[]) solo corren mientras esta sala es la activa. Si sales de la sala, el vigía deja de chequearse; vuelves y se retoma (todavía respetandofiredWatcherssi ya se disparó). - Vigías Globales (
rules.globalWatchers[]) igual se autoran por sala — agregas uno desde el archivo de reglas de la sala que tenga sentido para declararlo — pero en el primer ingreso a esa sala,_onRoomEnter()deshell/room_enter.jscopia cada uno astate.registeredGlobalWatchers(deduplicado por id) y se queda ahí por el resto de la sesión, corriendo en todos los cuadros sin importar en qué sala esté parado el jugador en ese momento. El comentario detickRules(state, dt, watchers)encore/ruleEngine.jslo dice claramente: loswatchersque se pasan cada cuadro son "los vigías de la sala activa MÁS todos los vigías globales registrados." Un vigía cross-room que no pertenece a ninguna sala concreta tiene un hogar dedicado: elige 🌐 Global (cross-room) en el desplegable de Cuarto y autorálo directo en_global.rules.js, el bucket compartido donde también viven los catch watchers cross-room y las reacciones de NPC condicionadas globalmente.
Los docs de autoría enmarcan la elección en una sola pregunta: si el jugador se aleja, ¿esto
debería seguir corriendo? Sí → global (un NPC que persigue, una consecuencia a nivel mundo que
tiene que concretarse sin importar a dónde haya ido el jugador). No → local (una estufa
quemándose en la cocina es un evento de cocina — no debería resolverse fuera de pantalla).
Equivocarse en cualquiera de las dos direcciones es el gotcha clásico: un vigía global autorado
para un puzzle de una sola sala sigue corriendo (y puede dispararse) mucho después de que el
jugador se fue de esa sala por completo, lo cual se lee como "¿por qué se disparó esto en una
sala en la que nunca estuve?" hasta que te acuerdas de que se registró una vez y nunca se
desregistró — no hay un desmontaje por-sala para un vigía global, solo CLEARWATCHER para
evitar que vuelva a dispararse.
El lenguaje de condiciones#
when se arma con el mismo árbol de condiciones visual que usan las guardas de reacciones de
hotspot: null (siempre verdadero), un predicado único { p, a, a2 }, o composiciones
all/any/not anidando más condiciones. El evalCond() de core/ruleEngine.js es la única
fuente de verdad de qué predicados existen; la tabla de abajo se genera de la lista real del
picker, así que siempre está al día. Cada argumento que porta un ID (objeto, flag, sala, región,
hotspot, NPC…) es un picker tipado, nunca texto libre. Cuando el picker muestra un nombre más
amigable que el id del motor, va (entre paréntesis).
| Predicado | Argumentos | Qué comprueba |
|---|---|---|
flag |
flag name |
¿Está encendido este interruptor recordado? |
hasItem |
item id, owner (player/char) |
¿Lleva el jugador (o un personaje concreto) este objeto? |
npcInRoom |
npc id, room id |
¿Está este NPC en esa sala ahora mismo? |
npcSharesRoomWith |
npc id, meets: npc/@party |
¿Comparte este NPC la sala con ese personaje — o con alguien del equipo elegido (@party)? |
playerInRoom |
room id |
¿Está el jugador en esta sala? |
isRoomLit |
room id (opt) |
¿Está encendida la luz de la sala? (sin sala = la actual) |
isOpen |
hotspot id |
¿Está abierto este hotspot abrible (puerta, cofre…)? |
isSwitchedOn |
hotspot id |
¿Está encendido este hotspot (p. ej. su sonido en bucle está sonando)? |
isWalkableOn |
walkable area id, room id (opt) |
¿Está activa esta área caminable? |
isRegionOn |
region id, room id (opt) |
¿Está activa esta región de disparo al pasar? |
isLightZoneOn |
light zone id, room id (opt) |
¿Está encendida esta zona de luz? |
timerExpired |
timer name |
¿Ya venció esta cuenta atrás? |
timerRunning |
timer name |
¿Sigue corriendo esta cuenta atrás (iniciada, aún sin vencer)? |
behaviourFinished |
npc id, behaviour id |
¿Terminó este NPC esa rutina? |
counterGte |
counter name, value |
¿Este contador llegó al menos a este valor? |
valEq (valueEquals) |
flag/value name, value |
¿Este valor guardado es exactamente igual a este texto? (comparación de texto) |
cmp (compare) |
flag/counter, number |
Comparación numérica contra un valor guardado, con el operador que elijas: <, <=, >, >=, ==, !=. |
touching (touching (hitbox)) |
npc id, target:, / char / npc id, margin px (opt), depth px (opt) |
¿Se están tocando ahora mismo las cajas de este NPC y su objetivo? |
partyHas (in party) |
character |
¿Está este personaje en el equipo elegido? (sin equipo elegido = cuentan todos) |
soundPlaying (sound playing) |
sound kind, sound file (opt) |
¿Está sonando ahora audio de este tipo (música, ambiente, sfx, voz)? (sin clip nombrado = cualquiera de ese tipo) |
allItemsCollected (has all items) |
items (set) |
¿Se juntaron TODOS los objetos listados? (constructor de condiciones de logros) |
allRoomsVisited (visited all rooms) |
rooms (set) |
¿Se visitaron TODAS las salas listadas? (constructor de condiciones de logros) |
allNpcsTalked (talked to all npcs) |
npcs (set) |
¿Se habló con TODOS los NPCs listados? (constructor de condiciones de logros) |
touching: margin y depth#
touching pregunta si dos actores están lo bastante cerca como para contar como que se
tocan. Compara sus siluetas visibles — los píxeles reales del sprite, recortando el relleno
vacío del PNG — no el rectángulo entero de la imagen. Dos números opcionales ajustan qué
significa "lo bastante cerca", y responden preguntas distintas:
- margin — qué tan cerca en pantalla. En
0, las siluetas tienen que solaparse de verdad. Súbelo y agregas esa cantidad de píxeles de holgura alrededor, así "casi tocándose" también cuenta. El margin solo puede hacer el test más permisivo — nunca más estricto, así que no puedes ajustar una captura achicándolo. - depth — qué tan cerca en el piso. Por sí solo el test es plano: dos personajes parados en planos de profundidad completamente distintos igual se solapan en pantalla, así que con solo caminar por delante de un NPC se registra un toque. Pon depth y los pies de ambos tendrán que caer además dentro de esa cantidad de píxeles en el eje de profundidad de la sala (la línea de los pies). Déjalo en blanco y no hay test de profundidad — el comportamiento clásico, de solo solape.
La regla práctica: el margin ensancha el toque, el depth exige que compartan el mismo piso. Una persecución que deba agarrar al jugador apenas el monstruo se acerca quiere un margin generoso y sin depth. Un "parado justo en el mostrador" quiere un margin chico más un depth, para que alguien cruzando en primer plano no lo dispare.
do es una lista ordenada de tokens de efecto, autorada con el mismo widget de efectos dirigido
por manifiesto que usan el Editor de Salas y el de Cinemáticas — el mismo despacho que corre en
todos lados (applyEffects()). Nada en la lista de efectos de un vigía es especial; solo cómo se
evalúa lo es.
Los nombres de timer se autocablean como los flags. Los predicados timerExpired/timerRunning
y los efectos STARTTIMER/CLEARTIMER autocompletan desde una lista a nivel proyecto de cada
timer ya referenciado en cualquier lado — un timer suele arrancarse en un sitio y vigilarse en
otro, así que esto te ofrece el id que querías en vez de pedirte que lo retipees de memoria. Los
timers son un conjunto abierto, así que el texto libre sigue creando uno nuevo; las sugerencias
solo cierran el clásico bug silencioso donde un id de timer mal tipeado hace un vigía que
calladamente nunca dispara.
Bucket de Reacciones#
La pestaña Reacciones es la casa de este editor para las reacciones guardadas — las listas de
reglas { when, do } con clave "<hotspotId>.<verb>" (o "<hotspotId>.<verb>_<itemId>" para
usar-objeto-sobre-objetivo) que resolveReaction() chequea antes de caer al string plano
reactions[verb] de un hotspot del Editor de Salas. Un modal dedicado + Añadir Reacción elige
un objetivo — hotspot, NPC o región —, un verbo, y opcionalmente un objeto para una
clave compuesta, previsualiza el string de clave resultante, y avisa si ya existe (con un atajo
Ir a ella en vez de crear un duplicado). Si eliges región, el modal se acota a lo que una
región puede hacer de verdad: la lista de objetivos se llena con las regiones de esa sala, el
verbo queda fijado a walkover (el único evento que dispara una región — no miras una), la
opción compuesta "+ sobre objeto" desaparece, y la clave se previsualiza como
<idDeRegión>.walkover. Cada tarjeta de reacción tiene una lista ordenada de reglas
{ when, do } — gana la primera que coincide — más un campo opcional de texto libre puzzleTag
usado únicamente para filtrar/agrupar (ver Grafo, más abajo). Esta pestaña es una comodidad para
autorar la lógica de guarda que determina el resultado de un hotspot; la lista de hotspots del
Editor de Salas sigue siendo la dueña del hotspot en sí.
No hace falta venir hasta acá para llegar a una reacción guardada, además: en el Editor de Salas, una fila de verbo con reglas guardadas detrás muestra una pequeña insignia de regla de puzzle — al hacer clic se abre la misma edición de condición/efecto en un modal, ahí mismo, sin salir del Editor de Salas.
Bucket de GUI Puzzles#
No todos los puzzles viven en una reacción de hotspot o en un vigía. Un GUI abierto desde una
sala — por ejemplo, OPENGUI:digitlock en el verbo usar de un hotspot — puede llevar su propia
lógica en las acciones de clic de sus botones: un teclado que va agregando dígitos a un código,
un botón ENTRAR que lo valida y desbloquea algo. Esa lógica se autora en el propio GUI (ver el
Editor de GUI), así que es fácil perderle el rastro una vez que queda escondida detrás del
hotspot de una sala. La pestaña GUI Puzzles cierra ese hueco: escanea las reacciones y
vigías de esta sala buscando tokens OPENGUI (incluidos los que están enterrados dentro de un
efecto condicional, y las cadenas de menús GUI-a-GUI) y le da una tarjeta a cada uno.
Un GUI solo se gana una tarjeta acá si de verdad se comporta como un puzzle — algún botón fija un flag, escribe un valor, otorga un objeto, arranca un temporizador, o se ramifica según una condición. Los GUIs puramente visuales o de navegación (un menú que solo se cierra a sí mismo o desliza a otra pantalla) quedan fuera de la lista de tarjetas y en cambio se resumen en una sola línea atenuada, para que sigan siendo descubribles sin llenar el bucket de cosas que en realidad no son puzzles. Un GUI que tus reglas intentan abrir pero que no existe en el proyecto igual recibe una tarjeta, marcada como un error de autoría que vale la pena corregir.
Cada tarjeta muestra desde dónde se abre el GUI, y lista cada botón con una acción de clic: su etiqueta visible ("ENTRAR", "1", "BORRAR") va primero, con el id interno del botón mostrado atenuado al lado. Un botón condicional — uno que chequea algo antes de actuar — queda marcado, y su condición y ramas (SI / ENTONCES / SI NO) se muestran como filas legibles, con el mismo código de colores de tokens que usa el resto de este editor (las líneas de diálogo en verde, las escrituras de flag/valor en violeta, los objetos otorgados en ámbar).
Editar la acción de un botón sin salir de la sala#
Haz clic en el lápiz junto a cualquier botón para editar su acción de clic ahí mismo, con el
mismo armador de condiciones y efectos que el resto de este editor — pickers tipados, bloques
SI, nada que no hayas usado ya en una reacción o un vigía. Guardar escribe solo ese botón
de vuelta al GUI; Cancelar descarta la edición. Este es un guardado genuinamente separado
del archivo de reglas de la sala: el Guardar de la barra de herramientas del editor de
puzzles nunca toca un GUI, y el Guardar de este botón nunca toca las reglas de la sala. Se
muestra una advertencia mientras editas: si además tienes el mismo GUI abierto en el Editor de
GUI al mismo tiempo, el que guarde último gana — recarga el otro después para que no te pise
el cambio.
Pestaña Grafo#
Una visualización de dependencias de solo lectura: nodos para objetos/hotspots/NPCs referenciados
por las reglas de esta sala, aristas etiquetadas por relación (requiere, valida, espera
a, depende, abre) — arrastra nodos, rueda para zoom, arrastra el lienzo para panear. Un
switch Entre cuartos carga cada sala del proyecto y agrega aristas que cruzan los límites de
sala (útil para detectar una cadena de globalWatchers que llega hasta otra sala).
Los GUIs con puzzle del bucket GUI Puzzles se suman al mismo grafo como nodos propios
(mostrados en ámbar): las escrituras de flag/valor y los objetos otorgados por un widget
producen recursos igual que los efectos de una reacción, su condición los consume de la misma
manera, y el hotspot o vigía que abre el GUI recibe una arista abre apuntando hacia él — así
soda_machine.use → abre → el GUI digitlock aparece como un paso normal en el grafo, y un
código que un teclado escribe y que su botón ENTRAR valida después se muestra como el GUI
validando su propio flag.
El panel es explícito sobre sus propias limitaciones: las aristas cubren flags y valores,
objetos, temporizadores, walkables/regiones, y aperturas de GUI — pero una guarda de ubicación
(que el jugador o un NPC estén en cierta sala), un chequeo touching, un chequeo de estado de
audio como soundPlaying, o un comportamiento de NPC no tienen arista acá. Eso es esperado, no
un fallo; esas condiciones no tienen forma de recurso de una manera que un grafo de dependencias
pueda representar.
Pestaña Vista previa#
Corre las funciones reales del motor — evalCond, applyEffects, resolveReaction
importadas directo de core/ruleEngine.js — contra un estado de prueba dentro del propio editor,
el mismo enfoque de "runtime real, no una simulación" que la pestaña Vista previa del Editor de
Cinemáticas. Configuras flags, inventario, la sala del jugador, y posiciones de NPC (pares
id:cuarto) en un formulario chico; el panel entonces lista automáticamente cada clave de
reacción, cada vigía (de cuarto y global), y cada botón de GUI con puzzle del bucket GUI
Puzzles del cuarto cargado como chips clicables, agrupados bajo encabezados colapsables
Reacciones / Vigías / Widgets de GUI para que un cuarto con muchos casos siga siendo
fácil de recorrer. También puedes escribir un id de hotspot/NPC y un verbo a mano y Ejecutar
Reacción.
Un flag se puede fijar con un valor plano (puzzle_done) o dándole uno específico
(lock_code=1234), así que un puzzle de GUI armado alrededor de un código o un valor escrito —
no solo un flag simple de encendido/apagado — también es testeable acá. Ejecutar un chip de
vigía evalúa su when contra tu estado de prueba y, si es verdadero, aplica su do e imprime
los tokens resultantes; ejecutar un chip de botón de GUI aplica su acción de clic directamente
— un botón no tiene una guarda when propia, así que cualquier condición que chequee vive
dentro de la acción misma, y la vista previa reporta cada cambio de flag, valor, u objeto que
resulta, incluidos los que están enterrados dentro de una rama que tomó (así que hacer clic en
el botón ENTRAR de un teclado con el código correcto muestra el flag que fija).
El formulario de estado y los chips de casos hacen scroll en su propia zona; el ejecutor manual
(los campos de objetivo/verbo, Ejecutar Reacción, y la caja de resultado) queda fijo abajo
para estar siempre visible, sin importar cuán larga sea la lista de casos. La única salvedad,
señalada directamente por la herramienta: los predicados que leen estado de runtime en vivo no
se pueden simular acá. Los espaciales como touching no tienen x/y en el estado de prueba, y
los de audio como soundPlaying no tienen audio realmente sonando en el editor, así que ambos
siempre leen falso — la vista previa avisa en vez de mentir sobre el resultado.
Notas del autor#
Cada card de reacción y de vigía tiene un campo Nota del autor — el lugar para por qué
existe esta regla, que la regla misma no puede decir. Lo que escribas ahí se guarda en el
.rules.js como un comentario // justo arriba de esa entrada, y una nota que ya esté en el
archivo se carga en el campo: el archivo de reglas y el editor son dos vistas del mismo texto.
Las notas quedan ancladas por nombre — a una clave de reacción, a un id de vigía o a una sección entera —, no por posición, y eso es lo que las hace sobrevivir al guardado. Reordenar reglas nunca despega una nota de lo que describe; renombrar una clave de reacción o un id de vigía se lleva su nota con el nombre nuevo; y borrar una reacción se lleva la suya, en vez de dejarla colgada sobre la regla siguiente.
Flujo de trabajo#
- Elige un Cuarto (cualquier sala del proyecto, tenga o no un archivo de reglas todavía — uno se crea al primer guardado) o Nuevo.
- Pestaña Reacciones: + Añadir Reacción para asociar un hotspot, NPC o región + verbo (+ objeto
opcional), y arma su lista ordenada de reglas
{ when, do }. - Pestaña Vigías de Cuarto: + Añadir Vigía de Cuarto para lógica que solo debería correr mientras esta sala está cargada.
- Pestaña Vigías Globales: + Añadir Vigía Global para lógica que tiene que seguir corriendo sin importar a qué sala vague el jugador — pregúntate "si el jugador se aleja, ¿esto debería seguir corriendo?"
- Pestaña GUI Puzzles: revisa si algún GUI que esta sala abre (un teclado, una cerradura de combinación) lleva su propia lógica de puzzle, y edita la acción de un botón ahí mismo si necesita un ajuste.
- Revisa el Grafo para chequear de qué depende realmente una reacción/vigía/puzzle de GUI, especialmente con Entre cuartos activado si sospechas que un vigía global llega más allá de esta sala.
- Recorre cada caso en Vista previa — clic en los chips auto-listados (colapsa una sección que no estés usando para mantener la lista manejable) o manéjalo a mano — antes de confiar en él dentro del motor.
- Mantén un ojo en Validar — además de claves de reacción faltantes/mal formadas, también
bloquea Guardar ante cualquier effect token al que le falte un argumento obligatorio (un
SETFLAG:vacío y similares — chequeado recursivamente dentro de bloquesif/then/elsetambién), porque el motor correría ese token con una clave vacía que ningún predicado podría volver a leer. Guardar escribe el archivo de reglas de la sala. Los comentarios//que escribes entre reacciones/watchers sobreviven al round-trip, anclados a la entrada junto a la que están — la excepción es el bloquecutscenes:, donde un comentario pierde su anclaje y Guardar avisa antes de descartarlo.
Validar hace más que contar claves faltantes: también lee cada token de efecto — en las
reglas de reacción, en los vigías y dentro de los bloques if — contra el manifiesto de
efectos, y avisa de cualquier argumento obligatorio vacío. SETFLAG: sin nombre de
bandera se guardaba tan contento y después, en runtime, seteaba la bandera vacía, una que
ningún predicado puede leer jamás; ahora es un error, y un error bloquea Guardar hasta
que lo arregles. Los argumentos legítimamente opcionales no molestan: un PICKUP sin objeto
otorga el id del propio hotspot, SHOWTEXT sin color dibuja en blanco, y las colas de
velocidad/opciones pueden ir todas vacías.
Validar también avisa — nunca bloquea — cuando el propio orden de una cadena arriesga
quedarse congelada. Una cadena solo se aparca en un WAIT, un WAITFOR o una caminata
bloqueante; sin eso corre entera de un tirón y nada de esto aplica. Con uno de esos, cualquier
token ANTERIOR que se lleve el frame deja el resto colgado: abrir un modal del motor que
pausa el mundo (la bolsa de inventario, Opciones, Guardar/Cargar, la confirmación de salir) y
después aparcar en una espera congela para siempre, porque ni el propio botón de cerrar del
modal puede correr mientras la cadena está aparcada. Una escena, cutscene, etapa de arcade u
otro CUTSCENE se queda con el frame en cambio — normalmente sin problema, porque la cola
sigue cuando termina, salvo una escena con final "esperar input" que no termina sola. Y un
token que reconstruye el mundo (GOTOBLOCK, LOADGAME, QUITGAME…) descarta todo lo que
quedaba en cola después, en silencio. El chequeo camina la estructura real if/then/else
de la cadena, no la lista aplanada, así que sabe en qué rama vive cada paso. Es compartido
entre este editor, el Reactions Editor y el modal de reacciones propio del Room Editor — los
tres lugares que autoran cadenas; el Cutscene Editor queda afuera a propósito, porque sus
pasos corren en su propio runner por-frame y no se pueden congelar así.
Un vigía que ya se disparó se queda disparado hasta que
CLEARWATCHERdiga lo contrario — y un vigía global sigue corriendo en salas donde el jugador no está parado. Son dos caras del mismo gotcha: los vigías son fáciles de razonar en aislamiento ("cuando X, haz Y") pero su tiempo de vida no es obvio con solo leer la regla. Antes de autorar un puzzle que esperas que se reinicie o se repita (un interruptor que se puede prender y apagar, una persecución que debería poder re-dispararse), decide de antemano si necesitas unCLEARWATCHERen algún lugar de los efectos que lo deshaga — y antes de hacer un vigía global, confirma que el evento realmente pertenece al mundo y no solo a esta sala, ya que no hay un desmontaje por-sala, solo el guardia de dispara-una-vez.Guardar reescribe el archivo de reglas, y hay dos clases de comentario que se comportan distinto. El bloque de la cabecera, arriba de todo, se preserva tal cual — ese sigue siendo el lugar de las notas que hablan del archivo entero. Las notas pegadas a un nodo viajan como se explica arriba. Lo que el viaje de ida y vuelta no puede cargar es un comentario escrito adentro de un bloque que el serializador re-emite desde el objeto vivo — hoy,
cutscenes:. Tanto Guardar como el guardado del panel de exportación frenan y te listan exactamente esas líneas antes de escribir, así puedes cancelar y moverlas a algún lugar que sobreviva.