Головна › Моддинг › Створити мутатор
Розділ 03

Створити мутатор

Невеликий .oamut поверх базової гри чи будь-якого моду: тека, маніфест, план, який повертає mutate, параметри, пісочниця і порядок застосування мутаторів.

Цей розділ стисло викладає docs/mutators/authoring.md і docs/mutators/oamut-standard.md.

Що таке мутатор

Мутатор — це невеликий пакет .oamut, що накладається поверх базової гри чи будь-якого моду. Він змінює один матч. Бібліотека встановлює його в теку Mutators під id з маніфесту, і встановлення його не вмикає. Гравець вмикає мутатор для сутички, кімнати бою чи кампанії. works-with вказує, яким модам він підходить, а зірочка означає будь-який мод і базову гру.

Пакет

У корені теки лежить oamut.yaml. Поруч із ним — вхідний скрипт: mutator.lua, якщо entry не називає інший, і ніколи не в files/, rules/ чи lua/. У lua/ лежить додатковий вихідний код Lua — це єдині файли, які читає require. У files/ лежать байти, які може додати шар files. У rules/ лежать файли правил з іменами, що закінчуються на .sm. Іконка — це PNG, який називає маніфест. Нотатку з іменем, що закінчується на .md чи .txt, пакет містить для людей, і гра її не завантажує. Файл поза цим переліком відхиляється. Під час порівняння регістр літер ASCII не враховується.

my-mutator.oamutфайл, який отримує гравець├─ oamut.yamlобовʼязково маніфест├─ mutator.luaвхідний скрипт, mutate(ctx)├─ lua/необовʼязково; модулі Lua — єдині файли, які читає require├─ files/необовʼязково; моделі, скрипти та інші байти├─ rules/необовʼязково; файли правил .sm├─ icon.pngнеобовʼязково; PNG, названий в icon└─ README.mdнотатка; гра її не завантажує

Маніфест

Строгий YAML, ті самі правила, що й для профілю моду: один документ, одне відображення верхнього рівня, без якорів і блокових скалярів. Файл починається з oamut, якому задано ціле число 1. Ключ, якого немає в стандарті, відхиляється. Бери в лапки значення, що починається зі знака «більше», і зірочку, інакше читач сприйме їх як щось інше. Саме тому requires.engine пишуть у лапках. Версію теж беруть у лапки: просте число відхиляється.

КлючОбовʼязковийЩо робить
oamutтакФормат. Ціле число 1. 1.0, як і 1 у лапках, відхиляється.
idтакkebab-case у нижньому регістрі, від 1 до 64 байтів. Без дефіса на початку чи в кінці і без подвоєного дефіса. Назва теки встановлення.
nameтакВід 1 до 64 байтів, без керівних символів. Назва, яку бачать гравці.
versionтакУ лапках, щонайбільше 32 байти. Від однієї до трьох частин, зʼєднаних крапкою, кожна — число від 0 до 65535 без нуля на початку.
authorтакВідображення. name обовʼязковий, від 1 до 128 байтів. email необовʼязковий.
descriptionніНеобовʼязково, від 1 до 2000 байтів. Символ нового рядка дозволено. Перший рядок, обрізаний до 200 байтів, — це короткий опис, який показує каталог.
homepageніНеобовʼязково, від 1 до 256 байтів. Адреса http або https.
iconніНеобовʼязково. Шлях у пакеті до квадратного PNG, що закінчується на .png. Інсталятор перевіряє зображення.
tagsтакВід одного до чотирьох ідентифікаторів, без повторів. Вісім, які малює Бібліотека, наведено нижче.
works-withтакВід однієї до 32 умов, жоден id двічі. Зірочка означає будь-який мод і базову гру, і тоді це єдиний елемент. ta-3.1c означає базову гру без моду. Будь-який інший id — це мод, з необовʼязковим діапазоном версій.
requiresніНеобовʼязково. Лише engine і mutators. engine — діапазон у лапках, з яким порівнюється ця збірка. mutators називає пакети, які мають бути ввімкнені; вони застосовуються перед цим, у порядку запису.
conflicts-withніНеобовʼязково. Мутатори, поруч із якими цей відмовляється працювати. id тут не може бути серед названих у requires.mutators і не може бути власним id цього мутатора.
layersтакВід однієї до девʼяти назв, без повторів: files, units, weapons, features, sides, tables, menus, maps і hacks. План може записувати лише в шар, названий тут.
clashesніНеобовʼязково, add або replace: що робить цей мутатор із юнітом чи зброєю, чия назва вже є в грі. Спершу діє вибір гравця, потім цей ключ, потім налаштування mutators.clash-default, яке без значення дорівнює replace.
optionsніНеобовʼязково, щонайбільше 16. Налаштування, які гравець обирає перед матчем. Їх читає ctx.options.
stringsніНеобовʼязково, щонайбільше 16 мовних тегів. Переклади назви, опису й підписів параметрів.
entryніНеобовʼязково. Вхідний скрипт — шлях у пакеті, що закінчується на .lua і не лежить у files/, rules/ чи lua/. Якщо ключ пропущено — mutator.lua.
legacyніНеобовʼязково, від 1 до 16 записів про мутатори TA: Mutation, які замінює цей пакет. Кожен запис — це name, prefix, compatibility і files. Окреме відображення без списку відхиляється.

