所有格式页面 ↓
教程与参考

从头到尾制作一个单位模组

来自 coreprime/kbot @ 0ab97bf · 在 GitHub 上编辑

本教程带你从原版的横扫千军安装出发,做出一个小小的模组,新增 Arm Flash 坦克的一个变体——一个速度翻倍的换皮版本。完成后,你会得到一个可以发布的 .ufo 压缩包,放进游戏文件夹就能加载;同时也会对 kbot 支持的每种格式建立起清晰的整体认识。

整个练习大约需要 20 分钟,会用到 HPI、FBI、COB、3DO、PCX、TDF 和 sidedata.tdf。

Important

以下步骤假定使用类 UNIX 的 shell。kbot 命令行在 Windows 上完全相同;必要时把路径中的 / 换成 \。


0. 准备工作

  • 位于 $TA 的完整 TA 安装(GOG、Steam 或原版光盘)。
  • 安装好 kbot:
    go install github.com/coreprime/kbot/cmd/kbot@latest
    kbot ctx add "$TA" --alias ta --game totala
  • 留出磁盘空间,存放展开后的一份工作文件(约 120 MB)。

1. 展开安装目录

你要逐个编辑文件;先把压缩包展开一次,就能用普通工具读取它们。

kbot mount "$TA" flatten --target ./ta-flat

看看得到了什么:

ls ta-flat/                # ai/  anims/  features/ ... weapons/
ls ta-flat/units/ | head   # ARMCOM.FBI, ARMFLASH.FBI, ...

文件夹布局与虚拟文件系统的结构一致——压缩包在运行时如何分层叠加,见 HPI。


2. 创建模组工作目录

为横扫千军制作模组是增量式的:把一个 .ufo 放在现有压缩包旁边,其中的文件就会覆盖基础游戏。在一个镜像目录树中构建你的模组:

mkdir -p mymod/{units,scripts,objects3d,unitpics,download}

Note

你只需要发布你改动过的文件。 不要把整个游戏复制到 mymod/ 里——那会让 .ufo 臃肿不堪,还可能遮蔽你并不想覆盖的东西。download/ 目录按惯例存放我们将在第 5 步添加的建造菜单注册文件。


3. 挑一个单位来派生

我们以现有的 Arm Flash 为基础制作 MYFLASH。复制四个文件:

cp ta-flat/units/armflash.fbi      mymod/units/myflash.fbi
cp ta-flat/scripts/ARMFLASH.cob    mymod/scripts/MYFLASH.cob
cp ta-flat/objects3d/armflash.3do  mymod/objects3d/myflash.3do
cp ta-flat/unitpics/armflash.pcx   mymod/unitpics/myflash.pcx

为什么是这四个?每个单位都需要:

文件 用途 页面
units/X.fbi 属性和元数据 FBI
scripts/X.cob 动画/行为字节码 COB
objects3d/X.3do 3D 网格 3DO
unitpics/X.pcx 建造菜单用的 96×96 单位头像 PCX
download/X.tdf 建造菜单注册(在第 5 步添加) TDF

按照惯例,文件名是 FBI 中 Objectname 的小写形式,.fbi 本身有时用大写。引擎在所有地方都不区分大小写。


4. 改写 FBI

打开 mymod/units/myflash.fbi。必须修改的两个关键字段是 UnitName(查找键)和 Objectname(文件基名引用):

[UNITINFO]
{
    UnitName=MYFLASH;             // ← was ARMFLASH
    Objectname=myflash;           // ← was armflash
    Side=ARM;
    Designation=ARM-MV;
    Name=Super Flash;             // ← display name
    Description=Twice-as-fast Flash variant;
    ...
}

然后调高一项属性来证明改动生效——把速度翻倍:

    MaxVelocity=4.0;              // was 2.0
    Acceleration=0.30;            // was 0.15

完整的字段目录见 FBI 附录。未设置的字段都沿用引擎的默认值。

Warning

每个值末尾都要有 ;。 这是“我的改动没生效”的头号原因——漏掉的分号会悄无声息地把这个值与下一行合并。


5. 在建造菜单中注册单位

一个单位即使存在,只要没有任何建造者能造它,就无法被建造。为新单位添加建造位的正确方法,是在模组中放一个 download/<UNITNAME>.tdf 文件——Cavedog 自己的 Core Contingency 资料片就是这样发布新单位的,你能找到的每个只含一个单位的 .ufo 附加包(AFark.ufo、AFlea.ufo、CorNecro.ufo……)也都遵循同样的约定。

创建 mymod/download/MYFLASH.tdf:

[MENUENTRY1]
{
    UNITMENU=ARMVP;       // The builder this unit appears under
    MENU=3;               // Build-menu page number (1-indexed)
    BUTTON=4;             // Slot within that page (0–5 in a 2×3 grid;
                          // 4 = bottom-left)
    UNITNAME=MYFLASH;     // The unit being placed (matches your FBI's UnitName)
}

