王国之泪 公主之花 MOD 本质是什么,如何自行实现
王泪买回来玩了 400 小时也吃灰了 1 年多了,官方大师模式,是不大可能了。
最近在 B 站看到很多王国之泪的整合 MOD 的推荐,也就了解到了 公主之花,而 B 站很多人在问却没人解答的问题是:它到底是用香蕉网(GameBanana)的哪些三方 MOD 合并出来的,这里将最近自己折腾的经验分享出来。
吐槽
关于 MOD:一堆乱七八糟的材料、繁多的逼氪数值行为、游戏到处都有的 QQ 群提示,我稍微试玩了一下就卸载了。加群观望了一个月,感觉也没啥更新,因为三方 MOD 基本上停更,他也就只能改改数值,做下贴图整合。
关于他的群:没必要加,他一个蠢问题收费 10 元,所以基本上没人说话,只发表情包。其他人回答,哪怕是用他自己的原话(不喜欢那个字体,可删 Font 目录。这些问题可以问 AI),也会被禁言撤回,换句话说,他是那个群里的土皇帝,不允许其他人解答问题。
如何做一个纯净或者更好的 MOD
公主之花的底包,我猜是从 Rauru and the Secret Stone 开始,但是按 Rauru 作者自己的意思,这年头也不再推荐。
直接从 DAR 下手,https://dark-army-resurrection.fandom.com/wiki/DAR_for_Tears_of_the_Kingdom
DAR 有付费包和免费包的区别,我这里没啥要求,免费包足矣。于是根据官方章节 DAR_+_CM_+_DOTK_+_WoLR 可以很轻松的得到基础包架构:

