移植旧变异器
把 KroggyComm 1.1 从原档案做成包,以及一份 TA: Mutation 规则文件:用 sm 原样保留,或改写成 Lua。
本章概述 docs/mutators/authoring.md 和 docs/mutators/oamut-standard.md。
原始归档
KroggyComm 1.1,作者 Immerman,以 }{KroggyComm11.tam 和 }{KroggyComm11.ccx 发布。.tam 是 TA: Mutation 的记录:名称、署有作者的说明文字,以及兼容代码 TACC 和 UH。.ccx 里有 Krogoth 模型、存了两份的一个指挥官脚本(Arm 和 Core 各一份)、两名指挥官的单位文件、脚本源码和一具尸体。本章不粘贴那些归档。它说明整理后的包保留了什么,以及每一块去了哪里。
从导入开始
oa-tool mutator import 读取 .tam,并在旁边找到 .ccx。输出文件夹不要放在存放 .tam 的文件夹里。警告说明了要整理什么:标签是默认值,TACC 变成 ta-3.1c,UH 没有可对应的模组。
$ oa-tool mutator import 'originals/}{KroggyComm11.tam' --out imports
imported kroggycomm-1-1 from originals/}{KroggyComm11.tam: 0 rule files, 1 archives
tags default to gameplay
TACC maps to ta-3.1c; Core Contingency's units are only there when it is on
UH is not mapped to a mod
导入把整个 .ccx 留在 files/kroggycomm-1-1.ccx,它写下的脚本只加入那个文件夹。它的清单是版本 1.0、标签 gameplay、works-with ta-3.1c、files 层和 legacy 记录。这个文件夹可以运行,它是这个包的起点,不是完成的变异器。
导入结果 ·mutator.lua-- Made by oa-tool mutator import from the TA: Mutation mutator "KroggyComm 1.1".
-- Its rule file is in rules/ and its archives in files/; files OA protects are left out.
function mutate(ctx)
return {
files = { add = { "files" } },
}
end
模型和脚本变成 files/
整理后的包只保留游戏会从归档里读取的东西:files/ 下的三条路径,每条都放在游戏寻找它的位置。
files/objects3d/KROGCOM.3do模型,来自 .ccx 里的 objects3d/KROGCOM.3dofiles/scripts/armcom.cobArm 的脚本,来自 scripts/armcom.cobfiles/scripts/corcom.cobCore 的脚本:与 Arm 的字节相同,在归档里存为 scripts/Corcom.cob两份单位文件也不随包发布:它们的字段变成了下面的规则。归档里还有两样东西被去掉。scripts/KroggyCom.bos 是脚本源码,游戏从不读取它。features/corpses/Corkrog_dead.tdf 是 Core Contingency 的尸体,内容没有改。
FBI 的改动变成规则
Krogoth 的单位字段变成整理后 mutator.lua 里的规则。两名指挥官都使用物体 KROGCOM,武器 CORKROG_FIRE、CORKROG_ROCKET 和 CORKROG_HEAD,以及花费、占地和移动。隐形和不良目标字段被去掉,这属于那个设计。HealTime、OvrAdjust 和 DefaultMissionType 保持 3.1c 的值:2001 年的单位文件早于这些字段,所以缺少它们并不是 Krogoth 的设计。Arm 的声音类别变成 KROGOTH。Core 仍是 CORE_COM,所以脚本传入 nil,不设置 soundcategory。那三件武器缺失时,units 钩子拒绝本局。
入口脚本 ·mutator.lua-- HealTime, OvrAdjust, DefaultMissionType and the localized names stay.
-- The 2001 unit files predate those 3.1c fields, so their absence is not the Krogoth's design.
local function krogoth_changes(sound)
local changes = {
acceleration = set(0.09),
badtargetcategory = remove(),
brakerate = set(0.19),
buildcostenergy = set(116664),
buildcostmetal = set(29489),
builddistance = set(120),
buildtime = set(382193),
cantbetransported = set(1),
cloakcost = remove(),
cloakcostmoving = remove(),
corpse = set("corkrog_dead"),
downloadable = set(1),
energymake = set(32),
energyuse = set(7),
explodeas = set("NUCLEAR_MISSILE"),
footprintx = set(3),
footprintz = set(3),
maxdamage = set(29918),
maxslope = set(17),
maxvelocity = set(1),
maxwaterdepth = set(12),
mincloakdistance = remove(),
movementclass = set("TANKDH3"),
noautofire = set(0),
objectname = set("KROGCOM"),
onoffable = set(1),
selfdestructas = set("NUCLEAR_MISSILE"),
sightdistance = set(255),
turnrate = set(960),
weapon1 = set("CORKROG_FIRE"),
weapon2 = set("CORKROG_ROCKET"),
weapon3 = set("CORKROG_HEAD"),
wpri_badtargetcategory = remove(),
}
if sound ~= nil then
changes.soundcategory = set(sound)
end
return changes
end
function mutate(ctx)
return {
files = { add = { "files" } },
rules = {
named("ARMCOM"):change(krogoth_changes("KROGOTH")),
named("CORCOM"):change(krogoth_changes(nil)),
},
units = function(units, ctx)
local weapons = ctx.weapons
if weapons["CORKROG_FIRE"] == nil or weapons["CORKROG_ROCKET"] == nil or weapons["CORKROG_HEAD"] == nil then
ctx.incompatible("KroggyComm needs Core Contingency's Krogoth weapons")
end
end,
}
end
legacy 块与署名
legacy 点名原作。保留导入写下的记录:名称 KroggyComm 1.1,前缀 }{,compatibility 为 TACC 和 UH,files 为 }{KroggyComm11.tam 和 }{KroggyComm11.ccx。作者仍是 Immerman,描述里写明所取代的原作及其作者:这就是署名。其余部分经过整理:版本 1,标签 commanders 和 new-units,works-with 为星号,因此这个包适用于任何模组和基础游戏,以及给文件、规则和钩子用的 files 层和 units 层。conflicts-with 点名 anni-comm、special-tech-comm、commander-blast 和 tribe-commander,它们写同样的指挥官字段,或附带同一个脚本。下面的清单就是整份文件。
清单 ·oamut.yamloamut: 1
id: "kroggy-comm"
name: "Krogoth Commander"
version: "1"
author:
name: "Immerman"
description: "Use an amphibious Krogoth as a commander. Turn it off to disable the radar, the sonar and the head laser in exchange for 7 energy. The D-gun aims the head laser. Arm and Core are both named because one script is shipped for each commander. This package replaces KroggyComm 1.1 by Immerman. The model and the scripts stay as files, and the Krogoth's stats are rules, including the cloak and bad-target removals that belong to that design. Heal time, the override adjust, the default mission and the localized names stay, because the 2001 unit files left them out. It needs Core Contingency's Krogoth weapons."
tags: ["commanders", "new-units"]
works-with: ["*"]
requires:
engine: ">= 0.8.5"
conflicts-with: ["anni-comm", "special-tech-comm", "commander-blast", "tribe-commander"]
layers: ["files", "units"]
legacy:
- name: "KroggyComm 1.1"
prefix: "}{"
compatibility: ["TACC", "UH"]
files: ["}{KroggyComm11.tam", "}{KroggyComm11.ccx"]
检查,并与导入结果对比
在文件夹外执行 pack,会写出 kroggy-comm-1.oamut。oa-tool mutator check 读取那个文件。这个包的最后一行是 result: ok。diff 把整理后的文件夹与导入结果 kroggycomm-1-1 对比。它在 commanders 的 build 文件夹里运行,带上这一组的 allow 文件,DIR 代表游戏文件夹。allow 文件写明哪些差异可以留下。
$ oa-tool mutator pack kroggy-comm
$ oa-tool mutator check kroggy-comm-1.oamut
$ oa-tool mutator diff --game-dir DIR --mutator ./kroggy-comm --versus ./_imports/kroggycomm-1-1 --allow _verify/kroggy-comm.allowed
带上这份 allow 文件,对比以 0 退出。在以 # 开头的表头行之后,它打印下面的行:0 differences, 7 allowed, 0 unused allowances。这七行是右侧的导入结果:两名指挥官上都去掉了 defaultmissiontype、healtime 和 ovradjust,并加入了 scripts/kroggycom.bos。整理后的包保留这三个字段,不附带 .bos。那次运行所用的游戏文件夹里,units 钩子没有拒绝这个包:三件 Krogoth 武器都在。
allowed right only field units/armcom.fbi [unitinfo] defaultmissiontype: Standby -> (absent)
allowed right only field units/armcom.fbi [unitinfo] healtime: 27 -> (absent)
allowed right only field units/armcom.fbi [unitinfo] ovradjust: 1 -> (absent)
allowed right only field units/corcom.fbi [unitinfo] defaultmissiontype: Standby -> (absent)
allowed right only field units/corcom.fbi [unitinfo] healtime: 27 -> (absent)
allowed right only field units/corcom.fbi [unitinfo] ovradjust: 1 -> (absent)
allowed right only file added scripts/kroggycom.bos aef95595e9dc1a1e543cf87c954c0b19e6523a227e89c4abaa40e6d264043889
mutator diff: 0 differences, 7 allowed, 0 unused allowances
一份 TA: Mutation 规则文件
整理后的包不附带 .sm 文件。oa-tool mutator import 保留原始规则文件,并在计划里用 sm 点名它。Hide Damage,作者 Kirk,就是这份短的。导入写出 rules/hide-damage.sm,以及一份 mutator.lua,其中的 rules 项是 sm "rules/hide-damage.sm"。下面的 .sm 就是那个文件,连换行字节一并保留。
导入结果 ·mutator.lua-- Made by oa-tool mutator import from the TA: Mutation mutator "Hide Damage".
-- Its rule file is in rules/ and its archives in files/; files OA protects are left out.
function mutate(ctx)
return {
rules = { sm "rules/hide-damage.sm" },
}
end
规则文件 · rules/hide-damage.sm[*all*]
{
HideDamage=1;
}同一条规则写成 Lua 就是 all():change { hidedamage = set(1) }。这就是 [*all*] 和 HideDamage=1 变成的样子。整理后的包发布的是这份脚本,不是 .sm。它的 legacy 记录仍然点名 {}HideDamage.tam 和 {}HideDamage.sm,作者仍是 Kirk。
入口脚本 ·mutator.luafunction mutate(ctx)
return {
rules = {
all():change { hidedamage = set(1) },
},
}
end
清单 · oamut.yamloamut: 1
id: "hide-damage"
name: "Hide Damage"
version: "1"
author:
name: "Kirk"
description: "Opponents cannot see how much health a unit has left.\n\nKirk's Hide Damage sets that flag on every unit.\n\nThis package keeps the flag."
tags: ["gameplay"]
works-with: ["*"]
requires:
engine: ">= 0.8.5"
layers: ["units"]
legacy:
- name: "Hide Damage"
prefix: "{}"
compatibility: ["*"]
files: ["{}HideDamage.tam", "{}HideDamage.sm"]
命令是 oa-tool mutator import INPUT... --out DIR。需要时再加上 --id、--version、--tag、--works-with、--pack 和 --force。.sm 被复制到 rules/ 下,计划用 sm 点名它。导入只是这个包的起点。发布之前,把变体收成选项,把规则文件改成 Lua 形式或继续用 sm 点名,只有模型或脚本需要文件时才保留文件。