Inicio › Info de modding › Crear un mutador
Capítulo 03

Crear un mutador

Un .oamut pequeño sobre el juego base o cualquier mod: la carpeta, el manifiesto, el plan que devuelve mutate, las opciones, el aislamiento y el orden en que se aplica una pila.

Este capítulo resume docs/mutators/authoring.md y docs/mutators/oamut-standard.md.

Qué es un mutador

Un mutador es un paquete .oamut pequeño, en capas sobre el juego base o cualquier mod. Cambia una partida. La Biblioteca lo instala en la carpeta Mutators bajo el identificador del manifiesto, e instalarlo no lo activa. El jugador lo activa para una escaramuza, una sala de batalla o una campaña. works-with dice con qué mods encaja, y un asterisco significa cualquier mod y el juego base.

El paquete

En la raíz de la carpeta está oamut.yaml. El script de entrada va a su lado: mutator.lua, salvo que entry nombre otro, y nunca bajo files/, rules/ o lua/. lua/ guarda más código Lua, los únicos archivos que lee require. files/ guarda los bytes que la capa files puede añadir. rules/ guarda archivos de reglas cuyo nombre acaba en .sm. Un icono es el PNG que nombra el manifiesto. Una nota cuyo nombre acaba en .md o .txt viaja para las personas, y el juego no la carga. Un archivo fuera de esa lista se rechaza. La comparación ignora las mayúsculas de las letras ASCII.

my-mutator.oamutel archivo que recibe un jugador├─ oamut.yamlobligatorio el manifiesto├─ mutator.luael script de entrada, mutate(ctx)├─ lua/opcional; módulos Lua, los únicos archivos que lee require├─ files/opcional; modelos, scripts y otros bytes├─ rules/opcional; archivos de reglas .sm├─ icon.pngopcional; el PNG que nombra icon└─ README.mduna nota; el juego no la carga

El manifiesto

YAML estricto, las mismas reglas que un perfil de mod: un documento, un mapeo de nivel superior, sin anclas ni escalares de bloque. El archivo empieza con oamut como el entero 1. Una clave que el estándar no lista se rechaza. Entrecomilla un valor que empiece por un signo de mayor que, y una estrella, o el lector los toma por otra cosa. requires.engine va entre comillas por eso. La versión también: un número suelto se rechaza.

ClaveObligatorioQué hace
oamutsíEl formato. El entero 1. 1.0, y un 1 entre comillas, se rechazan.
idsíKebab-case en minúsculas, de 1 a 64 bytes. Sin guion al inicio, al final ni doble. El nombre de la carpeta de instalación.
namesíDe 1 a 64 bytes, sin carácter de control. El nombre que ven los jugadores.
versionsíEntre comillas, como mucho 32 bytes. De una a tres partes unidas por un punto, cada una un número de 0 a 65535 sin cero a la izquierda.
authorsíUn mapeo. name es obligatorio, de 1 a 128 bytes. email es opcional.
descriptionnoOpcional, de 1 a 2.000 bytes. Se permite un salto de línea. La primera línea, cortada a 200 bytes, es el resumen que muestra el catálogo.
homepagenoOpcional, de 1 a 256 bytes. Una dirección http o https.
iconnoOpcional. La ruta en el paquete de un PNG cuadrado, terminada en .png. El instalador comprueba la imagen.
tagssíDe uno a cuatro identificadores, ninguno repetido. Los ocho que dibuja la Biblioteca están abajo.
works-withsíDe 1 a 32 condiciones, sin identificador repetido. Un asterisco significa cualquier mod y el juego base, y entonces es la única entrada. ta-3.1c significa el juego base sin mod. Cualquier otro identificador es un mod, con un rango de versión opcional.
requiresnoOpcional. Solo engine y mutators. engine es un rango entre comillas frente a esta build. mutators nombra paquetes que deben estar activos; se aplican antes que este, en el orden escrito.
conflicts-withnoOpcional. Mutadores junto a los que este se niega a ejecutarse. Un identificador aquí no es uno que nombre requires.mutators, ni el propio de este mutador.
layerssíDe uno a nueve nombres, ninguno repetido: files, units, weapons, features, sides, tables, menus, maps y hacks. Un plan solo puede escribir una capa nombrada aquí.
clashesnoOpcional, add o replace: qué hace este mutador con una unidad o un arma cuyo nombre ya está en el juego. Primero cuenta la elección del jugador, luego esta clave y luego la preferencia mutators.clash-default, que es replace si no tiene valor.
optionsnoOpcional, como mucho 16. Ajustes que el jugador elige antes de la partida. ctx.options los lee.
stringsnoOpcional, como mucho 16 códigos de idioma. Traducciones del nombre, la descripción y las etiquetas de las opciones.
entrynoOpcional. El script de entrada, una ruta del paquete que termina en .lua y no está bajo files/, rules/ ni lua/. Si falta la clave, es mutator.lua.
legacynoOpcional, de 1 a 16 registros de mutadores de TA: Mutation que este paquete sustituye. Cada registro es name, prefix, compatibility y files. Un mapeo suelto se rechaza.