TA 的建造菜单每页是一个 2 列 × 3 行的网格,因此 BUTTON 取值 0–5,对应关系如下:

┌─────┬─────┐
│  0  │  1  │   page N, top row
├─────┼─────┤
│  2  │  3  │   page N, middle row
├─────┼─────┤
│  4  │  5  │   page N, bottom row
└─────┴─────┘

在目标建造者现有的布局中挑一个空位——基础游戏中每个建造者逐页的完整布局,见 TA 建造树参考。

引擎在启动时读取每个 download/*.tdf,解析其中的每个 [MENUENTRY<N>],并把这些条目合并到 sidedata.tdf 所声明的建造菜单中。不需要修改 sidedata.tdf。

为什么这比修改 sidedata.tdf 更好

做法 优点 缺点
修改 sidedata.tdf 单一的权威来源 覆盖整个文件(约 50 KB);与任何同样改动它的模组冲突;基础游戏下次打补丁时你的添加内容就会丢失
download/*.tdf 增量式,约 150 字节,不与其他模组冲突,对模组友好 每添加一个单位就要一个文件(而单位本来就是制作模组的自然单元)

这是 Cavedog 官方认可的扩展钩子——它的存在正是为了让只含一个单位的附加包不必另外复制修改一份 sidedata.tdf。

由多个建造者建造

要让单位可以由多个建造者建造,只需添加更多 [MENUENTRY<N>] 节。Cavedog 自己的 download/Armfort.tdf(Arm 防御工事墙,随 ccdata.ccx 发布)正是这样做的:

[MENUENTRY1] { UNITMENU=ARMACK; MENU=3; BUTTON=4; UNITNAME=ARMFORT; }
[MENUENTRY2] { UNITMENU=ARMACV; MENU=3; BUTTON=4; UNITNAME=ARMFORT; }
[MENUENTRY3] { UNITMENU=ARMACA; MENU=3; BUTTON=4; UNITNAME=ARMFORT; }

——这样 ARMFORT 就可以由高级建造 Kbot、高级建造车和高级建造飞机建造。每个建造者一个条目。

选择 MENU 和 BUTTON 的值

原版 TA 把前两页菜单(MENU=1、MENU=2)留给基础游戏的单位。社区的惯例是把可下载的单位放在 MENU=3(或更高)上,以免与 Cavedog 发布的任何内容冲突。BUTTON 是该页内的槽位。

拿不准时,从一个向同一建造者添加单位的现有 download/*.tdf 中照抄这些值。提取 Cavedog 的 Armfort.tdf、Armmark.tdf、Cormort.tdf 等作为可用的参考:

kbot hpi extract /path/to/ccdata.ccx "*.tdf" -t /tmp/cc-downloads
ls /tmp/cc-downloads/download/

Note

两个模组使用相同的 (UNITMENU, MENU, BUTTON) 三元组时,会以无法预料的方式冲突——后加载的那个占据该槽位。如果发布的模组要与其他模组共存,请选一个较高的页码(MENU=4 或 5)。

字段参考见 TDF:[MENUENTRY]。


6. 重新编译 COB(可选)

MYFLASH.cob 是从 ARMFLASH.cob 复制来的——原样就能用。如果你想调整动画,就反编译、编辑,再重新编译:

# Decompile to readable BOS
kbot cob decompile mymod/scripts/MYFLASH.cob -t mymod/scripts/MYFLASH.bos

# Edit MYFLASH.bos in any text editor
# (See cob.md for the BOS language reference.)

# Compile back to bytecode
kbot cob compile  mymod/scripts/MYFLASH.bos -t mymod/scripts/MYFLASH.cob

# Lint for common issues
kbot cob lint     mymod/scripts/MYFLASH.cob

对于 Cavedog 的每一个零售版脚本,反编译→编译的往返都是逐字节一致的——kbot cob roundtrip 会对游戏中的全部脚本验证这一点。


7. (可选)重绘单位头像

unitpics/myflash.pcx 是一张 96×96 的带调色板 PCX。可以用任何支持 8 位 PCX 的图像编辑器(GIMP、Aseprite、Krita)编辑它,但要保留 TA 调色板。检查调色板是否完好:

kbot pcx describe mymod/unitpics/myflash.pcx
# Expected: BitsPerPixel: 8, embedded palette present

如果调色板被弄乱了,保存前重新导入标准的 TA 调色板(palettes/palette.pal)。关于 0x0C 标记和 BytesPerLine 填充的坑,见 PCX。


8. (可选)重做 3D 模型的外观

objects3d/myflash.3do 是一个层级网格——顶点、图元、纹理引用。尽管年代久远,Cavedog 的编辑器(3DO Builder)仍是最实用的 3DO 编辑器。kbot 不能直接编辑 .3do;网页界面只把它们渲染出来供查看:

kbot mount $(kbot ctx path) --server
# → browse to objects3d/myflash.3do for the piece tree and textures

如果你在编写工具,磁盘结构见 3DO。


9. 打包成 .ufo

kbot hpi pack ./mymod --target myflash.ufo

默认情况下,kbot 使用分块的 LZ77 压缩、标准的 Cavedog 文件头密钥,以及游戏所要求的 Cavedog 版权尾部标记——也就是说,引擎会直接接受它,不会报错。确认一下:

kbot hpi info  myflash.ufo
# Should show ~5–8 files, marker 0x49504148 (HAPI), decrypt key 0xBF,
# and "TA 3.1c would mount: yes". A "no" names the reason (for example
# a missing Cavedog trailer), and the game would silently skip the file.

kbot hpi list  myflash.ufo -v
# units/myflash.fbi, scripts/MYFLASH.cob, objects3d/myflash.3do, ...

10. 安装并测试

为什么用 .ufo?TA 3.1c 先挂载 rev31.gp3,然后是每个 .ccx、每个 .ufo,而 .hpi 只挂载前十个,每一组都按 ASCII 大写名称排序;每个文件都从第一个包含它的压缩包中读取(见 HPI 加载顺序)。.ufo 总会被挂载,而且排在所有 .hpi 之前;.hpi 模组则要去争夺零售版安装已经占满的那十个 *.hpi 名额。rev31.gp3 或某个 .ccx 中也有的文件(例如 units/ARMCOM.FBI 或 gamedata/sidedata.tdf)仍然会从那些压缩包中读取:这类覆盖文件要以散文件的形式放在安装根目录中发布。studio 的 Export mod… 对话框会在你下载之前列出某个工作区中的这类文件。

把 .ufo 放进 TA 安装根目录,与 totala1.hpi 放在一起:

cp myflash.ufo "$TA/"

启动 TA。开一局遭遇战,建造一座 Arm 载具工厂,你的 Super Flash 就应该出现在建造菜单中——速度是普通 Flash 的两倍。

Tip

快速迭代。 不必每次改动后都重新打包,你可以直接把 mymod/ 放进一个展开后的安装目录(那里的文件优先于压缩包中的内容)。等准备好发布时再打包。


故障排查

症状 可能的原因
单位没有出现在建造菜单中。 缺少 download/<UNITNAME>.tdf,UNITMENU= 有误(建造者名称拼错),或者 (MENU, BUTTON) 槽位已被另一个单位占用。
建造菜单显示了该单位,但点击后没有反应。 download TDF 中的 UNITNAME= 与 FBI 的 UnitName= 不一致。或者 FBI 中该单位的 Bmcode= 为 0(表示“不可建造”)。
游戏在加载时崩溃。 FBI 值有误(漏了 ;、[SECTION] 格式错误)。运行 kbot mount mymod --server,在网页界面的 TDF 查看器中检查该 FBI——它会高亮显示解析错误。
单位显示为一团品红色。 FBI 中的 Objectname 指向一个不存在的 .3do 文件名。检查 objects3d/<Objectname>.3do。
单位不移动。 MovementClass 引用了一个不在 moveinfo.tdf 中的类别。要么添加这个类别,要么使用现有的类别。
单位能移动,但网格没有动画。 COB 脚本引用了一个 3DO 中没有的部件名。拿 `kbot cob decompile myflash.cob
单位速度对了,但头像不对。 unitpics/<Objectname>.pcx 不存在,或者引擎看到的仍是原版的 armflash.pcx(模组在基础压缩包之后才加载?)。
建造菜单显示空白图标。 PCX 没有保存为 8 位带调色板格式。运行 kbot pcx describe 确认。

下一步

  • 添加新武器——从 weapons/ 中复制一个 .tdf,编辑后在 FBI 的 Weapon1= 中引用它。见 weapons.tdf 参考。
  • 添加新的移动类别——追加到 moveinfo.tdf 中。见 Gamedata。
  • 制作自定义地图——用 .sct 区块拼装一个 .tnt(或者用 kbot tnt pack 直接手工制作 TNT)。见 TNT。
  • 添加新音效——把 WAV 放进 sounds/,在 gamedata/sound.tdf 中关联起来。见音效。
  • 调整 AI——在 ai/default.txt 中为你的新单位添加 Weight/Limit 规则。见 AI。
  • 研究现有模组——kbot hpi list 加上 kbot hpi extract 同样适用于第三方的 .ufo。研究别人如何构建他们的压缩包,是掌握模组制作惯例的最快途径。

另见

  • HPI——压缩包打包细节。
  • FBI / TDF——单位定义语言,附完整的字段词典。
  • COB / BOS——脚本语言。
  • 3DO——网格格式。
  • Gamedata——sidedata.tdf、moveinfo.tdf、weapons.tdf 参考。
  • 术语表——术语参考。