Вісім тегів

Читач приймає будь-який тег у kebab-case в нижньому регістрі, від 1 до 32 байтів, щонайбільше чотири. Для цих восьми id, за точним збігом, Бібліотека малює іконку й перекладений підпис. Будь-який інший id показується так, як його записано, без іконки. Коли маніфест не називає icon, значок бере іконку першого тегу, якщо цей id — один із восьми.

КлючЩо робить
statisticsХарактеристики
economyЕкономіка
commandersКомандири
new-unitsНові підрозділи
disableВимкнення
gameplayГеймплей
aiШІ
mapsМапи

План

Вхідний скрипт визначає mutate. Рушій викликає mutate(ctx) один раз, у фазі плану, і цей виклик сам по собі гру не змінює. mutate повертає одну таблицю. Порожня таблиця нічого не змінює. Ключ, якого рушій не знає, відхиляється.

files — це таблиця з add і mask. Кожен із них — список рядків, і будь-який можна пропустити. add називає теки в пакеті по черзі, і шлях, що є в обох, дістається пізнішій теці. mask приховує шляхи. rules — це список готових блоків, створених за допомогою where, all, named чи on, а потім :change, і шляхів sm, що називають файл .sm. Зміна — це set, scale, lock, remove або append. scale може мати нижню й верхню межу, і ця межа обмежує лише цей один множник. Хуки — це функції. Вони виконуються в такому порядку: units, weapons, features, sides, tables, потім menus. maps виконується після всіх мутаторів і лише тоді, коли матч обрав мапу. hacks задає на цей один матч параметр, який реєстр відкриває для мутаторів. Записувати дозволяє саме оголошення шару.

Параметри та ctx

Під час mutate у ctx є мод (його id, версія й гра), версія рушія, параметри та ctx.incompatible. ctx.mod.id дорівнює ta-3.1c, коли жоден мод не ввімкнено. Виклик ctx.incompatible з причиною зупиняє цей мутатор, а причина — це текст, який бачить гравець. Колекції ще не завантажено. Хук може читати units, weapons, features, sides, tables і menus у ctx без оголошення шару. Для запису шар потрібен.

ctx.options містить по одному полю на кожен id параметра. Перемикач — true або false. Число, а також вибір, значення якого — числа, є числом. Вибір, значення якого — ідентифікатори, є текстом. Параметр, якого гравець не чіпав, має значення за замовчуванням. type — це toggle, choice або number. Вибір перелічує від 2 до 16 values, усі числа або всі ідентифікатори, і labels, коли слова відрізняються від значень. Число має min, max, step і default. Гравець може обрати лише значення від min до max, що лежить на кроці, тож скрипту не треба вдруге перевіряти діапазон: значення поза кроком відхиляється ще до запуску скрипту. id параметра — це імʼя Lua, і ключове слово Lua відхиляється.

Пісочниця

Скрипт виконується як Lua в одній пісочниці. У нього немає файлів, мережі, годинника, оточення й процесів. io, os, debug, package і coroutine не відкрито, а попередньо скомпільований фрагмент відхиляється. Кожен фрагмент — вихідний код. Два мутатори не мають спільного стану.

Кожна фаза починається знову з повного ліміту інструкцій, 50 000 000, і з повного ліміту реального часу в 10 секунд. Обмеження памʼяті — 64 MiB, і для наступної фази його не видають знову. Один рядок — щонайбільше 65 536 байтів. Для характеристики, яку обчислює скрипт, використовуй fixed. Він рахує в 1/65 536, тож той самий скрипт записує той самий текст на кожній машині. pairs обходить ключі у фіксованому порядку. Результат не залежить від машини.

Накладання мутаторів

Гравець розставляє мутатори в певному порядку, і вони застосовуються згори донизу. Перший застосовується першим. Кожен наступний бачить гру такою, якою її лишили ті, що вище. Мутатори, названі в requires.mutators, вмикаються разом із цим і застосовуються перед ним, у тому порядку, в якому їх записано в цьому списку. Понад 32 мутатори, id, указаний двічі, вимога, якої не задовольняє жоден мутатор вище, або два мутатори, що конфліктують, — і весь список відхиляється, нічого не виконується.

Спершу накладаються файли всіх мутаторів у порядку списку, і спільний шлях дістається пізнішому мутатору. Потім кожен мутатор у тому самому порядку читає свої файли юнітів, зброї й download як записи, застосовує свої правила, а тоді виконує свої хуки. Правила застосовують по одній зміні за раз, у фіксованому порядку. Множник множить поточне число, а обмеження стосується лише цього множника, а не пізнішого. Присвоєння замінює поточне значення. Фіксація (lock) задає значення й не дає жодному пізнішому мутатору змінити це поле. Усередині одного блоку Lua зміни виконуються за назвою поля після зведення до нижнього регістру ASCII, а не в порядку, в якому записано таблицю. Між мутаторами немає усереднення. Після того як застосовано всі мутатори, число юніта чи зброї, що виходить за ширину, яку зберігає гра, і число обʼєкта, що виходить за діапазон, який читає гра, один раз утримується на межі цього діапазону.