← Bonemark

模组

通过编写小的文本文件来添加内容。不需要编程,也不需要编译器。共五部分:安装别人的模组、你的第一个模组、改动已有的游戏、一份含每个族类与每个诊断码的参考,以及如何与它长期共处。你能做出什么,那张表是从构建里量出来的,不是许诺的。

使用mods

mods文件夹在哪里

从主菜单打开 Mods。该路径写在屏幕顶部,旁边有一个按钮,可在文件管理器中打开该文件夹。

它位于您的保存旁边,无论您是安装其他人的模组还是编写自己的模组,它都是同一个文件夹。游戏运行时不会读取任何内容,因此移动文件时游戏是否打开并不重要。

安装一个

mod 是一个顶部带有 mod.json 的文件夹。大多数下载都是 zip 中的该文件夹。

1.提取它这样包含 mod.json 的文件夹就直接位于 mods 文件夹内。提取到 northern_reach/northern_reach/mod.json 的 zip 太深了一层,游戏将看不到它。
2.重新启动游戏启动时读取包。没有热安装。
3.打开它打开 Mod 并使用开关。复制的文件夹被“找到”并保持关闭状态:仅通过出现在文件夹中就不会加载任何内容。
4.再次重新启动该行显示活动 — 重新启动以加载,直到您执行此操作。然后它说已加载

你复制到的模组会保持关闭状态,直到你这么说。游戏毫无疑问地拒绝可执行文件,但数据包仍然可以以你没有要求的方式改变价格、物品和人员,而在已经运行的游戏中自行弹出的一个问题是没有人愿意诊断的。所以游戏会问。这是第一次额外的重新启动,并且对于该包再也不会。

没有启动器,没有要编辑的加载顺序文件,也没有任何可记录的内容。加载顺序是每个包内的一个数字,由其作者选择。

对于添加人物、地点或任务的 mod 包,请开始新的一局。已经进行中的存档会保留创建它时的世界。只改变数字、图像或颜色的 mod 包可以在已经开始的游戏中显示。音频和字体文件会被验证,但当前没有运行中的 mod 包界面消费它们。

加载了吗?

模组,在主菜单中。找到的每个包都占一行,具有单字状态:已加载、已禁用、无效、冲突、需要另一个 mod、被忽略。

模组也可以自行关闭,并且它说明了原因。 您放置的开关适用于您放置它的包,而不是其在文件夹中的名称。 mod id 由作者选择,没有任何东西可以协调它们,因此两个不相关的 mod 都称为 northern_reach 是一个普通的意外 - 如果没有这个,第二个将继承第一个的开关。如果某个 id 下的 mod 不是您打开的 mod,则该行会这样显示:*这不是您打开的 mod*。就地更新模组可以保留您的开关;删除它并复制另一个号码。

如果您是某个 mod 的作者,并且在您的包上看到该行,则说明您与其他人的 mod 发生了 id 冲突。选择一个不太明显的 ID。

其中两个词是关于您欠的重启,而不是软件包。 活动 — 重新启动加载意味着您已将其打开,但尚未有人阅读; 关闭-重新启动下载意味着相反,并且其内容仍然在游戏中,直到您重新启动。它们是故意分开的:当你按下开关时,屏幕上会显示“已加载”,这会让你在世界各地寻找尚不存在的东西。

当状态未“加载”时,下面的行会用您正在玩的语言告诉您原因,并且没有您未编写的标识符:游戏拒绝运行哪个文件,缺少哪个包,需要哪个版本。下面是包裹内容的作用:输入了多少条目,拒绝了多少条目。 显示详细信息 打开其余部分,即 ID 和每个被拒绝的记录所打破的确切规则。

在屏幕上报告中这是什么意思
已加载active可装载,无障碍。
无效的invalid清单带来锁定的脚本或可执行文件。
需要另一个模组skipped_missing_dependency声明的依赖项不存在或被禁用。
需要另一个模组skipped_incompatible_dependency声明的依赖项超出了其范围。
忽略incompatible该模组针对的是游戏的更新版本。
冲突conflict两个可加载 mod 指向相同的覆盖 id(它们仍然可加载;load_order 获胜,两者均报告)。
禁用disabled你把它关掉了,或者你从来没有打开过它。这些软件包可以自由选择:将一个软件包放入文件夹中即可安装它,但不会打开它。
开启 — 重新启动以加载你打开它,但还没人读过它。在您重新启动之前,其内容不会出现在游戏中。
关闭 — 重新启动以下载你把它关掉了,它仍然在充电。其内容保留在游戏中,直到您重新启动。

两行故意共用一个词: 需要另一个模组 对于玩家来说,这都是同样的问题,无论他们需要的包丢失还是版本错误,下面的行都说了。当两个数据包声明相同的记录时,load_order 最高的数据包最后写入并获胜 - 但没有人声明的接管是错误,而不是注释。两条线都会被报告,失败者的线会命名获胜者,获胜者仍然会被计算出来,而不是听凭机会:拒绝也不一定是抛硬币。 当两个 mods 想要相同的东西时 解释了如何故意声明一个。

“已上传”并不意味着您可以在世界上看到它。为此,请阅读该行下方的计数,然后现在在游戏中找到它会告诉您每种类型的东西会在哪里弹出。

计数总是累加起来。 床位被申请,更多被拒绝,更多被另一个模式取代,更多等待他们自己的条件 - 最后两个被提名而不是留下一个洞。另一个包最后写入的记录不会被拒绝,因为它没有任何问题,甚至不会被强制执行,因为这不是游戏保留的内容。这就像阅读一行代码和花一个晚上在一个没有错误的文件中查找错误之间的区别。 显示详细信息 告诉哪个记录以及哪个包现在拥有该记录。

总和旁边有一个数字,而不是内部:没有人读取过的文件。 家族不在 content_types 中的文件从未被打开过,因此没有记录可计数,也无法知道其中有多少个。它是文件计数,而不是记录计数,这正是它不能是第六项的原因:总和从 read 开始,而这些从未被读取过。

在向某人寻求帮助之前

打开 Mod 并按 复制报告。将所有内容粘贴到您的消息中,然后说出您的期望。

简单的文本,可用于论坛、Discord 消息或错误报告:您所在的版本、mods 文件夹、每个包及其版本、加载顺序和状态、每次拒绝背后的原因、每种内容类型的计数以及哪个包赢得了每场战斗。

the report the Mods screen copies

Bonemark mod report
game build: 0.0.0-dev
mods folder: C:/Users/you/AppData/Roaming/Godot/app_userdata/Bonemark/mods
packages: 2 found, 1 loaded

PACKAGES
  northern_reach  v0.1.0  order 100  active
    goods: 12 read, 12 applied, 0 rejected
  winter_roads  unreadable manifest
    - game_version must not be empty

CONTENT (1 families: 12 read, 12 applied, 0 rejected)
  goods: 12 read, 12 applied, 0 rejected

十有八九答案就在眼前,没有人必须先问你任何一个问题。它不会读取 mods 文件夹之外的任何内容,不会更改任何内容,也不包含任何个人信息。

即使您使用另一种语言玩游戏,它也是英语的。这是有意为之的:帮助你的人可能不会读到你的内容,而且它包含的每一个事实——id、版本、计数——在所有语言中仍然是相同的。

删除一个

删除其文件夹并重新启动。卸载都在这儿了。

您的任何内容都不会随之删除。 保存会保留它无法再解析的 id、标记它们,并在重新安装软件包时返回内容。无法理解保存的会话甚至不会覆盖它:原始文件保持原样,这就是失败的下午和失败的游戏之间的区别。 Saves 是完整的报告。

如果游戏在你安装某些东西后停止运行,那么出路就不需要游戏了。 打开mods文件夹并移出你最后添加的东西。只能从该文件夹中读取软件包,因此不存在的文件夹将无法加载软件包,并且下次启动与以前相同。您不需要工作菜单、控制台或启动来执行此操作。

即使游戏也会自行尝试 - 如果游戏没有开始,它只是有限次数的尝试,然后在没有加载任何包的情况下返回 - 但这是腰带,移动文件夹是吊带。

从这里开始

今天您可以构建什么

现在无需请求任何人:商品及其商人、物品、人物和所在位置、建筑及其服务、地图上的地点、对话、场景、任务计划、在 Tiled 中绘制的地图、图像和颜色,以及全部七种语言的文字。音频和字体文件会被检查并读取,但目前没有 mod 包界面消费它们;状态表会明确说明这一点,而不会把它们称为可用。全部系列 是测量得出的完整列表,状态来自构建结果,而不是承诺。

还不能做到,当前还不能做什么 会解释每一项:quests 系列、mod 包音频、mod 包字体、打包的全面转换,以及作为功能而非内容的 mod 包。

永远不会,由于项目选择:代码。没有脚本,没有场景,没有资源文件,没有任何可供游戏运行的东西。这就是下载陌生人的模组变得安全的原因,而且这不是该项目正在经历的阶段。 mod 永远无法做到的事情

在游戏中看到第一件事的时间:大约十分钟,主要花在寻找文件夹上。 【十分钟一个mod】(#a-mod-in-ten-分钟)一路过关斩将,最后的剑才是真的。

您还不能做什么以及为什么

这里把它写在靠前的位置,而不是留到读者离开页面时才发现。这些内容会被构建验证,但目前不会放到面向玩家的 mod 包界面上;另外还包括根本不属于 mod 包内容的项目。

什么为什么不呢它会改变
quests 系列它被识别和检查,并且其背后没有运行时映射器,因此以它为目标的包会绕过所有检查并且不会安装任何内容。相反,写你的任务quest_plans是一个活着的家庭,这就是游戏真正的内容。是的,当映射器公开时
mod 包音频音频描述文件和音频文件会被验证并读取,但当前没有运行中的界面消费 mod 包音频信号;因此 mod 可以提供最终保持静音的声音。是的
mod 包字体字体描述文件和语言覆盖范围会被验证,但当前没有运行中的主题消费 mod 包字体。是的
总转化打包该版本理解宣言并带来了 Ashen Reach 装置。缺少的是为创作者提供的打包工作流程,而不是机制。 总转化是的
一个包就是一个功能完全决定,没有家庭携带它,所以没有海报可以要求它。 每个家庭 将其列在还没有文件夹的事物中。是的
无论完成什么脚本层不会出现。清单携带一种传递行为的包类型,唯一可以授权其执行的东西拒绝它,它后面没有沙箱,并且声明它今天被拒绝的包。 mod 永远无法做到的事情

游戏中从未有过的一个机制是第四排戴着另一顶帽子。剑击得越重,它就是一个数字,它就是你的;发射光束的武器需要光束规则,而规则是某人编写和测试的代码。

什么是模组

文本文件的文件夹。你不写代码。你在游戏中写下你想要的东西的列表,游戏启动时会读取它们。

单词这是什么意思
包裹你的模组。一个文件夹,上面有你的名字。
显现mod.json,位于该文件夹的顶部。你是谁,你带来什么。
记录你补充一件事。一把剑就是一个记录。
家庭类似的事情。剑、头盔和面包都是items。每个家庭都有自己的文件夹。
IDyour_package:the_thing — 例如 northern_reach:frost_blade

其他一切都遵循的一条规则:您可以添加更改数据。你不能让游戏执行代码。这就是下载模组的安全性:陌生人的模组最糟糕的事情就是向你挥出一把愚蠢的剑。

今天有 34 个内容系列可直接使用,包括 itemsbuildingspoisnpc_definitionsvendor_inventoriesquest_planscaravansperks全部系列 是完整表格,说明每个系列的用途;逐个查看系列 会列出字段和可复制的记录。

选择你的道路

这是整个指南的目录 - 每个主题都写在其中,无论您今天是否正在构建它。第 3 部分的顶部是第二个较短的索引:这是六个教程,按照它们相互构建的顺序排列。如果你来这里是为了做某事而不是为了寻找什么,那就直接去那里吧。

你想要前往
从头到尾构建一些东西从你想做的事开始 — 六个教程,只需一个包
十分钟内上传文件十分钟内的模组
搜索家庭字段和示例家庭,一一
查看您被允许执行的所有操作每个家庭
改变游戏已经带来的东西更改游戏已有的内容
添加您自己的艺术、声音、文字或颜色图片、声音、文字、颜色
在 Tiled 中绘制一个地方您的地图
写下使命你的任务
理解为什么什么都没有出现什么也没出现
查找错误代码每个诊断代码
知道 mod 永远不能做什么mod 永远做不到的事
不要破坏某人的保存保存
把它放在人们可以拿到的地方分享

或者你心里的事情。本指南按照工作发生的顺序排列——清单、验证、内容、报告——这是已经了解系统的人会选择的顺序。不认识他的人会想*我要添加一个商人*,然后寻找商人这个词:

你正在添加做这件事的家庭它们写在哪里
贸易和货物goodsvendor_inventoriescaravansrecipes事物、贸易和战斗背后的数字
球员随身携带的东西itemscombat_balance事物、贸易和战斗背后的数字
人们npc_definitionsmercenary_templatesnoble_housesrelationshipsperksenemy_archetypesenemy_variantsgroup_archetypes人、房子和他们能做什么
地点和建筑物buildingspoismapsworld_generation世界和其中的地方
玩家读到的单词localesdialoguescenesloremr_linesquest_plansquest_metadataprogress故事、任务和玩家读到的单词
它的外观和声音如何imagesaudiofontsthemeseffectspresentation_bindingsscreens这一切看起来和听起来如何
命令和困难input_bindingssettingsadaptive玩家控制什么,以及观看什么

你需要什么

游戏必要的没有 Godot,没有编译器,没有构建步骤。
理解 JSON 的文本编辑器必要的VS Code、Sublime、Notepad++ — 全部免费。 Windows 记事本可以工作,但无法帮助您。
像素艺术编辑器只为你的艺术Aseprite (~20 €),或免费:LibreSprite, Piskel, Krita, GIMP.)
音频编辑器只为你的声音Audacity. 突然出现的短暂效果:sfxr, ChipTone.
平铺仅适用于您的地图自由的。导出到 .tmj

当您仍在查看 JSON 时,为 JSON 着色的编辑器会向您显示缺少的逗号,而不是让游戏稍后告诉您该文件不可读。

Python 和控制台都是可选的。游戏本身就够用:放入 mod 包,重启并打开 Mods,那里会说明每条被拒绝的记录及原因。作者使用的 checkout 是公开的。想更快迭代或自动发布的作者可以克隆公开的 Bonemark checkout,并在离线工具中运行工具;安装已发布 mod 包的玩家不需要 Python 或 Godot。同一个公开 checkout 提供验证器和运行时声明,因此下面两个章节描述的是同一套工具链。工具使用与游戏相同的声明——记录架构和安全边界各自只有一个来源——所以它们只会更早告诉你结果,不会给出不同结果。调试控制台有助于检查已加载的 mod 包,但不是编写 mod 包的必要条件。

创建一个

从你想做的事情开始

该行以下的所有内容均按工作发生的顺序排列:海报,然后文件,然后家庭,然后报告。寻找某事的顺序是正确的,而开始的顺序则是错误的,因为没有人从宣言开始。它以“我想要一个商人”开头。

然后:选择与您想要做的事情相似的短语。

你想要前往多久时间
添加要买卖的东西卖得好15分钟
添加玩家随身携带的东西携带物品10分钟后,上面的
添加销售人员持有它的商人30分钟
在定居点​​添加一扇门建筑物的服务20分钟
在世界地图上添加一个地点地图上的地点20分钟
改变游戏已有的东西改变已经存在的内容15分钟
绘制地图、书写使命、带来艺术你的地图你的任务图片、声音、文字、颜色时间更长,而且三个人都是活着的家庭
带上quests家族,打包的总转换,或者是一个功能的包还没有。 你还不能做什么,以及为什么 给出了每项的原因,并说明了哪些将会改变。
添加游戏从未有过的规则这里什么都不会发生,也不会发生。 mod 永远不能做什么 在一段中说明了原因。

这六个教程是一个单独的包,一次构建一个:蜂蜡蜡烛、玩家随身携带的包、出售蜂蜡的制造商、商店的门、制革厂后面的坑(牛油的来源),最后是对游戏已有蜡烛的修改。按顺序进行这些操作,最终得到一个可能有人下载的模组。在中间放一个,它就可以自行工作。

游戏号码在哪里

这里的每个教程都会通过将新东西与游戏中已经出售的东西进行比较来定价,因为旁边没有任何内容的数字是一个猜测,而在城市之间进行贸易的经济体中的猜测不会停留在你输入的位置。

您无法打开游戏文件。 它的记录是打包构建中的 Godot 资产 - 与您编写的 JSON 的格式不同,其中 category = 1 您的文件显示为 "MANUFACTURED"。没有可供复制的文件夹,解包也不是任何人都需要记录的工作流程。

你不需要它。 目录发布了游戏的内容,这些内容是根据每次构建的相同记录生成的:270个物品及其类别、重量、硬币价值和堆栈大小、49种武器、42件盔甲、37个位置。这是本指南所锚定的参考,它不能偏离游戏,并且字段的名称打印在每行旁边。

在给某样东西定价之前需要了解的十几个值:

游戏已经开始发售了硬币
粘土、石头、芦苇1地板。挖掘或切割,内部无需工作
谷物、木材2
蜡烛3一个轻松的夜晚
羊毛、鱼、葡萄4
面包6一天的食物
盐、蜂蜜、绳子8
布(块)10由 2 根羊毛和 1 根芦苇编织而成
精铁、咸鱼12
黑胡椒14进口,你可以感觉到
皮革、奶酪15
葡萄酒25
单手武器50–300频带,而不是单个值
双手武器150–600
厚板500–1500整个经济的天花板

如果你的新东西比板甲更贵,那就出问题了,游戏不会告诉你——它会默默地成为世界上最赚钱的货物,每个商队都会携带它。

出售的商品

你将拥有一种经济知道如何定价的商品,与游戏已经销售的蜡烛挂钩,准备好供商人持有。

屏幕截图: 尚未拍摄。这个空间一直是空的,直到出现一个真实的空间:一张它可能看起来像的图画将是页面上唯一不真实的东西。

先阅读: 什么是 mod · 十分钟的 mod · 名称和 ids

复制自:名为 chandlery 的文件夹,该文件夹已位于您的 mods 文件夹中。游戏第一次启动、关闭时就放在那里,这就是这六个教程的最终结果:下面的每条记录都在那里。它也是存储库的测试通道针对加载程序旋转的包,因此这里没有游戏会拒绝的记录。打开它看看它是否工作,或者复制文件夹,重命名它并使其成为您的。

文件去向:

where the files go

mods
└ chandlery
  ├ mod.json
  └ content
    └ economy
      └ goods
        └ goods.json

从游戏已有的蜡烛开始。 它的名字叫candle,成本3,重量0.5,分别是MANUFACTUREDPRESERVED,由药剂师制作。你的也是用更好的蜡制成的,所以保留所有这些答案并换两个。

mod.json之前:

mod.json

{
  "id": "chandlery",
  "name": "The Chandlery",
  "version": "0.1.0",
  "game_version": "0.0.0-dev",
  "dependencies": [],
  "load_order": 100,
  "content_types": ["goods"],
  "overrides": [],
  "canon_safe": true
}

然后content/economy/goods/goods.json

a goods record

[
  {
    "id": "chandlery:beeswax_candle",
    "display_name": "Beeswax Candle",
    "category": "MANUFACTURED",
    "decay_tier": "PRESERVED",
    "base_price": 9,
    "weight": 0.4,
    "production_class": "chandler",
    "daily_consumption_class": "household",
    "tags": ["light", "household"]
  }
]
场地为什么这个值
id您的包裹名称,冒号,然后是您的单词。任何前面没有你的命名空间的东西都会被拒绝,所以你不能意外地拿别人的 id。
display_name玩家读什么。没有冠词——“Beeswax Candle”,从来没有“A Beeswax Candle”:冠词是由它周围的短语给出的,哪个冠词取决于语言。 玩家读到的单词
categoryMANUFACTURED,因为有人这样做。这五项分别是原材料、神器、消耗品、弹药和装备,你选择的一项决定了哪些生产建筑和商队受到影响。
decay_tierPRESERVED — 90 天,就像游戏蜡烛一样。蜡被保存;它不会永远保存。 PERISHABLE 为 7 天,ETERNAL 永不腐烂。
base_price9. 游戏中的简单蜡烛为 3,一罐蜂蜜为 8。蜂蜡与蜂蜜来自同一个蜂巢,燃烧时没有融化脂​​肪的气味,因此它的含量略高于蜂蜜,大约是牛油蜡烛的三倍。它不是进口的:黑胡椒有14个,是远渡重洋的。
weight0.4,略低于简单蜡烛的 0.5。重量是商队可以携带的东西,所以没有重量却卖得很贵的商品是你故意写的一个错误。
production_class她做什么职业? chandler 是参考包使用的。
daily_consumption_class谁消费它。 household 意味着城市不断消耗它,这就是保持商人供应的原因。
tags自由言语。其他记录和您的后续文件可以通过它们进行搜索。

完成 - 现在在游戏中找到它。重新启动,打开Mod,下面的行显示 1 entry added。这是商品本身所做的一切:它有价格,有销路,而且它不会出现在任何人的柜台上,因为还没有人拥有它。这不是失败,而是曾经让所有人感到困惑的事情。继续库存的商人

如果未显示: 没有显示 按顺序有六个原因。到目前为止最常见的是 content_types — 该行中缺少一个系列意味着该文件夹永远不会打开,无论它包含什么。然后在你向任何人寻求帮助之前,这是一个按钮。

需要携带的物体

你将拥有玩家捡起的东西,堆放在他们的背包中,然后转售,与你刚刚编写的商品配对。

屏幕截图: 尚未拍摄。

先阅读: 卖得好 · 名称和 ids

复制自: chandlery/content/inventory/items/items.json 到您的 mods 文件夹。

文件去向:

where the files go

mods
└ chandlery
  ├ mod.json
  └ content
    ├ economy
    │ └ goods
    │   └ goods.json
    └ inventory
      └ items
        └ items.json

商品和物体是同一个东西的两半。商品是经济学的观点:一个城市生产什么,一个商队运输什么,值多少钱。对象是玩家的视角:背包里装的是什么,堆放的是什么,商店里展示的是什么。小麦是一种商品,但没有物体,因为没有人随身携带一袋小麦。蜡烛两者都有。

"items"添加到mod.json中的content_types,然后写入content/inventory/items/items.json

a items record

[
  {
    "id": "chandlery:beeswax_candle_bundle",
    "display_name": "Bundle of Beeswax Candles",
    "category": "MATERIAL",
    "rarity": "COMMON",
    "weight": 0.4,
    "max_stack": 20,
    "base_value": 10,
    "sellable": true,
    "tags": ["light", "household"]
  }
]
场地为什么这个值
id他的身份证,而不是货物的身份证。它们在不同的家族中有不同的记录,没有什么强制它们匹配:将它们配对是你的工作,下面的商人行是配对发生的地方。
categoryMATERIAL,这就是游戏蜡烛。不是 CONSUMABLE:你不吃任何东西。
rarityCOMMON。稀有度是战利品表和商店滚动时显示的内容;一件常见的事情发生了。
weight0.4,跟货一样。当两者不一致时,玩家的背包和商队在同一物品上不一致。
max_stack20,喜欢烤蛋糕和参考包捆绑包。二十是游戏中常见的一堆小东西,存放你随身携带的小东西; 1 代表独特的东西。
base_value10 与货物的 9 相比。捆绑包比散装价格有小幅溢价 - 参考捆绑牛油捆绑是 4 件商品与 3 件商品,这与上一步的形状相同。
sellable是的,否则商家无法从你那里买回来。

完成 - 现在在游戏中找到它。 无人交付的物品已加载并且可以从无到有。在调试版本中,item chandlery:beeswax_candle_bundle 会立即将一个命令放入您的背包中,这是它已加载的最快证明 - 但该命令在人们下载的游戏中不存在,因此它对您来说是一个快捷方式,而不是玩家的答案。真正的答案是下一个教程。

如果未显示: 没有显示任何内容,然后在向任何人寻求帮助之前

持有它的商人

你将会有一个有名字的女人站在旧座位上,那里有一个柜台,每两天补充一次的用品,柜台上还有你的蜡烛。

屏幕截图: 尚未拍摄。

先阅读: 要携带的物品 · 现在在游戏中找到它

复制自: chandlery/content/narrative/npcs/npcs.jsonchandlery/content/world/vendor_inventories/vendors.json

文件去向:

where the files go

mods
└ chandlery
  ├ mod.json
  └ content
    ├ economy
    │ └ goods
    ├ inventory
    │ └ items
    ├ narrative
    │ └ npcs
    │   └ npcs.json
    └ world
      └ vendor_inventories
        └ vendors.json

这是两个家庭必须同意的。 人携带着银行的id,银行携带着人的id,银行的每一行都携带着一个物体的id。三个 id,每个 id 的书写方式都必须与您在其他文件中的书写方式完全相同。这个错误花费了一个晚上的时间,Mods 屏幕将其命名为:一条指向无人提供的 id 的行被列为“需要另一个未安装的 mod”。

"npc_definitions""vendor_inventories" 添加到 content_types

a npc_definitions record

[
  {
    "id": "chandlery:hesta",
    "display_name": "Hesta the Chandler",
    "title": "Candle Seller",
    "short_bio": "She renders fat behind the tannery and sells what burns longest.",
    "voice_tone": "brisk",
    "faction": "NONE",
    "role": "NONE",
    "settlement_id": "old_seat",
    "is_vendor": true,
    "vendor_inventory_id": "chandlery:candle_stall",
    "price_multiplier": 1.0,
    "personality_tags": ["brisk", "practical"],
    "offers_quest_ids": []
  }
]

a vendor_inventories record

[
  {
    "id": "chandlery:candle_stall",
    "display_name": "Chandler's Stall",
    "npc_id": "chandlery:hesta",
    "global_price_multiplier": 1.0,
    "buyback_rate": 0.35,
    "entries": [
      {
        "item_id": "chandlery:beeswax_candle_bundle",
        "kind": "misc",
        "daily_stock": 6,
        "price_multiplier": 1.0,
        "restock_days": 2,
        "min_standing": 0
      }
    ]
  }
]
场地为什么这个值
settlement_id使用作者预先制作的聚落 ID。聚落 ID 是作者预先制作且稳定的:Durnwall、Thorngate、Valdmere、Grentham 和十二个村庄都可以命名。种子改变它们周围的地形和生物群系、当年的短缺以及政治格局,但不会改变 ID。
is_vendor + vendor_inventory_id他们一起把一个人变成了一家商店。缺一不可,就是一个卖不出去的人,或者一个无人看管的柜台。
price_multiplier1.0 — 询问某物值多少钱。以上1是知道你别无选择的地方;如果地图上没有任何原因,游戏中的商人都是1.0。
buyback_rate0.35:支付大约您卖给她的商品价值的三分之一。这是玩家最常听到的数字,也是参考包经销商使用的数字。
daily_stock6. 银行充值时他有多少。六是廉价家居用品的参考包装图;其中一个是针对一个城市每年两次出现的事物。
restock_days2,所以它每两天补充一次——而不是你安装模组的那天。这就是为什么新的商人一开始看起来是空的。在调试版本中,day 会前进一天。
min_standing0:任何人都可以购买。高于零的是她为她喜欢的人保留的股票。
kind它在什么样的柜台上——misc,用于家居用品。其他为 weaponarmorshieldconsumableammo

完成 - 现在在游戏中找到他。 重新启动,前往旧座位,找到赫斯塔,打开交易屏幕。如果银行是空的,则尚未补充:这是 restock_days,不是错误。这个链条可以通过三种方式打破,所有三种方式都在 Mod 屏幕上:无人持有的物品、指向不存在的物品 ID 的计数器、指向不存在的计数器 ID 的人。