Las ocho etiquetas

El lector acepta cualquier etiqueta en kebab-case y minúsculas, de 1 a 32 bytes, como mucho cuatro. La Biblioteca dibuja un icono y una etiqueta traducida para estos ocho identificadores, coincidentes exactamente. Cualquier otro identificador se muestra como se escribió, sin icono propio. Si el manifiesto no nombra un icono, la insignia usa el icono de la primera etiqueta cuando ese identificador es uno de los ocho.

ClaveQué hace
statisticsEstadísticas
economyEconomía
commandersComandantes
new-unitsUnidades nuevas
disableProhibiciones
gameplayJugabilidad
aiIA
mapsMapas

El plan

La entrada define mutate. El motor llama a mutate(ctx) una vez, en la fase de plan, y esa llamada no cambia el juego por sí sola. mutate devuelve una tabla. Una tabla vacía no cambia nada. Una clave que el motor no conoce se rechaza.

files es una tabla de add y mask. Cada una es una lista de texto, y cualquiera puede faltar. add nombra carpetas del paquete, en orden, y una carpeta posterior gana una ruta que ambas tienen. mask oculta rutas. rules es una lista de bloques terminados, hechos con where, all, named u on y luego :change, y de rutas sm que nombran un archivo .sm. Un cambio es set, scale, lock, remove o append. scale puede llevar un límite bajo y uno alto, y ese límite solo acota ese factor. Los hooks son funciones. Corren en este orden: units, weapons, features, sides, tables y luego menus. maps corre después de cada mutador, y solo cuando la partida ha elegido un mapa. hacks fija, para esta partida, un parámetro que el registro abre a los mutadores. Declarar la capa es lo que permite la escritura.

Opciones y ctx

Durante mutate, ctx tiene el mod (su identificador, versión y juego), la versión del motor, las opciones y ctx.incompatible. ctx.mod.id es ta-3.1c cuando no hay mod. Llamar a ctx.incompatible con un motivo detiene este mutador, y el motivo es el texto que ve el jugador. Las colecciones aún no están cargadas. Un hook puede leer units, weapons, features, sides, tables y menus en ctx sin declarar la capa. Escribir una necesita la capa.

ctx.options tiene un campo por identificador de opción. Un interruptor es true o false. Un número, y una elección cuyos valores son números, es un número. Una elección cuyos valores son identificadores es texto. Una opción que el jugador dejó es el valor por defecto. type es toggle, choice o number. Una elección lista de 2 a 16 values, todos números o todos identificadores, y labels cuando las palabras difieren de los valores. Un número tiene min, max, step y default. El jugador solo puede elegir un valor de min a max que caiga en un paso, así que el script no tiene que volver a comprobar el rango: un valor fuera de los pasos se rechaza antes de que corra el script. El identificador de la opción es un nombre de Lua, y una palabra clave de Lua se rechaza.

El aislamiento

El script corre como Lua en un aislamiento. No tiene archivo, ni red, ni reloj, ni entorno, ni proceso. io, os, debug, package y coroutine no se abren, y un fragmento precompilado se rechaza. Cada fragmento es fuente. Dos mutadores no comparten estado.

Cada fase vuelve a empezar con la asignación completa de instrucciones, 50.000.000, y con el límite completo de tiempo real de 10 segundos. El tope de memoria es 64 MiB y no se reparte de nuevo para la fase siguiente. Una cadena es como mucho 65.536 bytes. Usa fixed para un valor que calcule el script. Cuenta 65.536avos, así el mismo script escribe el mismo texto en cada máquina. pairs recorre las claves en un orden fijo. El resultado no depende de la máquina.

Apilar

El jugador lista los mutadores en un orden, aplicados de arriba abajo. El primero se aplica primero. Cada uno posterior ve el juego como lo dejaron los de encima. Los mutadores que nombra requires.mutators se activan con este y se aplican antes, en el orden en que la lista los escribe. Más de 32 mutadores, un identificador dos veces, un requisito que nada por encima cumple, o dos que entran en conflicto, rechaza la lista entera, y no corre nada.

Los archivos de cada mutador se ponen en capas primero, en el orden de la lista, y un mutador posterior gana una ruta. Luego cada mutador, en el mismo orden, lee sus propios archivos de unidades, armas y descargas como registros, aplica sus reglas y después ejecuta sus hooks. Las reglas aplican un cambio cada vez, en un orden fijo. Un factor multiplica el número actual, y un tope limita solo ese factor, no uno posterior. Una asignación sustituye el valor actual. Un bloqueo fija el valor e impide que cualquier mutador posterior cambie ese campo. Dentro de un bloque Lua los cambios corren por el nombre del campo tras pasarlo a minúsculas ASCII, no en el orden en que se escribió la tabla. No hay promedio entre mutadores. Cuando todos los mutadores se han aplicado, un número de unidad o de arma más allá del ancho que guarda el juego, y un número de elemento más allá del rango que lee el juego, se mantiene en el extremo de ese rango, una vez.