这样的底包有些词条是未汉化的,用 msbt editor 导出 Mals 中的 CNzh.Product.121 文件为 txt 后,找个 AI 翻译一下再导入回去,重新用 restbl 工具生成数据库即可。
当然,上面并非重点,重点是 TKMM 无法合并的 MOD 如何处理,毕竟上面的底包加什么都会错,其实很简单,你需要的只是一个差异处理脚本,可以选择用 AI 写 PY 脚本,也可以用 Beyond Compare 手动对比导出,本质总结如下:
MOD 合并流程:新添加文件直接合入,差异文件按 romfs 相对路径,复制到 out 目录下分两组 CLEAN/romfs、MOD/romfs
逻辑已经整合至:prepare_tkmm.py
打开 TKMM 以 CLEAN 文件夹为底包,合入 MOD 冲突文件,将合并结果移除不需要的文件后覆盖至 CLEAN 再重新计算 restbl 即可。
把上面的底包作为 CLEAN 底包,MOD 则从香蕉网下载即可,大的小的,都可以这样合并,没有任何问题,我这里在底包上按这个思路处理过的有:
Rauru's Secret Stone
Yet Another Better Sages
Shinobi no Satori
The Latverian Legacy
warm-embrace-comfort
Menacing Chuchus
Slots of Fun!
Master Sword - Wind Razor
Sword of the Hero with Beam and Phantom Fuse
这里附上我的脚本,可给 AI 参考:
prepare_tkmm.py
import argparse
import filecmp
import os
import re
import shutil
import sys
from pathlib import Path
PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
if PROJECT_ROOT not in sys.path:
sys.path.insert(0, PROJECT_ROOT)
from config.constants import CLEAN_ROMFS, MERGED_DIR, MOD_ROMFS, OUT_DIR
def prepare_tkmm_diff_files():
"""
预处理 MOD 与 CLEAN 文件:
1. CLEAN 有的文件:直接对比,不一致则提取至 OUT/CLEAN 和 OUT/MOD 供 TKMM 合并
2. CLEAN 没有的文件:
- 若带版本号 (.Product.XXX):跳过不复制
- 若不带版本号:直接合入 CLEAN
"""
clean_romfs_dir = Path(CLEAN_ROMFS)
mod_romfs_dir = Path(MOD_ROMFS)
out_dir = Path(OUT_DIR)
out_clean_romfs = out_dir / "CLEAN" / "romfs"
out_mod_romfs = out_dir / "MOD" / "romfs"
if not clean_romfs_dir.exists():
print(f" CLEAN_ROMFS 目录不存在: {clean_romfs_dir}")
return
if not mod_romfs_dir.exists():
print(f" MOD_ROMFS 目录不存在: {mod_romfs_dir}")
return
# 清空 OUT 目录下的旧比对目录
for target_dir in [out_clean_romfs, out_mod_romfs]:
if target_dir.exists():
shutil.rmtree(target_dir)
target_dir.mkdir(parents=True, exist_ok=True)
added_count = 0
diff_count = 0
same_count = 0
skipped_ver_count = 0
print("=" * 75)
print(" 开始预处理文件(精准对比 / 按需提取)...")
print(f" CLEAN 底包 : {clean_romfs_dir}")
print(f" MOD 来源 : {mod_romfs_dir}")
print(f" OUT 提取 : {out_dir}")
print("=" * 75)
# 遍历 MOD_ROMFS
for mod_file in mod_romfs_dir.rglob("*"):
if mod_file.is_dir():
continue
rel_path = mod_file.relative_to(mod_romfs_dir)
clean_file = clean_romfs_dir / rel_path
# 判断文件名是否带有版本号标识 (如 .Product.110)
is_versioned = bool(re.search(r'\.Product\.\d+', mod_file.name))
# -----------------------------------------------------
# 情况 1:CLEAN 中已存在该文件 -> 直接对比内容差异
# -----------------------------------------------------
if clean_file.exists():
is_different = not filecmp.cmp(mod_file, clean_file, shallow=False)
if is_different:
dest_clean_file = out_clean_romfs / rel_path
dest_mod_file = out_mod_romfs / rel_path
dest_clean_file.parent.mkdir(parents=True, exist_ok=True)
dest_mod_file.parent.mkdir(parents=True, exist_ok=True)
shutil.copy2(clean_file, dest_clean_file)
shutil.copy2(mod_file, dest_mod_file)
diff_count += 1
print(f" [冲突差异 -> 提取至 OUT] {rel_path}")
else:
same_count += 1
# -----------------------------------------------------
# 情况 2:CLEAN 中不存在该文件
# -----------------------------------------------------
else:
if is_versioned:
# 带版本号但在 CLEAN 中没有 -> 跳过不复制
skipped_ver_count += 1
print(f" [CLEAN 缺失该版本文件,跳过] {rel_path}")
else:
# 不带版本号的新文件 -> 拷贝合入 CLEAN
clean_file.parent.mkdir(parents=True, exist_ok=True)
shutil.copy2(mod_file, clean_file)
added_count += 1
print(f" [普通新文件 -> 合入 CLEAN] {rel_path}")
# 统计汇总
print("\n" + "=" * 75)
print(" 分类统计摘要")
print("=" * 75)
print(f" 直接合入 CLEAN 的新增文件 : {added_count} 个")
print(f" 双向提取至 OUT 的冲突文件 : {diff_count} 组")
print(f" 内容无变化跳过的相同文件 : {same_count} 个")
print(f" 忽略的异版本不匹配文件 : {skipped_ver_count} 个")
print("=" * 75)
if diff_count > 0:
print("\n 提取完成,待合并文件已就绪:")
print(f" • 底包路径: {out_clean_romfs}")
print(f" • MOD路径 : {out_mod_romfs}")
else:
print("\n 无任何冲突差异文件,所有 MOD 新增文件已全部合并完毕!")
def copy_merged_back_to_clean():
"""
按 Merged_DIR/romfs 中的相对路径,将 TKMM 合并后的文件覆盖回 CLEAN_ROMFS
"""
merged_dir = Path(MERGED_DIR)
merged_romfs = merged_dir / "romfs" if (merged_dir / "romfs").exists() else merged_dir
clean_romfs_dir = Path(CLEAN_ROMFS)
if not merged_romfs.exists():
print(f" Merged_DIR/romfs 目录不存在: {merged_romfs}")
return
# 清理 merged_romfs 中由 TKMM 生成的空文件夹
for p in sorted(merged_romfs.rglob("*"), key=lambda x: len(x.parts), reverse=True):
if p.is_dir() and not any(p.iterdir()):
p.rmdir()
copied_count = 0
print("=" * 75)
print(" 开始将合并结果写回 CLEAN 工程...")
print(f" 合并源路径 : {merged_romfs}")
print(f" CLEAN目标 : {clean_romfs_dir}")
print("=" * 75)
for merged_file in merged_romfs.rglob("*"):
if merged_file.is_dir():
continue
rel_path = merged_file.relative_to(merged_romfs)
target_clean_file = clean_romfs_dir / rel_path
target_clean_file.parent.mkdir(parents=True, exist_ok=True)
shutil.copy2(merged_file, target_clean_file)
copied_count += 1
print(f" [覆盖回 CLEAN] {rel_path}")
print("\n" + "=" * 75)
print(f" 覆盖完成!共将 {copied_count} 个合并文件成功写回 CLEAN 目录。")
print("=" * 75)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="TKMM 差异提取与写回工具")
parser.add_argument("back", nargs="?", help="将 Merged_DIR/romfs 中的合并结果覆盖回 CLEAN_ROMFS")
args = parser.parse_args()
if args.back:
copy_merged_back_to_clean()
else:
prepare_tkmm_diff_files()
此时主体大差不差了,这个 MOD 实现对于普通玩家看到这里,也就够了,不出意外可以得出以下结果:

