Criar um mutador
Um .oamut pequeno sobre o jogo base ou qualquer mod: a pasta, o manifesto, o plano que mutate retorna, as opções, o sandbox e a ordem em que uma pilha se aplica.
Este capítulo resume docs/mutators/authoring.md e docs/mutators/oamut-standard.md.
O que é um mutador
Um mutador é um pacote .oamut pequeno, em camada sobre o jogo base ou qualquer mod. Ele muda uma partida. A Biblioteca o instala na pasta Mutators, sob o ID do manifesto, e instalar não o ativa. O jogador o ativa numa escaramuça, numa sala de batalha ou numa campanha. works-with diz com quais mods ele combina, e um asterisco significa qualquer mod e o jogo base.
O pacote
O topo da pasta contém oamut.yaml. O script de entrada fica ao lado: mutator.lua, a menos que entry indique outro, e nunca em files/, rules/ ou lua/. lua/ contém mais código-fonte Lua, os únicos arquivos que require lê. files/ contém os bytes que a camada Files pode acrescentar. rules/ contém arquivos de regras cujos nomes terminam em .sm. Um ícone é o PNG que o manifesto indica. Uma nota cujo nome termina em .md ou .txt vai junto para as pessoas lerem, e o jogo não a carrega. Um arquivo fora dessa lista é recusado. A comparação ignora maiúsculas e minúsculas nas letras ASCII.
my-mutator.oamuto arquivo que um jogador obtém├─ oamut.yamlobrigatório o manifesto├─ mutator.luao script de entrada, mutate(ctx)├─ lua/opcional; módulos Lua, os únicos arquivos que require lê├─ files/opcional; modelos, scripts e outros bytes├─ rules/opcional; arquivos de regras .sm├─ icon.pngopcional; o PNG indicado por icon└─ README.mduma nota; o jogo não a carregaO manifesto
YAML estrito, com as mesmas regras de um perfil de mod: um documento, um mapeamento de nível superior, sem âncoras e sem escalares de bloco. O arquivo começa com oamut definido como o inteiro 1. Uma chave que o padrão não lista é recusada. Ponha entre aspas um valor que começa com o sinal de maior, e também um asterisco, senão o leitor os toma por outra coisa. É por isso que requires.engine fica entre aspas. Uma versão também vai entre aspas: um número simples é recusado.
| Chave | Obrigatório | O que faz |
|---|---|---|
oamut | sim | O formato. O inteiro 1. 1.0 e um 1 entre aspas são recusados. |
id | sim | Kebab-case em minúsculas, de 1 a 64 bytes. Sem hífen no início, no fim ou duplicado. O nome da pasta de instalação. |
name | sim | De 1 a 64 bytes, sem caractere de controle. O nome que os jogadores veem. |
version | sim | Entre aspas, no máximo 32 bytes. De uma a três partes unidas por ponto, cada uma um número de 0 a 65535 sem zero à esquerda. |
author | sim | Um mapeamento. name é obrigatório, de 1 a 128 bytes. email é opcional. |
description | não | Opcional, de 1 a 2.000 bytes. Quebra de linha é permitida. A primeira linha, cortada em 200 bytes, é o resumo que o catálogo mostra. |
homepage | não | Opcional, de 1 a 256 bytes. Um endereço http ou https. |
icon | não | Opcional. O caminho, no pacote, de um PNG quadrado, terminado em .png. O instalador verifica a imagem. |
tags | sim | De um a quatro IDs, sem repetição. Os oito que a Biblioteca desenha estão abaixo. |
works-with | sim | De uma a 32 condições, sem ID repetido. Um asterisco significa qualquer mod e o jogo base, e então é a única entrada. ta-3.1c significa o jogo base sem mod. Qualquer outro ID é um mod, com uma faixa de versões opcional. |
requires | não | Opcional. Só engine e mutators. engine é uma faixa entre aspas, comparada com esta compilação. mutators lista pacotes que precisam estar ativos; eles se aplicam antes deste, na ordem escrita. |
conflicts-with | não | Opcional. Mutadores ao lado dos quais este se recusa a rodar. Um ID aqui não pode ser um que requires.mutators cite, nem o ID do próprio mutador. |
layers | sim | De um a nove nomes, sem repetição: files, units, weapons, features, sides, tables, menus, maps e hacks. Um plano só pode escrever numa camada citada aqui. |
clashes | não | Opcional, add ou replace: o que este mutador faz com uma unidade ou arma cujo nome já existe no jogo. A escolha do jogador vem primeiro, depois esta chave, depois a preferência mutators.clash-default, que é replace quando não definida. |
options | não | Opcional, no máximo 16. Configurações que o jogador escolhe antes da partida. ctx.options as lê. |
strings | não | Opcional, no máximo 16 tags de idioma. Traduções do nome, da descrição e dos rótulos das opções. |
entry | não | Opcional. O script de entrada, um caminho no pacote terminado em .lua e fora de files/, rules/ e lua/. mutator.lua quando omitido. |
legacy | não | Opcional, de 1 a 16 registros de mutadores do TA: Mutation que este pacote substitui. Cada registro tem name, prefix, compatibility e files. Um mapeamento solto é recusado. |
As oito tags
O leitor aceita qualquer tag em kebab-case minúsculo de 1 a 32 bytes, no máximo quatro. A Biblioteca desenha um ícone e um rótulo traduzido para estes oito IDs, com correspondência exata. Qualquer outro ID aparece como foi escrito, sem ícone. Quando o manifesto não indica um ícone, o emblema usa o ícone da primeira tag, se esse ID for um dos oito.
| Chave | O que faz |
|---|---|
statistics | Estatísticas |
economy | Economia |
commanders | Comandantes |
new-units | Novas unidades |
disable | Desativação |
gameplay | Jogabilidade |
ai | IA |
maps | Mapas |
O plano
A entrada define mutate. O motor chama mutate(ctx) uma vez, na fase do plano, e essa chamada não muda o jogo por si só. mutate retorna uma tabela. Uma tabela vazia não muda nada. Uma chave que o motor não conhece é recusada.
files é uma tabela de add e mask. Cada um é uma lista de textos, e qualquer dos dois pode ser omitido. add lista pastas do pacote, em ordem, e uma pasta posterior vence num caminho que as duas contêm. mask esconde caminhos. rules é uma lista de blocos prontos, feitos com where, all, named ou on e depois :change, e de caminhos sm que indicam um arquivo .sm. Uma mudança é set, scale, lock, remove ou append. scale pode receber um limite inferior e um superior, e esse limite restringe só aquele fator. Os hooks são funções. Eles rodam nesta ordem: units, weapons, features, sides, tables e depois menus. maps roda depois de todos os mutadores, e só quando a partida já escolheu um mapa. hacks define, só para esta partida, um parâmetro que o registro de ajustes abre aos mutadores. Declarar a camada é o que permite a escrita.
Opções e ctx
Durante mutate, ctx contém o mod (ID, versão e jogo), a versão do motor, as opções e ctx.incompatible. ctx.mod.id é ta-3.1c quando nenhum mod está ativo. Chamar ctx.incompatible com um motivo interrompe este mutador, e o motivo é o texto que o jogador vê. As coleções ainda não estão carregadas. Um hook pode ler units, weapons, features, sides, tables e menus em ctx sem declarar a camada. Escrever numa delas exige a camada.
ctx.options tem um campo por ID de opção. Uma opção toggle é true ou false. Uma opção number, e uma choice cujos valores são números, dá um número. Uma choice cujos valores são identificadores dá texto. Uma opção que o jogador deixou como estava vale o padrão. type é toggle, choice ou number. Uma choice lista de 2 a 16 valores, todos números ou todos identificadores, e labels quando as palavras diferem dos valores. Uma number tem min, max, step e default. O jogador só pode escolher um valor de min a max que caia num passo, então o script não precisa testar a faixa de novo: um valor fora do passo é recusado antes de o script rodar. O ID da opção é um nome Lua, e uma palavra reservada de Lua é recusada.
O sandbox
O script roda como Lua num sandbox. Ele não tem arquivo, rede, relógio, ambiente nem processo. io, os, debug, package e coroutine não são abertos, e um trecho pré-compilado é recusado. Todo trecho é código-fonte. Dois mutadores não compartilham estado.
Cada fase recomeça com a cota completa de instruções, 50.000.000, e com o limite completo de tempo real, 10 segundos. O teto de memória é 64 MiB e não é renovado para a fase seguinte. Uma string tem no máximo 65.536 bytes. Use fixed para um atributo que o script calcula. Ele conta em unidades de 1/65.536, então o mesmo script escreve o mesmo texto em todas as máquinas. pairs percorre as chaves numa ordem fixa. O resultado não depende da máquina.
Empilhamento
O jogador lista os mutadores numa ordem, aplicada de cima para baixo. O primeiro se aplica primeiro. Cada um dos seguintes vê o jogo como os de cima o deixaram. Os mutadores citados em requires.mutators são ativados junto com este e se aplicam antes dele, na ordem em que essa lista os escreve. Mais de 32 mutadores, um ID listado duas vezes, um requisito que nenhum mutador acima atende ou dois mutadores em conflito recusam a lista inteira, e nada roda.
Os arquivos de todos os mutadores entram em camadas primeiro, na ordem da lista, e um mutador posterior vence num caminho. Depois cada mutador, nessa mesma ordem, lê seus próprios arquivos de unidades, armas e download como registros, aplica suas regras e roda seus hooks. As regras aplicam uma mudança por vez, numa ordem fixa. Um fator multiplica o número atual, e um limite restringe só aquele fator, não um posterior. Uma atribuição substitui o valor atual. Um lock define o valor e impede que qualquer mutador posterior mude aquele campo. Dentro de um bloco Lua, as mudanças rodam pelo nome do campo depois de convertido para minúsculas ASCII, não na ordem em que a tabela foi escrita. Não há média entre mutadores. Depois que todos os mutadores se aplicaram, um número de unidade ou arma além da largura que o jogo armazena, e um número de elemento além da faixa que o jogo lê, fica preso no extremo dessa faixa, uma única vez.