她也能说话。 当玩家点击她时,一个 speaker 为她的 id 的 dialogue_graph 会提供她的台词;你的模组无需重新定义游戏已经拥有的任何内容即可获得这些台词——参见自定义对话。一个 locales 文件会以七种语言提供全部内容。

如果没有显示任何内容: 首先检查这三个 ID,然后没有显示,然后在向任何人寻求帮助之前

建筑物的服务

你将在定居点有一扇门,上面有你的标签和颜色,打开后可进入游戏已有的内部空间。

屏幕截图: 尚未拍摄。

先阅读: 保留它的商人 · mod 永远做不到的事情

复制自: chandlery/content/world/buildings/buildings.json

文件去向:

where the files go

mods
└ chandlery
  └ content
    └ world
      └ buildings
        └ buildings.json

您正在重新组合,而不是构建。 buildings 记录添加了带有标签、端口颜色和例程角色的新服务,并且可以通过命名来重用游戏已有的扩展。不能带延期。扩展是场景,场景是代码,命名路径 res://.tscn 的数据包在读取该记录之前就会被拒绝。这不是一个等待填补的洞:它是一条可以安全安装陌生人模组的线路。

a buildings record

[
  {
    "id": "chandlery:chandlery",
    "label": "Chandlery",
    "role": "merchant",
    "color": { "r": 0.44, "g": 0.38, "b": 0.24 },
    "interior_service": "shop"
  }
]
场地为什么这个值
label门上的字。如果你省略它,游戏会将你的 id 大写,读起来就像一个 id。
role人们整天在里面做什么——merchant 将店主的日常工作隐藏在门后。角色是游戏的词汇,而不是你的:一个陌生人冲进来,表现得没什么特别的。
color蜂蜡棕色,0.44 / 0.38 / 0.24。每个通道的范围从 0 到 1,HTML 十六进制字符串也适用。选择与门所画尺寸相符的东西 - 适合的艺术
interior_serviceshop — 游戏已经为商店设计的内饰。诀窍就在这里:你不用带任何东西就能得到一间真正的、带家具的房间。

完成 - 现在在游戏中找到它。重新启动并输入有您的服务的定居点。没有 settlement 的记录会被加载并放置在任何地方,这与失败的记录相同:Mod 屏幕会显示 1 entry added,但您将找不到任何内容。在寻找门之前先阅读线路。

如果没有显示: 什么都没有显示 · 在向任何人寻求帮助之前

地图上的一个地方

您将在世界地图上找到一个玩家可以偶然发现的地点,并附有该地点的描述及其对队伍情绪的影响。

屏幕截图: 尚未拍摄。

先阅读: 建筑服务 · 现在在游戏中找到它

复制自: chandlery/content/world/pois/pois.json

文件去向:

where the files go

mods
└ chandlery
  └ content
    └ world
      └ pois
        └ pois.json

坐标是绝对的,世界会围绕作者预先制作的地点生成。地图大小为 61 440 × 34 560 世界像素,Old Seat 在每局中都正好位于中心 (30720, 17280)。作者制作的城市和村庄会保留自己的名称与位置。种子会改变它们周围的地形和生物群系、当年的短缺、政治格局以及值得行走的道路。因此一个点仍是真实且稳定的地点,但它 旁边 的内容每局都会变化。诚实的用法有两种:把兴趣点放在作者制作的聚落附近,让玩家一定会经过;或者选择空旷之处,因为多年无人走过的渲染坑本来就不该位于某个特定地点。

a pois record

[
  {
    "id": "chandlery:tallow_pit",
    "kind": "RUINS",
    "display_name": "The Tallow Pit",
    "description": "A rendering pit behind the tannery. The smell reaches the road.",
    "world_position": { "x": 5400.0, "y": 3000.0 },
    "discovery_radius": 2.0,
    "one_time_loot": false,
    "morale_modifier": -1,
    "awareness_modifier": 0.0
  }
]
场地为什么这个值
kindRUINS — 地图是由什么绘制的以及游戏认为它是什么。
world_position(5400, 3000),中心西北方向:故意无效,上面两个诚实用途中的第二个。将其移动到 (30720, 17280) 的几千像素内,它就成为玩家实际找到的地方。
discovery_radius2.0. 队伍必须通过的距离有多近。大到可以沿着一条路找到它,小到不会从一个省的一端到另一端宣布它。
morale_modifier−1. 这是融化的脂肪坑。这个数字故意很小:一个地方是一个地方,而不是一个事件,-1 是一种情绪,而不是一种惩罚。
awareness_modifier0.0 — 没有帮助看到。当零是一个决定时,将数字保留为零而不是删除该字段。
one_time_loot错误:没有什么可以拿走,因此没有什么东西只能拿走一次。

完成 - 现在在游戏中找到它。 去做吧。无论是在调试版本中还是在外部,都没有传送命令,因此请选择您愿意在尝试时行走的坐标。

如果它没有出现: 你可能已经超出了 discovery_radius,或者位置是比赛种子放置海洋的某个地方。 什么也没出现

改变已有的东西

您将更改游戏带来的记录 - 并且您将声明它,因此玩家和所有其他模组都可以看到更改。

屏幕截图: 尚未拍摄。

先阅读: 更改游戏已有的内容 · 当两个 mods 想要相同的东西时

复制自: chandlery/content/economy/goods/goods.json,在同一文件中添加一条记录并纠正游戏中的一条记录。

文件去向: 没有新的地方。对游戏中已存在的内容的更改与您的记录所在的同一个家庭文件夹中 - 该文件说明了它想要哪个记录以及它正在对它做什么。

where the files go

mods
└ chandlery
  ├ mod.json          the change is declared here
  └ content
    └ economy
      └ goods
        └ goods.json  your record and the patch, in one file

文件之前有两条规则。 对他人记录的更改必须在 mod.json 内的 overrides 中命名 - 落在您未声明的 id 上的记录将被拒​​绝,因此没有任何东西可以秘密重写玩家不同意的内容。而 patch 则更改一个字段并保留其余字段,需要 "manifest_version": 2

mod.json

{
  "id": "chandlery",
  "name": "The Chandlery",
  "version": "0.1.0",
  "game_version": "0.0.0-dev",
  "manifest_version": 2,
  "load_order": 100,
  "content_types": ["goods", "items", "npc_definitions", "vendor_inventories", "buildings", "pois"],
  "overrides": ["candle"],
  "canon_safe": true
}

a goods record

[
  {
    "op": "patch",
    "id": "candle",
    "changes": [
      { "op": "set", "field": "base_price", "value": 4 },
      { "op": "append_unique", "field": "tags", "value": "chandlery_touched" }
    ]
  }
]
选择为什么
patch,不是 replacereplace 没有继承任何内容:您必须重写蜡烛的重量、衰减程度、连接的对象和生产类别,并且当游戏为蜡烛提供新字段的那一天,您的副本将是世界上唯一没有它的蜡烛。
3 → 4一枚硬币,原因是模组本身:你的城市可以正常熔化蜡,所以这里的普通蜡烛更值钱一点。从 3 到 30 不会改变蜡烛,而是改变每个商队的装载优先级。
append_uniquetags唯一两个模组可以同时做而不会发生冲突的事情。如果它们都排队相同的标签,则不是冲突,也不会加倍。
命名一个字段,而不是一个位置tags.0 被拒绝。今天的第三个标签是你装完别人包裹后的第二个标签。

完成 - 现在在游戏中找到它。 Mod 屏幕为您获得的记录命名。另一位作者的屏幕也这样做,如果有的话:当两个数据包写入相同的 id 时,失败者的行现在显示*替换:蜡烛 - 'chandlery'最后写入*,而不是默默地显示比他写的少一个条目。谁的 load_order 最高,谁就最后写入并获胜。

获胜与获得许可不同。 两个数据包在 supersedes 中没有命名另一个记录的情况下被报告为 undeclared_collision 并且组合不好:离线验证器说了同样的事情并拒绝:

typed into the debug console

ERROR: conflict on goods:candle: ['early', 'late'] each supply the whole record
and none declares the others under `supersedes`

获胜者仍然是计算出来的,因为拒绝并不一定是抛硬币,但两个都想要的作者必须这么说。 当两个模组想要同样的东西时 就是这样的对话。

如果没有出现: 通常的原因是 overrides — id 必须在该列表中,并且准确写入,否则记录将被拒​​绝而不是应用。 当两个模组想要相同的东西时 · 什么都没有出现

十分钟搞定模组

1.在你的mods文件夹中创建一个文件夹,名称小写加下划线:northern_reach。一切都发生在那里。

2.在顶部写入mod.json

mod.json

{
  "id": "northern_reach",
  "name": "The Northern Reach",
  "version": "0.1.0",
  "game_version": "0.0.0-dev",
  "dependencies": [],
  "load_order": 100,
  "content_types": ["items"],
  "overrides": [],
  "canon_safe": true
}

id 必须与文件夹名称匹配。 content_types 列出了您带来的系列 - 该行中缺少的系列永远不会被读取,无论文件夹中有什么。

3.创建文件夹 content/inventory/items 并将 blades.json 放入其中:

a items record

[
  {
    "id": "northern_reach:frost_blade",
    "display_name_key": "northern_reach.item.frost_blade.name",
    "display_name": "Frost Blade",
    "category": "weapon",
    "base_value": 240,
    "weight": 3
  }
]

方括号是一个列表:添加任意数量的剑,用逗号分隔。 Family 文件夹中的每个 .json 文件都会被读取,因此可以根据需要拆分它们。

240并不是一个为了给人留下深刻印象而选择的数字。在这个游戏中,单手武器的范围从50到300,所以240的霜刃是一把昂贵的剑,而不是传奇剑,玩家大约在他能买得起铁匠已经出售的好剑的时候就可以买得起它。 游戏号码在哪里 是在选择任何号码之前要查看的表格;旁边没有任何内容的价格是一个假设,而在城市之间进行贸易的经济中,假设不会停留在你设定的地方。

4.启动游戏并从主菜单打开模组。您的包裹仅获得一种状态,而 加载了吗? 具有全部六种状态。

5.阅读下面的行,了解已阅读、应用和拒绝的内容,以及每次拒绝的原因。 显示详细信息 有 ID。

6。你的剑就在游戏中。 接下来的一切都差不多。

现在在游戏中找到它

报告称applied。这意味着记录已加载,这与能够走在记录前面不同。这是每个指南停止的地方,也是每个作者开始猜测的地方。

你添加了什么弹出的地方陷阱
goods在商家上,只需要一行 vendor_inventories 即可。一种无人持有的商品,无论你怎么称呼它,都可以装载、定价、销售,并且不会出现在任何地方的柜台上。添加商品就成功了一半。另一半是线。
vendor_inventoriesnpc_id 中命名的商户。每行都有自己的 daily_stockrestock_days,因此带有 restock_days: 2 的行每两天补充一次,而不是您添加它的那一天。在控制台中使用 day 跳过一天而不是等待它。
items到处都有东西给你:一条商业线、一张战利品表、一份任务奖励。存在不授予任何内容的对象,并且只能通过控制台中的 item <id> 访问。item northern_reach:frost_blade 立即将其放入背包中,这是查看其已加载的最快方法。
npc_definitionssettlement_id 中所示的结算,在 location_morning / location_afternoon / location_evening 所示的位置。在编写 settlement_id 之前,请阅读下一段相关内容。
buildingssettlement 中显示的结算,是用您提供的 rolecolor 绘制的。 interior_service是玩家进入时发现的。没有 settlement 的建筑物将被加载并放置在任何地方。
poisworld_position 的世界地图上,可由 discovery_radius 发现。阅读下面有关坐标的段落。这是大家关心的。

settlement_id 指向作者预先制作的地点。聚落 ID 是作者预先制作且稳定的:Durnwall、Thorngate、Valdmere、Grentham 和十二个村庄都可以命名。种子改变它们周围的地形和生物群系、当年的短缺以及政治格局,但不会改变 ID。如果你希望某个人物一定会被玩家遇到,就使用任意作者制作的聚落 ID,并把名称保存在 mod 包的语言数据中。

坐标是绝对的,世界会围绕作者预先制作的地点生成。地图大小为 61 440 × 34 560 世界像素,Old Seat 在每局中都正好位于中心 (30720, 17280)。作者制作的城市和村庄会保留自己的名称与位置。种子会改变它们周围的地形和生物群系、当年的短缺、政治格局以及值得行走的道路。因此 (6000, 2200)world_position 在地图最西北仍是一个真实且稳定的点,但它 附近 的内容每局都会变化:可能是道路、森林,也可能是荒地。诚实的用法有两种:

  • 仍在中心。 在每场游戏中,距 (30720, 17280) 几千像素的兴趣点都位于旧座位附近,因此这是玩家会找到的地方。
  • 你的意思是空虚。一百年来无人经过的废墟,一定在任何地方。绝对坐标对此完全正确,种子将决定它的邻居。

最节省时间的控制台命令。 day [n]hour [n] 提前时间,这就是您在不体验电源的情况下看到电源的方式。 item <id> [count]gold <amount>把东西交到你手里。 flagquest_startfaction_rep 移动条件可能正在等待的状态。没有传送命令:要到达一个地方,就前往那里。

mod.json,逐个字段

场地What fa
id在上面的示例中。 您的包的名称。它必须与文件夹完全匹配,并且它是您编写的每个 id 中冒号之前的单词。
name在上面的示例中。 玩家看到的内容。大写和空格在这里都很好。
version在上面的示例中。 您选择它。每次改变某些东西时就提高它。
game_version在上面的示例中。 您为其创建的构建。
content_types在上面的例子中。 您带来的家人。无论文件夹中有什么内容,都不会读取此列表中缺少的家庭。
dependencies在上面的示例中。 您需要的软件包。名称或带有 optional: true 的对象。
load_order在上面的示例中。 当两个数据包接触到同一物体时,谁先走。最低的首先加载。
overrides在上面的示例中。 您想要更改的基本游戏 ID。 id 或 file.json:id(当您指的是生成精确文件的副本时)。
canon_safe在上面的示例中。 您的模组是否适合游戏的故事。这是你告诉玩家的,而不是游戏决定的。
roots家庭文件夹,当您想要将其放在家庭,一一中默认位置以外的位置时。留在包裹内。
manifest_version您正在写什么形式的宣言? 更改游戏已有内容 操作需要 2。此构建最多读取 2。
type是什么样的包裹。第四个值是发送行为而不是数据的值,并且此构建中唯一对执行行为说“是”的东西说“不”,因此声明它的数据包将被拒绝。上榜是因为形式已经决定,而不是因为大门敞开; mod 永远做不到的事情 是诚实的读物。 contentoverhaultotal_conversionfeature_extension 之一。
capabilities如果上层开放的话,包裹会问客人什么。这里的未知字段会因关闭而失败,而不是被忽略。
trust_tier不受信任,这就是玩家下载的模组的本质。由一位客人提名另一位客人;这里写的包没有任何内容可以提升它。 untrustedtrusted 之一。
supersedes打算覆盖的包。以这种方式声明的字段不再被报告为冲突。这里也有一个未知字段无法关闭。
fallback_policy当包覆盖的内容丢失时,包会依赖什么? vanillanone 之一。
campaign转化所具有的营销活动。
campaign_package声明此包*是*一个活动,具有自己的 ID、名称和版本。携带它的包仅在其活动进行时才会被读取,并且玩家在新游戏之前在模组屏幕中选择它。 总转化

依赖项可以是对象而不是名称:{"id": "some_mod", "version": "", "optional": true}

命名另一个包的值是​​跨模块引用,并且该引用必须是已声明的依赖项。如果该依赖项是可选的,请为该字段指定 fallback,否则当依赖项不存在时,该记录将被跳过:

a goods record

[
  {
    "op": "add",
    "id": "northern_reach:alloy",
    "display_name": "Alloy",
    "linked_item_id": "absent_helper:ore",
    "fallback": { "linked_item_id": "iron_ore" }
  }
]

每个文件的去向

where the files go

northern_reach/
  mod.json                  the label
  content/assets/images/
    images.json             your art
  content/inventory/items/
    blades.json             your first record
  content/narrative/quest_plans/
    the_long_winter.json    your quest

姓名和 ID

id 是小写字母、数字和下划线,仅此而已。 frost_blade,不是 Frost Blade,不是 frost-blade,也不是 frost.blade。它甚至不带有自己的分隔符,因为 id 内的分隔符是泄漏到名称中的文件夹:移动文件并且 id 不再与磁盘一致。上面的 : 是唯一的例外,两半都遵循规则。

冒号之前的部分是您的包 ID。这就是两个模组可以同时添加冰霜之刃而不发生冲突的方式。

玩家读到的单词

记录中写入的文本是单一语言的文本。相反,指向一个键:

a locale CSV

northern_reach.item.frost_blade.name
northern_reach.item.frost_blade.description

键是小写的,由点连接,命名空间作为 id。将单词带入 locales 系列 - content/locale 下的 .csv 以及 key 列和语言列。 家庭,一一 具有精确的形状。

还要在密钥旁边写上简单的 display_name。一张只有一句话的记录,翻译的那天就得用手重写,到那时就会有四百条。

犯错的两种方法会以非常不同的方式失败,只有其中一种告诉你这一点。 不响应任何操作的按键本身会显示为按键本身 - northern_reach.item.frost_blade.name,在屏幕上,故意丑陋以便有人修复,并算作一个洞。仅包含文本而没有键的记录永远不会出现:它以您的语言适用于每种语言的每个玩家。没有任何内容被拒绝,没有任何内容丢失,因此没有任何报告,并且用葡萄牙语阅读的玩家默默地阅读您的意大利语。你发现第一个错误。第二个找到你的读者。

翻译模组并被翻译

该游戏有七种语言版本,因此对于七分之六的安装者来说,记录中包含英语的软件包读起来就是英语。这就是避免它的成本,如果你在第一天这样做,这几乎没有什么,如果你在第四天这样做,则需要重写。

那里的语言

七,这个表是从构建中读取的,而不是在这里手写的,因此到达或离开的语言会在同一天移动它:

写这个舌头列标题
en英语en源语言
it意大利语it
fr法国人fr
de德语de
es西班牙语es
pt-BR葡萄牙语(巴西)pt_BR
zh-Hans简体中文zh_Hans

其中两个代码有第二个拼写在流通中 - pt-BR 是数字店面使用的拼写,本页 pt_BR 是引擎符合的拼写 - 并且 在列标题中两者都被接受。 写下您复制的那个。

携带不止一种语言的单词

content/locale 下的 CSV,其中 key 第一个,每种语言一列:

a locale CSV

key,en,it,de
northern_reach:GOOD_FROST_SALT,Frost Salt,Sale di Brina,Frostsalz
northern_reach:ITEM_FROST_BLADE_NAME,Frost Blade,Lama di Brina,Frostklinge
规则为什么
每个键都适合您的命名空间northern_reach:GOOD_FROST_SALT,与 ids 使用相同的冒号。除非 overrides 声明它,否则发出的密钥将被拒绝 - 否则两个都写入 GOOD_GRAIN 的数据包将由加载顺序静默解析。
命名游戏不支持的语言的列将被拒绝没有被忽视。装载机默默地扔下的一列不会带来任何东西,你会从玩家那里找到它。
空白单元格不是答案它会被跳过而不是存储,因此您尚未掌握的语言会进入下一步,而不是在屏幕上保持空白。
永远不要两者兼而有之带有 _key 字段*和*相同内容的逐字字符串的记录将被拒​​绝。关键是承诺;字符串是密钥替换的内容。

当按键没有以玩家的语言进行响应时,游戏会沿着固定的阶梯下降:玩家的语言,然后是您的软件包声称编写的语言,然后是游戏目录,然后是按键本身。最后一步是故意丑陋的:未解决的密钥必须看起来是错误的,才能有人修复它。完全转换会跳过游戏目录,因为 Old Seat 出现在另一个大陆的世界中并不是一个小的翻译疏忽,而是闪耀的基础游戏。

编写可翻译的文本

  • 没有分段构建的句子。 词序在所有语言中都不相同,因此在运行时从一列形容词和一列名词组合而成的名称会在意大利语中生成 Oro Cervo。为每种语言编写一个完整的条目。
  • 人名永远不会被翻译或变形。 Aldric 在所有语言中都是 Aldric。这也意味着按键不得将名称放在倾斜位置 - "of {name}""{name}'s" - 因为许多语言拒绝使用专有名称,而游戏则不会。
  • 没有字符限制,这与没有限制不同。 没有字段计算字符数;最终成为屏幕空间。德语比英语长约三分之一,是一种令人兴奋的语言。中国人要短得多,而且几乎从不这么做。如果您只尝试一种翻译,请尝试德语,并为标签提供仍然正确的最短措辞。

翻译您的包裹的人

添加一列并将文件发送回给您。工作流程都在这里,这就是为什么格式是 CSV,而不是对程序员更友好的格式:翻译人员可以在电子表格中打开它,并且他们的工具已经读取它。

翻译的软件包和未翻译的软件包之间有两点区别。 保持密钥稳定 - 重命名的密钥是丢失的翻译,翻译器会在玩家发现时发现。 说出一行的用途:名为 NR_MSG_01 的键得到猜测,而 northern_reach:VENDOR_HERB_GREETING 得到草药卖家的问候。

如果你是翻译别人的包的人,同样的规则也会约束你:列是游戏携带的语言,键是它的键而不是你的,名称仍然是名称。

改变游戏已有的内容

你想要手术你需要什么
添加新内容add您自己的 id 和您自己的命名空间。没有别的了。
改写一项游戏记录replaceoverrides 中列出的记录 ID。完整的记录:它没有继承任何东西。
更改一个字段并保留其余字段patchoverrides,加上mod.json中的"manifest_version": 2
退役记录removeoverrides,还有一个接受他的家庭。请参阅取出某些东西

part of mod.json

"overrides": ["iron_sword"]

overrides 是一个承诺。 落在您未声明的 ID 上的记录将被拒​​绝,因此您永远无法悄悄更改玩家一无所知的内容。

a goods record

[
  {
    "op": "patch",
    "id": "iron_ore",
    "changes": [
      { "op": "set", "field": "base_price", "value": 14 }
    ]
  }
]
手术What fa需要拒绝
add在您的命名空间下提供一条新的完整记录。带有命名空间的 id已经存在的 id,无论它来自基础游戏还是其他 mod
replace为已经存在的 id 提供完整的记录,并声明它。覆盖声明,记录完成注册表中不存在的 id,以及清单未在 overrides 下列出的 id
patch更改现有记录的命名字段并保留其余部分。声明覆盖、更改注册表中缺少的 id、系列不允许的字段以及 patch_operations 之外的任何形式的修改
remove淘汰现有记录并在其位置留下墓碑。声明覆盖,可移动族注册表中缺少的 ID,以及下面未标记为可移动的任何系列

补丁一次命名其更改:

  • 设置 — 将 value 写入 field,无论之前是什么。它是用fieldvalue编写的。
  • unset — 从记录中删除 field,以便读者看到该系列的默认值。它是用field编写的。
  • append_unique — 将 value 添加到 field 中的列表(如果尚不存在)。它是用fieldvalue编写的。
  • remove_value — 从 field 的列表中删除每个出现的 value。它是用fieldvalue编写的。
  • 按路径命名字段,而不是按位置。 tags.0 被拒绝。今天的第三个标签是你上传别人的mod后的第二个标签。
  • 路径最多由四个由句点连接的小写名称组成。 任何包含运算符的内容都会被拒绝。
  • append_unique 是两个 mod 可以共享的标签。 如果它们都排队相同的标签,则不是冲突,也不会加倍。

只是有时

记录可以告诉你什么时候值得。在 op 旁边添加 when,与 "manifest_version": 2 放在一个包中:

a presentation_bindings record

{
  "op": "add",
  "id": "my_mod:snowy_cloak",
  "subject": "wool_cloak",
  "kind": "item",
  "slot": "icon",
  "cue": "my_mod:cloak_snowy",
  "when": { "season": { "is": "winter" } }
}

没有运算符,也没有什么可计算的。条件可以说的所有内容都在这两个表中。

询问有关决定了证据价值观
packages加载时all_ofnone_ofMod ID 已上传到您的旁边
campaign加载时isany_ofnot_any_of比赛开始的战役
locale加载时isany_ofnot_any_of您正在玩游戏的语言
season玩耍时isany_ofnot_any_ofspringsummerautumnwinter
weather玩耍时isany_ofnot_any_of游戏滚动的天气 ID
day_phase玩耍时isany_ofnot_any_ofdawndaydusknight
day玩耍时at_leastat_most比赛持续了多少天
审判需要真实时
is一个名字答案正是如此
any_of一个清单答案是其中之一
not_any_of一个清单答案不是这些
at_least一个数字答案是这个或者更高
at_most一个数字答案是这个或更低
all_of一个清单他们都在那里
none_of一个清单没有人

when 中最多有四个受试者,每个受试者进行两次试验。对同一主题的两次试验是一个区间:{ "day": { "at_least": 10, "at_most": 30 } }

哪个家庭拿什么。 每个家庭拿三个在装载时决定的。只有 presentation_bindingseffects 会采用在游戏时移动的四个,因为当世界发生变化时只有这两个会被重建。在其他地方提名 season 会被拒绝,并且该消息会说明该家庭真正选择的科目。

原因就在于救助。决定一个项目、一个人或一个任务的记录在下次加载时必须是相同的记录,而移动条件正是阻止它这样做的原因。

季节性皮肤出现在链接上,而不是图像上。 仅将图像带一次,然后为她提供两条 presentation_bindings 记录:一条带有 when,一条没有。 imagesaudiofonts 拒绝 when 而不进行讨论。

保留并不被拒绝。 不满足的条件保留其记录,负载报告按名称说明:

what the game prints back

WITHHELD my_mod:snowy_cloak from my_mod: season is winter, and it is spring

包含五十个赛季记录的包在任何时候都有四分之三保持。这是有效的包。

如果任何条件表示关联被拒绝,报告仍显示声明的系列并打印 bound=0 以及每个 WITHHELD 行;不会错误地将包裹报告为没有展示面。如果没有无条件绑定提供相同的槽,它还会打印 NO_APPLICABLE kind/subject/slot 以及未答复的条件,这意味着“在此世界状态中没有任何内容适用”,而不是“记录无效”。在假设关联已被拒绝之前,使用相应的世界状态测试主机或运行时通道中的条件。

同一事物的两个版本。 带来两个具有相同 id 和不同条件的 add 记录。条件成立的人就是发起指控的人。如果两者都成立,则第二个将被视为重复而被拒绝 - 这就是报告重叠条件而不是通过文件顺序解决的方式。

删除一些东西

remove 表示*停止*,而不是*不存在*。该记录继续自行解决并被标记:不再提供、库存、制造或生成任何新东西,并且玩家已经拥有的一切以及命名他的人继续准确地阅读他一直阅读的内容。

家庭remove会发生什么
goods是的撤回。它仍然解决了 id 问题,与游戏提供的内容不同。
vendor_inventories是的取消。该线被移除。
其他一切拒绝了,有理由。

a goods record

{ "op": "remove", "id": "iron_ore" }

vendor_inventories 是唯一一个删除记录的系列,而且只是因为保存规则已经表明没有人指向该行。

remove 不能携带 when。必须决定救援可能命名的撤回,否则 id 会在一天晚上解决,而不是第二天晚上。

对于组合而言,删除是永久性的。 针对已停用 ID 的后续 patchreplace 或第二个 remove 都会被拒绝,即使商品召回通过永久删除使旧记录保持可解析。这可以防止保存报告指示“已停用”,而后续包会导致记录再次按提供的方式运行。当需要新记录时添加新的命名空间ID;不要依赖移除然后默默复活。

当两个模组想要同样的东西时

他们都加载。每个更改都是在构建之前完成的,因此游戏可以看到两者。

