Next Run · 模组
Next Run 模组指南
详细介绍 Next Run 模组的工作方式、文件结构以及游戏组件。创建和发布自制模组时,请保存此链接以便快速查找答案。
1. 总览
本文档介绍 Next Run 的模组系统:如何安装模组、创建自己的模组,以及如何与其他玩家分享。
- 至少阅读一次第 2 章,了解模组的创建方式和工作原理。
- 将第 3 章和第 4 章作为参考手册使用。
- 查看游戏内示例,了解其在实践中的运作方式,Steam 创意工坊:https://steamcommunity.com/app/1295870/workshop/。
- 可在此处获取 1.1.0 版本的游戏文件:https://clarusvictoria.com/files/next_run_files_examples_1.1.0.zip。
2. 模组系统
启动游戏并点击“游玩”“创建游戏”后,游戏会扫描目录中的 Mods 文件夹。若子文件夹内存在 modinfo.json 文件,则该子文件夹被视为一个模组。
2.1. Steam 创意工坊、安装与发布模组
如果你在 Steam 客户端中启动游戏,“游玩”菜单下会显示“模组”面板,包含以下按钮:
- Steam 创意工坊
- 模组文件夹
- 发布
- 指南
2.1.1. Steam 创意工坊
在 Steam 客户端内打开创意工坊。要下载模组,请先订阅。之后会自动开始下载。若模组体积较大,下载可能需要一些时间。下载状态会显示在 Steam 客户端。
2.1.2. 模组文件夹
打开你游戏的模组文件夹。
2.1.3. 发布
游戏会自动扫描 Mods 文件夹,并将所有你作为作者的模组发布到 Steam 创意工坊。
- 如果是新模组,会自动生成 steam_id。
- 如果模组已存在,则会被更新。
- 发布按钮在上传时会改变外观。
- 只有有变动的模组才会发布。
- 修改 modinfo.json 文件不视为内容变更。
- 发布的模组会对全球其他玩家可见。Steam 创意工坊并非唯一的发布渠道——也可以直接将模组文件夹放入 Mods 目录来分发。
2.1.4. 指南
本指南的链接。
2.2. JSON 文件
游戏中的所有数据和文本都使用 JSON 格式。与普通文本格式的主要区别在于数据必须包含在大括号 {} 中。
JSON 语法说明:
- https://en.wikipedia.org/wiki/JSON
- https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Scripting/JSON
建议参考游戏中的示例文件。
2.3. 文件结构
每个模组的文件结构与游戏本体相同。这些文件要么添加新内容,要么修改现有内容。JSON 文件会添加或修改游戏中的单个元素。其他格式的文件(png、ogg)会整体替换。
示例:如果你创建 data/game.json 并在其中修改实体 "Warrior"(职业),则只会修改该职业,其余 game.json 中的实体保持不变。如果你添加 portrait_warrior_front.png,由于文件名相同,它将完全替换游戏中的对应图片。
模组内有必需和可选的文件与文件夹。标准结构如下:
- 模组文件夹名称(任意,不是模组名称)
- modinfo.json
- preview.png
- data/
- icons/
- sounds/
- texts/
- tiles/
为了更好地理解,建议学习游戏示例和现有模组。以下是每个文件夹和文件的详细说明。
2.3.1. modinfo.json
包含模组元数据的文件。其中一部分数据会在发布时用于 Steam 创意工坊。
- title — 模组名称,会显示在 Steam 中。
- version — 模组版本。
- description — 模组描述。
- tags — Steam 创意工坊中的导航标签。
- order — 模组加载顺序。如果多个模组修改同一数据,order 更大的模组会覆盖数值更小的模组。
- steam_id — 无需手动填写,发布时自动生成。
- created_time — 创建时间。
- changed_time — 修改时间。
- 允许添加其他字段,但只会在文件内使用。模组作者会通过 Steam 创意工坊自动确定。
2.3.2. preview.png
用于 Steam 创意工坊的模组图标。推荐分辨率为 256x256 或 512x512,比例为正方形,可用透明 PNG 或 JPG。
2.3.3. data
存放数据 JSON 文件的文件夹。包含用于修改或新增游戏实体的文件。你只需创建需要修改或添加的文件与字段。可变数据的详细说明见第 3 章。
2.3.4. icons
存放游戏图标的文件夹。包含除 GUI 和地块外的大多数图片。不同场景会用到多个标准尺寸和图层。游戏使用带透明背景的 PNG 文件。
2.3.5. sounds
存放音效和音乐的文件夹。可以添加新文件或替换现有文件。使用的格式为 OGG。
2.3.6. texts
存放游戏本地化文本的文件夹。每个文件对应一种语言,使用 IETF BCP-47 / ISO 标准。目前支持 13 种语言:ruRU.json、trTR.json、jaJP.json、koKR.json、zhTW.json、zhCN.json、plPL.json、ptBR.json、itIT.json、esES.json、frFR.json、deDE.json、enUS.json。
2.3.7. tiles
存放地块图像的文件夹。使用带透明背景的 PNG 文件。标准地块尺寸为 256x384。地块由多个图层组成,如地面、物体、森林、山脉、道路等。
2.4. Mod 同步
获得 Mod 后,游戏每次启动时都会自动与 Steam 创意工坊发布的最新版本同步。
如果你是该 Mod 的作者,则不会执行同步,Mod 文件也不会被覆盖。这样可以防止在制作 Mod 时重启游戏后修改内容丢失。
如果你想基于他人的 Mod 制作自己的 Mod,在重新启动游戏之前需要:
- 将 Mod 文件夹名称改成与其 id 不同的任意名称。
- 在 modinfo.json 文件中删除字段:"author"、"created_time"、"steam_id"、"changed_time"。
2.5. 数据合并
模组和游戏的 JSON 数据文件不会被替换,而是会被合并。
合并顺序:
- 首先以游戏 JSON 文件中的原始实体为基础。
- 再叠加模组的数据。模组会按照 modinfo.json 中 order 字段设置的优先级依次应用。
合并时会分别处理所有组件的每个字段。例如,若实体中有 "hideIfZero":true,需要变成 false,光删除该字段并不够——必须显式写出 "hideIfZero":false。
list.json 中的列表也按相同原则合并。如果只想添加一个条目,不必将每个列表连同所有字段都复制一遍。不过只包含简单数据的列表会被完全替换,例如 RndGoodEvents 和 RndEvents。
3. 组件
Next Run 基于 ECS 架构。整个游戏由实体组成。实体是组件的容器,只有一个 id 字段。所有其他数据都由组件描述,并在 JSON 文件中设置。
JSON 文件中的示例条目:
"Speed": {
"Button": {"panel": "statsPanel","iconType": "btnBig","numText1Type": "total","icon": "arrow2"},
"Tooltip": {"text": "Speed"},
"Total": {"now": 25}
}此示例描述实体 "Speed",包含三个组件:Button —— 决定游戏中按钮的外观和行为;Tooltip —— 气泡提示描述;Total —— 实体的数值,在此示例中速度为 25。
下文对组件及其字段进行更详细的说明。部分组件属性由游戏自动确定,无法在 JSON 文件中编辑。例如,地下城清理的难度取决于等级和其他由游戏计算的参数。
3.2. Tooltip
描述按钮提示的内容。
- text = string,游戏中显示的实体名称。
- dontShowDuration = bool,不显示持续时间数值。
- hideSources = bool,不显示影响该实体数值的来源实体。
- hideAsSubjTT = bool,禁止将该对象作为关联实体的来源显示。
- desc = string,描述文本,显示在提示开头。
- desc2 = string,描述文本,显示在提示末尾。
- redDesc = string,红色高亮的描述文本,显示在末尾。
- totalTextAs = string,用作“总计”替代文本。
- ttPos = string,提示相对按钮的位置,可选 "top"、"left"。
3.3. GameClass
描述职业机制。
- text = string,游戏中的职业名称。
- portrait_back = string,选择职业时的背景图 391x598。
- portrait_front = string,选择职业时的前景图 411x620,透明。
- figurine = string,地图上的角色头像 149x243。
- doll = string,背包中的黑白职业图 460x784。
- bonusSkill1 = string,获得加成的技能 1 名称。
- bonusSkillVal1 = double,技能 1 的加成数值。
- bonusSkill2 = string,获得加成的技能 2 名称。
- bonusSkillVal2 = double,技能 2 的加成数值。
- debuffSkill1 = string,受到减益的技能 1 名称。
- debuffSkillVal1 = double,减益 1 的数值。
- debuffSkill2 = string,受到减益的技能 2 名称。
- debuffSkillVal2 = double,减益 2 的数值。
- gold = double,职业初始黄金数量。
- remains = double,初始遗骸数量。
- equip = List<string>,初始装备列表。
- units = string,初始单位名称。
- itemName = string,初始背包物品名称。
- itemNum = double,初始背包物品数量。
- learnList = string,要学习的法术或图纸列表,列表在 list.json 中。
- learnNum = double,将从列表中学习的法术或图纸数量。
- lessTime = double,地狱攻击之间的时间减少量。
- manaBonus = double,法力加成(上限与总量)。
- upgradeDexterityBonusMod = double,“敏捷”技能对可升级物品的加成。
- skillPointsPerLevel = double,升级时获得的技能点数。
- upgradeManaCostMod = double,法术升级效率加成。
- freeRegion = bool,免费区域。
- necroBonus = bool,“死灵法师”玩法与加成。
- druidBonus = bool,“德鲁伊”玩法与加成。
- stances = bool,是否有姿态/形态/指令。
- defStance = string,默认姿态。
- notDemo = bool,在试玩版中不可用。
- notTutorial = bool,在教程模式中是否可用。
3.4. GameMode
描述游戏模式的机制。
- text = string,模式名称。
- back = string,选择模式时的背景图 391x598。
- moreTime = double,地狱攻击之间增加的时间。
- lessTime = double,地狱攻击之间减少的时间。
- woundChance = double,受伤概率。
- notDemo = bool,在试玩版中不可用。
- scenario = string,该模式的专属地图名称。
- noHellAttacks = bool,此模式无地狱攻击(类似沙盒)。
- savesOnExitOnly = bool,此模式仅在退出游戏时保存。
3.5. Biome
定义生物群系的机制。
- frequency = double,地图生成时该生物群系的出现频率。数值越大越常见,为 0 时不生成。Lava 生物群系总是作为最终区域生成。
- hexBase = string,该生物群系的基础地块,在聚落下方生成。
- music = string,生物群系的音乐文件名。
- hexPatterns = List<string>,生物群系中的对象模板列表。其工作方式类似牌堆:模板随机洗牌后抽取,耗尽后重新生成。模板格式为:对象名#对象名,# 为分隔符。
- mobLevel1 .. mobLevel8 = string,根据区域等级生成的生物名称。
3.6. TileAsset
定义地图上对象的外观。
- tileMap = string,图层名称:LandTilemap —— 地表,ObjectTilemap —— 普通对象,RoadTilemap —— 道路等,仅叠放顺序不同。
- rawSprite = string,添加到地图的 256x384 图片。
- icon = string,覆盖所有 TileMap 的图标。
- buttonIcon = bool,是否从 Button 获取图标。
- delLevel = double,移除等级,表示用行动删除对象的难度。
3.7. Shop
描述商店机制。
- slots = int,商店槽位数量。
- type = string,list.json 中商店货表的名称。
3.8. Item
描述物品机制。
- slot = string,装备槽名称。
- stackable = bool,是否可堆叠。
- upgradable = bool,是否可升级,升级时长取决于等级。
- upProgress = double,升级所需时长。
- order = double,商店中物品排序,数值越小越靠前。
3.9. Mob
描述生物机制。
- hell = bool,是否为地狱生物。贿赂有惩罚,参与地狱攻击,并提供额外遗骸。
- undead = bool,是否为亡灵。不可贿赂,有特殊升级机制。
- type = string,生物类型 —— "Warriors"、"Defenders"、"Mages"、"Gatherers"、"Crafters",决定底色、命中率、伤害类型、战利品类型。
- upMob = string,生物升级后的名称。
- upCostName = string,升级所需物品名称。
- upCostNum = double,升级所需资源数量,默认 1。
3.10. Dungeon
描述地下城机制。
- magic = bool,是否为魔法地下城,影响伤害类型、掉落和扩展。
- boss = bool,是否为最终地下城。
3.11. Ruins
描述废墟机制——搜寻物品的地点。
3.12. Addon
扩展机制。扩展是位于地下城或废墟格子上的对象,会修改其参数并提供额外奖励。
- skill = string,清理地下城或探索废墟后玩家获得的技能名称,可指定 "Random"、"Strength" 等。
- unit = string,完成行动后获得的奖励单位名称,可指定 "Random"。
- item = string,完成行动后获得的奖励物品名称,可指定 "Random"。
- phyChanceMulti = double,清理时物理伤害概率修正,例如 50(%)。
- magChanceMulti = double,清理时魔法伤害概率修正,例如 50(%)。
- progressMulti = double,清理或探索行动所需时间的增幅,例如 100(%)。
- dmgMulti = double,清理时伤害量的修正,例如 50(%)。
3.13. Build
标记该对象为建筑。
3.14. Center
定义该对象为聚落。
- captureProgress = double,占领聚落所需的努力。
- upProgress = double,升级聚落所需的努力。
- upCostName1 = string,升级需要的物品 1 名称。
- upCostNum1 = double,所需物品 1 数量。
- upCostName2 = string,物品 2 名称。
- upCostNum2 = double,物品 2 数量。
- upCostName3 = string,物品 3 名称。
- upCostNum3 = double,物品 3 数量。
- upProp = string,升级后的聚落名称。
3.15. Gatherable
定义该对象可被采集并获得资源。
- gather = string,采集后获得的资源名称。
- deposit = bool,该资源是否为矿脉,如果是,则可以建造矿井。
3.16. AlliedForest
在扮演德鲁伊时,“盟友森林”机制及其数值。
- allyBonus = double,“盟友森林”加成数值。
3.17. Graveyard
定义该对象为墓地,对死灵法师玩法重要。此处的遗骸数量为随机生成。
- now = double,当前遗骸数量。
- rndMin = double,遗骸随机数最小值。
- rndMax = double,遗骸随机数最大值。
- rndCeil = bool,随机值是否向上取整。
3.18. Pred
动作组件。虽然组件的大部分功能隐藏在代码中,但有一部分可用。
- action = string,执行后触发的动作名称。
- local = bool,与对象交互是否需要位于同一格。
- attackPred = bool,该动作为攻击动作,若施放战斗法术会自动应用。
- gatherPred = bool,该动作为采集动作,若施放采集法术会自动应用。
- craftPred = bool,该动作为制作动作,若施放制作法术会自动应用。
- skill = string,执行动作所用技能,例如攻击类动作使用“攻击”。
- longPred = bool,该动作非即时,需要时间。
- repeat = bool,动作会重复执行直至停止。
- noOwner = bool,该动作不需要选中任何对象。
- skipLongTooltip = bool,使用简化的动作提示。
- onlyClass = string,该动作属于姿态、形态或指令,仅对特定职业可用。
3.19. Total
定义实体的数值组件,通常表示数量。
- now = double,当前数值。
- inc = double,每回合增长。
- max = double,最大值。
- min = double,最小值。
- rndMin = double,随机数最小值。
- rndMax = double,随机数最大值,生成时会替换 now。
- rndCeil = bool,随机值向上取整。
- overMax = bool,允许超出上限。
- delIfZero = bool,数值为 0 时删除。
- numPercent = bool,数值是否为百分比。
3.20. Level
定义实体等级的组件。
- now = double,当前等级。
- max = double,最高等级。
- min = double,最低等级。
- localLevelPlus = int,本地等级加值,仅对地图对象有效,其等级为区域等级加上此值。
3.21. Duration
定义实体持续时间的组件。
- now = double,当前持续时间。
- max = double,最大持续时间。
- min = double,最小持续时间。
- delIfZero = bool,为 0 时删除。
3.22. Mods
修改器列表组件。创建该组件时会生成一组影响其他实体的更改,删除实体时这些更改会消失。
- radius = int,修改影响的半径,仅在地图上有效。
- objType = string,受修改影响的实体类型,例如 "Stat"、"Skill"、"Prop"、"Item"、"ModableVal"、"PropMod"。
- objName = string,实体名称,例如 "Speed"。
- objComp = string,受影响的组件,例如 "Total"、"Level"。
- objKey = string,受影响的组件字段,例如 "now"、"inc"、"max"。
- modType = string,字段的影响方式:"add"、"mult"、"addPerLevel"、"multPerLevel"。
- now = double,修改器的数值。
- subjTooltipText = string,会在动态提示中添加主体说明。
- skipPerTooltip = bool,在提示中将 PerLevel 替换为 Plus。
- skipSubjTooltip = bool,跳过该主体的提示。
3.23. ModableVals
全局变量列表组件。与具体实体的绑定是形式上的。大部分逻辑在游戏代码中。
- now = double,变量值。
3.24. Slot
定义实体为背包槽位的组件。
- name = string,槽位名称。要将物品放入该槽,物品的 Item.slot 字段必须一致。
3.25. Container
将实体定义为带有格子的容器。
- cells = int,容器格子数量。
- cellsPanel = string,面板名称。
3.26. Tom
定义该实体为可学习的法术卷册,使用后可获得或升级法术。
- cast = string,法术名称。
3.27. Cast
定义该实体为法术。
- mana = double,法术法力消耗。
- predSkill = string,激活该法术时启动的动作类型,例如 Attack 类型会自动启动攻击类动作。
- notSkills = string,提示使用该法术所需的动作。
- attack = double,施放该法术对“攻击”类行动的加速程度,视作魔法伤害。
- gather = double,施放该法术对“采集”类行动的加速程度。
- craft = double,施放该法术对“制作”类行动的加速程度。
- heal = double,为玩家英雄回复的生命值。
- newEvent = string,法术触发的事件名称,通常是增益类事件。
- teleport = bool,传送到选定位置。
- explore = double,探索该格及相邻格子。
3.28. Blueprint
图纸实体的机制。
- item = string,将要制作的物品名称。
- build = string,将要建造的建筑名称。
- costName1 = string,制作所需物品 1 名称。
- costNum1 = double,所需物品 1 数量。
- costName2 = string,物品 2 名称。
- costNum2 = double,物品 2 数量。
- costName3 = string,物品 3 名称。
- costNum3 = double,物品 3 数量。
3.29. Cost
价格组件,定义实体可买卖的价格。
- raw = double,未包含修改的基础价格。买卖价格基于此计算。
3.30. Event
事件组件。
- uniq = bool,事件唯一;若再次出现同名事件,会删除旧事件。
- rndEvent = bool,事件为随机事件。
- nextEvent1 = string,当前事件结束后开始的第一个事件名称。
- nextEvent2 = string,当前事件结束后开始的第二个事件名称。
- castType = string,法术增益效果的类型,会覆盖相同类型。
3.31. Proc
处理触发概率(proc)的组件,例如疾病发生的概率。
- addEvent = string,当触发成功时会发生的事件。
3.32. ProcMod
允许实体影响触发概率的组件。
- proc = string,被影响的触发名称。
- chance = double,影响强度,部分功能在代码中。
- dependsLevel = bool,是否取决于实体等级。
3.33. Usable
一次性使用的组件,提供效果,例如药水。通过“使用”动作激活。
- stat = string,受影响的属性名称。
- skill = string,受影响的技能名称。
- nowBonus = double,影响 Total.now 字段的加成。
- maxBonus = double,影响 Total.max 字段的加成。
- cure = bool,是否治愈“疾病”效果。
3.34. Drankable
允许在地图上饮用对象的组件,例如湖泊、绿洲等。
3.35. Sphinx
地图上的任务组件:狮身人面像。参数根据区域等级自动确定。
3.36. Living_tree
地图上的任务组件:活树。参数根据区域等级自动确定。
3.37. Vision
地图对象的机制,玩家英雄进入该格时会提高地图视野。
- explore = int,侦查半径。1 —— 普通侦查,2 —— 比普通多一格。
3.38. Remains
作为遗骸组件的实体描述。允许将此类实体变为亡灵。
3.39. Audio_comp
允许根据实体类型播放声音的组件。
- click = string,点击实体时的声音,用于行动和法术。
- added = string,创建实体时播放的声音,用于事件。
- ambient1 = string,环境音轨 1。
- ambient2 = string,环境音轨 2。
- ambient3 = string,环境音轨 3。
- process = List<string>,执行动作时播放的声音列表。
- waits = List<double>,播放间的停顿列表。
- finish = string,完成动作时的声音。
- rndProcess = bool,播放过程中是否带有细微随机效果。
3.40. Childs
递归创建新实体的组件。
- list = List<Entity>,会自动创建并绑定到该实体的子实体列表。
3.41. Preds
为实体创建动作的组件,尽管大多数实体在游戏代码中定义。
- list = List<string>.
3.42. Equip
标记该物品可装备在英雄身上的组件。
3.43. Res
资源指示组件。用于提示、动画和游戏汇总。
3.44. TurnAct
表示该实体需要在每个游戏时间刻检查,例如 Total 和 Duration 组件。
4. 列表
list.json 文件包含一组数据分段,它们不是实体或组件,定义了用于生成游戏内容的各种列表。
4.1. RndGoodEvents
在游戏开始时生成的良性随机事件列表。
4.2. RndEvents
在游戏过程中生成的正面和负面随机事件列表。
4.3. Generator_dungeon_addons_physical
为物理伤害型地下城生成的扩展(addons)列表。
4.4. Generator_dungeon_addons_magical
为魔法伤害型地下城生成的扩展(addons)列表。
4.5. Generator_ruins_addons
为废墟生成的扩展(addons)列表。
4.6. Generator_settlement_levels
区域等级与聚落实体名称的对应列表,例如 "lvl1":"Village" 表示 1 级区域会生成 Village 类型的聚落。
4.7. Generator_rar_metals
区域等级与矿脉名称的对应列表,例如 "lvl2":"Deposit_tin" 表示 2 级区域会生成锡矿脉。
4.8. Generator_mages
区域等级与会生成并守卫法师塔的法师名称对应列表,例如 "lvl3":"Priestesses" 表示 3 级区域会生成 Priestesses。
4.9. LevelMobs_
不同区域等级的生物列表,玩家在清理地下城解救囚犯或探索废墟后会获得这些生物。
4.10. Crafter_start, Lord_start, Mage_start,
在 GameClass 组件的 learnList 字段中,不同职业在开局获得的物品列表,数量由 learnNum 字段生成。
- obj = string,物品名称。
- min = double,随机数量最小值。
- max = double,随机数量最大值。
- chance = double,生成该物品的概率。
- 可以创建其他列表并绑定到不同职业,以便学习不同的图纸或法术。
4.11. Gold_
该列表根据区域等级确定生成的黄金数量。黄金会以 50% 概率出现在所有地图奖励中。语法参见 4.10。
4.12. Loot_-
这组列表根据区域等级决定奖励掉落。适用于生物、地下城和废墟。对于生物,会以 50% 概率掉落特定物品;其余 50% 使用 4.13 中的列表。语法参见 4.10。
4.13. Warriors_, Defenders_, Mages_, Gatherers_, Crafters_,
这组列表基于区域等级和生物职业决定奖励。仅用于生物。该列表扩展了 Loot_- 列表,并在 50% 的情况下生成与职业相关的奖励,例如让法师更常掉落法术卷册和法杖。语法参见 4.10。
4.14. Shop_, Books_
不同区域等级的列表,例如 Books5 或 Shop6,用于生成商店的商品。语法参见 4.10。这些列表在 Shop 组件的 type 字段中指定,法师塔的列表由游戏代码生成。