进阶:和公主之花还差点什么呢
林可儿(我不喜欢)
Rauru and the Secret Stone (有了 DAR 与 Challenge Mode 这个无所谓的)
349 个公开的定制 weapon (有很多是 香蕉网 的零散武器 MOD)
230 个防具相关 模型与贴图 (乱七八糟的其他 MOD 偷过来的一堆,动作还偷不全)
一些剑气 (香蕉网和那啥 mod 付费的忘了,没啥兴趣)
空岛商店那些 NPC 放置 (可以自己拿 TwnObj_DemonStatue_A_01 以及 Npc_TAOBeedle_C0 事件流程去改,还能自己移除特里流程的废话)
但你手上有公主之花的 MOD,也就只需要一个 AI 做下分析,也就能用脚本拿过来了,那些加载中的无需尝试,因为 mc 中对应的贴图文件未公开,这里能分享的似乎只有 py 脚本的运行环境:
Dockerfile
FROM python:3.12-slim
# 清华源
RUN sed -i 's/deb.debian.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list.d/debian.sources
# 在系统层直接安装 cmake 和 C++ 编译环境(解决 oead 源码编译问题),并补充 zsh 和 curl
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
cmake \
git \
zsh \
curl \
&& rm -rf /var/lib/apt/lists/*
RUN git config --global core.autocrlf input \
&& git config --global core.filemode false
# 安装 byml 和 pyyaml,msbt 可选 PyLibMS
RUN pip install --no-cache-dir byml pyyaml restbl oead zstandard pymsbmnl evfl
# 1. 静默/非交互模式安装 Oh My Zsh
RUN sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended
# 2. 下载 zsh-autosuggestions 插件
RUN git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions
# 3. 配置 .zshrc (启用插件 + 开启历史记录去重)
RUN sed -i 's/plugins=(git)/plugins=(git zsh-autosuggestions)/g' ~/.zshrc \
&& echo 'setopt HIST_IGNORE_DUPS' >> ~/.zshrc \
&& echo 'setopt HIST_IGNORE_ALL_DUPS' >> ~/.zshrc \
&& echo 'setopt HIST_EXPIRE_DUPS_FIRST' >> ~/.zshrc \
&& echo 'setopt HIST_FIND_NO_DUPS' >> ~/.zshrc \
&& echo 'setopt HIST_SAVE_NO_DUPS' >> ~/.zshrc
WORKDIR /data/DC/Tools
# 切换默认 Shell 环境为 zsh
ENV SHELL=/bin/zsh
CMD ["zsh"]
# docker build -t byml-env .
还有很多内容说不完,说完对于普通玩家也是云里雾里,实际上那些地图上多到用不完的武器和防具,要不要也无所谓,找点自己喜欢的防具武器 MOD 合一下更好。
于是可以说点直接作用于整合 MOD 的:
王国之泪的 MOD,物品主要是靠 label,比如 埃辛诺斯战刃 是 Weapon_Sword_War,于是根据这个 label 就能知道 RSDB 里哪些文件和 埃辛诺斯战刃 有关,什么一刀 9999,无敌 1 血 也就那么回事。
同时 Weapon_Sword_War 的 pack.zs 里也就有 modelinfo 指向模型”{project}.{fmdb}.bfres.mc”,想改模型与贴图参考香蕉网教程:How to Create Custom Weapons 这篇教程跑通,王泪 MOD 编辑也就入门了。
而需要的工具也就这些,当然我这里基本都是 AI 用 py 脚本处理的,只是刚开始不懂才用用:

有四个软件是非 Windows 不可,好在虚拟机 Windows 11 能用:
1、mesh_codec不要用 gui 版本,arm 无法运行,mc 转 bfres 后,py 就可以直接解析mc文件中的贴图,命令行直接批处理更快。只支持解压mc,压回要用 toolbox,可写 AutoHotkey 批量自动保存。
2、Gamedata,物品的新增有关,不然游戏中无法识别到新增内容,格式特殊不可用其他工具编辑。
3、TotkTagEditor.Desktop,物品的新增有关,背包排序以及对于特定类别物品的定义,防具/武器,格式特殊不可用其他工具编辑。
4、每次 MOD 修改完 都得重新生成数据库的 restbl,格式特殊无其他工具替代。
不过 Gamedata、TotkTagEditor 都是手动合并 MOD 或者修改内容才需要,TKMM 可以自动合并大多数文件,而且比自己写脚本处理得更好,那些无法合并和解析的比如 ELink2 这些都是 TKMM 直接覆盖的。
能说的就这么多了,以上提到的任何工具,都是 Github 开源的,太多所以懒得贴链接。最后祝各位塞尔达玩家,国庆快乐~
有问题可以留言,以上。