什么冲突会发生什么
同一条记录的不同字段两者都适用。什么都没有丢失。
同样简单的字段后来赢得了 load_order未声明的冲突是一个错误undeclared_collision,并且构图不正确。
提供完整记录的两个包相同。获胜者在 load_order 上决定,并且该计划仍然拒绝,直到有人宣布为止。
相同的列表,带有 append_unique / remove_value没有冲突。两者都说列表应该包含什么,而不是它应该是什么。
一个 mod 包撤回记录,另一个 mod 包修改或替换它撤回保持有效。后续操作会被拒绝,与加载顺序无关。
两个包装相同的主题后来的装载顺序获胜,失败者会在报告中列出。
一个包裹另一个包裹的内容物Refused.

赢得和获得许可是两个不同的问题,这就是令人惊讶的部分。游戏总是计算它最后写入的数据包——如果让它碰巧的话,即使是抛硬币也会被拒绝——并且仍然将这对数据标记为没有人声明的冲突。离线验证器会在没有讨论的情况下拒绝同一对,因此您可以在玩家之前发现。

宣言中的 supersedes 是你表达自己故意这样做的方式。命名另一个数据包的 id,冲突变为 declared_replacement:已注册,有原因,不再是错误。

给你的包一个自己的load_order 两个共享一个号码的包不会被拒绝,然后获胜者就会脱离mod id的字母顺序:一个作者没有选择的顺序,并且没有玩家可以在屏幕上读取。

图像、声音、文字、色彩

引入文件和“使用”它是两个单独的步骤,并且您都需要。没有任何指向的文件被读取、检查、测量并且从不显示。

Type文件已安装这是什么意思
image.png.webp是的读取文件并构建纹理。
audio.ogg.wav描述符经过验证,标头被读取,持续时间被定界,但没有任何声音:没有内容系列携带音频,并且音频功能不要求任何目录提供数据包声音。当家庭存在时,带来声音;今天他会谨慎而沉默。
font.ttf.otf描述符经过验证并检查语言覆盖范围,并且没有主题解析包字符。该界面根据其自带的主题构建字体,因此将检查包提供的字体,而不将其设置为任何内容。

带上文件

每个资源族都是一个文件描述符加上它命名的文件。描述符的命名必须与其系列相似:images.jsonaudio.jsonfonts.json

where the files go

content/assets/images/
  images.json
  river_guard.png
家庭文件夹接受必填字段
imagescontent/assets/images.png.webpidfileformat
audiocontent/assets/audio.ogg.wav(未压缩)idfilecodecrole
fontscontent/assets/fonts.ttf.otfidfileformatsizescoversfallback_font
themescontent/assets/themes颜色标记idtokens
effectscontent/assets/effects主机型号idtemplate

a images record

[
  {
    "id": "northern_reach:river_guard",
    "file": "river_guard.png",
    "format": "png"
  }
]

三个咬人的规则:

  • 在对其进行解码之前会检查标头。 format 是文件的内容,而不是扩展声明的内容。
  • 包含 ..~ 或以 /\res://user:// 开头的 file 名称将被拒绝
  • 无法解析的 id 会收到占位符和警告,永远不会沉默。

赌上它

在您携带的记录上,其中包含一个包含您的图像 ID 的字段:

家庭场地它是什么
itemsicon_id您携带的物品上的图标。
npc_definitionsportrait_id一个有名字的NPC的肖像。
perksicon特权的图标。

任何内容,包括基本游戏内容,并使用 presentation_bindings 记录命名主题、其类型槽位

a presentation_bindings record

[
  {
    "id": "northern_reach:iron_sword_icon",
    "subject": "iron_sword",
    "kind": "item",
    "slot": "icon",
    "cue": "northern_reach:river_guard",
    "alternative_key": "northern_reach_iron_sword_icon_alt"
  }
]
Slot你携带它出现在哪里alternative_key绘制
portraitimage对话的框架,用于说话者的 id。强制性的是的
spriteimage部队标记、世界地图地形或定居点中的建筑物。是的
iconimage库存单元格,适用于任何物品 - 您的或游戏的。强制性的是的
bannerimage他日记页上的房子颜色。是的
voiceaudio当扬声器的线路出现时,就会发出声音。强制性的尚未支持
use_soundaudio当物品被使用且使用生效时发出声音。尚未支持
ambienceaudio当玩家站在该地形上时它会循环。尚未支持
themetheme您的哪个调色板具有该界面。是的
fontfont您的哪个角色佩戴该界面。尚未支持
effecteffect与其关联的地面上的天气和光线。是的

当插槽携带信息时,alternative_key 是强制性的:它是语言密钥,对无法接收图像的玩家说同样的事情。

声音

role 是一个限制,而不是一个标签:每个都有自己的最大持续时间、一起玩的上限以及玩家寻找的光标。

角色为了光标
music歌曲音乐
ambience房间、时间、地点环境
sfx短期效应效果
voice笑话效果

压缩的 WAV 会被拒绝:对其进行解码需要解析器,而解析器正是您要避免的东西。

著作

covers 命名您的字体携带字形的语言,并且构建拒绝为任何其他语言安装它。缺少语言的角色不会失败:画一些小方块,屏幕上读起来就像半成品的翻译,有正确的文本和字体的错误。

fallback_font 是必需的:命名您自己或系统系列的另一个字体 ID(Segoe UINoto Sans)。 sizes 是字形缓存的计算依据。

只有一个字符,而不是一个集合 - .ttc 包含多个字符,并且哪个到达取决于描述符无法携带的索引。覆盖范围广泛的免费字体:Google Fonts, Font Squirrel.) 检查许可证是否允许您重新分发该文件 - 您的软件包中包含该文件。

颜色

令牌,绝不是场景、脚本或资源路径。这些名称是游戏的名称:bg_deepbg_midbg_buttonbg_hoverborderborder_hitexttext_dimaccentgold。日志中提到了此构建不知道的名称,而不是坐在那里似乎已应用。

a themes record

[
  {
    "id": "northern_reach:dusk",
    "tokens": {
      "bg_deep": { "kind": "colour", "value": "#12131a" },
      "text": { "kind": "colour", "value": "#e8e2d0" },
      "border": { "kind": "colour", "value": "#7f6ab0" }
    },
    "contrast_pairs": [
      { "text": "#e8e2d0", "background": "#12131a" }
    ]
  }
]

contrast_pairs 以 4.5 及以下的比率进行检查,主题将被拒绝。 WebAIM 测量仪 在您佩戴前告诉您一双的比例。

关闭包装,界面恢复其颜色和文字。

感觉良好的艺术

构建检查图像是否是图像。它对于它看起来是否正确没有什么可说的,在一个用灰色绘制的世界中,一把明亮、欢快、高分辨率的剑并不会因为通过了所有的审查而不再是错误的。这就是今天所知道的。

寄存器像素艺术,灰色,不太英雄气概。暗淡、磨损、被时间玷污。适合在经历了糟糕的一年的城市中的一个下雨的午后使用的调色板。
销钉16 像素,用于在地图内绘制的任何内容。 您的地图
格式和限制.png.webp,每侧最多 8192 个,最多 8 MB,在任何解码之前由标头控制。
界面颜色themes 的十个令牌,以及 contrast_pairs 比率为 4.5,低于该比率主题将被拒绝。

完整的风格指南尚未发布。 它将带来什么:调色板本身、绘制每种类型事物的尺寸,以及并排说明世界中的事物和事物的结果的示例。等待它而不是猜测是值得的,因为它防止的失败不是一个被拒绝的文件:它是一个可以完美安装并使游戏感觉像两个游戏的包。

只要它不存在,可靠的方法就是不需要任何文档的方法:将您的图像放在游戏图像旁边,然后将它们放在一起查看。

你的地图

