Créer un mutateur
Un petit .oamut posé sur le jeu de base ou n'importe quel mod : le dossier, le manifeste, le plan que mutate renvoie, les options, le bac à sable et l'ordre d'une pile.
Ce chapitre résume docs/mutators/authoring.md et docs/mutators/oamut-standard.md.
Ce qu'est un mutateur
Un mutateur est un petit paquet .oamut, posé sur le jeu de base ou n'importe quel mod. Il change une partie. La Bibliothèque l'installe dans le dossier Mutators sous l'identifiant du manifeste, et l'installation ne l'active pas. Le joueur l'active pour une escarmouche, une salle de bataille ou une campagne. works-with dit à quels mods il convient, et une étoile veut dire n'importe quel mod et le jeu de base.
Le paquet
Le sommet du dossier porte oamut.yaml. Le script d'entrée est à côté : mutator.lua, sauf si entry en nomme un autre, et jamais sous files/, rules/ ou lua/. lua/ porte d'autres sources Lua, les seuls fichiers que require lit. files/ porte les octets que la couche files peut ajouter. rules/ porte les fichiers de règles dont le nom finit par .sm. Une icône est le PNG que le manifeste nomme. Une note dont le nom finit par .md ou .txt est emportée pour les gens, et le jeu ne la charge pas. Un fichier hors de cette liste est refusé. La comparaison ignore la casse des lettres ASCII.
my-mutator.oamutle fichier qu'un joueur obtient├─ oamut.yamlrequis le manifeste├─ mutator.luale script d'entrée, mutate(ctx)├─ lua/facultatif ; modules Lua, les seuls fichiers que require lit├─ files/facultatif ; modèles, scripts et autres octets├─ rules/facultatif ; fichiers de règles .sm├─ icon.pngfacultatif ; le PNG nommé par icon└─ README.mdune note ; le jeu ne la charge pasLe manifeste
YAML strict, les mêmes règles qu'un profil de mod : un document, une table de premier niveau, pas d'ancres et pas de scalaires de bloc. Le fichier commence par oamut, l'entier 1. Une clé que le standard ne liste pas est refusée. Mettez entre guillemets une valeur qui commence par un signe supérieur, et une étoile, sinon le lecteur y voit autre chose. requires.engine est entre guillemets pour cette raison. Une version aussi : un nombre nu est refusé.
| Clé | Requis | Rôle |
|---|---|---|
oamut | oui | Le format. L'entier 1. 1.0, et un 1 entre guillemets, sont refusés. |
id | oui | Kebab-case en minuscules, de 1 à 64 octets. Pas de tiret en tête, en fin ou doublé. Le nom du dossier d'installation. |
name | oui | De 1 à 64 octets, aucun caractère de contrôle. Le nom que les joueurs voient. |
version | oui | Entre guillemets, au plus 32 octets. Une à trois parties jointes par un point, chacune un nombre de 0 à 65535 sans zéro en tête. |
author | oui | Une table. name est requis, de 1 à 128 octets. email est facultatif. |
description | non | Facultatif, de 1 à 2 000 octets. Un saut de ligne est permis. La première ligne, coupée à 200 octets, est le résumé que le catalogue montre. |
homepage | non | Facultatif, de 1 à 256 octets. Une adresse http ou https. |
icon | non | Facultatif. Le chemin, dans le paquet, d'un PNG carré, terminé par .png. L'installeur vérifie l'image. |
tags | oui | Un à quatre identifiants, aucun répété. Les huit que la Bibliothèque dessine sont plus bas. |
works-with | oui | De 1 à 32 conditions, aucun identifiant en double. Une étoile veut dire n'importe quel mod et le jeu de base, et elle est alors la seule entrée. ta-3.1c veut dire le jeu de base sans mod. Tout autre identifiant est un mod, avec une plage de version facultative. |
requires | non | Facultatif. Seulement engine et mutators. engine est une plage entre guillemets contre cette version. mutators nomme des paquets qui doivent être actifs ; ils s'appliquent avant celui-ci, dans l'ordre écrit. |
conflicts-with | non | Facultatif. Mutateurs à côté desquels celui-ci refuse de tourner. Un identifiant ici n'est pas un de ceux que requires.mutators nomme, ni l'identifiant de ce mutateur. |
layers | oui | Un à neuf noms, aucun répété : files, units, weapons, features, sides, tables, menus, maps et hacks. Un plan ne peut écrire qu'une couche nommée ici. |
clashes | non | Facultatif, add ou replace : ce que ce mutateur fait d'une unité ou d'une arme dont le nom est déjà dans le jeu. Le choix du joueur passe d'abord, puis cette clé, puis la préférence mutators.clash-default, qui vaut replace quand elle n'est pas réglée. |
options | non | Facultatif, au plus 16. Réglages que le joueur choisit avant la partie. ctx.options les lit. |
strings | non | Facultatif, au plus 16 codes de langue. Les traductions du nom, de la description et des libellés d'options. |
entry | non | Facultatif. Le script d'entrée, un chemin du paquet terminé par .lua, hors de files/, rules/ et lua/. mutator.lua quand la clé manque. |
legacy | non | Facultatif, de 1 à 16 fiches de mutateurs TA: Mutation que ce paquet remplace. Chaque fiche est name, prefix, compatibility et files. Une table seule est refusée. |
Les huit étiquettes
Le lecteur accepte toute étiquette en kebab-case minuscule, de 1 à 32 octets, quatre au plus. La Bibliothèque dessine une icône et un libellé traduit pour ces huit identifiants, à la lettre. Tout autre identifiant s'affiche tel qu'il a été écrit, sans icône à lui. Quand le manifeste ne nomme pas d'icône, le badge prend l'icône de la première étiquette si cet identifiant est l'un des huit.
| Clé | Rôle |
|---|---|
statistics | Statistiques |
economy | Économie |
commanders | Commandants |
new-units | Nouvelles unités |
disable | Interdictions |
gameplay | Jeu |
ai | IA |
maps | Cartes |
Le plan
L'entrée définit mutate. Le moteur appelle mutate(ctx) une fois, dans la phase de plan, et cet appel ne change pas le jeu à lui seul. mutate renvoie une table. Une table vide ne change rien. Une clé que le moteur ne connaît pas est refusée.
files est une table de add et mask. Chacun est une liste de texte, et l'un ou l'autre peut manquer. add nomme des dossiers du paquet, dans l'ordre, et un dossier plus tardif gagne un chemin que les deux portent. mask cache des chemins. rules est une liste de blocs finis, faits avec where, all, named ou on puis :change, et de chemins sm qui nomment un fichier .sm. Un changement est set, scale, lock, remove ou append. scale peut prendre une borne basse et une borne haute, et cette borne ne borne que ce facteur. Les hooks sont des fonctions. Ils tournent dans cet ordre : units, weapons, features, sides, tables, puis menus. maps tourne après chaque mutateur, et seulement quand la partie a choisi une carte. hacks règle, pour cette partie, un paramètre que le registre ouvre aux mutateurs. Déclarer la couche est ce qui permet l'écriture.
Options et ctx
Pendant mutate, ctx porte le mod (son identifiant, sa version et le jeu), la version du moteur, les options et ctx.incompatible. ctx.mod.id vaut ta-3.1c quand aucun mod n'est actif. Appeler ctx.incompatible avec une raison arrête ce mutateur, et la raison est le texte que le joueur voit. Les collections ne sont pas encore chargées. Un hook peut lire units, weapons, features, sides, tables et menus sur ctx sans déclarer la couche. Écrire l'une exige la couche.
ctx.options porte un champ par identifiant d'option. Un interrupteur vaut true ou false. Un nombre, et un choix dont les valeurs sont des nombres, est un nombre. Un choix dont les valeurs sont des identifiants est du texte. Une option que le joueur a laissée est la valeur par défaut. type vaut toggle, choice ou number. Un choix liste de 2 à 16 values, toutes des nombres ou toutes des identifiants, et labels quand les mots diffèrent des valeurs. Un nombre a min, max, step et default. Le joueur ne peut choisir qu'une valeur de min à max qui tombe sur un pas, donc le script n'a pas à revérifier la plage : une valeur hors des pas est refusée avant que le script tourne. L'identifiant d'option est un nom Lua, et un mot-clé Lua est refusé.
Le bac à sable
Le script tourne en Lua dans un bac à sable. Il n'a ni fichier, ni réseau, ni horloge, ni environnement, ni processus. io, os, debug, package et coroutine ne sont pas ouverts, et un fragment précompilé est refusé. Chaque fragment est du source. Deux mutateurs ne partagent aucun état.
Chaque phase repart de l'allocation complète d'instructions, 50 000 000, et de la limite complète de temps réel de 10 secondes. Le plafond de mémoire est de 64 Mio et n'est pas rendu pour la phase suivante. Une chaîne fait au plus 65 536 octets. Utilisez fixed pour une statistique que le script calcule. Il compte des 65 536es, donc le même script écrit le même texte sur chaque machine. pairs parcourt les clés dans un ordre fixe. Le résultat ne dépend pas de la machine.
Empiler
Le joueur liste les mutateurs dans un ordre, appliqués de haut en bas. Le premier s'applique le premier. Chaque suivant voit le jeu tel que ceux au-dessus l'ont laissé. Les mutateurs nommés dans requires.mutators sont activés avec celui-ci et s'appliquent avant lui, dans l'ordre où la liste les écrit. Plus de 32 mutateurs, un identifiant deux fois, un prérequis que rien au-dessus ne remplit, ou deux qui entrent en conflit, refuse la liste entière, et rien ne tourne.
Les fichiers de chaque mutateur sont empilés d'abord, dans l'ordre de la liste, et un mutateur plus tardif gagne un chemin. Puis chaque mutateur, dans le même ordre, lit ses propres fichiers d'unités, d'armes et de téléchargement comme des fiches, applique ses règles, puis lance ses hooks. Les règles s'appliquent un changement à la fois, dans un ordre fixe. Un facteur multiplie le nombre courant, et une borne ne borne que ce facteur, pas un facteur plus tardif. Une affectation remplace la valeur courante. Un verrou règle la valeur et empêche tout mutateur plus tardif de changer ce champ. Dans un bloc Lua les changements courent par nom de champ après mise en minuscules ASCII, pas dans l'ordre où la table a été écrite. Il n'y a pas de moyenne entre mutateurs. Une fois tous les mutateurs appliqués, un nombre d'unité ou d'arme au-delà de la largeur que le jeu stocke, et un nombre d'élément au-delà de la plage que le jeu lit, est tenu au bout de cette plage, une fois.