在[Tiled]中绘制(https://www.mapeditor.org/),导出到.tmj,索引到content/world/maps/maps.json

a maps record

[
  {
    "id": "northern_reach:river_bend",
    "file": "river_bend.tmj",
    "name_key": "NORTHERN_REACH_RIVER_BEND",
    "world_origin": [4096, 2560],
    "region_id": "northern_reach:lowlands"
  }
]
规则这是什么意思
套件16 像素图块,正交,右下,已完成。
级别是角色,而不是名称groundcollisionwalkable 是强制的。名为 collisions 的级别被拒绝而不是被忽略。
几何宣告自己碰撞和行走区域是您绘制的对象,而不是从图块的外观推断出来的。
每个对象名称都有自己的命名空间northern_reach:towpath,而不是 towpath
world_origin你的左上角在哪里,以世界像素为单位。据说,因为地图文件不知道它在世界的哪个位置。
地图可以告诉你在哪里,但不能告诉你什么bindings 图层上的 poi 对象命名您作为记录带来的兴趣点;该排列将其移动到您绘制的位置。
全有或全无被拒绝的条款绝对没有任何意义。
没有路线名称为 pathscenescriptresourcetemplate 的属性将被拒绝,无论其包含什么内容。

命名另一个包(或基础游戏)内容的链接会导致整个布局被拒绝。 modding_map_report 命名该规定以及拒绝它的规则。

你的使命

任务是一组仅在 content/narrative/quest_plans 中组合在一起才有意义的记录。

Type它是什么
arc故事。列出其中包含的任务。
quest任务:谁给的,任务叫什么,付多少钱。
objective玩家必须做的一件事。
ending电弧如何结束。

a quest_plans record

[
  {
    "kind": "arc",
    "id": "northern_reach:the_long_winter",
    "stages": ["northern_reach:bring_the_grain"]
  },
  {
    "kind": "quest",
    "id": "northern_reach:bring_the_grain",
    "name_key": "northern_reach.quest.bring_the_grain.name",
    "giver": "northern_reach:the_reeve",
    "in_arc": "northern_reach:the_long_winter",
    "objectives": ["northern_reach:gather_grain"],
    "rewards": [
      { "grant": "receive_coin", "coin": 250 }
    ]
  },
  {
    "kind": "objective",
    "id": "northern_reach:gather_grain",
    "quest": "northern_reach:bring_the_grain",
    "goal": "collect_item",
    "target": "northern_reach:winter_grain",
    "count": 40
  },
  {
    "kind": "ending",
    "id": "northern_reach:the_barns_are_full",
    "arc": "northern_reach:the_long_winter",
    "requires": ["northern_reach:bring_the_grain"]
  }
]
客观的今天看了
collect_item是的——你携带的东西已经够多了
defeat_unit是的——你已经杀够了一些东西
earn_coin是的——你有足够的钱
reach_place是的——你访问过一个定居点
survive_days是的——已经过去足够多的日子了
speak_todeliver_itemdefend_placeescort_unitlearn_lore — 被拒绝而不是被接受,然后从未完成
报酬今天交付
give_itemreceive_coin是的
change_relation是的,当主语是玩家时
其他五个大声拒绝
  • 计划要么全有,要么全无。 一个错误的记录并且没有安装:另一种选择是一条弧线,在玩家拿着剑而不是标题的情况下停止。
  • 奖励是 grant,而不是 kind kind 表示这是四个记录中的哪一个。用kind写的奖励读起来很好,被拒绝了。

使用 modding_quest_plan_report 检查您的。

你的谈话

对话是 content/narrative/dialogue 中的三种类型的记录:dialogue_graph 对其进行命名并说明其在哪个柱上打开,dialogue_node 柱是线,以及其上方的 dialogue_option 选择。

你的台词就是你的台词,没有什么可以重写它。 本地模型可以做的就是回答玩家写给角色的问题,并留在你的台词内——当它不能留在里面时,它会说它不知道。由玩家决定该表面是否存在;模型关闭后,角色说出你的句子并停止。你的笑话的翻译来自语言文件,就像你写的其他内容一样。

该图命名为 speaker,触发器就在那里。游戏中的每个角色都会在点击时询问这个家庭他们上方有哪些对话,因此您可以给铁匠一些话要说而无需重新定义铁匠

a dialogue record

[
  {
    "kind": "dialogue_graph",
    "id": "northern_reach:gate_toll",
    "entry": "northern_reach:gate_open",
    "speaker": "gate_warden",
    "name_key": "TALK_PACK_GATE"
  },
  {
    "kind": "dialogue_node",
    "id": "northern_reach:gate_open",
    "graph": "northern_reach:gate_toll",
    "voice": "line",
    "speaker": "gate_warden",
    "line_key": "TALK_PACK_GATE_OPEN"
  }
]

你写的是对话,而不是文字:每个笑话都是一个语言密钥,因此同一个包可以用玩家拥有的所有语言阅读。携带散文的数据包会被文件而不是屏幕拒绝。

笑话和选择可以包含每个条件,选择可以包含命令。条件决定了是否向玩家显示该事物;命令就是他接受命令时发生的事情。

查看需要他问今天回复
companion_presentcompanion那位同伴在那里听到了。是的
faction_stancefactionstance一个派系站在选择所期望的地方。是的,对于 hostile — 在第一个测量之前任何其他值都会被拒绝
has_coincoin玩家可以承受。是的
has_itemitemcount玩家随身携带它。是的
has_knowledgelore玩家被告知了这一点。是的
has_traittrait播放器是这样构建的。是的
lacks_knowledgelore玩家尚未被告知这一点。是的
quest_statequeststate使命就是选择所期望的地方。是的
relation_at_leastsubjecttargetregard一方至少是这么认为另一方的。是的
seasonseason我们正处于一年中的这个时期。是的
time_of_dayphase我们正处于一天中的那个阶段。是的
命令需要今天完成
change_relationsubjecttargetdelta在主机公布的关系规则范围内改变声望。是的
give_itemitemcount交付一些东西。是的
grant_knowledgelore对玩家说一些话。是的
open_shopvendor将商人的物资放在屏幕上。是的
pay_coincoin玩家付费。是的
receive_coincoin玩家得到报酬。是的
recruit_companioncompanion在主机公布的招募规则允许时,将某人加入队伍。是的
set_quest_statequeststate将任务带到他的记录允许的状态。是的,对于 activefailed — 在第一次测量之前任何其他值都会被拒绝
start_combatencounter结束对话。是的
take_itemitemcount它带走了一些东西。是的
travel_todestination把公司搬走吧是的
  • 命名此构建无法执行的操作的对话永远不会打开。不是使用它的选择:整个对话,在其第一行之前。停在第三个选项的讨论已经拿走了玩家的金币。
  • 没有什么比有的更移动了。 首先用 has_coinhas_item 询问;一个忘记它的包裹不能让玩家减掉四十个硬币,因为没有人接受过债务,也没有屏幕解释这一点。
  • 每个笑话都需要一条出路。 当图表加载时,玩家可以到达但无法离开的笑话会被拒绝。

使用 modding_dialogue_report 检查您的。

你的场景

场景是唯一一种脱离玩家控制的内容类型,因此它也是唯一具有结束规则的内容。这些场景位于 content/narrative/scenes 中,每个场景都命名为 where,即播放的位置。进入那个地方,场景就开始了。

a scenes record

[
  {
    "id": "northern_reach:the_morning_after",
    "where": "northern_reach:waystation",
    "beats": [
      { "beat": "fade_in", "seconds": 1.5 },
      { "beat": "lock_player" },
      { "beat": "say", "actor": "gate_warden", "line_key": "SCENE_PACK_GREETING" },
      { "beat": "wait", "seconds": 1.0 },
      { "beat": "unlock_player" }
    ]
  }
]
开玩笑需要时代今天玩过
ask_nameprompt_key等待她的场景是的
end场景仍在继续是的
fade_inseconds等待她的场景是的
fade_outseconds等待她的场景是的
lock_player场景仍在继续是的
narrateline_keyseconds等待她的场景是的
play_cuecue场景仍在继续是的
remove_actoractor场景仍在继续是的
sayactorline_key等待她的场景是的
show_exit场景仍在继续是的
start_dialoguegraph等待她的场景是的
unlock_player场景仍在继续是的
waitseconds等待她的场景是的
walk_toactoranchor等待她的场景是的
  • 删除控件的场景必须返回它们。 没有 unlock_player 结束的序列将被拒绝,因为替代方案是带来一个玩家只能通过关闭游戏退出的房间。
  • 线路按顺序排列,并且预计会出现阻塞线。这就是使场景成为场景而不是同时发生的一系列事情的原因。

使用 modding_scene_report 检查您的。

你的截图

屏幕布局告诉您哪些部分位于游戏已有屏幕的哪个面板中,以及按什么顺序。它列出了该构建绘制的各个部分;他无法添加一个,因为没有人写的部分没有什么可画的。

这些规定位于 content/ui/screens 中。 家庭,一一 有字段和记录可供复制。

使用 modding_screen_report 检查您的。

什么也没有出现

首先阅读 Mod 屏幕上的状态。几乎每个州都公开地在线指出了这个问题,最常见的错误也是如此:曾经位于该列表顶部的错误。

content_types 中缺少的系列。 您写入 goods.json,但在清单列表中忘记了 "goods",并且该文件夹从未打开:没有任何内容被拒绝,因为没有读取任何内容。包裹装载为空。现在屏幕会告诉您它浏览了哪个文件以及要添加的内容:

what the game prints back

content/economy/goods/goods.json was not read — add "goods" to content_types in mod.json

离线验证器打印相同的句子,因此两者不能不一致。仅当该行显示已加载且未命名任何未读文件时,才查看此列表。这是按照每个人成为罪魁祸首的频率排列的。

#症状验证者说什么
1文件夹路径错误WARN: declared goods root missing: …/content/economy/goods警告,而不是错误:包无论如何都会通过,这就是为什么在发布之前 --strict 是建议。 家庭,一一 拥有每个家庭的确切文件夹。
2id 没有冒号ERROR: add needs an id under your own namespacefrost_blade被拒绝; northern_reach:frost_blade 被接受。
3JSON 已损坏ERROR: invalid json goods.json: Expecting ',' delimiter: line 6 column 5。缺少逗号会使整个文件无法读取,并且系统会告诉您该行。
4文件位于错误的包中与 n 相同的消息。 2.带有别人命名空间的id不是你写的,检查无法区分它和拼写错误:它只知道前缀不是你的包id。
5缺少必填字段报告将其命名为——一个家庭实际需要的领域,这比你想象的要少。 它出现了,但它是错误的 是根本没有任何报告的情况。

报告永远不会让你猜测。被拒绝的记录会被命名,它出了什么问题,并且通常带有代码 - 请参阅每个诊断代码

出现了,而且是错误的

最困难的情况,因为根本没有任何报道。有两件事通过了所有的审查,但仍然给你一份不是你写的记录。

您省略的字段不是错误:它是默认值。 每个系列的架构都会告诉您记录不能没有哪些字段,并且对于几乎所有系列来说,该列表都很短。 goods 只需要一个:id。省略base_price,则为1。省略weight,则为1.0。省略category,商品为原材料。没有什么会提醒你,因为没有什么错:你要求一件好事,你就得到了一件。

即使不在选项中的值也是默认值。 读者在搜索之前将所有大写字母放在一起,因此 manufacturedMANUFACTURED 是相同的值,大写从来都不是问题:不要为此重写文件。问题是MANUFACTURED_GOODS:它不是成员,所以变成了RAW_MATERIALdecay_tierSLOW 变为 ETERNAL。记录安装完毕,屏幕显示已应用,您的蜡烛具有其他东西的价格和易腐烂性。

游戏中没有任何内容说明这一点,因为没有什么可说的:该字段被声明为字符串,拼写错误的字符串仍然是字符串。验证器是唯一可以使用它的地方,现在它使用它:

typed into the debug console

$ python tools/quality/validate_mod_data.py --root mods/northern_reach
WARN: northern_reach:goods:goods.json#1: category is "MANUFACTURED_GOODS",
  which is not one of RAW_MATERIAL, MANUFACTURED, CONSUMABLE, AMMUNITION,
  EQUIPMENT. It loads as RAW_MATERIAL.
  ERROR=0 WARN=1

这是警告而不是错误,因为记录实际上加载并且现在拒绝它会破坏已经工作的包。 --strict 将其变成错误,这就是您在发布之前运行 --strict 的全部原因。

您省略的字段保持沉默,并且不能被采用:省略 category 和写入 RAW_MATERIAL 是相同的请求。因此,家庭,一一 中的字段表标记为必填,并将值列指定为*加载程序检查的形状*。当一条记录加载并表现得像其他记录时,首先将您的字段与该表进行比较:您要查找的是您没有编写的字段,或者加载程序无法识别的单词。

参考

每个家庭

每个家庭一个文件夹和一份报告。状态栏是在构建时测量的,因此它绝不是游戏不兑现的承诺。 它是什么只是开头行,因此表格仍然是您可以用眼睛滚动的内容;每个家庭的完整描述及其字段和要复制的记录位于家庭,一一 中的条目。

家庭状态包中的文件夹报告命令它是什么
adaptive准备使用content/player/adaptivemodding_adaptive_report个人资料可查看比赛的进展情况并提出不同的方法。
audio已验证,但目前没有任何内容消费它content/assets/audiomodding_audio_report包携带的声音,由 id 命名:音乐、氛围、效果和声音,每个都指向其自己文件夹中的一个文件,并声明分隔它的角色。
buildings准备使用content/world/buildingsmodding_building_report定居点的建筑物和服务的定义:标签、颜色、角色和重复使用的内饰。
caravans准备使用content/logistics/caravansmodding_caravan_report商队行进的贸易路线:从哪里出发、要去哪里、带来什么、护送的情况以及行进的速度。
combat_balance准备使用content/combat/balancemodding_combat_balance_report有界战斗平衡值,无需添加规则、操作或机制即可调整现有解算器参数。
dialogue准备使用content/narrative/dialoguemodding_dialogue_report作为记录的对话:图表、其中的笑话以及上面的选择。
effects准备使用content/assets/effectsmodding_effect_report天气、灰尘、火花和灯光,由主机提供的模型组成。
enemy_archetypes准备使用content/threat/enemy_archetypesmodding_enemy_archetype_report战略级别知道的敌人类型:等级、他们部署的变种、他们扎营的地方、驻军有多大以及他们袭击的频率。
enemy_variants准备使用content/combat/enemy_variantsmodding_enemy_variant_report场上敌人身体类型的统计数据块:类别、等级、五种属性以及武器、副手和其携带的盾牌的 ID。
fonts已验证,但目前没有任何内容消费它content/assets/fontsmodding_font_report包携带的字体,由 id 命名:文件、绘制它们的大小以及它们携带的字形的语言。
goods准备使用content/economy/goodsmodding_goods_report适销对路的商品及其经济特性。
group_archetypes准备使用content/strategic/group_archetypesmodding_group_archetype_report生活在世界地图上的群体的可调整策略参数:警告半径、目标偏好、成员数量、补给和撤退阈值。
images准备使用content/assets/imagesmodding_image_report包带来的图像,由 id 命名:图标、肖像和精灵表,每个都指向其自己文件夹内的一个文件。
input_bindings准备使用content/inputmodding_input_report自己的一个动作包,用key自己想要。
items准备使用content/inventory/itemsmodding_items_report库存物品,包括武器和盔甲。
locales准备使用content/localemodding_locale_report玩家读取的单词,采用 CSV 格式,每种语言一列:包自己的密钥,以及包声明覆盖的游戏的密钥。
lore准备使用content/narrative/loremodding_lore_report法典条目:地点、人物、事件、习俗以及世界讲述的故事。
maps准备使用content/world/mapsmodding_map_report包在 Tiled 中绘制的排列,由 id 命名:文件、它在世界上的位置以及已知它的语言键。
mercenary_templates准备使用content/character/mercenariesmodding_mercenary_report可雇用的雇佣兵模型:姓名、阶级、出身、初始健康状况和士气、雇用成本以及首次出现的日期。
mr_lines准备使用content/medieval_realism/structuredmodding_mr_lines_report中世纪现实主义结构化线路,通过文件和线路 ID 而不是 JSON 中的 id 字段进行路由。
noble_houses准备使用content/politics/noble_housesmodding_noble_house_report贵族家族的初始数据:领主、继承人、家族所属的定居点以及谁算作竞争对手或盟友。
npc_definitions准备使用content/narrative/npcsmodding_npc_report指定 NPC 的定义。
perks准备使用content/character/perksmodding_perk_report声明性权限:触发器和效果,无需用代码编写任何处理程序。
pois准备使用content/world/poismodding_poi_report手写世界地图上按坐标放置的兴趣点。
presentation_bindings准备使用content/presentation/bindings-哪个包资源填充哪个主题的哪个插槽:对象上的图标、单位或图块上的精灵、派系上的横幅,无论是包的内容还是基础游戏的内容。
progress准备使用content/player/progress-玩家进度记录:目标、安全难度概况以及主机规则内的比赛概况。
quest_metadata准备使用content/narrative/quest_metadatamodding_quest_metadata_report任务元数据记录,通过 quest_id 而不是 id 进行索引。
quest_plans准备使用content/narrative/quest_plansmodding_quest_plan_report作为记录的任务计划:包中写入的弧线、任务、目标和结局,游戏从中构建自己的任务。
quests已检查,尚未安装content/narrative/quests-手写的任务资产,按路线加载,而不是解释为记录。
recipes准备使用content/economy/recipes-工艺配方:消耗什么、产生什么、在哪里制造、成本多少以及变质的可能性有多大。
relationships准备使用content/companion/relationships-交配模式、有界关系政策、招募条件和声明性纽带。
scenes准备使用content/narrative/scenesmodding_scene_report舞台场景:房间、房间里的人以及按顺序展开的台词。
screens准备使用content/ui/screensmodding_screen_report屏幕布局:哪些部分适合游戏已有屏幕的哪个面板,以及按什么顺序。
settings准备使用content/settingsmodding_settings_report玩家可以改变的选项,是宣布的而不是绘制的。
themes准备使用content/assets/themesmodding_theme_report界面调色板作为标记:命名的颜色、大小和间距,以及玩家必须能够读取其对比度的对。
vendor_inventories准备使用content/world/vendor_inventoriesmodding_vendor_inventory_report商家供应表。
world_generation准备使用content/world/generation-仅由数据组成的生成配置文件:生物群落和位置的加权选择,由主机拥有。
  • 开箱即用 - 发布形式,游戏安装您的记录,有一个示例,并且您的 ID 在保存和重新加载后仍然存在。
  • 已验证,但目前没有任何内容消费它——加载器会读取并检查该系列,但没有面向玩家的 mod 包界面消费它。音频和字体 mod 包属于这一档:干净的报告不会让静音信号或未使用的字体出现在游戏中。
  • 已检查,尚未安装 - 游戏会识别该系列并检查您的文件,并且不会将其放入正在进行的游戏中。以它为目标的包通过了所有检查并且不加载任何内容。它是故意出现在页面上的:另一种选择是有人在那里度过一个晚上而从未发现他们没有做错任何事。

完全决定,没有任何家人携带,所以没有海报可以问她:

会是它会去哪里它是什么
feature_extension还是没有文件夹一个包是一个功能而不是内容。 mod 永远不能做的事情 是对本文的诚实阅读。

这不是浪费。 mod 永远不能做的事情 就是这个列表。

一家人,一一

构建的每个系列都知道,它接受什么,以及您可以复制的记录。

  • 强制字段是指没有这些字段就无法安装记录的字段。
  • 值列是加载器检查的形状,而不是提示。
  • 如果一个家庭这么说,表中未命名的字段将与其所在的记录一起被拒绝。字段名称中的拼写错误是一条无法加载的记录,家庭报告按名称也是如此。

每个条目还说明了玩家卸载你的那天保存会发生什么:

回答救援是做什么的
preserve_inert_referenceid 保留,解析为空,然后报告。玩家拥有的那个仍然有名字。
substitute_placeholder引擎拥有的稳定替换会做出响应,因此世界无论如何都会加载,并且原始 ID 会保留在附近。
drop_optional_presentation该引用被删除,因为没有任何东西依赖于它。只有演示族可以声明这一点。

这里没有任何手写内容。这些字段来自每个系列的已发布架构。每个示例都是框架的测试数组针对加载器旋转的包之一,放回到 northern_reach 命名空间下,并在进入此页面时根据其模式重新检查:游戏将拒绝的示例会导致构建失败。

世界及其包含的地方

5个系列:buildingscaravansmapspoisworld_generation

buildings

定居点的建筑物和服务的定义:标签、颜色、角色和重复使用的内饰。

  • 状态 可供使用
  • 旅行过 建筑物的服务
  • 文件夹 content/world/buildings
  • id 字段路由的记录
  • 报告 modding_building_report
  • 如果玩家卸载了你 substitute_placeholder。曾经有服务的地方如果有漏洞,则无法进行;读取并恢复了明显缺失的建筑物。

字段。 此表未命名的字段将随记录一起被拒绝。

场地必要的价值观
id是的文本,id
role是的细绳
color-任何人
description_key-细绳
interior-文本,id
interior_service-文本,id
label-细绳
label_key-细绳
map_binding-文本,id
services-列表
settlement-文本,id
tier-0 到 5 之间的整数

在名为 buildings.json 的文件中,或者在该文件夹中您喜欢的任何名称 .json 中:

a buildings record, under content/world/buildings

[
  {
    "id": "northern_reach:guildhall",
    "label": "Guild Hall",
    "role": "reeve",
    "color": {
      "r": 0.4,
      "g": 0.34,
      "b": 0.26
    },
    "interior_service": "moot_hall"
  }
]

caravans

商队行进的贸易路线:从哪里出发、要去哪里、带来什么、护送的情况以及行进的速度。

  • 状态 可供使用
  • 文件夹 content/logistics/caravans
  • id 字段路由的记录
  • 报告 modding_caravan_report
  • 如果玩家卸载了你 preserve_inert_reference。数据包消失的路由保留其名称并且不携带任何内容。更换目的地会将玩家的货物发送到他们从未接受过的地方。

字段。 此表未命名的字段将随记录一起被拒绝。

场地必要的价值观
id是的文本,id
origin_settlement_id是的细绳
destination_settlement_id是的细绳
cargo_type-细绳
cargo_value-整数,0或更大
daily_progress-0.01 到 1.0 之间的数字
display_name-细绳
group_archetype_id-细绳
guard_strength-nonelightmediumheavy
initial_spawn_offset_days-0 到 30 之间的整数

在名为 caravans.json 的文件中,或者在该文件夹中您喜欢的任何名称 .json 中:

a caravans record, under content/logistics/caravans

[
  {
    "id": "northern_reach:salt_road_run",
    "display_name": "Salt Road Run",
    "origin_settlement_id": "valdmere",
    "destination_settlement_id": "old_seat",
    "cargo_type": "salt",
    "cargo_value": 240,
    "guard_strength": "light",
    "daily_progress": 0.08,
    "initial_spawn_offset_days": 3
  }
]

maps

包在 Tiled 中绘制的排列,由 id 命名:文件、它在世界上的位置以及已知它的语言键。索引就是记录;它旁边的排列被读取为数据而不是资源,标准化为规范形式,对照已发布的套件进行检查并在放置任何东西之前进行组装。被拒绝的布局根本不会放置任何东西,因为一半的地图是玩家进入的区域,而无法知道哪一半已经到达。

  • 状态 可供使用
  • 文件夹 content/world/maps
  • id 字段路由的记录
  • 报告 modding_map_report
  • 如果玩家卸载了你 drop_optional_presentation。没有任何救援能够命名处置。保存会命名布局已移动的兴趣点,并且该记录保留其坐标,因此退役地图会花费布局而不是内容。放弃它才能让世界回到它的记录所说的那样,而不是坚持一个没有人再提供的立场。

字段。 此表未命名的字段将随记录一起被拒绝。

场地必要的价值观
id是的文本,id
file是的文本,fixed shape
name_key是的细绳
world_origin是的从 -1000000 到 1000000 的整数列表
region_id-细绳
sha256-文本,fixed shape

在名为 maps.json 的文件中,或者在该文件夹中您喜欢的任何名称 .json 中:

a maps record, under content/world/maps

[
  {
    "id": "northern_reach:river_bend",
    "file": "river_bend.tmj",
    "name_key": "MAP_RIVER_BEND",
    "world_origin": [
      4096,
      2560
    ],
    "region_id": "northern_reach:lowlands"
  }
]

pois

手写世界地图上按坐标放置的兴趣点。

  • 状态 可供使用
  • 前往 地图上的地点 的路线
  • 文件夹 content/world/pois
  • id 字段路由的记录
  • 报告 modding_poi_report
  • 如果玩家卸载了你 preserve_inert_reference。一个被发现的地方仍然被发现。任务和旅行历史都指向 ID。

字段。 此表未命名的字段将随记录一起被拒绝。

场地必要的价值观
id是的文本,id
display_name是的细绳
awareness_modifier-从-1到1的数字
description-细绳
discovery_radius-1 到 10 的数字
kind-整数或字符串
linked_quest_id-细绳
morale_modifier--10 到 10 之间的整数
narrative_significance_key-细绳
one_time_loot-布尔值
world_position-任何人

在名为 pois.json 的文件中,或者在该文件夹中您喜欢的任何名称 .json 中:

a pois record, under content/world/pois

[
  {
    "id": "northern_reach:drowned_mile",
    "kind": "RUINS",
    "display_name": "The Drowned Mile",
    "description": "A stretch of road the river took back. The milestones still stand, chest deep.",
    "world_position": {
      "x": 0.0,
      "y": 0.0
    },
    "discovery_radius": 3.0,
    "one_time_loot": true,
    "morale_modifier": -1,
    "awareness_modifier": 0.05,
    "narrative_significance_key": "POI_DROWNED_MILE_LORE"
  }
]

world_generation

仅由数据组成的生成配置文件:生物群落和位置的加权选择,由主机拥有。

  • 状态 可供使用
  • 文件夹 content/world/generation
  • id 字段路由的记录
  • 报告不是他的; modding_preflight_report 负责处理它
  • 如果玩家卸载了你 preserve_inert_reference。保存会记录所选配置文件的 ID。如果它的包丢失,保留并报告该 ID 比使用基础游戏地图默默地重建游戏更安全。

字段。 此表未命名的字段将随记录一起被拒绝。

场地必要的价值观
kind是的任何人
id是的文本,id
stream是的文本,id
tables是的目的
description_key-细绳
name_key-细绳

在名为 profiles.json 的文件中,或者在该文件夹中您喜欢的任何名称 .json 中:

a world_generation record, under content/world/generation

[
  {
    "kind": "generation_profile",
    "id": "northern_reach:ashen_reach",
    "stream": "northern_reach:world_stream",
    "tables": {
      "biomes": [
        {
          "id": "plains",
          "weight": 60
        },
        {
          "id": "forest",
          "weight": 30
        },
        {
          "id": "hills",
          "weight": 10
        }
      ],
      "settlements": [
        {
          "id": "northern_reach:hamlet",
          "weight": 100
        }
      ],
      "buildings": [
        {
          "id": "northern_reach:longhouse",
          "weight": 100
        }
      ],
      "pois": [
        {
          "id": "northern_reach:standing_stone",
          "weight": 100
        }
      ]
    }
  }
]

人、家庭以及他们能做什么

8 个系列:enemy_archetypesenemy_variantsgroup_archetypesmercenary_templatesnoble_housesnpc_definitionsperksrelationships

enemy_archetypes

战略级别知道的敌人类型:等级、他们部署的变种、他们扎营的地方、驻军有多大以及他们袭击的频率。

  • 状态 可供使用
  • 文件夹 content/threat/enemy_archetypes
  • id 字段路由的记录
  • 报告 modding_enemy_archetype_report
  • 如果玩家卸载了你 preserve_inert_reference。一个阵营仍然指向它的建立者。替换会悄然改变围困定居点的事物;命名我们读到的缺席。

字段。 此表未命名的字段将随记录一起被拒绝。

场地必要的价值观
id是的文本,id
aggression-从 0 到 1 的数字
behavior_profile_mix-字符串列表
camp_count-0 到 12 之间的整数
camp_glyph-细绳
corruption_chance-从 0 到 1 的数字
description-细绳
display_name-细绳
encounter_id-细绳
garrison_max-1 到 60 之间的整数
garrison_min-1 到 60 之间的整数
preferred_camp_biomes-字符串列表
raid_cooldown_days-0 到 30 之间的整数
sortie_size_max-1 到 30 之间的整数
sortie_size_min-1 到 30 之间的整数
target_preferences-字符串列表
tier-1 到 5 之间的整数
variant_ids-字符串列表
variant_weights-列表

在名为 enemy_archetypes.json 的文件中,或者在该文件夹中您喜欢的任何名称 .json 中:

a enemy_archetypes record, under content/threat/enemy_archetypes

[
  {
    "id": "northern_reach:salt_reavers",
    "display_name": "Salt Reavers",
    "description": "Coastal raiders who winter inland and burn what they cannot carry.",
    "tier": 2,
    "corruption_chance": 0.1,
    "preferred_camp_biomes": [
      "marsh",
      "coast"
    ],
    "camp_count": 3,
    "garrison_min": 8,
    "garrison_max": 16,
    "aggression": 0.4,
    "raid_cooldown_days": 5,
    "sortie_size_min": 4,
    "sortie_size_max": 9,
    "target_preferences": [
      "caravan",
      "settlement"
    ],
    "camp_glyph": "tent"
  }
]

enemy_variants

场上敌人身体类型的统计数据块:类别、等级、五种属性以及武器、副手和其携带的盾牌的 ID。

  • 状态 可供使用
  • 文件夹 content/combat/enemy_variants
  • id 字段路由的记录
  • 报告 modding_enemy_variant_report
  • 如果玩家卸载了你 substitute_placeholder。已经在场上但没有属性块的身体无法进行战斗。引擎所拥有的稳定替代品使战斗可以解决,并且原始ID也被保留下来。

字段。 此表未命名的字段将随记录一起被拒绝。

场地必要的价值观
id是的文本,id
archetype_id是的细绳
agility-0 到 12 之间的数字
ai_behavior-细绳
aim-0 到 12 之间的数字
constitution-0 到 12 之间的数字
display_name-细绳
main_weapon_id-细绳
off_weapon_id-细绳
shield_id-细绳
special_ability_description-细绳
special_ability_name-细绳
strength-0 到 12 之间的数字
tier-1 到 4 之间的整数
variant_class-soldierarcherberserkerrangerfinisher
will-0 到 12 之间的数字

在名为 enemy_variants.json 的文件中,或者在该文件夹中您喜欢的任何名称 .json 中:

a enemy_variants record, under content/combat/enemy_variants

[
  {
    "id": "northern_reach:salt_reaver_archer",
    "archetype_id": "northern_reach:salt_reavers",
    "display_name": "Salt Reaver Archer",
    "variant_class": "archer",
    "tier": 2,
    "strength": 3.0,
    "agility": 5.0,
    "constitution": 3.5,
    "aim": 6.0,
    "will": 2.5,
    "main_weapon_id": "short_bow",
    "ai_behavior": "keeps distance and gives ground rather than trade blows"
  }
]

group_archetypes

生活在世界地图上的群体的可调整策略参数:警告半径、目标偏好、成员数量、补给和撤退阈值。

  • 状态 可供使用
  • 文件夹 content/strategic/group_archetypes
  • id 字段路由的记录
  • 报告 modding_group_archetype_report
  • 如果玩家卸载了你 substitute_placeholder。战略情报必须读取某个地方的阈值。它响应引擎拥有的默认值,这与该系列已经依赖的相同。

字段。 此表未命名的字段将随记录一起被拒绝。

场地必要的价值观
id是的文本,id
aggression-细绳
alarm_radius_px-数字从 0 到 2000
behavior_profile_mix-字符串列表
captain_archetype_id-细绳
display_name-细绳
faction_id-细绳
kind-nonecaravanpatrolarmylaircamp、…
max_members-1 到 60 之间的整数
member_archetype_mix-字符串列表
min_members-1 到 60 之间的整数
night_aggression_multiplier-数字从 0.25 到 4
provisions_max-0 到 99 之间的整数
retreat_hp_pct-从 0 到 1 的数字
target_preference-细绳

在名为 group_archetypes.json 的文件中,或者在该文件夹中您喜欢的任何名称 .json 中:

a group_archetypes record, under content/strategic/group_archetypes

[
  {
    "id": "northern_reach:pilgrim_column",
    "display_name": "Pilgrim Column",
    "kind": "nomad",
    "faction_id": "",
    "target_preference": "wandering",
    "aggression": "avoid_player",
    "alarm_radius_px": 300.0,
    "night_aggression_multiplier": 0.5,
    "min_members": 6,
    "max_members": 14,
    "behavior_profile_mix": [
      "coward",
      "balanced"
    ],
    "provisions_max": 6,
    "retreat_hp_pct": 0.6
  }
]

mercenary_templates

可雇用的雇佣兵模型:姓名、阶级、出身、初始健康状况和士气、雇用成本以及首次出现的日期。

  • 状态 可供使用
  • 文件夹 content/character/mercenaries
  • id 字段路由的记录
  • 报告 modding_mercenary_report
  • 如果玩家卸载了你 preserve_inert_reference。已经雇佣的雇佣兵作为一个单位生活在救援中;只有酒馆列表失去了模板。 id 仍然被命名,因此有机物的来源仍然可以读取。

字段。 此表未命名的字段将随记录一起被拒绝。

场地必要的价值观
id是的文本,id
display_name是的细绳
available_from_day-0 到 999 之间的整数
background-细绳
class_id-细绳
hire_cost-0 到 9999 之间的整数
hp_max-1 到 999 之间的整数
morale_start-1 到 100 之间的整数

在名为 mercenaries.json 的文件中,或者在该文件夹中您喜欢的任何名称 .json 中:

a mercenary_templates record, under content/character/mercenaries

[
  {
    "id": "northern_reach:ditchwater_sapper",
    "display_name": "Ditchwater Sapper",
    "class_id": "skirmisher",
    "background": "Dug siege trenches for whoever was paying, and stopped asking which side it was.",
    "hp_max": 24,
    "morale_start": 70,
    "hire_cost": 180,
    "available_from_day": 6
  }
]

noble_houses

贵族家族的初始数据:领主、继承人、家族所属的定居点以及谁算作竞争对手或盟友。

  • 状态 可供使用
  • 文件夹 content/politics/noble_houses
  • id 字段路由的记录
  • 报告 modding_noble_house_report
  • 如果玩家卸载了你 preserve_inert_reference。玩家对房子的重视程度会记录在他的id上。更换一个就重写,而无需对那些忠诚的人说任何话。

字段。 此表未命名的字段将随记录一起被拒绝。

场地必要的价值观
id是的文本,id
alignment-pro_crownpragmaticisolationisthostileneutralopportunist、…
ally_house_ids-任何人
apex_ambition-任何人
apex_claim_legitimacy-任何人
captain_initial_opinion-0 到 100 之间的整数
captain_initial_stance-hostilesuspiciousneutralwillingallied
castle_id-细绳
corruption_risk-lowmoderatehighcriticalunknown
current_lord_id-细绳
designer_hooks-细绳
display_name-细绳
display_name_key-细绳
family_npc_ids-任何人
heir_id-细绳
house_power_base-任何人
is_defunct-布尔值
is_minor-布尔值
lord_state-healthyailingcorruptedmissingdeadnone
lore_summary-细绳
predecessor_house_id-细绳
rival_house_ids-任何人
secret_flags-任何人
settlement_ids-任何人
steward_npc_id-细绳
strength-dominantstablereducedweakenedvacantextinct

在名为 noble_houses.json 的文件中,或者在该文件夹中您喜欢的任何名称 .json 中:

a noble_houses record, under content/politics/noble_houses

[
  {
    "id": "northern_reach:house_tidewatch",
    "display_name_key": "VALID_NOBLE_HOUSE_MOD_HOUSE_TIDEWATCH",
    "display_name": "House Tidewatch",
    "strength": "reduced",
    "alignment": "isolationist",
    "corruption_risk": "moderate",
    "is_minor": true,
    "lord_state": "ailing",
    "captain_initial_stance": "suspicious",
    "captain_initial_opinion": 35,
    "apex_ambition": 20,
    "apex_claim_legitimacy": 15,
    "house_power_base": 25,
    "lore_summary": "Kept the coast road open for two hundred years and was paid in salt for it."
  }
]

npc_definitions

指定 NPC 的定义。

  • 状态 可供使用
  • 进入 持有它的商人
  • 文件夹 content/narrative/npcs
  • id 字段路由的记录
  • 报告 modding_npc_report
  • 如果玩家卸载了你 preserve_inert_reference。一个拥有被全世界记住的名字的人与一个从未存在过的人是不一样的,报告指向了这个身份。

字段。 此表未命名的字段将随记录一起被拒绝。

场地必要的价值观
id是的文本,id
display_name是的细绳
faction-字符串或整数
flag_keys-字符串列表
is_vendor-布尔值
kill_reputation_delta--100 到 100 之间的整数
location_afternoon-文本,id
location_evening-文本,id
location_morning-文本,id
lore_only-布尔值
need_quest_ids-字符串列表
offers_quest_ids-字符串列表
personal_need-细绳
personality_tags-字符串列表
portrait_id-文本,id
price_multiplier-0.1 到 10 之间的数字
role-字符串或整数
settlement_id-文本,id
short_bio-细绳
starts_hidden-布尔值
title-细绳
vendor_inventory_id-文本,id
voice_tone-细绳

在名为 npcs.json 的文件中,或者在该文件夹中您喜欢的任何名称 .json 中:

a npc_definitions record, under content/narrative/npcs

[
  {
    "id": "northern_reach:wandering_herbalist",
    "display_name": "Wandering Herbalist",
    "title": "Travelling Healer",
    "role": "NONE",
    "settlement_id": "old_seat",
    "is_vendor": true,
    "vendor_inventory_id": "northern_reach:herb_stall",
    "personality_tags": [
      "gentle",
      "secretive"
    ]
  }
]

perks

声明性权限:触发器和效果,无需用代码编写任何处理程序。

  • 状态 可供使用
  • 文件夹 content/character/perks
  • id 字段路由的记录
  • 报告 modding_perk_report
  • 如果玩家卸载了你 preserve_inert_reference。角色会保留他所赢得的东西。删除某个功能会默默地重写玩家在游戏中所花费的建筑物。

字段。 此表未命名的字段将随记录一起被拒绝。

场地必要的价值观
id是的文本,id
skill是的文本,fixed shape
name_key是的细绳
kind是的roadjunctionlateralcapstone
col是的0 到 4 之间的整数
row是的1 到 7 之间的整数
level是的1 到 300 之间的整数
description_key-细绳
icon-文本,id
parents-字符串列表
side-LR

在名为 perks.json 的文件中,或者在该文件夹中您喜欢的任何名称 .json 中:

a perks record, under content/character/perks

[
  {
    "id": "northern_reach:stoneskin",
    "skill": "armour",
    "name_key": "PERK_STONESKIN",
    "description_key": "PERK_STONESKIN_DESC",
    "kind": "lateral",
    "side": "L",
    "col": 0,
    "row": 7,
    "level": 100,
    "parents": [],
    "icon": "northern_reach:stoneskin_icon"
  }
]

relationships

交配模式、有界关系政策、招募条件和声明性纽带。

  • 状态 可供使用
  • 文件夹 content/companion/relationships
  • id 字段路由的记录
  • 报告不是他的; modding_preflight_report 负责处理它
  • 如果玩家卸载了你 preserve_inert_reference。伴侣关系的种子仍然附着在他的身份上,因此删除包裹并不能默默地消除信任、怨恨或遗弃历史。

字段。 该系列包含多个记录类型,并且每种类型都会根据自己的列表进行检查。该表未命名的字段将与记录一起被拒绝。

一条带有kind: bond的记录:

场地必要的价值观
id是的文本,id
kind是的bond
relation是的细绳
subject是的细绳
target是的细绳
initial_regard是的-100 到 100 之间的整数
policy是的细绳
description_key-细绳
name_key-细绳
note_key-细绳

一条带有kind: companion_template的记录:

场地必要的价值观
id是的文本,id
kind是的companion_template
unit是的细绳
recruit是的细绳
loyalty是的细绳
description_key-细绳
leave_below--100 到 100 之间的整数
name_key-细绳
starting_regard--100 到 100 之间的整数

一条带有kind: recruit_terms的记录:

场地必要的价值观
id是的文本,id
kind是的recruit_terms
means是的细绳
cost-0 到 1000000 之间的整数
description_key-细绳
name_key-细绳
requires_bond-细绳

一条带有kind: relationship_policy的记录:

场地必要的价值观
id是的文本,id
kind是的relationship_policy
relation_kinds是的字符串列表
bounds是的目的
bands是的对象列表
decay_per_day-0 到 20 之间的整数
description_key-细绳
max_change_per_event-1 到 50 之间的整数
name_key-细绳

在名为 relationships.json 的文件中,或者在该文件夹中您喜欢的任何名称 .json 中:

a relationships record, under content/companion/relationships

[
  {
    "id": "northern_reach:marsh_policy",
    "kind": "relationship_policy",
    "relation_kinds": [
      "comrade",
      "feud",
      "sworn"
    ],
    "bounds": {
      "floor": -100,
      "ceiling": 100
    },
    "bands": [
      {
        "name": "hostile",
        "from": -100,
        "to": -61
      },
      {
        "name": "cold",
        "from": -60,
        "to": -31
      },
      {
        "name": "wary",
        "from": -30,
        "to": -11
      },
      {
        "name": "neutral",
        "from": -10,
        "to": 10
      },
      {
        "name": "warm",
        "from": 11,
        "to": 40
      },
      {
        "name": "trusted",
        "from": 41,
        "to": 70
      },
      {
        "name": "devoted",
        "from": 71,
        "to": 100
      }
    ],
    "max_change_per_event": 12,
    "decay_per_day": 1
  },
  {
    "id": "northern_reach:hire_terms",
    "kind": "recruit_terms",
    "means": "hire",
    "cost": 240
  },
  {
    "id": "northern_reach:marsh_companion",
    "kind": "companion_template",
    "unit": "northern_reach:marsh_unit",
    "recruit": "northern_reach:hire_terms",
    "loyalty": "northern_reach:marsh_policy",
    "starting_regard": 8,
    "leave_below": -60
  }
]

事物、贸易和冲突背后的数字

5个系列:combat_balancegoodsitemsrecipesvendor_inventories

combat_balance

有界战斗平衡值,无需添加规则、操作或机制即可调整现有解算器参数。

  • 状态 可供使用
  • 文件夹 content/combat/balance
  • id 字段路由的记录
  • 报告 modding_combat_balance_report
  • 如果玩家卸载了你 substitute_placeholder。余额是主机持有的定义数据,而不是玩家的库存。当其包不存在时,规范且稳定的平衡会做出响应,并且随后的加载不会带来保存调整的第二种方式。

字段。 此表未命名的字段将随记录一起被拒绝。

场地必要的价值观
id是的文本,id
values是的目的

在名为 balance.json 的文件中,或者在该文件夹中您喜欢的任何名称 .json 中:

a combat_balance record, under content/combat/balance

[
  {
    "id": "northern_reach:coastal_balance",
    "values": {
      "zone_penalty_head": 22,
      "crit_damage_mult": 1.75,
      "friendly_fire_redirect_chance": 0.2
    }
  }
]

goods

适销对路的商品及其经济特性。

  • 状态 可供使用
  • 旅行过 A good-to-sell
  • 文件夹 content/economy/goods
  • id 字段路由的记录
  • 报告 modding_goods_report
  • 如果玩家卸载了你 preserve_inert_reference。一个侍从说出无人提供的商品的名字,这就是诚实的。取代她会默默地改变一名球员的能力。

字段。 此表未命名的字段将随记录一起被拒绝。

场地必要的价值观
id是的文本,id
base_price-0 到 1000000 之间的整数
category-字符串或整数
daily_consumption_class-细绳
decay_tier-字符串或整数
display_name-细绳
display_name_key-细绳
linked_item_id-细绳
production_class-细绳
tags-字符串列表
weight-0 到 10000 之间的数字

在名为 goods.json 的文件中,或者在该文件夹中您喜欢的任何名称 .json 中:

a goods record, under content/economy/goods

[
  {
    "id": "northern_reach:spiced_wine",
    "display_name": "Spiced Wine",
    "category": "consumable",
    "decay_tier": "preserved",
    "base_price": 12,
    "weight": 0.5,
    "tags": [
      "luxury",
      "drink"
    ]
  }
]

items

库存物品,包括武器和盔甲。

  • 状态 可供使用
  • 路径为 要携带的物品
  • 文件夹 content/inventory/items
  • id 字段路由的记录
  • 报告 modding_items_report
  • 如果玩家卸载了你 preserve_inert_reference。存储库不断命名其中的内容,这是重新安装将其返还给他们的唯一原因。

字段。 此表未命名的字段将随记录一起被拒绝。

场地必要的价值观
id是的文本,id
base_value-整数,0或更大
category-字符串或整数
condition-从 0 到 1 的数字
description_key-细绳
display_name-细绳
display_name_key-细绳
icon_id-文本,id
max_stack-整个、1个或多个
quality_tier-整数,0或更大
rarity-字符串或整数
sellable-布尔值
tags-字符串列表
weight-数量,0个或多个

在名为 items.json 的文件中,或者在该文件夹中您喜欢的任何名称 .json 中:

a items record, under content/inventory/items

[
  {
    "id": "northern_reach:spiced_wine_bottle",
    "display_name": "Bottle of Spiced Wine",
    "category": "CONSUMABLE",
    "rarity": "UNCOMMON",
    "weight": 0.5,
    "max_stack": 10,
    "base_value": 14,
    "sellable": true,
    "tags": [
      "drink",
      "luxury"
    ]
  }
]

recipes

工艺配方:消耗什么、产生什么、在哪里制造、成本多少以及变质的可能性有多大。

  • 状态 可供使用
  • 文件夹 content/economy/recipes
  • id 字段路由的记录
  • 报告不是他的; modding_preflight_report 负责处理它
  • 如果玩家卸载了你 preserve_inert_reference。保存中没有任何内容命名配方:保存命名进程生成的对象,并且该对象的族对其负责。退役的食谱留下的是一个不再提供某些东西的站,这是报告的而不是固定的,因为发明一个替代食谱会将一个没有包提供的物品放在玩家手中。

字段。 此表未命名的字段将随记录一起被拒绝。

场地必要的价值观
id是的文本,id
inputs是的目的
craft_tax_rate-从 0.0 到 1.0 的数字
description_key-细绳
display_name_key-细绳
enhancer_policy-noneconsumedpreserveddamagedtransformed
failure_policy-nonelose_fuellose_catalystlose_alldamaged_output
gold_cost-0 到 9999 之间的整数
legality-legallicensedsuspiciousforbiddenblack_market
optional_enhancer-细绳
output_count-1 到 99 之间的整数
output_good_id-细绳
output_item_id-细绳
quality_policy-fixedmaterial_inputscrafter_skillenhancermaterials_and_crafter
recipe_kind-normalequipmentspecialenhancement
requires_perk_id-细绳
requires_service-细绳
station_fee-0 到 9999 之间的整数
success_chance-从 0.0 到 1.0 的数字
time_cost_minutes-1 到 60 之间的整数
tools_required-字符串列表

在名为 recipes.json 的文件中,或者在该文件夹中您喜欢的任何名称 .json 中:

a recipes record, under content/economy/recipes

[
  {
    "id": "northern_reach:salt_cured_ration",
    "display_name_key": "VALID_RECIPE_MOD_SALT_CURED_RATION",
    "recipe_kind": "normal",
    "inputs": {
      "salt": 1,
      "dried_meat": 2
    },
    "output_item_id": "northern_reach:salt_cured_ration",
    "output_count": 3,
    "requires_service": "kitchen",
    "gold_cost": 4,
    "time_cost_minutes": 20,
    "success_chance": 0.95,
    "failure_policy": "lose_fuel",
    "quality_policy": "material_inputs",
    "legality": "legal"
  }
]

vendor_inventories

商家供应表。

  • 状态 可供使用
  • 进入 持有它的商人
  • 文件夹 content/world/vendor_inventories
  • id 字段路由的记录
  • 报告 modding_vendor_inventory_report
  • 如果玩家卸载了你 drop_optional_presentation。库存得到再生。货架为空的商家是可读状态,并且该行不指向任何其他内容。

字段。 此表未命名的字段将随记录一起被拒绝。

场地必要的价值观
id是的文本,id
display_name是的细绳
entries是的对象列表
buyback_rate-从 0 到 1 的数字
description-细绳
global_price_multiplier-数量,0个或多个
npc_id-细绳

在名为 vendors.json 的文件中,或者在该文件夹中您喜欢的任何名称 .json 中:

a vendor_inventories record, under content/world/vendor_inventories

[
  {
    "id": "northern_reach:herb_stall",
    "display_name": "Herbalist's Stall",
    "npc_id": "northern_reach:wandering_herbalist",
    "global_price_multiplier": 1.0,
    "buyback_rate": 0.4,
    "entries": [
      {
        "item_id": "northern_reach:spiced_wine_bottle",
        "kind": "consumable",
        "daily_stock": 3,
        "price_multiplier": 1.1,
        "restock_days": 2,
        "min_standing": 0
      }
    ]
  }
]

故事、任务和玩家读到的文字

9个系列:dialoguelocalesloremr_linesprogressquest_metadataquest_plansquestsscenes

dialogue

作为记录的对话:图表、其中的笑话以及上面的选择。三种类型共享该系列,kind 表示是哪一种。包编写对话,而不是单词 - 每个击键都是一个语言键 - 每个条件和每个结果都是此构建已经执行的检查或命令。

  • 状态 可供使用
  • 文件夹 content/narrative/dialogue
  • id 字段路由的记录
  • 报告 modding_dialogue_report
  • 如果玩家卸载了你 preserve_inert_reference。保存记录了对话所做的事情——一个已经转移的任务、一个易手的物品、一个学到的真相——而不是对话本身,它在你写东西的那一刻就结束了。当包裹消失时,后果仍然存在,因为它们从来都不是对话的一部分,而且对话也不再被提供。替换它会将单词放入其作者从未写过的角色的嘴中。

字段。 该系列包含多个记录类型,并且每种类型都会根据自己的列表进行检查。该表未命名的字段将与记录一起被拒绝。

一条带有kind: dialogue_graph的记录:

场地必要的价值观
kind是的dialogue_graph
id是的细绳
entry是的细绳
description_key-文本,fixed shape
name_key-文本,fixed shape
speaker-细绳

一条带有kind: dialogue_node的记录:

场地必要的价值观
kind是的dialogue_node
id是的细绳
graph是的任何人
voice是的line
speaker是的细绳
line_key是的任何人
conditions-任何人
description_key-任何人
name_key-任何人
reveals-任何人

一条带有kind: dialogue_node的记录:

场地必要的价值观
kind是的dialogue_node
id是的细绳
graph是的任何人
voice是的narration
line_key是的任何人
conditions-任何人
description_key-任何人
name_key-任何人
reveals-任何人

一条带有kind: dialogue_node的记录:

场地必要的价值观
kind是的dialogue_node
id是的细绳
graph是的任何人
voice是的end
conditions-任何人
description_key-任何人
line_key-任何人
name_key-任何人
reveals-任何人

一条带有kind: dialogue_option的记录:

场地必要的价值观
kind是的dialogue_option
id是的细绳
node是的细绳
label_key是的文本,fixed shape
goto是的细绳
commands-任何东西的清单
conditions-任何东西的清单
description_key-文本,fixed shape
name_key-文本,fixed shape

在名为 gate_toll.json 的文件中,或者在该文件夹中您喜欢的任何名称 .json 中:

a dialogue record, under content/narrative/dialogue

[
  {
    "kind": "dialogue_graph",
    "id": "northern_reach:gate_toll",
    "entry": "northern_reach:gate_open",
    "speaker": "gate_warden",
    "name_key": "TALK_PACK_GATE_TOLL_NAME",
    "description_key": "TALK_PACK_GATE_TOLL_DESC"
  },
  {
    "kind": "dialogue_node",
    "id": "northern_reach:gate_open",
    "graph": "northern_reach:gate_toll",
    "voice": "line",
    "speaker": "gate_warden",
    "line_key": "TALK_PACK_GATE_OPEN"
  },
  {
    "kind": "dialogue_option",
    "id": "northern_reach:opt_pay_the_toll",
    "node": "northern_reach:gate_open",
    "label_key": "TALK_PACK_OPT_PAY",
    "goto": "northern_reach:gate_paid",
    "commands": [
      {
        "step": "pay_coin",
        "coin": 25
      },
      {
        "step": "change_relation",
        "subject": "player",
        "target": "gate_warden",
        "delta": 4
      }
    ]
  }
]

赛程包含12条记录;示出了3个。

locales

玩家读取的单词,采用 CSV 格式,每种语言一列:包自己的密钥,以及包声明覆盖的游戏的密钥。

  • 状态 可供使用
  • 文件夹 content/locale
  • 报告 modding_locale_report
  • 如果玩家卸载了你 preserve_inert_reference。保存会命名记录,而不是说出它的单词,因此在两个会话之间撤回的包需要翻译而不是任何东西。密钥被保留并显示,读起来像是缺失的翻译而不是缺失的内容。

列。 该表未命名的列将随记录一起被拒绝。

柱子必要的价值观
key是的文本,id
en-细绳

在名为 words.csv 的文件中。文件名是地址的一半,行 id 是另一半,因此两个文件可以包含相同的行 id 而不会发生冲突:

a locales file

key,en,it
word_pack:GOOD_FROST_SALT,Frost Salt,Sale di Brina

lore

法典条目:地点、人物、事件、习俗以及世界讲述的故事。上传的条目不是已知条目。

  • 状态 可供使用
  • 文件夹 content/narrative/lore
  • id 字段路由的记录
  • 报告 modding_lore_report
  • 如果玩家卸载了你 preserve_inert_reference。玩家阅读过的法典条目就是他们所看到的内容。拿走它会抹掉他对他所度过的世界的一些了解,并且任务和其他条目都指向该身份。

字段。 此表未命名的字段将随记录一起被拒绝。

场地必要的价值观
id是的文本,id
category是的placepersoneventcustomthing
title_key是的细绳
body_key是的细绳
chronology_index-全部的
citation_key-细绳
content_warnings-字符串列表
era-细绳
relates_to-字符串列表
requires-字符串列表
reveals-字符串列表

在名为 lore.json 的文件中,或者在该文件夹中您喜欢的任何名称 .json 中:

a lore record, under content/narrative/lore

[
  {
    "id": "northern_reach:the_drowned_causeway",
    "category": "place",
    "title_key": "STORY_PACK_DROWNED_CAUSEWAY_TITLE",
    "body_key": "STORY_PACK_DROWNED_CAUSEWAY_BODY",
    "era": "before_the_mark",
    "citation_key": "STORY_PACK_CAUSEWAY_CITATION"
  },
  {
    "id": "northern_reach:the_tide_watch",
    "category": "custom",
    "title_key": "STORY_PACK_TIDE_WATCH_TITLE",
    "body_key": "STORY_PACK_TIDE_WATCH_BODY",
    "relates_to": [
      "northern_reach:the_drowned_causeway"
    ]
  }
]

mr_lines

中世纪现实主义结构化线路,通过文件和线路 ID 而不是 JSON 中的 id 字段进行路由。

  • 状态 可供使用
  • 文件夹 content/medieval_realism/structured
  • 报告 modding_mr_lines_report
  • 如果玩家卸载了你 drop_optional_presentation。一个没有任何意义的色彩笑话。删除它不需要任何成本,保留它会显示一个空字符串。

列。 允许使用此表未命名的列,并且必须是简单值而不是列表或对象。

柱子必要的价值观
line_id是的文本,id
mechanical_hint-细绳
public_label-细绳
public_line-细绳
public_summary_line-细绳
speaker-细绳
tone-细绳
voice-细绳

每条记录至少需要public_linepublic_labelpublic_summary_line之一。

这些名称无论包含什么内容,都会毫无疑问地被拒绝:unsafe_exampleunsafe_reasonaudit_noteexpected_block_reasonscriptsceneresource_path。有些是玩游戏的人写的验证栏,另一些是mod永远不能做的事情到处拒绝的代码形状的名称。一张有记录的记录会被拒绝,而不是被悄悄地删除。

在名为 MR_L03_TAVERN_INN_LINES.csv 的文件中。文件名是地址的一半,行 id 是另一半,因此两个文件可以包含相同的行 id 而不会发生冲突:

a mr_lines file

line_id,tavern_state,speaker_role,tone,public_line,mechanical_hint
northern_reach:tavern_extra_01,evening_rush,innkeeper,welcoming,"Warm bread and a clean cup if you've the coin for it, friend.",food_only

progress

玩家进度记录:目标、安全难度概况以及主机规则内的比赛概况。

  • 状态 可供使用
  • 文件夹 content/player/progress
  • id 字段路由的记录
  • 报告不是他的; modding_preflight_report 负责处理它
  • 如果玩家卸载了你 preserve_inert_reference。当其包不存在时,获得的成就和选择的比赛资料仍会被命名;默默地带走他们会改写球员的历史或比赛合同。

字段。 该系列包含多个记录类型,并且每种类型都会根据自己的列表进行检查。该表未命名的字段将与记录一起被拒绝。

一条带有kind: achievement的记录:

场地必要的价值观
id是的文本,id
kind是的achievement
name_key是的细绳
description_key是的细绳
condition是的对象列表
campaign-细绳
hidden-布尔值
icon-bannerbladecoincrownhandroad、…

一条带有kind: difficulty_profile的记录:

场地必要的价值观
id是的文本,id
kind是的difficulty_profile
name_key是的细绳
modifiers是的目的
campaign-细绳
description_key-细绳
permadeath-布尔值

一条带有kind: run_profile的记录:

场地必要的价值观
id是的文本,id
kind是的run_profile
name_key是的细绳
difficulty是的细绳
campaign-细绳
description_key-细绳
seed_stream-细绳
starting_origin-细绳

在名为 progress.json 的文件中,或者在该文件夹中您喜欢的任何名称 .json 中:

a progress record, under content/player/progress

[
  {
    "id": "northern_reach:hard_tide",
    "kind": "difficulty_profile",
    "name_key": "DIFF_HARD_TIDE",
    "description_key": "DIFF_HARD_TIDE_DESC",
    "modifiers": {
      "enemy_strength_percent": 140,
      "coin_gain_percent": 80
    },
    "permadeath": true
  },
  {
    "id": "northern_reach:tide_run",
    "kind": "run_profile",
    "name_key": "RUN_TIDE",
    "description_key": "RUN_TIDE_DESC",
    "difficulty": "northern_reach:hard_tide",
    "seed_stream": "tide"
  },
  {
    "id": "northern_reach:held_tide",
    "kind": "achievement",
    "name_key": "ACH_HELD_TIDE",
    "description_key": "ACH_HELD_TIDE_DESC",
    "condition": [
      {
        "when": "days_survived",
        "count": 30
      }
    ],
    "icon": "tower"
  }
]

quest_metadata

任务元数据记录,通过 quest_id 而不是 id 进行索引。

  • 状态 可供使用
  • 文件夹 content/narrative/quest_metadata
  • quest_id 字段路由的记录
  • 报告 modding_quest_metadata_report
  • 如果玩家卸载了你 preserve_inert_reference。他描述的任务本身可能已经被简化为墓碑;把它拿走会让他们失去描述而不是消失。

字段。 此表未命名的字段将随记录一起被拒绝。

场地必要的价值观
quest_id是的文本,id
arc_id-文本,id
choice_valence-细绳
consequence_hooks-字符串列表
difficulty_band-细绳
faction_context-细绳
failure_consequence-细绳
moral_pressure-细绳
notification_policy-细绳
novelty_tags-字符串列表
player_model_tags-字符串列表
quest_role-细绳
replay_suppression_key-细绳
reward_intent-细绳
story_turn_role-细绳
urgency_band-细绳
world_reason-细绳

在名为 quests.json 的文件中,或者在该文件夹中您喜欢的任何名称 .json 中:

a quest_metadata record, under content/narrative/quest_metadata

[
  {
    "quest_id": "northern_reach:tavern_errand",
    "world_reason": "settlement_shortage",
    "quest_role": "recovery",
    "difficulty_band": "standard",
    "urgency_band": "soon"
  }
]

quest_plans

作为记录的任务计划:包中写入的弧线、任务、目标和结局,游戏从中构建自己的任务。任务的记录形式,位于手写资源旁边,而不是在其位置。

  • 状态 可供使用
  • 文件夹 content/narrative/quest_plans
  • id 字段路由的记录
  • 报告 modding_quest_plan_report
  • 如果玩家卸载了你 preserve_inert_reference。一项计划构建了与游戏运行相同的任务,因此退役的计划会留下与手写留下的相同的漏洞。进度是玩家无法重建的一件事:未解决的任务被报告并且从未完成或默默取消。

字段。 该系列包含多个记录类型,并且每种类型都会根据自己的列表进行检查。该表未命名的字段将与记录一起被拒绝。

一条带有kind: arc的记录:

场地必要的价值观
kind是的任何人
id是的文本,id
stages是的列表
description_key-文本,fixed shape
name_key-文本,fixed shape

一条带有kind: ending的记录:

场地必要的价值观
kind是的任何人
id是的文本,id
arc是的细绳
requires是的列表
description_key-文本,fixed shape
epilogue_key-文本,fixed shape
name_key-文本,fixed shape

一条带有kind: objective的记录:

场地必要的价值观
kind是的任何人
id是的文本,id
quest是的细绳
goal是的collect_itemdefeat_unitdefend_placedeliver_itemearn_coinescort_unit、…
count-1 到 999 之间的整数
description_key-文本,fixed shape
name_key-文本,fixed shape
optional_step-布尔值
target-细绳

一条带有kind: quest的记录:

场地必要的价值观
kind是的任何人
id是的文本,id
name_key是的文本,fixed shape
giver是的细绳
objectives是的列表
deadline_days-1 到 3650 之间的整数
description_key-文本,fixed shape
forfeits-任何东西的清单
in_arc-细绳
rewards-任何东西的清单

在名为 the_long_winter.json 的文件中,或者在该文件夹中您喜欢的任何名称 .json 中:

a quest_plans record, under content/narrative/quest_plans

[
  {
    "kind": "arc",
    "id": "northern_reach:the_long_winter",
    "name_key": "northern_reach.arc.the_long_winter.name",
    "stages": [
      "northern_reach:bring_the_grain"
    ]
  },
  {
    "kind": "quest",
    "id": "northern_reach:bring_the_grain",
    "name_key": "northern_reach.quest.bring_the_grain.name",
    "description_key": "northern_reach.quest.bring_the_grain.description",
    "giver": "northern_reach:the_reeve",
    "in_arc": "northern_reach:the_long_winter",
    "objectives": [
      "northern_reach:gather_grain",
      "northern_reach:pay_the_toll"
    ],
    "deadline_days": 30,
    "rewards": [
      {
        "grant": "receive_coin",
        "coin": 250
      },
      {
        "grant": "give_item",
        "item": "northern_reach:reeves_seal",
        "count": 1
      }
    ]
  },
  {
    "kind": "objective",
    "id": "northern_reach:gather_grain",
    "quest": "northern_reach:bring_the_grain",
    "goal": "collect_item",
    "target": "northern_reach:winter_grain",
    "count": 40,
    "name_key": "northern_reach.objective.gather_grain.name"
  }
]

赛程包含5条记录;示出了3个。

quests

手写的任务资产,按路线加载,而不是解释为记录。想要自己的使命的包会写 quest_plans。

  • 状态 已检查,尚未安装
  • 文件夹 content/narrative/quests
  • 报告不是他的; modding_preflight_report 负责处理它
  • 如果玩家卸载了你 preserve_inert_reference。进步是玩家无法重建的一件事。未解决的任务会被报告并且从未完成或默默取消。

该族是通过路径加载的,而不是作为记录读取,并且包无法携带它想要的文件;请参阅mod 永远无法做到的事情。相反,应写入 quest_plans

scenes

舞台场景:房间、房间里的人以及按顺序展开的台词。这是唯一脱离玩家控制的内容,这就是为什么永远不会到达 end 的序列会被拒绝而不是播放。笑话和道具的名称取自已发布的列表;这里没有加载戈多场景、资源和脚本。

  • 状态 可供使用
  • 文件夹 content/narrative/scenes
  • id 字段路由的记录
  • 报告 modding_scene_report
  • 如果玩家卸载了你 preserve_inert_reference。保存记录了一个场景所做的事情——选择了一个名字、移动了一个任务、打开了一扇门——而不是记录了它被观看的事实。它在一个会话中播放并结束,因此离开的包会花费场景,而不是观看它的后果。替换它会上演一些作者从未以他所写的名义写过的东西。

字段。 此表未命名的字段将随记录一起被拒绝。

场地必要的价值观
id是的文本,id
beats是的任何东西的清单
cast-任何东西的清单
name_key-任何人
stage-目的
where-细绳

在名为 scenes.json 的文件中,或者在该文件夹中您喜欢的任何名称 .json 中:

a scenes record, under content/narrative/scenes

[
  {
    "id": "northern_reach:tollhouse_wake",
    "name_key": "STAGE_PACK_TOLLHOUSE_WAKE",
    "stage": {
      "room": [
        880,
        600
      ],
      "light": "candle",
      "props": [
        {
          "prop": "bed",
          "at": "bedside"
        },
        {
          "prop": "storage",
          "at": "east",
          "label_key": "STAGE_PACK_BELONGINGS"
        },
        {
          "prop": "light_marker",
          "at": "north",
          "light": "candle"
        },
        {
          "prop": "walkway",
          "at": "bedside",
          "to": "door"
        }
      ]
    },
    "cast": [
      {
        "actor": "northern_reach:tollkeeper",
        "name_key": "STAGE_PACK_TOLLKEEPER",
        "sprite": "default",
        "at": "bedside"
      }
    ],
    "beats": [
      {
        "beat": "lock_player"
      },
      {
        "beat": "fade_in",
        "seconds": 2.0
      },
      {
        "beat": "say",
        "actor": "northern_reach:tollkeeper",
        "line_key": "STAGE_PACK_WAKE_1"
      },
      {
        "beat": "wait",
        "seconds": 0.8
      },
      {
        "beat": "say",
        "actor": "northern_reach:tollkeeper",
        "line_key": "STAGE_PACK_WAKE_2"
      },
      {
        "beat": "play_cue",
        "cue": "northern_reach:door_latch"
      },
      {
        "beat": "walk_to",
        "actor": "northern_reach:tollkeeper",
        "anchor": "door"
      },
      {
        "beat": "remove_actor",
        "actor": "northern_reach:tollkeeper"
      },
      {
        "beat": "show_exit"
      },
      {
        "beat": "unlock_player"
      },
      {
        "beat": "end"
      }
    ]
  }
]

你如何看到和听到一切

7个系列:audioeffectsfontsimagespresentation_bindingsscreensthemes

audio

包携带的声音,由 id 命名:音乐、氛围、效果和声音,每个都指向其自己文件夹中的一个文件,并声明分隔它的角色。

  • 状态 已验证,但目前没有任何内容消费它
  • 文件夹 content/assets/audio
  • id 字段路由的记录
  • 报告 modding_audio_report
  • 如果玩家卸载了你 preserve_inert_reference。保存会命名主题,而不是其上方的声音,因此在两次会话之间撤回的包会消耗气氛而不是东西。参考文献被保留并报告:无话可说的沉默正是这个家庭所要避免的状态。

字段。 此表未命名的字段将随记录一起被拒绝。

场地必要的价值观
id是的文本,id
file是的文本,fixed shape
codec是的oggwav
role是的musicambiencesfxvoice
duration_seconds-数量,0个或多个
sha256-文本,fixed shape
subtitle_key-细绳

在文件 audio.json 中,这是读取此文件夹的唯一文件:

a audio record, under content/assets/audio

[
  {
    "id": "northern_reach:hearth_hum",
    "file": "hearth_hum.wav",
    "codec": "wav",
    "role": "ambience",
    "duration_seconds": 0.25,
    "sha256": "23fc92432963f74bd638f38ea9d7ddb475853f022810bdc8b344269bf43d5830"
  }
]

effects

天气、灰尘、火花和灯光,由主机提供的模型组成。包命名模型并在声明的范围内设置参数;任何地方都没有任何字段带有着色器、场景或脚本 - 这就是允许陌生人的包在无法请求程序的情况下请求启动的原因。

  • 状态 可供使用
  • 文件夹 content/assets/effects
  • id 字段路由的记录
  • 报告 modding_effect_report
  • 如果玩家卸载了你 preserve_inert_reference。保存中没有任何内容命名效果。当群体离开时,空气会恢复到基础游戏所绘制的状态,这会花费一方面的费用,而玩家则不会拥有任何东西。

字段。 此表未命名的字段将随记录一起被拒绝。

场地必要的价值观
id是的文本,id
template是的dust_driftlightning_flashrain_sheetsmoke_columnsnow_driftspark_burst、…
parameters-目的
priority-0 到 100 之间的整数

在名为 effects.json 的文件中,或者在该文件夹中您喜欢的任何名称 .json 中:

a effects record, under content/assets/effects

[
  {
    "id": "northern_reach:moor_drift",
    "template": "dust_drift",
    "parameters": {
      "amount": 64,
      "lifetime": 6,
      "scale": 2,
      "wind": 4,
      "colour": "#c8bfa8"
    },
    "priority": 40
  }
]

fonts

包携带的字体,由 id 命名:文件、绘制它们的大小以及它们携带的字形的语言。相反,封面声称是暴露的,因为缺少某种语言字形的字符不会失败:它会画出小方块,屏幕上读起来就像有人留下了一半的翻译。

  • 状态 已验证,但目前没有任何内容消费它
  • 文件夹 content/assets/fonts
  • id 字段路由的记录
  • 报告 modding_font_report
  • 如果玩家卸载了你 preserve_inert_reference。保存中没有任何内容命名角色。当包离开时,界面将恢复为工具包字体,这是作者必须选择的唯一字体。

字段。 此表未命名的字段将随记录一起被拒绝。

场地必要的价值观
id是的文本,id
file是的文本,fixed shape
format是的ttfotf
sizes是的8 到 96 之间的整数列表
covers是的列表
fallback_font是的细绳
glyphs-列表
oversampling-1 到 4 之间的整数
sha256-文本,fixed shape

在文件 fonts.json 中,这是读取此文件夹的唯一文件:

a fonts record, under content/assets/fonts

[
  {
    "id": "northern_reach:plain",
    "file": "plain.ttf",
    "format": "ttf",
    "sizes": [
      12,
      16,
      24
    ],
    "oversampling": 1,
    "covers": [
      "en"
    ],
    "fallback_font": "Segoe UI",
    "sha256": "613b1d24f9f8b0365a94f01214155af8e87ca72aa6633befd5e0ee05b3dc4122"
  }
]

images

包带来的图像,由 id 命名:图标、肖像和精灵表,每个都指向其自己文件夹内的一个文件。

  • 状态 可供使用
  • 文件夹 content/assets/images
  • id 字段路由的记录
  • 报告 modding_image_report
  • 如果玩家卸载了你 preserve_inert_reference。保存时会命名物体和人物,而不是其中一个的图像,因此停止解析的图像会花费一张绘图而不是任何东西。引用被保留并报告:用另一个包中的艺术替换它会向玩家展示作者没有选择的东西,而默默地删除 ID 会让丢失的图标看起来像一个设计缺陷。

字段。 此表未命名的字段将随记录一起被拒绝。

场地必要的价值观
id是的文本,id
file是的文本,fixed shape
format是的pngwebp
frame_columns-1 到 256 之间的整数
frame_rows-1 到 256 之间的整数
sha256-文本,fixed shape

在文件 images.json 中,这是读取此文件夹的唯一文件:

a images record, under content/assets/images

[
  {
    "id": "northern_reach:salt_pouch",
    "file": "salt_pouch.png",
    "format": "png"
  }
]

presentation_bindings

哪个包资源填充哪个主题的哪个插槽:对象上的图标、单位或图块上的精灵、派系上的横幅,无论是包的内容还是基础游戏的内容。

  • 状态 可供使用
  • 文件夹 content/presentation/bindings
  • id 字段路由的记录
  • 报告不是他的; modding_preflight_report 负责处理它
  • 如果玩家卸载了你 preserve_inert_reference。保存时会命名主题——物体、人物、作品——而不是用什么图像来装饰它,因此停止解析的链接会花费一幅画而不是一件事。参考文献被保留并报告:主题返回到构建已有的艺术,这是没有作者必须选择的唯一答案。

字段。 此表未命名的字段将随记录一起被拒绝。

场地必要的价值观
id是的文本,id
subject是的文本,id
kind是的buildingfactioninterfaceitemregiontile、…
slot是的ambiencebannereffectfonticonportrait、…
cue是的文本,id
alternative_key-细绳

在名为 bindings.json 的文件中,或者在该文件夹中您喜欢的任何名称 .json 中:

a presentation_bindings record, under content/presentation/bindings

[
  {
    "op": "add",
    "id": "northern_reach:cloak_icon",
    "subject": "wool_cloak",
    "kind": "item",
    "slot": "icon",
    "cue": "northern_reach:cloak_plain",
    "alternative_key": "item_wool_cloak_icon_alt"
  },
  {
    "op": "add",
    "id": "northern_reach:cloak_icon_winter",
    "subject": "wool_cloak",
    "kind": "item",
    "slot": "icon",
    "cue": "northern_reach:cloak_snowy",
    "alternative_key": "item_wool_cloak_icon_alt",
    "when": {
      "season": {
        "is": "winter"
      }
    }
  }
]

screens

屏幕布局:哪些部分适合游戏已有屏幕的哪个面板,以及按什么顺序。它有一些此构建绘制的部分,无法添加:一个新屏幕需要小部件、数据源和单击处理程序,它们一起构成一种编程语言。

  • 状态 可供使用
  • 文件夹 content/ui/screens
  • id 字段路由的记录
  • 报告 modding_screen_report
  • 如果玩家卸载了你 preserve_inert_reference。救援中没有任何事情能够命名为处置。它决定在加载包时如何绘制页面,并且页面在离开时恢复到此构建所采用的布局:它会花费一个皮肤,而玩家不会拥有任何东西。

字段。 此表未命名的字段将随记录一起被拒绝。

场地必要的价值观
id是的文本,id
screen是的character_sheet
panels是的目的

在名为 screens.json 的文件中,或者在该文件夹中您喜欢的任何名称 .json 中:

a screens record, under content/ui/screens

[
  {
    "id": "northern_reach:character_sheet",
    "screen": "character_sheet",
    "panels": {
      "header": [
        "header"
      ],
      "left": [
        "vitals",
        "combat"
      ],
      "middle": [
        "attributes",
        "skills"
      ],
      "right": [
        "service",
        "weight",
        "background"
      ]
    }
  }
]

themes

界面调色板作为标记:命名的颜色、大小和间距,以及玩家必须能够读取其对比度的对。绝不是场景、脚本或资源路径。

  • 状态 可供使用
  • 文件夹 content/assets/themes
  • id 字段路由的记录
  • 报告 modding_theme_report
  • 如果玩家卸载了你 preserve_inert_reference。保存中没有任何内容命名主题。当包离开时,界面将恢复为工具包颜色,这是任何作者必须选择的唯一调色板。

字段。 此表未命名的字段将随记录一起被拒绝。

场地必要的价值观
id是的文本,id
tokens是的目的
contrast_pairs-对象列表

在名为 themes.json 的文件中,或者在该文件夹中您喜欢的任何名称 .json 中:

a themes record, under content/assets/themes

[
  {
    "id": "northern_reach:dusk",
    "tokens": {
      "bg_deep": {
        "kind": "colour",
        "value": "#12131a"
      },
      "bg_panel": {
        "kind": "colour",
        "value": "#1b1c26"
      },
      "bg_panel_hi": {
        "kind": "colour",
        "value": "#262838"
      },
      "text": {
        "kind": "colour",
        "value": "#e8e2d0"
      },
      "text_bright": {
        "kind": "colour",
        "value": "#f4efe2"
      },
      "text_mute": {
        "kind": "colour",
        "value": "#6f6a80"
      },
      "border": {
        "kind": "colour",
        "value": "#7f6ab0"
      },
      "border_dark": {
        "kind": "colour",
        "value": "#14151c"
      },
      "border_soft": {
        "kind": "colour",
        "value": "#4a4560"
      },
      "danger": {
        "kind": "colour",
        "value": "#d4564b"
      },
      "success": {
        "kind": "colour",
        "value": "#7fc46a"
      },
      "warning": {
        "kind": "colour",
        "value": "#e0b13c"
      },
      "accent_player": {
        "kind": "colour",
        "value": "#6f97e8"
      },
      "accent_enemy": {
        "kind": "colour",
        "value": "#c94a4a"
      }
    },
    "contrast_pairs": [
      {
        "text": "#e8e2d0",
        "background": "#12131a"
      },
      {
        "text": "#f4efe2",
        "background": "#1b1c26"
      },
      {
        "text": "#e8e2d0",
        "background": "#262838"
      }
    ]
  }
]

玩家控制什么,他观察什么

3 个系列:adaptiveinput_bindingssettings

adaptive

个人资料可查看比赛的进展情况并提出不同的方法。结果是建议,而不是改变:可以起作用的配置文件将是软件包带来的唯一能够在玩家或客人没有要求的情况下改变游戏的东西,并且在差异中它看起来就像一个调整表。输入是已发布的游戏聚合列表,每个聚合都是游戏已经拥有的关于自身的计数或平均值。

  • 状态 可供使用
  • 文件夹 content/player/adaptive
  • id 字段路由的记录
  • 报告 modding_adaptive_report
  • 如果玩家卸载了你 drop_optional_presentation。不保存配置文件名称。配置文件所触及的是一个乘数,每次改变时,活跃的变异器都会重新计算乘数,因此不再查询撤回的包,并且游戏将返回到玩家所选择的内容。没有什么可以保留,所以没有什么可以保留。

字段。 该系列包含多个记录类型,并且每种类型都会根据自己的列表进行检查。该表未命名的字段将与记录一起被拒绝。

一条带有kind: adaptive_profile的记录:

场地必要的价值观
kind是的任何人
id是的文本,id
name_key是的文本,fixed shape
policy是的enemy_compositionevent_cadencehint_frequencypace_economypace_encountersweather_variety
reads是的列表
fallback_policy是的enemy_compositionevent_cadencehint_frequencypace_economypace_encountersweather_variety
confidence_floor_percent-1 到 100 之间的整数
description_key-文本,fixed shape
sample_days-1 到 365 之间的整数

一条带有kind: threshold_set的记录:

场地必要的价值观
kind是的任何人
id是的文本,id
profile是的文本,id
thresholds是的对象列表
description_key-文本,fixed shape
name_key-文本,fixed shape

在名为 adaptive.json 的文件中,或者在该文件夹中您喜欢的任何名称 .json 中:

a adaptive record, under content/player/adaptive

[
  {
    "kind": "adaptive_profile",
    "id": "northern_reach:hard_roads",
    "name_key": "ADAPTIVE_HARD_ROADS",
    "description_key": "ADAPTIVE_HARD_ROADS_BODY",
    "policy": "pace_encounters",
    "reads": [
      "battles_won_ratio",
      "days_survived",
      "party_size"
    ],
    "fallback_policy": "event_cadence",
    "confidence_floor_percent": 60,
    "sample_days": 14
  },
  {
    "kind": "threshold_set",
    "id": "northern_reach:hard_roads_lines",
    "profile": "northern_reach:hard_roads",
    "name_key": "ADAPTIVE_HARD_ROADS_LINES",
    "thresholds": [
      {
        "signal": "battles_won_ratio",
        "above": 80,
        "advise": "raise"
      },
      {
        "signal": "battles_won_ratio",
        "below": 35,
        "advise": "lower"
      },
      {
        "signal": "party_size",
        "below": 3,
        "advise": "lower"
      },
      {
        "signal": "days_survived",
        "above": 60,
        "advise": "hold"
      }
    ]
  }
]

input_bindings

自己的一个动作包,用key自己想要。玩家决定:以他已经分配的组合结束的建议失败,并且该动作没有按钮,因为默默地做其他事情的按钮比什么也不做的按钮更糟糕。

  • 状态 可供使用
  • 文件夹 content/input
  • action_id 字段路由的记录
  • 报告 modding_input_report
  • 如果玩家卸载了你 preserve_inert_reference。重新分配玩家仍然存储在操作 ID 下,因此重新安装包会找到您放置它的按钮。当包离开时,操作本身将从命令映射中删除,因此分配屏幕永远不会列出不响应任何内容的内容。

字段。 此表未命名的字段将随记录一起被拒绝。

场地必要的价值观
action_id是的文本,id
label_key是的细绳
context是的explorationcombatmenuglobal
suggested_keyboard是的细绳
suggested_controller-细绳

在名为 bindings.json 的文件中,或者在该文件夹中您喜欢的任何名称 .json 中:

a input_bindings record, under content/input

[
  {
    "action_id": "northern_reach:call_scout",
    "label_key": "KEY_PACK_CALL_SCOUT",
    "context": "exploration",
    "suggested_keyboard": "f9"
  }
]

settings

玩家可以改变的选项,是宣布的而不是绘制的。一个包说明了选项是什么,它可以有什么值,以及值存在于哪里;该控件由访客构建。任何跨越此边界的东西都不是控件或脚本,这是设置菜单可以在不执行陌生人代码的情况下显示陌生人选项的唯一原因。

  • 状态 可供使用
  • 文件夹 content/settings
  • key 字段路由的记录
  • 报告 modding_settings_report
  • 如果玩家卸载了你 preserve_inert_reference。存储的值保留在其密钥下,因此重新安装包会在玩家留下的位置找到玩家的选择。该软件包留下的是个人资料中的一行无人阅读的内容:它不需要任何费用,并且保留玩家所做的选择。

字段。 此表未命名的字段将随记录一起被拒绝。

场地必要的价值观
key是的文本,id
type是的boolintfloatstringenum
default是的任何人
scope是的installationcampaignpresentation
label_key是的细绳
help_key-细绳
max_length-1 到 4096 之间的整数
maximum-数字
migrates_from-文本,id
minimum-数字
options-字符串列表
requires_restart-布尔值
secret-布尔值

在名为 settings.json 的文件中,或者在该文件夹中您喜欢的任何名称 .json 中:

a settings record, under content/settings

[
  {
    "key": "northern_reach:patrol_density",
    "type": "int",
    "default": 3,
    "minimum": 1,
    "maximum": 9,
    "scope": "campaign",
    "label_key": "OPTION_PACK_PATROL_DENSITY",
    "help_key": "OPTION_PACK_PATROL_DENSITY_HELP"
  },
  {
    "key": "northern_reach:show_road_names",
    "type": "bool",
    "default": true,
    "scope": "presentation",
    "label_key": "OPTION_PACK_SHOW_ROAD_NAMES"
  }
]

控制台快捷键

这些是快捷方式,而不是步骤。 下面的所有内容都在 Mods 屏幕上占有一席之地,这是正常路线的所在,也是下载您的软件包的任何人都会看到的地方。当您进行迭代并且它已经打开时,控制台会更快,并且它仅存在于调试版本中:游戏的已发布副本没有控制台,因此包作者需要的任何内容都不能单独存在于此处。

命令Mod 屏幕上也有同样的情况
modding_open_folder顶部的路径和旁边的按钮
modding_manifest_report状态列以及每行下面的行
modding_<family>_report每个包裹下的计数,以及显示详细信息
modding_preflight_report检查兼容性
modding_roots_reportmodding_safety_report复制报告
modding_reload屏幕上没有按钮。 重新启动游戏会执行相同的操作,并且是发布版本的唯一方法;这使您不必在迭代时重新启动。这是这里唯一的一行,它是一种方便,而不是屏幕已经执行的操作的快捷方式。

modding_manifest_report 开始 — 游戏是否看到您的包裹,处于什么状态? — 然后 modding_preflight_report 对安装的所有内容进行单一判断。然后是个别家庭的报告。

modding_reload 会在不重启的情况下重新读取文件。编辑文件,按 Alt-Tab,输入命令,然后查看结果。它会重建没有被占用的内容——绑定、效果和图像——并列出被保留的系列,因为运行中的存档可能仍在使用这些记录:

what the game prints back

HELD BY THE RUN items: edited files are read on the next load

modding_reload all 再次读取所有内容,用于没有正在进行的游戏的启动屏幕。 modding_condition_report 打印游戏现在可以回答 when 的内容以及不能回答的内容。

命令它告诉你什么
modding_roots_report数据模型的根源和足迹
modding_manifest_reportMod 状态(有效/无效/忽略/冲突)
modding_fingerprint_report确定性保存足迹(save_wired=no)
modding_safety_report安全姿势(行为模式关闭、文件锁定)
modding_preflight_report所有活动模组的绿色/红色判决
modding_packaging_report2 级 PCK/ZIP 检测(默认关闭)
modding_campaign_reportModding_campaign_report [id] - 以只读方式安装的活动;有了身份证,你就可以去那里
modding_condition_report世界上发布什么记录条件
modding_reloadModding_reload [all] - 重读包; all 仅当没有游戏正在进行时
modding_binding_report提交链接:捆绑/拒绝/覆盖
modding_open_folder创建(如果需要)并打开用户的 mods 文件夹

离线工具

这些工具面向作者和发布自动化。它们随公开的 Bonemark checkout 提供;安装已发布 mod 的玩家不需要 Python 或 Godot。如果你正在编写 mod,请从 github.com/tallowgames/Bonemark 克隆匹配的版本,把工作中的 mod 包放在玩家 mods 文件夹之外,然后从该 checkout 运行下面的命令。游戏仍然是运行时的最终权威。

Python 3.10 或更高版本; Godot 仅适用于运行时通道。将您的包保存在播放器 mods 文件夹的外部并尝试复制。

a command line

python tools/modding/new_mod.py --list
python tools/modding/new_mod.py --id my_mod --family goods --family items

它会编写一个在您编写任何内容之前就通过验证的包:预编译的 mod.json、您要求的每个系列的工作记录以及包含接下来两个命令的自述文件。这些记录来自构建已检查这些系列的固定装置,因此停止工作的启动器会导致导致固定装置失败的相同检查,而不是在模型内腐烂。它拒绝写入名为 mods 的文件夹。

a command line

python tools/quality/validate_mod_data.py --root "<mod-root>"
python tools/quality/validate_mod_data.py --strict --root "<mod-root>"

检查 mod.json、系列文件夹、ID、架构、引用、限制和阻止的有效负载。 --strict 将警告转变为失败。

将改装表面与版本进行比较

当游戏发生变化时,请在更新包之前比较存档的表面快照。它包含一个摘要以及每个公共系列的字段和操作,因此结果表明哪个系列发生了变化以及原因:

a command line

python tools/quality/modding_surface_contract.py --json
python tools/quality/modding_surface_contract.py --before "<previous-build>/game/games/bonemark/modding/data/mod_surface_contract.json" --json

区别是 unchangedadditivebreaking。失败原因明确:field_removedrequired_addedtype_changeddefault_changedconstraint_changedoperation_removedroot_changedformat_changedid_field_changedcatalogue_changedfamily_removedcontract_major_changed_without_new_id。兼容修改名称 field_addedrequired_removedoperation_addedfamily_added。不带 --before 的命令还会检查存储的基线。如果当前表面已移动,则审核将失败,直到维护人员检查 tools/quality/modding_surface_contract_changes.json 中准确的之前/之后摘要;重大变更还必须记录每个原因、决定、迁移说明和审核者。有意修改的快照的推广是明确的:

a command line

python tools/quality/modding_surface_contract.py --write-baseline

这是维护者/发布检查; mod作者只需要--before比较,安装已发布包的玩家不需要运行它。

a command line

python tools/modding/mod_test_host.py --root "<mod-root>" --repo-root "<framework-root>" --json

无需启动 Godot 且无需运行任何包,即可读取清单、依赖项、兼容性和加载顺序。

从不打开内容文件。这就是分工:主机回复*这些数据包将被一起加载*,验证器回复*这条记录是正确的* - 但这意味着验证器拒绝的数据包仍然可以在这里干净地组合。对 14 个故意损坏的数据包进行测量,两者在每次拒绝上都不一致:主机暂存所有 14 个空 refused,其中一个携带只有验证器才能找到的 scripts/payload.sh拨号与安全安装不同。 在发布之前执行这两项操作。当测试集分文件夹时重复--root;然后,主机在确定性计划中组成完整的集合。

a command line

python tools/modding/mod_test_matrix.py --repo-root "<framework-root>" --root "<mod-root>" --godot "<godot-exe>" --require-runtime --report "mod_test_matrix.json"

它运行验证器、测试主机、每个系列开箱即用的固定装置以及 Godot 运行时通道。如果没有Godot,请删除--require-runtime;然后报告会说运行时测试被跳过,没有通过。

对于复合集,重复该选项:

a command line

python tools/modding/mod_test_matrix.py --repo-root "<framework-root>" --root "<mod-a>" --root "<mod-b>" --godot "<godot-exe>" --require-runtime

该报告为每个根保留一个结果,并为整个集合添加 composed_set。此块是演示包冲突、重复 ID 和依赖性错误的地方。仅干净的包装并不能证明该套件将被一起装载。该报告还包括 surface_contract、系列合约的当前版本和审计摘要,因此当存储库兼容性快照过时时,矩阵不能为绿色。使用--require-runtime,读取runtime.reachability.loaded_familiesruntime.reachability.reachable_families。第一个表示组成的记录已加载;第二个只有当戈多探测器中针对玩家的真实路径消耗了他们时才会填充。 runtime.reachability.observations 维护每行的包、族、记录 ID、路径和状态,而 unreachable 列出尚未有任何路径的已加载行。一个家族可以被验证和上演,但仍然不存在于 reachable_families 中:“已加载”与“玩家可以到达它”不同。

在构建此页面时,上面的每个命令都会根据工具本身进行检查:脚本必须存在,并且每个选项都必须是可接受的选项。

每个诊断代码

不要按顺序阅读此列表。在这里,您在报告中遇到的代码是一个有答案的问题 - 一个小写的单词,如 asset_missing。将其粘贴到本页顶部的搜索框中。

某些代码属于数据包尚无法到达的机制。我在这里也是一样的:一个你无法触发的代码会花费你永远不会阅读的一行,而一个丢失的代码会花费一个晚上的时间。

代码是什么原因造成的该怎么办
adaptive_brings_a_model试图加载某些东西或到达某个地方的数据包。删除路径或地址并按名称选择已发布的策略。您带来的任何文件都不会上传到此处。
adaptive_fell_back个人资料未到达其楼层并使用其已声明的政策。没有什么可以解决的,除非我永不停歇。该个人资料在他阅读的内容中没有足够的信号,因此他使用了他所说的政策作为后备。
adaptive_invalid该记录不是此构建将加载的记录。阅读代码旁边的判决。列出打破记录的一条规则,每条规则都是要删除的字段、要添加的字段或要更改的单词。
adaptive_over_budget超出声明上限的包裹。该报告将测量值打印在允许值旁边。拆分记录,或删除超出行的条目:上限是屏幕或阅读器可以容纳的内容,而不是建议。
adaptive_text_not_key需要目录键的句子。将短语移至您的语言目录并将其关键字放入该字段中。以 _key 结尾的字段包含一个键;那里的一句话让您的包裹永远以一种语言显示。
adaptive_unknown_step此构建没有的政策、信号或方向。该名称不在该表的已发布列表中。选择其中的一个:列表很短,因为每个条目都是此构建已经完成的事情。
adaptive_unresolved_reference无人提供的命名记录。组合中没有任何内容提供命名的 id。您要么携带它指向的记录,要么依赖携带它的包。
assembly_dangling_reference楼梯、门口或入口命名了此地图不包含的内容。将命名对象添加到此映射,或更正 ID。着陆点不在地图上的楼梯是玩家可以进入但不能退出的楼层,入口不是通道的建筑物是画在墙上的门。两端必须在同一个文件中。
assembly_leaked拆卸释放的节数比组装释放的节数少。您的包中没有任何需要修复的内容,并且包中的任何内容都不会导致该问题。反汇编释放的节点少于汇编所占用的节点,因此某些东西保留了前一个映射的某些部分 - 将其与生成它的映射一起写入。它被视为每次你进入同一个地方时都会增长的记忆。
assembly_missing_aspect布局的强制部分没有生成任何内容,因此无法适应地图。将缺失的部分添加到其图层上并再次导出。该消息指出:可步行矩形位于可步行图层上,碰撞时发生碰撞,地形图块图层必须覆盖地图。一张没有任何可步行的地图是玩家可以进入但不能移动的地方,因此它会被拒绝而不是发布。
assembly_over_budget组装后的形式超出了宣布的屋顶范围。删除消息计数的部分内容,或划分地图。屋顶是根据组装的内容而不是文件的大小来测量的,因此压缩层不会改变任何内容:消息中的数字是机器应该保存的数字。
assembly_refused什么也没建造,因为建造半张地图比不建造更糟糕。修复此运行中的任何其他消息并再次导出。没有任何东西是故意建造的:地图的一半是一个没有围墙的房间,你无法知道是哪一半建造的。
assembly_unreachable_affordance锚地是指没有任何地方可以步行的地方,因此没有人可以到达它所提供的地方。在同一平面上绘制一个可行走的矩形,该矩形接触消息命名的锚点。锚点就是物体本身,演员站在它旁边,所以所有在可步行区域内的柜台都是玩家走过的柜台,而周围没有任何东西的柜台是无人能到达的服务。首先检查楼层属性:楼上的铺位不由下面的房间提供服务。
asset_invalid描述符存在,但此构建拒绝它。判决书说了什么规则。阅读代码旁边的判决。列出打破记录的一条规则,每条规则都是要删除的字段、要添加的字段或要更改的单词。
asset_kind_mismatch调用者请求一种类型,而描述符声明另一种类型。无论如何解决这个问题都会为期待声音的东西提供纹理。绑定槽所采用类型的资源。没有人为某个地区画一幅肖像,因此永远不会绘制出其中的联系,也没有人能说明原因。
asset_missing该软件包已安装,并且未在该 id 下声明任何描述符。资源 ID 不会解析为组合中的任何内容。带上该文件,或将链接指向您的包中实际包含的文件。
asset_package_missing没有已安装的软件包响应 id 命名的命名空间。未安装提供此资源的包。重新安装它,或将插槽绑定到适合已安装包的东西。
audio_cue_refused此版本不记录的声音或播放列表。阅读代码旁边命名的规则并重新编码以遵守它。通常的原因是我们未解码的格式以及超出声明限制的持续时间。
audio_placeholder_used被拒绝或丢失的声音在保留的替代中得到解决,并通知呼叫者。如果你想要的话,没什么可修复的。声音消失了,所以它的类型的替代品发出了声音,并且替代品发出了信号,而不是保持沉默。
audio_refused此版本无法再现声音。判决书说了什么规则。音频文件本身在播放之前就被拒绝了。将其重新编码为声明大小内的声明格式,并将采样率保持在已发布列表中。
audio_stream_overran超出其描述符声明的持续时间的流将在限制处停止。流的长度超过了其插槽允许的长度。缩短它,或者将其移动到预算可以覆盖的位置:超出的流是混音器必须在字中剪切的流。
binding_invalid此构建未建立连接。阅读代码旁边的判决。列出打破记录的一条规则,每条规则都是要删除的字段、要添加的字段或要更改的单词。
binding_missing_alternative玩家在没有任何其他东西携带的情况下无法接收到的信息。肖像和图标需要描述键,台词需要字幕键。添加替代方案:这是玩家直接听到的唯一可访问性规则。
binding_over_budget提交的包裹超出了其中一个总数允许的范围。该报告将测量值打印在允许值旁边。拆分记录,或删除超出行的条目:上限是屏幕或阅读器可以容纳的内容,而不是建议。
binding_placeholder_used一种无人提供的声音,解决了其类型的替代问题。如果你想要的话,没什么可修复的。该链接解析为其插槽的资源类型的替代项,并且报告会说明哪个插槽,因此您可以区分决策和疏忽。
boot_attempt_recorded在作文开始之前就写了一次尝试。没什么可修复的。引导在尝试之前就已写入书面内容,这就是让下一次引导知道出了问题的原因。
boot_last_known_good_offered相反,会提供过去启动的配置文件。失败的作品并不是有效的作品,因此提供了最后一份有效的作品。获取它,然后一次一个地重新安装软件包,以找到破坏所有内容的软件包。
boot_marker_unwritable这次尝试没有被记录。游戏在本次会话中禁用恢复的情况下启动,并如此说明。无法写入启动书签,因此下次您将无法区分崩溃和干净退出。检查游戏data文件夹是否可写;这与你的包裹无关。
boot_package_rejected数据包在恢复期间被拒绝。记录的是 id,而不是路径。该软件包导致游戏无法启动并被排除在外。报告指出了拒绝的原因;修复它并重新安装,或者将其保留。
boot_retry_offered低于限制;再次尝试相同的配置文件。接受重试。如果第二次启动也失败,则问题出在组合而不是时间上,下一次提供的将是安全模式。
boot_safe_mode_offered限额已用尽;该游戏无需任何包即可启动。接受安全模式,然后一次删除一个数据包,直到启动。您的保存不会被触及:安全模式会读取它但不会写入它。
budget_aggregate_exceeded安装的集已超出共享限制。指定的包是按加载顺序传递给它的包。从构图中去掉一些东西。超出上限的是所有包裹,而不是您一个人的包裹,报告会在上限旁边打印总数。
budget_degraded维度被减少而不是被拒绝,并且它被命名为它所折叠的内容。没什么可修复的,除非你另有打算。该作品保持在预算之内,放弃了质量而不是内容:什么都没有丢失,有些东西变小了。
budget_package_exceeded数据包已超出其大小限制。阅读报告中提到的尺寸并剪下其尺寸。在一个包裹允许使用的数量旁边打印出您的包裹已使用的数量。
budget_soft_warning超出软阈值,无论如何加载,报告给那些创建者。目前没什么可修复的。你已经足够接近另一个群体可以超越的上限,并且在其他人之前知道是有帮助的。
budget_unknown_dimension有一份关于此版本未声明的大小的消耗报告,即有人在不存在的表面上书写。预算列出了本次构建无法衡量的内容。从发布的列表中选择一个尺寸 - 我们不测量的尺寸将永远不会被执行。
budget_unknown_profile此版本未声明的配置文件。应用更严格的轮廓而不是更宽的轮廓。从发布的列表中选择预算配置文件。配置文件是选择的而不是描述的,因此我们不发布的配置文件是没有人会强制执行的。
campaign_hardcoded_identity消费者写下基本营销活动 ID,而不是询问选择了哪个营销活动。有些东西会按名称获取基本活动 ID、文本或场景,而不是询问所选活动。通过活动的背景来解决这个问题,否则转化会收到这个世界的响应,而不是它自己的响应。
campaign_invalid该语句不是此构建会选择的语句。阅读代码旁边的判决。列出打破记录的一条规则,每条规则都是要删除的字段、要添加的字段或要更改的单词。
campaign_not_found已为 ID 选择了一个营销活动,但没有任何语句响应该 ID。未安装指定的营销活动 ID。检查你是如何编写它的,或者安装提供它的包:这里它不会依赖于基本的活动。
character_carries_handler命名私有符号的公共数据。删除命名方法或回调的字段。发布内部符号使其成为公共合同,而破坏它的重命名玩家将其报告为游戏破坏。
character_invalid该记录不是此构建将加载的记录。阅读代码旁边的判决。列出打破记录的一条规则,每条规则都是要删除的字段、要添加的字段或要更改的单词。
character_origin_missing一个没有任何人提供出身的角色,充满了后备力量。重新安装编写此源代码的软件包。该角色已为自己加载了保留的后备资源,并且他丢失的 ID 会随身携带,因此重新安装会使他完全恢复原来的样子。
character_tree_unenterable进度树中无法到达的循环或节点。查看报告是否显示循环或孤儿,然后重新连接树的该部分。玩游戏时也不会出现错误 - 该选项根本不会提供,并且文件显示正确。
character_unknown_property对于任何系统来说都没有任何意义的属性。使用此构建具有的属性。接受一个没有的字段会在保存中放置一个字段,该字段对任何系统都没有任何意义,并且永远无法向任何人解释。
combat_carries_formula一个试图提供冲突算术的包。删除该字段。第一级是数据:运行的内容属于游戏,新功能来自受信任的提供商。
combat_effect_expired已保存的状态,其校准已消失,在加载时终止。校准此状态的软件包已不再安装,因此该状态最终被应用为无人拥有的数字。重新安装它以保留它。
combat_invalid该记录不是此构建将加载的记录。阅读代码旁边的判决。列出打破记录的一条规则,每条规则都是要删除的字段、要添加的字段或要更改的单词。
combat_over_budget超出声明上限的包裹。该报告将测量值打印在允许值旁边。拆分记录,或删除超出行的条目:上限是屏幕或阅读器可以容纳的内容,而不是建议。
combat_phase_unreachable一个已写下但从未达到的阶段。两个阶段共享一个阈值,因此其中一个阶段永远不会启动。给他们不同的剩余生命值。
combat_unknown_operation求解器没有的运算或参数。从发布的列表中选择操作并仅为其提供参数。具有价值的推动是误读的路线,而不是更强有力的推动。
combat_unknown_status此版本未发布的状态。校准此构建发布的状态,而不是发明一个状态。一个发明的状态位于一个空白图标后面的单元上,没有什么可以把它夺走。
combat_unresolved_reference无人提供的命名记录。组合中没有任何内容提供命名的 id。您要么携带它指向的记录,要么依赖携带它的包。
conversion_external_reference数据包外部的地址或路径。一个转换指出了它自己的包。带上你所提到的内容,否则全世界都会去寻找你没有写过的内容。
conversion_fallback_allowed这种转换并没有否认基础游戏的后备,无论是在海报还是在战役中。没什么可修复的。这个家庭可以依靠基础游戏,这句话说明了为什么这不是一种逃避。
conversion_family_unclassified内容系列已存在,并且此目录不会对其进行分类。声明该家族归乡村或发动机所有。未排名的家庭是基础游戏逃脱检查根本无法推理的家庭。
conversion_missing_file夹具声明但不具有的文件。声明的转换所需的文件不在包中。带上它:缺少自身一部分的转换开始,然后无法继续。
conversion_partial_atomic_family仅部分提供了原子族。被拒绝而不是发表,但接缝处可见。带上全家人或者根本不带他们。半个任务列表是一个世界,指的是没有人写过的任务。
conversion_required_family_missing一个原本拥有乡村的家庭却缺席了。带上家人。目录说明了转换需要哪些内容,没有它们,世界就只是具有新艺术的基础游戏。
conversion_unclaimed_family软件包为其提供文件但活动未声明的家庭。领取包裹中的家人,或声明推迟并有理由。由于无人认领,没有任何证据表明他的缺席是否是故意的。
conversion_unknown_family该活动宣布了一个该构建不知道的家庭。从内容类型目录中命名一个系列。在任何人提供声明之前,家人都必须在那里声明自己的身份。
conversion_vanilla_leak既不属于转换也不属于引擎的保留命名空间的 id。替换报告命名的 ID、文本或场景。这种转换否定了后备,因此玩家可以选择在另一个世界中看到这个世界。
dialogue_carries_expression尝试运行某些东西或当场写入文字的包。删除该字段。第一级是数据:运行的内容属于游戏,新功能来自受信任的提供商。
dialogue_dead_end玩家无法退出的对话。有一个选项从该节点指向一条到达终点的路径。一个周期就可以了;死循环是玩家无法退出的对话。
dialogue_invalid该记录不是此构建将加载的记录。阅读代码旁边的判决。列出打破记录的一条规则,每条规则都是要删除的字段、要添加的字段或要更改的单词。
dialogue_orphan_node任何事物都无法到达的节点。没有任何内容进入该节点,因此没有玩家会读取它。让他对某个选项下注,或者注销他。
dialogue_over_budget超出声明上限的包裹。该报告将测量值打印在允许值旁边。拆分记录,或删除超出行的条目:上限是屏幕或阅读器可以容纳的内容,而不是建议。
dialogue_text_not_key需要目录键的句子。将短语移至您的语言目录并将其关键字放入该字段中。以 _key 结尾的字段包含一个键;那里的一句话让您的包裹永远以一种语言显示。
dialogue_unguarded_reveal一个没有任何先兆的秘密。在节点上至少设置一个条件。空的条件列表算作“无”:秘密将属于打开对话的任何人。
dialogue_unknown_step此版本没有的控件或命令。该名称不在该表的已发布列表中。选择其中的一个:列表很短,因为每个条目都是此构建已经完成的事情。
dialogue_unresolved_reference无人提供的命名记录。组合中没有任何内容提供命名的 id。您要么携带它指向的记录,要么依赖携带它的包。
distribution_hash_mismatch磁盘上的文件不是记录所描述的。光盘上的软件包不是发布的软件包。重新下载:不匹配是指传输出错或文件被其他人更改。
distribution_invalid该记录不是该版本可以接受的记录。阅读代码旁边的判决。列出打破记录的一条规则,每条规则都是要删除的字段、要添加的字段或要更改的单词。
distribution_offline根据安装时记录的内容检查出处。检查您的连接,然后重试。已安装的软件包继续工作;在服务恢复之前不会出现新的情况。
distribution_reported有人举报了。玩家收到通知并做出决定。阅读报告并做出决定。该包的工作原理是相同的:报告存在,以便决策是在它前面而不是在它的位置上做出的。
distribution_revoked包裹被隔离或报废。它无法安装。取出包装。发表后被撤回,不再上传;如果是你写的,撤销通知会说明原因。
distribution_update_deferred有一个新版本可用,并且针对旧版本的活动正在进行中。重新启动以获取更新。在正在进行的游戏下交换包是保存开始命名无人提供的东西的方式。
economy_expression_refused一个可以带来一些评估的领域。价格条目试图带来一些有价值的东西。从该构建实现的四个曲线中按名称选择一条曲线:可以执行的一个价格是通过经济达到的 1 级边界。
economy_invalid该记录不是此构建将加载的记录。阅读代码旁边的判决。列出打破记录的一条规则,每条规则都是要删除的字段、要添加的字段或要更改的单词。
economy_out_of_bounds超出规定范围的数字。返回声明范围内的数字。这里的每个数字字段都有一个,没有声明范围的字段将被拒绝而不是允许通过。
economy_overridden一个包替换了另一个包或基础游戏声明的记录。没什么可修复的。该记录是由另一个包获取的,报告会说明是哪个包,因此您可以确定这是否是有意的。
economy_unresolved_reference一种配方或罐子,其名称无人提供。组合中没有任何内容提供命名的 id。您要么携带它指向的记录,要么依赖携带它的包。
effect_carries_source命名着色器、场景或代码的描述符。删除命名着色器、脚本或场景的字段。效果由引擎原语组成;提供源码就是提供程序。
effect_degraded一种缩小到适合框架内部的效果,这样命名就不是什么神秘的事情了。没什么可修复的,除非你另有打算。为了保持在帧预算之内,效果会降低质量:它仍然存在,而且更小。
effect_dropped一种根本不存在的效果。看看预算声明中所说的规模是多少,然后削减它。框架空间不足,根本没有绘制出这种效果。
effect_refused此版本不会产生效果。判决书说了什么规则。读取报告中指定的参数,并在其旁边打印的范围内报告该参数。在任何东西绘制之前,效果就被拒绝了。
extension_forbidden_field清单包含任何扩展都无法携带的字段,例如脚本、解析器或私有导入的路径。删除该字段。脚本、求解器、私有导入或项目设置更改的路径超出了来宾中的合同,并且需要它的扩展正在请求功能而不是声明功能:在 requires 下声明功能。
extension_foreign_namespace声明的状态命名空间不是扩展的包 ID,因此一旦它消失,它的状态就无法归因。state_namespace 重命名为扩展的包 ID。一旦包裹消失,其他地方写的状态就无法归属或删除,并且客人保留他们的名字。
extension_missing_field缺少访客需要安装、获取印模、返回或删除扩展的字段。将字段添加到扩展清单中。其中每一个都是客人在订购扩展、将其放入合成足迹、返回或再次删除之前需要的东西:一张缺少海报的海报描述了客人可以安装但永远不会删除的功能。
extension_teardown_incomplete删除扩展所返回的内容少于所花费的内容,这使得它在下次安装时丢失,而不是现在。返回扩展在声明完全反汇编之前获取的所有内容,如果真实数字已更改,则更新 takes。返回 less 现在不会失败:它会在下一次安装时丢失,并且在一个会话中安装相同的扩展两次是很常见的。
extension_unbounded规定的预算缺失或不是数字,因此没有任何东西可以超越它。为合同指定的每个预算写一个数字。被省略或写成句子的预算,读起来与规定的一样,并且不与任何内容进行比较,因此扩展永远不会超过它。
extension_unknown_capability该扩展需要或提供此版本未发布的功能。将技能 ID 与此版本发布的技能 ID 进行比较,并删除或重命名任何不匹配的内容。在安装之前拒绝是有意的:在旋转时发现缺失能力的扩展会在玩家面前发现它。
extension_would_add_autoload清单将添加一个全局变量。拒绝信任级别所说的任何内容,因为可以添加信任级别的软件包将撤消此构建所基于的撤退。从清单中删除自动加载、单例或基本自动加载名称。任何级别的信任都不允许这样做:此构建所依赖的所有迁移都是退休全局变量,因此可以添加变量的扩展将从外部撤消它。将状态放在扩展命名空间下,并通过其发布的功能到达来宾。
font_locale_fallback所选字符不携带的字形,从后备中绘制并报告。您提供的字体没有这种语言的字形,因此后备绘制了它。带上覆盖该语言的字体,否则文本是小方块。
font_refused此版本不使用的角色。判决书说了什么规则。字体文件被拒绝。检查格式是否是我们上传的格式之一,并且文件不包含任何程序。
image_bomb_refused请求超出解码预算的标头在任何解码器看到它之前就被拒绝。图像解压缩后的大小远远大于文件显示的大小。重新导出它的真实大小:在解码之前被拒绝,因为解码它是损坏的。
image_frame_grid其声明的网格不能精确划分的工作表。精灵表的框架并未精确划分其尺寸。调整网格,否则第一帧之后的每一帧都会被其余帧移动。
image_hash_mismatch描述符验证后字节发生变化。该图像不是广告中的图像。重新导出或重新声明:不匹配意味着文件和清单在移植内容上不一致。
image_placeholder_used被拒绝或丢失的图像在保留的替代中得到解决,并通知呼叫者。如果你想要的话,没什么可修复的。图像丢失,并绘制了其类型的替代品,并标记了替代品而不是留空。
image_refused此构建无法解码的图像。判决书说了什么规则。重新导出为报告指定的大小、格式和预算。该图像在绘制之前就被拒绝了。
inference_cancelled执行超出了其延迟预算并被停止。启发式应答,因此呼叫者无需等待。如果预算确实太紧张,可以缩小模型,或者提高 max_latency_usec。执行超出了预算并被停止,启发式响应而不是让调用者等待:等待的帧是玩家查看的帧。
inference_digest_mismatch模式的字节不是记录的字节,这使其成为一种不同的模式而不是较旧的模式。将声明的摘要更新为您要移植的模型的 SHA-256,或者移植摘要命名的模型。不同的字节意味着这是不同的模型,并且没有其他方法可以区分。
inference_forbidden_field该声明包含运行时、脚本、端点、某些遥测或权限声明。删除该字段。适配器属于引擎,因此包提供权重,但不提供执行权重的代码;端点会将模型放置在审查后可以更改的位置,遥测技术将报告玩家的要求。带上重物,让发动机来完成。
inference_load_refused该语句很好,并且此构建没有将其加载到推理适配器中,因此确定性启发式响应。您的包裹中没有任何需要修复的内容。此构建不携带任何推理适配器,因此不会加载任何格式的模型并且确定性启发式响应。无论如何,该声明都会经过验证,因此今天移植的模型是适配器无需修改即可加载的模型。
inference_missing_field模型声明缺少适配器在执行花费任何内容之前所需的内容。将字段添加到模型声明中。每一个都是适配器在运行之前需要的东西:摘要是模型的身份,模式是您提供给它的内容以及它将接受的内容,平台是允许测试它的地方。
inference_output_rejected该模型的响应与规定的输出模式不匹配,因此被丢弃而不是宽容地解释。将模型返回的内容与声明的输出模式进行比较。几乎正确的答案会被丢弃,而不是被宽容地解释,因为以错误形式通过的提案会被随后的每次检查视为有效。
inference_unbounded规定的限制缺失或不是数字,因此任何东西都不能超过它。为合同指定的每个限制写一个数字。省略的限制或用文字写成的限制,按规定读取,并且不与任何内容进行比较,因此出现错误的执行是无人测量的。
inference_unknown_format模型格式不是引擎适配器实现的格式。以引擎适配器实现的格式之一重新导出模型。不实现的格式并不是一条慢路:它什么都不是。
inference_wrong_platform该模型没有声明此平台,因此确定性启发式响应。如果需要的话,没什么可修复的。模型没有声明这个平台,所以确定性启发式在这里做出了回应;仅当模型已实际构建并测试时,才将平台添加到声明中。
input_binding_conflict建议的键已分配。现有的分配保留了它,并且提示被记录下来而不是强制执行。您的包裹中没有任何东西需要修理,也没有任何东西被取出。该按钮已被分配,因此玩家的分配保留了它,并且您的操作在分配屏幕中没有按钮的情况下提供。如果您希望继续安装,请选择一个不太拥挤的默认值。
input_binding_orphaned重新分配属于未安装的软件包声明的操作。保留而不是删除,因此重新安装它会发现它位于玩家离开的位置。没什么可修复的。重新分配属于未安装的包声明的操作,并且会保留而不是删除,因此重新安装包会找到玩家离开的按钮。
input_core_action指定或试图替换主机操作之一的包。重命名该动作。游戏动作属于宿主,包既不能声明也不能替换它;拿pause玩一个你无法逃脱的游戏。在旁边声明你的行动并让玩家分配两者。
input_forbidden_field该声明包含对设备、监听器、火把或玩家无法更改的任务的直接读取。删除该字段。声明一个动作就是整个界面:直接读取设备、安装监听器、开火或强制执行任务,所有这些都会让玩家失去决定权,并且在他们可能检查的每个屏幕中都是不可见的。
input_foreign_namespace操作 ID 不适合声明它的包的命名空间。将操作 ID 重命名为您的包命名空间。玩家重新分配是附加到我们身上的,因此属于其他人的 id 是一个重新分配,当两个包之一被删除时,它会更改 master。
input_keyboard_unreachable该操作没有键盘分配,因此没有控制器的玩家无法访问它。在控制器分配旁边编写键盘分配。对于没有垫子的玩家来说,只有垫子的任务是无法完成的,而在没有垫子的情况下也可以玩的游戏,对他来说,它会默默地失败。
input_missing_field操作语句缺少分配屏幕或重新分配所需的内容。将字段添加到操作声明中。每一个都是屏幕所需要的:标签键是指派列表中显示的内容,而不是您的内部 ID,上下文是告诉游戏该操作何时有效,而不是在有人输入保存名称时触发它。
input_reserved_chord包请求属于系统或窗口的组合。选择另一个键。关闭窗口、退出游戏,平台密钥属于操作系统,持有该密钥的包可以防止某人退出。
input_unknown_context声明的上下文不是此构建发布的上下文,因此没有人知道该操作何时处于活动状态。选择已发布的上下文之一。没有人知道一只股票在未发布的环境中何时处于活动状态,因此它要么永远不会触发,要么总是会触发,这两者都不是您的意思。
lore_invalid该记录不是此构建将加载的记录。阅读代码旁边的判决。列出打破记录的一条规则,每条规则都是要删除的字段、要添加的字段或要更改的单词。
lore_player_state_in_definition描述定义中找到的玩家的字段。删除该字段。传说记录是一个定义,玩家所知道的是:加载传说永远不会授予知识,因此声称这样做的字段将是一个没有人阅读的字段。
lore_replaced包替换了现有条目,保留其 ID 和链接。没什么可修复的。另一个包替换了这个条目并保留了它的 id,因此指向它的所有内容仍然指向某个东西。
lore_unresolved_referencerelated_to 中的 id 揭示或要求无人提供。组合中没有任何内容提供命名的 id。您要么携带它指向的记录,要么依赖携带它的包。
lore_verbatim_text文本代替目录键,因此它只会以一种语言出现。以 _key 结尾的字段包含一个短语。将其移至您的语言目录:绕过此处的所有其他检查,仅将您的知识转化为一种语言。
map_bad_layer_data不覆盖其所属地图的图层。重新导出未压缩的图层,没有块,也没有短行。我们接受的子集是我们知道如何控制的子集。
map_carries_path命名要加载或运行的内容的映射。删除指向文件的字段。地图从套件中为其图块命名;路径是数据包离开自身的方式。
map_duplicate_anchor两个对象声明相同的 id。两个锚点共享一个名称,因此某物附加到哪一个取决于阅读顺序。重命名一个。
map_invalid该地图不是此构建将组装的地图。阅读代码旁边的判决。列出打破记录的一条规则,每条规则都是要删除的字段、要添加的字段或要更改的单词。
map_kit_mismatch针对此版本没有的套件设计的地图。该地图是根据与此版本发布的不同的套件编写的。根据当前套件重新导出它:角色和类别已移动。
map_layer_missing强制级别缺失或设计不当。添加合同要求的级别。该套件的项目文件列出了它们,其中缺少一张加载时带有洞的地图。
map_normalization_failed该地图没有产生任何规范形式。删除报告命名的结构,然后再次导出。如果没有规范形式,您就无法证明运行时和离线验证器在此映射上一致。
map_outside_package来自包外部的图块集或模板。地图指向它自己的包之外的东西。将其带入,否则地图取决于安装的内容。
map_over_budget地图标准化超出了规定的限制。该报告将测量值打印在允许值旁边。拆分记录,或删除超出行的条目:上限是屏幕或阅读器可以容纳的内容,而不是建议。
map_unresolved_reference没有人提供的命名 ID。组合中没有任何内容提供命名的 id。您要么携带它指向的记录,要么依赖携带它的包。
map_unsupported_subset文件中的某些内容不属于格式的子集。该文件使用此构建读取的子集中的 Tiled 函数:折叠图层、图像图层、组、块或多边形。复出口无。
pack_claims_host_surface自动加载、输入操作或项目设置。覆盖内容而不是文件。包添加和替换内容;游戏本身启动所需的表面并不在其中。
pack_collision另一个包已经拥有的声明。放弃两个包之一中的文件。报告中提到了他们两人的名字,如果保留这样的名字,就会赢得装配令。
pack_mount_failed他没有安装发动机;他没有安装发动机。之前的设置仍然有效。该包根本无法组装。检查存档是否完整且采用此构建读取的格式。
pack_replaces_vanilla基础游戏具有的声明。覆盖内容而不是文件,或请求可信替换功能。替换基础游戏文件不是数据包所做的事情。
pack_restart_required组装起来的整体会发生变化,而变化在这个过程中无法生效。此更改无法应用于正在运行的游戏。重新启动:在游戏中交换已安装的内容会使一半的游戏读取旧文件。
progress_invalid该记录不是此构建将加载的记录。阅读代码旁边的判决。列出打破记录的一条规则,每条规则都是要删除的字段、要添加的字段或要更改的单词。
progress_origin_lost获得的成就的包已消失、保存并命名。没什么可修复的。声明该包裹已消失,而玩家获得的包裹仍然存在;身份证就在那里,所以他知道什么能让他回来。
progress_over_budget超出声明上限的包裹。该报告将测量值打印在允许值旁边。拆分记录,或删除超出行的条目:上限是屏幕或阅读器可以容纳的内容,而不是建议。
progress_reaches_outside试图做某事或代表平台发言的包。删除该字段。里程碑是否到达平台取决于其名称空间,而不是记录所说的内容。
progress_reserved_namespace一个包声明了一个不属于它自己的命名空间。使用您的包名称空间。保留的是我们的,人们会相信似乎来自平台的目标。
progress_text_not_key需要目录键的句子。将短语移至您的语言目录并将其关键字放入该字段中。以 _key 结尾的字段包含一个键;那里的一句话让您的包裹永远以一种语言显示。
progress_unknown_step此构建不具备的条件或修饰符。该名称不在该表的已发布列表中。选择其中的一个:列表很短,因为每个条目都是此构建已经完成的事情。
progress_unresolved_reference无人提供的命名记录。组合中没有任何内容提供命名的 id。您要么携带它指向的记录,要么依赖携带它的包。
provider_forbidden_capability一个包需要一种没有级别授予的功能,例如文件系统、网络或进程。去掉容量。没有级别授予另一个包的文件系统、网络、进程或命名空间,并且没有修订或签名改变这一点:构建对文件系统的操作不是任何人都可以通过读取它来控制的属性。使用 propose_intent 将提案传递给规范所有者,并使用 write_own_namespace 传递必须生存的状态。
provider_native_extension_refused找到了本机扩展。在任何策略推出之前,它对整个流程拥有完全的权限,因此它会因其自身原因而被拒绝,而不是因为信任检查失败。从包装中取出扩展件。在该策略的任何部分运行之前,引擎会加载具有对该进程的完全权限的 GDExtension,因此它会因其本身而被拒绝,而不是由谁签署,并且批准供应商级别不会更改该响应。
provider_tier_inactive行为提供者层在此版本中未得到批准,因此未加载任何可执行文件。您的包裹中没有任何需要修复的内容。此版本尚未批准行为供应商层,因此无论谁签署脚本、打包场景或本机扩展都会被拒绝。如果已发布的系列之一可以携带该机制,则将该机制作为声明性记录,并在向供应商写入反对该级别之前阅读批准该级别的版本的发行说明。
provider_unknown_capability一个包要求提供此版本未发布的功能。从清单中删除该功能,或将其替换为此版本发布的功能。该列表故意简短:没有人发布的权限是主机无法推理的权限,因此它被拒绝而不是被忽略。
provider_unknown_load_kind一个软件包提供了此版本未排名的东西。拒绝而不是被视为数据,因为这里的假设错误就是在执行它的方向上出错。将包提供的内容与此构建分类的四种类型进行比较:声明性数据、打包场景、脚本或本机扩展。任何其他的事情都是拒绝而不是猜测,因为这里的猜测意味着猜测执行的方向。
provider_untrusted该包处于不加载任何内容的受信任状态,这是每个包开始时的状态。包中没有任何需要修复的内容,包本身也无法修复任何内容。信任附加在确切的字节上,并且是玩家提供的,因此从他选择的来源安装软件包并让他确认;已撤销的摘要不会因再次检测到而再次变得可信。
provider_user_trust_required该级别允许这样做,但还没有一个人对这个确切的内容表示同意。将玩家带到模组列表并让他们确认此包。该级别允许这样做,而且还没有人对这一确切内容表示同意,这是签名故意不取代的唯一步骤。
quest_already_applied已经执行过的命令。没什么可修复的。该命令已经执行并且没有重复,这可以防止重新加载两次支付奖励。
quest_carries_expression试图做某事或为自己保留“一次”响应的数据包。删除该字段。第一级是数据:运行的内容属于游戏,新功能来自受信任的提供商。
quest_ending_unreachable一个无人能达到的结局。结局需要完成其故事线中不包含的任务。将任务添加到弧线的各个阶段,或请求那里的任务。
quest_invalid该记录不是此构建将加载的记录。阅读代码旁边的判决。列出打破记录的一条规则,每条规则都是要删除的字段、要添加的字段或要更改的单词。
quest_nothing_applied一个计划被拒绝了,所以什么都没有执行。该集合中的某些内容被拒绝,因此没有应用任何内容。将任何拒绝的情况写在报告中:半张弓是一种无人能描述的状态。
quest_over_budget超出声明上限的包裹。该报告将测量值打印在允许值旁边。拆分记录,或删除超出行的条目:上限是屏幕或阅读器可以容纳的内容,而不是建议。
quest_text_not_key需要目录键的句子。将短语移至您的语言目录并将其关键字放入该字段中。以 _key 结尾的字段包含一个键;那里的一句话让您的包裹永远以一种语言显示。
quest_unfinishable一项无人能完成的使命。为任务提供至少一个非可选目标,否则任务一接受就完成。
quest_unknown_step此构建没有的目标或让步。该名称不在该表的已发布列表中。选择其中的一个:列表很短,因为每个条目都是此构建已经完成的事情。
quest_unresolved_reference无人提供的命名记录。组合中没有任何内容提供命名的 id。您要么携带它指向的记录,要么依赖携带它的包。
relationship_band_gap具有没有带命名的值的区间。仅使用已发布的范围名称,覆盖保单的整个范围,从地板到屋顶,没有漏洞,也没有重叠。孔中的值是任何屏幕都无法命名的值。
relationship_carries_behaviour_code尝试提供报告更改时执行的内容的包。删除该字段。第一级是数据:运行的内容属于游戏,新功能来自受信任的提供商。
relationship_declares_live_state一个试图说明一段关系现在处于什么位置的包裹。相反,声明初始值。一段关系现在所处的位置是一个运行时间的问题,是玩家改变了它。
relationship_invalid该记录不是此构建将加载的记录。阅读代码旁边的判决。列出打破记录的一条规则,每条规则都是要删除的字段、要添加的字段或要更改的单词。
relationship_leave_unreachable永远不能离开,或者立刻离开的同伴。将放弃门槛纳入政策范围。在场上你永远不会失去你的伙伴;第一天晚上他就到了屋顶上。
relationship_origin_lost宣布债券的一揽子计划消失了,演变的价值仍然存在。没什么可修复的。声明该包裹已消失,而玩家获得的包裹仍然存在;身份证就在那里,所以他知道什么能让他回来。
relationship_pair_collision一对整洁的夫妇曾两次声明,但没有任何联系就离开了。两条记录声称具有相同的有序对。删除一个:保留两个将使先加载的包获胜。
relationship_unknown_relation此构建没有的一种关系或招募途径。从发布的列表中选择一个关系。这个版本没有的东西将会被夷为平地,你写的故事也不会发生。
relationship_unresolved_reference无人提供的命名记录。组合中没有任何内容提供命名的 id。您要么携带它指向的记录,要么依赖携带它的包。
resolution_cache_invalidated物品掉落是因为其供应商不再活跃。没什么可修复的。组成已更改,因此 id 解析的内容已重新计算而不是重用。
resolution_missing没有人提供 ID,也没有什么可以依靠的。重新安装提供该 ID 的软件包,或者更正该 ID。报告会保留它,以便您了解发生了哪两件事。
resolution_over_budget超出规定预算的一揽子计划或流程。该报告将测量值打印在允许值旁边。拆分记录,或删除超出行的条目:上限是屏幕或阅读器可以容纳的内容,而不是建议。
resolution_refused此构建没有提出请求。阅读报告提到的规则并将 ID 更改为该地点接受的内容。
resolution_restart_required无法下载旧字节的配置文件更改。该 id 解析的内容会以运行游戏无法遵循的方式进行更改。重新启动即可获取。
resolution_tombstoned包已删除的已知 ID。重新安装该软件包以使逻辑删除恢复到真实内容。 id 解析为它的墓碑,而不是什么都没有,这就是为什么重新安装可以让玩家找回他们的东西。
save_campaign_absent未安装进行保存的营销活动。安装救援命名的活动。救援不是针对另一个人展开的,因为那将是另一个世界的悄无声息。
save_composition_matches救援记录中的任何东西都没有移动。没什么可修复的。用于进行此保存的包是已安装的包。
save_content_absent未安装保存名称的内容。据报道,非致命。重新安装报告列出的软件包。 ID 保留在保存中,因此现在没有答案的内容将再次得到答案。
save_orphan_state_carried没有任何所有者安装的状态,结转而不被执行。重新安装该软件包以使该状态再次有意义。它被保留而不是被精确删除,以便它能够发挥作用。
save_provider_contract_moved救援所依赖的能力现在响应不同的合同。查看报告是否显示已迁移、忽略或拒绝。供应商的合同版本在保存和现在之间发生了变化,这就是三个响应。
save_write_beside_original会话写入了一个新文件,并保留了原始文件。没什么可修复的。恢复的保存写入在原始文件旁边而不是顶部 - 安全模式永远不会覆盖无法打开的文件。
selection_campaign_missing未安装所请求的营销活动,也未在其位置上编写任何内容。安装在消息中提供活动 ID 的软件包,或启动另一个活动。该 id 是所要求的内容,按照要求编写,因此请将其与包的 Campaign.json 中的 id 进行比较。没有任何内容被加载到它的位置:启动基础游戏将会以你所写的名字给你一个不同的世界。
selection_made选择了一项活动,并说明了这样做的原因。没什么可修复的。这句话说明了这个游戏是什么世界以及为什么选择它,当世界不是你所期望的那样时,它值得一读:原因告诉你它是被请求的,被恢复的,还是唯一安装的。
selection_safe_mode数据包被遗漏,要么是在启动失败后,要么是因为玩家要求这样做。在进行更改之前先阅读原因。 player_asked 表示您选择了它并且没有任何问题。 boot_failed 意味着该活动多次启动失败:停用最近安装的模组,启动一次,然后一次放回一个。在安全模式下,不会组成数据包,因此此处有效的匹配表明缺陷存在于数据包中。
selection_save_preserved恢复的保存写在原始保存的旁边而不是上面。没有什么需要修复的,也不要删除第二个文件。恢复将其结果写在您的保存旁边而不是上面,因此该消息命名了两个路径:原始路径是没有 .recovered 后缀的路径,并且它仍然与原来一样。
setting_invalid该声明不是此构建将绘制的声明。阅读代码旁边的判决。列出打破记录的一条规则,每条规则都是要删除的字段、要添加的字段或要更改的单词。
setting_migrated一个值在旧密钥下到达并被移植到当前密钥。没什么可修复的。设置更改为当前形式,旧值已落后。
setting_owner_missing存储的值属于未安装的包。保留,未应用。指定该设置的声明所有者。此版本所没有的一个设置是没有人会阅读的。
setting_restart_required该值已更改,直到下次启动才能生效。重新启动以应用它。游戏运行时该设置无法更改。
setting_secret_withheld秘密已从保存或报告中排除。没什么可修复的。标记为秘密的值已被排除在报告之外,这就是可以将报告粘贴到错误线程中的原因。
setting_value_refused超出声明允许范围的值。而是使用默认值进行响应。输入旁边打印的范围内的值,或从发布的列表中选择一个。报告显示了两者。
settlement_building_unresolved一座被保存的建筑,其包裹已经消失,只是被命名而不是被替换。重新安装消息提到的软件包以恢复建筑物,或者不理会它:什么都没有丢失。该建筑仍在其 ID 下的保存中,并且故意不替换为该建筑中最接近的建筑,否则会将其他人的货物放入您从未建造过的熔炉中。
settlement_carries_path命名场景、脚本或自身位置的记录。删除该字段并命名一个 id。内部是内部记录的 ID,而不是场景的路径,建筑物是通过命名地图上的对象而不是携带其自己的坐标来放置的。位置字段因第二个原因而被拒绝:保存坐标的记录是当其地图不再存在时最终可以知道在哪里的记录。
settlement_invalid此构建未加载的结算记录。阅读代码旁边的判决并更正其命名的记录。通常的原因是省略了必填字段、前面没有包命名空间的 id 以及属于其他五种记录类型之一的字段。
settlement_loot_table_absent一个容器,其战利品表与包裹一起消失了,因此它是空的,而不是从另一个容器中取出的。如果您希望容器再次填充,请重新安装提供战利品表的软件包。它是空的,而不是从另一张桌子上拉出来的,因为拉出来会以这个世界的名义传递另一个世界的东西。
settlement_over_budget建筑物或服务的数量超出了定居点所能容纳的数量。删除消息计数的一部分,或将结算一分为二。计数和上限都在消息中,所以区别在于必须输出多少个。
settlement_text_not_key屏幕上显示的字段,包含短语而不是目录键。使用目录键替换该短语并将该短语放入您的语言表中。记录内所写的姓名无法翻译,并且在所有语言中均以英文显示。
settlement_unreachable_service地图未声明的锚地提供的服务。使用服务命名的 ID 将锚点添加到地图的锚点图层,或将服务重命名为现有的服务。记录和地图本身都是合法的,结果是无人能敌的柜台。
settlement_unresolved_reference为无人提供的事物命名的记录。将指定的记录添加到您的包中,或者更正 ID。该消息命名它指向的记录和它指向的 id,然后将其与您声明的 id 进行比较。
society_dimension_leak身份的一个维度被发现会导致另一个维度。删除命名其他维度的字段。一种文化没有信仰领域:推导必须是不可能写出来的,而且不仅仅是不可取的,因此没有任何东西可以给一个派别一种没有人写过的信仰。
society_heraldry_path命名文件而不是原因的标志。名为a的纹章徽章。请说出一个原因:一个标志是从该构建设计的标志中选择的。
society_invalid该记录不是此构建将加载的记录。阅读代码旁边的判决。列出打破记录的一条规则,每条规则都是要删除的字段、要添加的字段或要更改的单词。
society_mutation_in_definition要求您做某事的定义。删除该字段。定义适配器描述;他们无权改变他们所描述的内容。
society_relationship_collision同一个有序对声明了两次。有序对已被声明两次,因此该对没有位置。删除一个 - 保留两个将使世界取决于最后加载的包。
society_relationship_one_sided没有人宣布反对的立场;相反的是默认值。如果你想要的话,没什么可修复的。仅声明了这一对的一个方向,未声明的相反方向是默认值:一个派别不知道自己有敌人是一个前提,而这条线在这里是一个选择的前提。
society_unresolved_reference无人提供的命名记录。组合中没有任何内容提供命名的 id。您要么携带它指向的记录,要么依赖携带它的包。
state_namespace_ignored包不再读取此状态。声明命名空间,或删除状态。它属于无人认领的一项,并且被搁置而不是被强制执行。
state_namespace_malformed保存中的命名空间不是此构建可接受的名称。编写一个明确标识包的名称空间。救援中的一切都悬而未决,因此我们不知道如何解决的一种形式是无人能认领。
state_namespace_orphaned没有已安装的软件包具有此状态并且已被推送。重新安装该包以恢复其状态。该名称空间属于已消失的名称空间,并且状态已被保留而不是被删除。
state_namespace_rejected该包已拒绝其为此会话保存的状态。该包尝试在其拥有的命名空间之外进行写入。在你自己的里面写:另一个包的状态不是由你来改变的。
state_namespace_reserved包已声明属于主机的命名空间。命名空间是访客的命名空间之一。从包裹中取出一份。
state_schema_future是从比此版本更新的软件包版本编写的。更新包。保存的状态是由比安装的版本更新的版本编写的,我们不认为会恢复状态。
state_schema_migrated构建的最旧状态,移交给包以继续使用。没什么可修复的。通过包本身的迁移,旧的状态变成了当前的形式。
state_schema_too_old注明比包装声称能够读取的地板更旧。查看报告显示该包选择了哪个答案。该状态比数据包迁移的最旧形式更旧,因此它决定如何处理它。
state_write_outside_namespace作者提出了一个不属于他的命名空间。在您的命名空间内写入。一个包改变另一个包的状态就是保存不再属于某人的原因。
strategic_carries_policy试图提供规则本身的包。删除该字段。第一级是数据:运行的内容属于游戏,新功能来自受信任的提供商。
strategic_invalid该记录不是此构建将加载的记录。阅读代码旁边的判决。列出打破记录的一条规则,每条规则都是要删除的字段、要添加的字段或要更改的单词。
strategic_over_budget超出声明上限的包裹。该报告将测量值打印在允许值旁边。拆分记录,或删除超出行的条目:上限是屏幕或阅读器可以容纳的内容,而不是建议。
strategic_text_not_key需要目录键的句子。将短语移至您的语言目录并将其关键字放入该字段中。以 _key 结尾的字段包含一个键;那里的一句话让您的包裹永远以一种语言显示。
strategic_unknown_term此构建没有的考虑因素、意图或类。该词不在该领域的已发布列表中。选择一个存在的词:在我们没有的词下,没有任何东西会做出反应。
strategic_unresolved_reference无人提供的命名记录。组合中没有任何内容提供命名的 id。您要么携带它指向的记录,要么依赖携带它的包。
strategic_weightless一个总是以同样的方式做出决定的计划者。至少给一个考虑因素赋予非零的权重。权重全部为零,每个选项的得分相同,并且永远选择按字母顺序排列的第一个。
theme_carries_executable命名场景、脚本或资产路径的主题。删除该字段。主题描述了你如何看待事物;主题内的脚本是在每个屏幕后面运行的程序。
theme_contrast_too_low低于最小对比度的一对颜色。移动前景或背景,直到比例超过旁边打印的最小值。这是玩家直接听到的唯一主题规则。
theme_refused此版本未注册的主题。读取报告命名的属性并在允许的范围内报告它。
tombstone_blocks_campaign已声明的家庭,没有该家庭,广告系列将无法加载。这家人携带着包裹,但他们的包裹丢失了,因此活动无法开始。重新安装它:如果没有它,世界就会缺少一些到处都提到的东西。
tombstone_placeholder_substituted一个被引擎附身的替代者代替他做出反应。重新安装包以恢复真实内容。报告称,同时使用了哪种替代品。
tombstone_recorded包裹消失的 id 被注册而不是被删除。没什么可修复的。一个包消失了,它的 id 留在了保存中,这是重新安装它可以让玩家找回东西的唯一原因。
tombstone_reinstall_recovered包裹返回,墓碑再次解析为真实内容。没什么可修复的。该包又回来了,它的墓碑再次解析为真实的内容。
tombstone_unresolved_reference保存中的某些内容仍然指向简化为墓碑的 ID。组合中没有任何内容提供命名的 id。您要么携带它指向的记录,要么依赖携带它的包。
unit_carries_behaviour_code试图提供某些行为的包。删除该字段。第一级是数据:运行的内容属于游戏,新功能来自受信任的提供商。
unit_incomplete_for_category缺乏其类别所需的单位。添加类别所需的部分。类别表列出了它们:同伴需要装备,队伍需要行为,领导者永远不会依赖任何人。
unit_invalid该记录不是此构建将加载的记录。阅读代码旁边的判决。列出打破记录的一条规则,每条规则都是要删除的字段、要添加的字段或要更改的单词。
unit_unknown_behaviour此构建没有的行为配置文件。从已发布的列表中选择行为配置文件。这个构建中没有的一个会被拒绝,而不是被默认替换,因为一个悄悄变成流浪者的老板是一场不会发生的战斗。
unit_unresolved_reference无人提供的命名记录。组合中没有任何内容提供命名的 id。您要么携带它指向的记录,要么依赖携带它的包。
unit_visual_missing他的接替解决了一方面问题。未提供您提到的方面,因此使用了该类型的替代品。将资源或点带到现有的资源或点。
world_calendar_inconsistent不可能发生的日历或聚会。放置报告中提到的夫妇。季节、月份和假期必须一致,而不一致的是世界以两种方式阅读的日历。
world_carries_clock_control一个提供自己时间的包。删除该字段。包裹声明了一个季节的价值,但无法移动时钟:佳能时钟只有一个所有者。
world_carries_randomness提供其自身随机性的包。删除种子并命名一个流。匹配的种子属于主机,并且流从主机开始,因此携带自己种子的数据包是一个忽略其所在匹配的世界。
world_invalid该记录不是此构建将加载的记录。阅读代码旁边的判决。列出打破记录的一条规则,每条规则都是要删除的字段、要添加的字段或要更改的单词。
world_unresolved_reference无人提供的命名记录。组合中没有任何内容提供命名的 id。您要么携带它指向的记录,要么依赖携带它的包。

限制、保存、共享

mod 永远无法做到的事情

被构建拒绝,并不气馁。

无代码脚本、扩展、可执行文件、shell 文件 - 包中的任何位置。
没有场景或资源文件即使该文件不存在,指向该文件的记录也会被拒绝。
基本文件没有变暗mod添加和更改记录;它不能替换游戏文件。
没有新事物是的,是一种新的特权,不是。
无命令、自动加载或项目设置根本无法到达。
没有实际取消remove 将记录从循环中删除并使其可解析。只有vendor_inventories拿走1个。

确切的列表,为什么拒绝提及它:

  • 一个记录文件可以为4MB,包含4096条记录,嵌套16层。游戏带来的最大目录包含数百个,因此触发这些限制之一的文件是格式错误的而不是雄心勃勃的。
  • 您的包根本不能包含的文件,无处可去:.bat.cmd.dll.dylib.exe.gd.gdc.gde.gdextension.ps1.sh.so.vbs。它们中的每一个都是行为:脚本、本机库或主机将执行的东西。
  • 记录不能指向的扩展名.bat.cmd.dll.dylib.exe.gd.gdc.gde.gdextension.ps1.res.scn.sh.so.tres.tscn.vbs。它是上面的列表加上场景和资产,因为命名一个的记录要求游戏构建它。
  • 密钥拒绝其包含的任何内容resource_local_to_sceneresource_pathscenescene_pathscript
  • 无论出现在何处,路径都会被拒绝:以 res://user:// 开头的任何路径。记录引导其自己的包内的内容。

每个包装和所有包装的尺寸也有上限,超过一个并不总是被拒绝:

  • 好的 低于限制。没有任何报道。
  • 警告 超出软阈值并加载相同的值。那些创造者受到警告;播放器没有停止。
  • 降级 超出大小限制,客人可以减少而不是拒绝。它之所以如此命名,是因为一款默默地以不同方式运行的游戏比一款说出原因的游戏更糟糕。
  • 拒绝 在没有更小版本的维度上越界。该包未加载并已命名。
尺寸一个包每个人如果他克服了它
records20 000120 000reject
decoded_image_bytes256MB1GBreject
decoded_audio_bytes128MB512MBreject
map_cells4 194 3048 388 608reject
map_objects65 536262 144reject
effect_instances4 09616 384degrade
provider_frame_usec2 0008 000degrade
worker_tasks832reject
queue_depth5122 048degrade
teardown_msec100400warn

全面检修会使这些数字增加一倍,而总转换则使这些数字增加四倍。四次,而非无限:包裹可以声明离开的限制不是限制。

只有移除线移动。 当一个家族成功地将正在退役的记录交付给装载机时,它就会接受 remove;今天有两个人这样做。这张桌子上的其他东西都是永久的。

没有脚本层即将到来。 宣言携带一种传送行为而不是数据的包:唯一可以授权其执行的东西拒绝它,它后面没有沙箱,并且声明它今天被拒绝的包。为数据而设计。

广义地理解“数据”。数字就是数据。平衡就是数据。武器的作用、伤口的成本、商品的售价、派系如何权衡决定:一切都由你决定。不是数据的是游戏从未有过的机制——这是某人编写和测试的代码。如果你的想法需要它,它是一个不同的游戏,而不是一个模组。

保存

你的 ID 最终会出现在玩家的保存文件中。发布的 id 就是一个承诺。

规则为什么
永远不要重命名 id每一次使用它的救援都陷入了困境。添加一个新的并保留旧的。
卸载永远不会删除玩家的东西保存会保留无法解析的 ID 并对其进行标记,因此重新安装会返回保管库。
每次更改某些内容时都会提高 version这是玩家可以看到的东西。

一组包与保存它的包不同的每一种方式都有一个名称,每个名称决定一件事:会话是否可以写入该文件。

判决它可以写你的保存这是什么意思
compatible是的该构图与进行保存的构图相对应。
degraded是的明白了,缺少一些指定的内容。比赛继续进行,并报告缺席。
incompatible不,文件被保留会话无法遵循保存的内容。原始文件被保留。
有什么不同判决这是什么意思
identical_compositioncompatible相同的软件包、相同的版本、相同的组成。
mod_addedcompatible救援人员对这个包裹一无所知。他所记录的一切都没有动过。
mod_missingdegraded未安装保存名称的软件包。他的 ID 仍然在文件中并且保留在那里。
mod_upgraded_compatibledegraded软件包已更改,但仍保持其声称的兼容性。已报告,因为即使它是合法答案,更改后的哈希也是更改后的答案。
provider_contract_incompatibleincompatible救援所指望的能力是通过合同已变更的供应商做出回应。继续前进就是猜测这意味着什么。
conversion_missingincompatible活动本身缺席。文件中的每个id都属于一个未安装的世界。
safe_mode_disableddegraded会话开始时有意关闭数据包。保存的内容是可读的,并且可以选择不存在其修改的内容。
orphan_state_preserveddegraded数据包消失的状态完好无损地通过。保存下来,从未表演过。

读取incompatible行两次:原始保存被保留。被不理解的会话覆盖的文件是一场失败的游戏,并且由于mod而失去一个游戏的玩家不会安装另一个游戏。

每个加载的包都会收到一个指纹:对于相同的清单和内容执行相同的操作,当内容文件更改时会有所不同。组合集摘要还包括每个包的 ID、版本、加载顺序和内容摘要,因此不同顺序的相同包不能假装具有相同的组合。 modding_fingerprint_report 打印这些值并保存方案 v56 记录活动指纹列表,以便稍后加载可以提醒您丢失或更改的包。增加你的 version 仍然是必要的,因为它是玩家在安装之前可以看到和比较的值。

分享一下

将文件夹压缩成zip。分发格式都在这里。游戏内没有目录;把它放在 Nexus Mods 上。

什么
查看在加载之前使用 --strict 清理验证器。
拉链相同的文件夹,因此存档包含 my_mod/mod.json
版本每次加载时将 version 升高到 mod.json
要求也在 Nexus 页面上列出您的 dependencies
从'您接触了哪些系列以及您用 override 覆盖了哪些 id。

永远不要更改你的包的 id 它是承载你的每个 id 的命名空间,另一个包将其命名为依赖项,以及保存时写入的内容。重命名它会使每个现有的保存都相信您的软件包已被卸载,并且另一个软件包已出现在它旁边。相反,更改显示的 name

告诉人们两件事,你会比其他任何事情都节省更多的支持电话:你构建的 game_version,以及你是否将 canon_safe.

今天要写的版本是0.0.0-dev。这是此构建响应的数字,也是本页上每个示例所声明的数字,并且它是单个数字而不是范围:当游戏推出时,它将首先在此处更改。

档案有限制,由标题决定,而不是提取后决定:

  • 最多 4 096 个条目,不超过 16 MB,总共提取 128 MB。
  • 名称 可以包含 200 个字符和 8 个文件夹。
  • 没有任何东西可以声称扩展超过 200 倍,任何诚实的内容都无法实现这一点:文本压缩了大约 15 倍。几千字节提取到千兆字节就是这个数字存在的攻击。
  • 拒绝简单文件或文件夹以外的条目:符号链接、硬链接、设备、fifo、套接字。符号链接才是重要的,因为它的名称可以是完全普通的,并且在它后面写它指向的地方。
  • 存档中的存档被拒绝而不是测量(.7z.bz2.gz.pck.rar.tar.xz.zip)。外面的那一个宣告了它的声音传播的范围;它无法声明内部的延伸范围。

今天没有可以发布到的商店,这就是将要发布的内容的形式。 现在的分发是上面的 zip 和 Nexus 页面:接下来的任何内容都不是您为本周可以执行的上传而填写的字段。之所以在这里,是因为这些字段已经在构建中声明了,因此到商店的路线只是将它们插入而不是发明它们,而且因为今天编写的包不必重写即可以这种方式传输。

穿过商店的包裹携带的东西比挎包携带的东西多:

它带来什么领域
谁是stable_idversion
它来自哪里authorlicensesource_urlpackage_hash
商店对此有何评价content_ratingcontent_warningsrevocation_status
如何交付storestore_idsubscription_id
状态它安装这是什么意思
none是的没有任何报道。
reported是的有人报告了此事,但​​什么也没决定。玩家收到通知并进行选择。
quarantined搁置待决定。它不会安装,也不会删除已安装的内容。
revoked撤回。它不会安装,并且已安装的副本会被停用而不是删除,因为玩家的保存游戏仍然会命名其内容。

阻止安装的两种状态仍然不会删除任何内容。

新版本可以对您的软件包做什么

game_version 不是装饰品。游戏会将您构建的内容与实际内容进行比较:

判决这对你意味着什么
supported您命名的构建就是这个,或者足够接近。无事可做。
older_build您已经针对较旧的游戏进行了构建。无论如何它都会加载,而可能的惊喜将来自于同时发生的变化。
newer_build您已经针对一款比您正在运行的游戏更新的游戏进行了构建。该包是这样命名的,而不是半加载的,希望它使用的所有内容都已经存在。
unreadable你写的game_version不是版本。这始终是一个错字。

您对此采取的措施取决于移动的内容:

班级这是什么意思游戏欠你什么
不变数据包可以观察到的任何东西都没有移动。没有任何
添加剂有一些新的东西,那里的一切仍然意味着它曾经的意义。增幅较小
打破现在,在旧表面上写入的数据包在未经修改的情况下可能是不正确的。更大的增加

由于以下原因之一,更改被视为中止:field_removeddefault_changedtype_changedconstraint_changedrequired_addedoperation_removedroot_changedformat_changedid_field_changedcatalogue_changedfamily_removedcontract_major_changed_without_new_iddefault_changed 看起来是累加的,但实际上并非如此。一个字段的默认移动重写了每个从未提及过它的包的行为,并且它的作者没有改变任何东西。 constraint_changed 涵盖限制和枚举,而根、格式、id 字段、其他目录元数据和系列删除更改会改变包的读取位置或是否可以读取。

即将消失的名称在被删除之前已被弃用,并且在弃用它的版本之后至少继续有效 2 个次要版本

政治,四句话

无论是谁决定是否要在一个包上花费一百个小时,实际上只是在问一个问题:游戏更新时他们会发生什么。在阅读列表之前,这是答案。

要求回答
我的包裹还会加载吗?是的,除非某个版本在下面列出为破坏性的,并且没有首先出现的版本就不是破坏性的。
玩家的保存会保存下来吗?是的。无法理解保存的会话会拒绝写入而不是覆盖它,并且保存会保留它无法解析的 ID,而不是丢弃内容。 保存
我会收到多少通知?名称在被删除之前已被弃用,并且在弃用该名称的版本之后至少在 2 个次要版本中继续有效。
我怎么知道?该行位于下表中,其中包含其所属版本之前已移动的内容和已更改的内容。

破坏软件包的版本

发布日期什么打破了该怎么办
还是什么都没有。没有发布破坏包。

该表是空的,不是占位符。 它现在存在,以便第一行有一个着陆的地方,以便上面的承诺在测试之前而不是测试之后写下来。这里的一行列出了该版本的名称、发布日期、停止接受的确切形式以及修复包的更改,而不是“杂项更改”。

会破坏某些内容的传入工作会进入同一个表,标记为到达,然后退出。

如果游戏没有开始

无法启动的配置文件会重试有限次数,然后游戏会提供返回的方法,而不是无休止地尝试。

配置文件重试 3 次。之后,游戏将停止尝试并提供其中之一。

  • 重试 低于重试限制。再次尝试相同的配置文件。
  • last_known_good 提供过去启动的配置文件。没有卸载任何东西。
  • 安全模式 会话不会加载任何包。配置文件保持完整,并在玩家请求时返回。

失败的地方告诉您要寻找什么:

失败的地方其目的是什么?
discovery阅读已安装的内容。这里的失败通常是格式错误的包。
provider_start开始创作已选择的作品。这里的失败指的是一种技能。
first_scene玩家看到的第一个场景。这里的失败在于内容,而不是布线。

这一切都不会卸载您的软件包或更改您的文件。 安全模式是一个不加载软件包的会话,当您请求时,您的配置文件正在等待您。

总转化

它还不是为创作者发布的路径。 该版本理解宣言并带来了 Ashen Reach 装置;打包的公共工作流程还没有出来。将夹具视为一份工程合同,而不是像今天就可以发布的承诺。

它是用 type: total_conversion 声明的。接下来,fallback_policy 决定半安装转换是否显示游戏内容或不显示游戏内容。

取代无法添加
地点、人物、战争、神话、地图、一切事物的名称。你的王国,你的神,你自己的经济。一种新的东西。剑击中重者是数字;剑击中重者是数字。发射光束并需要光束规则的武器是一个特征,而特征就是代码。

哪些变化,哪些不变

几乎没有任何变化。 文件夹是文件夹,mod.jsonmod.json,系列是具有相同字段的相同系列,id 以相同的方式命名,验证器应用相同的规则,Mod 屏幕报告相同的状态。本页上的每个教程都是构建转换片段的教程。添加商人的包裹和整个领域的包裹之间的距离是创纪录的金额,而不是不同的能力。

三件事确实发生了变化,在开始之前有必要了解这三件事:

什么作为
海报type: total_conversion,旁边是fallback_policy,即vanillanone,如果不写就值vanillavanilla 表示半安装转换显示您缺少的游戏内容; none 表示什么也不显示。
预算普通配置文件的四倍——并且是配置文件,而不是豁免。构建本身的文字:“四次,不是无限:可以声明的限制不是限制。”如果 total_conversion 删除了限制,它将成为每个包为逃避它们而写入的行。
未翻译的单词不再依赖于游戏中的单词通常,丢失的密钥会先到 player_locale,然后是程序包的默认语言,然后是游戏目录,然后是密钥本身。在完全转换时,第三步被删除。您未编写的密钥将被视为密钥并被报告。

第三步感觉像是一种损失,但事实恰恰相反。 Old Seat 出现在一个没有旧座位的世界中,这并不是一个稍微错误的翻译:它是一款基本游戏,从底层闪耀出你在其之上构建的东西。取消这一步骤意味着你的言语中的漏洞是你被告知的,而不是玩家发现的。

它要去哪里

值得明确地说出这一点,因为它改变了值得学习的东西。

Bonemark 下的引擎旨在处理 Bonemark 之外的更多内容。背景就是数据:地点、人物、经济、神话以及所有这些的词语都是本页所描述的相同类型的记录。这就是清单中存在完整转换类型的原因,也是构建带来第二个设置作为固定装置而不是作为代码行测试的原因。

所以长期的形式并不是“加一把剑”。而是任何一个学习这些家族的人都在学习在这个引擎上构建一个世界,而一个添加商人的包裹和一个整个领域的包裹之间的距离是一个创纪录的金额,而不是一个不同的技能。

Steam 创意工坊是向玩家获取包的方向,这就是为什么分享 描述了一个仍然没有任何东西的商店的字段。订阅一个包而不是提取一个包会改变它的到达方式,而不会改变它的编写方式:相同的文件夹、相同的 mod.json、相同的 id。

两者都没有日期,也没有命名第二个设置:其中一个作为工程固定装置存在,与已宣布的不同。这里所说的是一个方向,以及做好准备的代价:也就是说,当门打开时,你今天学到的东西不会停止。

拥有一个模组

每个改装场景都遵循同样的条件,因为它们才是有效的。这里没有什么不寻常的地方,也没有什么花哨的地方。

你的模组是你的你写的唱片,你画的图画,你发出的声音。它们仍然是你的。发布模组并不意味着任何人都有权使用您的作品。
游戏内容依然是游戏引用任何你想要的东西——覆盖一个 ID、修复一个字段、修饰一个对象。不要将其取出,不要重新包装,或将其副本放在包中。这主要是为您保留的:软件包不能遮盖游戏文件,因此很难意外跨越这条线。
版权不会朝任何一个方向移动这是上面两行的法定名称,值得说清楚,因为这是人们认为理所当然的事情。发布包并不会将您的作品交给工作室;而是将您的作品交给工作室。安装一个并不会将游戏拱手让给你。您所写的唱片和您所创作的艺术作品的版权归您所有,并且 Bonemark 的唱片、艺术作品、声音和背景仍归工作室所有。完全转换是值得明确说明的情况:替换玩家看到的设置并不许可替换的设置,并且包仍然无法携带游戏文件。
模组是免费的在任何商店或平台上都没有销售,没有付费墙,也没有付费抢先体验。而且它们甚至不属于我们出售:同样的规则也约束着工作室。
捐款很好一个小费罐、一个 Patreon、一个感谢页面。这是对一个人的支持,而不是一个模组的价格,每一个健康的场景都允许它。
别人的工作需要他们的许可一个角色、一个声音、一个精灵、另一个包中的一组记录:询问并在玩家可以阅读的地方引用作者。
默认允许翻译任何人都可以翻译您的包并发布翻译,并引用您的内容。如果您希望首先被询问,请在您的页面上说出来。
首先询问重用以某人的包裹为基础,继续废弃的包裹,获取他们的记录并将其放入您的记录中:询问他们。沉默并不是一个肯定。

因为免费是没有商量余地的。 付费模组已经被大规模尝试过,但每次都被淘汰:一旦涉及到金钱,争论的焦点就是谁拥有哪个想法,而不是下一步要构建什么,共享场景开始保持自己的地位。在这个生态系统中,每个人都处于同一水平,包括那些制作游戏的人。

我们可以要求的一件事。 删除某个软件包,并且仅出于狭隘的原因:它携带游戏文件、冒充某人或在其托管位置包含非法材料。不是因为我们不同意他的观点。

由工作室于2026年8月14日决定。这里的文字是政治;律师会在公开开放修改之前阅读它,如果这改变了一个词,这个页面会随着你的改变而改变。

去哪里询问

Discord,尚未开放。 这是修改问题的答案,并且邀请不会写在任何地方,因为没有任何内容可以邀请任何人。由于同样的原因,首页上的 Discord 品牌也显得乏味。它亮起的那一天就是这条线携带地址的那一天。

在地址存在之前说“Discord”比什么都不说更有价值:它告诉你去哪里寻找,并告诉你不要在从未打开过的论坛中寻找。

与此同时,在没有其他人参与的情况下回答几乎所有问题的方法是在你向任何人寻求帮助之前:预检块命名了每次拒绝背后的构建、包、状态和原因,几乎人们会回答的所有内容都已经在那里了。

已与游戏版本核对:2026-08-16。每个标签表示一种状态,而非承诺。阅读标签 →