准备工作
在开始制作模组之前,请检查这些必要事项
如果只是添加或编辑内容,你需要一个趁手的Json编辑器。我推荐使用Visual Studio Code或Visual Studio。此方式足够实现游戏自身全部功能,请放心学习。
如果需要添加新的界面或玩法,需要使用Visual Studio 2022,安装工作负载:.NET桌面开发,确保勾选。NET 9 组件
你需要掌握 C# 或 Visual Basic 语言,在后续章节了解更多
关于如何编辑已有数据,不难发现前文只介绍了如何新增数据,而编辑数据并未在后文提及。
要编辑数据,只需使用相同的 ID 即可,同时需提醒玩家要在之后加载您的模组。
但注意仅能实现对父级对象进行覆盖,例如:要重写一个角色,您需要将整个角色的所有数据都写出来,而不能只写要修改的部分。
模组布局
要创建一个新的模组,请先创建一个文件夹。
可以直接在游戏 Mods 文件夹中创建以方便调试,也可以先放在其他地方。
文件夹中的结构 名称 类型 用途 Manifest.1}] // 例如这个样子表示恢复远行队中所有无法作战角色并增加 10% 生命值
"脚本键": "", // 任务物品和收集品专用,绑定脚本的键名称,非对应类型指定无效
"种植键": "" // 消耗品专用,如果该物品是作物种子,那么指定生长过程键名称,非消耗品指定无效
},
{ // 物品信息2
"ID": "StrangeCoin",
"类型": 1,
"占用空间": 0.01,
"效果": [],
"脚本键": "",
"种植键": ""
}
// ...物品类型可选项:1:关键物资 2:制作材料 3:养成道具 4:消耗品 5:武器 6:装备 7:任务物品 8:收集品
消耗品效果说明:
- 除生命值外,所有效果均在下一场战斗结束后消失
- 重复使用时,效果数值将被覆盖
- 未上场角色不会消耗效果
- 最多支持三个效果,超出部分无效
消耗品效果类型:
1:恢复远行队中所有无法作战角色并增加指定的生命值(百分数小数形式)
2:恢复远行队中所有非无法作战角色生命值(百分数小数形式)
3:增加远行队中全体角色攻击力最终数值(整数)
4:增加远行队中全体角色防御力最终数值(整数)
5:增加远行队中全体角色速度最终数值(整数)
6:增加远行队中全体角色暴击率最终数值(整数)7:增加远行队中全体角色暴击伤害最终数值(整数)
8:增加远行队中全体角色速度最终数值(整数)
关于翻译,后续同理显示名称和显示描述的翻译键名称已经预定义,在翻译文件中指定以下两个对应键在语言文件夹的Item.json 文件中ID 的值后跟 _Name 来指定物品的显示名称,ID 的值后跟 _Description 来指定物品的显示描述。例如 ID 名为 Coin 的钱币,Coin_Name 在翻译文件中即表示显示名称。
添加武器:
在根目录创建 Weapon 文件夹,所有的武器全部放在这里。
然后在其中创建一个或多个 Json 文件,文件名随意,可根据实际需要进行归纳。
将以下数据抄写其中:
[
{ // 武器1
"ID": "", // 武器对象名称
"Type": 0, // 类型
"UseSpace": 0, // 消耗的空间
"StarRating": 2, // 星级,仅影响显示颜色
"CharacterProperty": {} // 角色基本属性数据结构,指定对人物的加成
},
{ // 武器2
"ID": "",
"Type": 0,
"UseSpace": 0,
"StarRating": 2,
"CharacterProperty": {}
}
//...翻译键:在ID字符串后加“_Name”是指定显示名称,在ID字符串后加“_Description”是指定显示描述。
武器星级:2级为普通,绿色;3级为精致,蓝色;4级为稀有,紫色;5级为传说,橙色;6级为特殊,红色。建议以5级作为上限,6级特殊可作为彩蛋武器。
武器类型:0为未指定,设定此值不会添加到游戏数据中;1为近战;2为投掷;3为弓箭;4为法器;5为火器。
关于投掷类型的武器,由于武器没有耐久度这类消耗值属性,对于普通武器来说容易显得不真实,例如扔不完的飞刀难以解释,因此在设计这类武器时,应作为特殊或者彩蛋武器。
属性数值武器仅提供固定的基础数值加成,在技术层面此处采用与角色数据中的角色基本属性相同的数据结构,因此可指定所有基础属性加成,详细键值对请参见后续内容。设计数值时需充分考虑显示效果,不建议设计超过5个属性加成,过多属性会挤压描述显示空间,甚至可能超出显示区域。武器不存在任何养成元素,设计时请注意。数值可以为负值!!!对于6级武器来说可以适当发挥 角色基本属性数据结构 在后面多个地方会用到这个结构 { "生命值": 0, // 生命值,整数 "攻击": 0, // 攻击,整数 "防御": 0, // 防御,整数 "速度": 0, // 速度,整数,基准值:100 "暴击率": 0, //暴击率,单精度值 "暴击伤害": 0, // 暴击伤害,单精度值 "抵抗概率": 0, // 抵抗概率,单精度值 "填充效率": 0, // 填充效率,单精度值 "护盾加成": 0, // 护盾加成,单精度值 "治疗加成": 0, // 治疗加成,单精度值 "物理伤害加成": 0, // 物理伤害加成,单精度值 "法术伤害加成": 0, // 法术伤害加成,单精度值 "生化伤害加成": 0, // 生化伤害加成,单精度值 "神秘伤害加成": 0, //神秘伤害加成,单精度值 "物质伤害加成": 0, // 物质伤害加成,单精度值 "黑暗伤害加成": 0, // 黑暗伤害加成,单精度值 "物理抗性": 0, // 物理抗性,单精度值 "法术抗性": 0, // 法术抗性,单精度值 "生化抗性": 0, // 生化抗性,单精度值 "神秘抗性": 0, // 神秘抗性,单精度值 "物质抗性": 0, // 物质抗性,单精度值 "黑暗抗性": 0, // 黑暗抗性,单精度值 "提供的远行队空间": 0 // 提供的远行队空间,整数
这些属性可以是负值,在需要的地方可以设计负值来平衡属性。
添加装备:在根目录创建【Equipment】文件夹,所有的装备全部在这里,然后在其中创建一个或多个Json。文件,文件名随意,可根据实际需要进行归纳。将以下数据抄写其中:
[
{ // 装备1
"ID": "", // 对象名称
"Type": 0, // 装备部件类型
"UseSpace": 0, // 使用负重
"StarRating": 2, // 星级,仅影响显示颜色
"CharacterProperty": {} // 角色基本属性数据结构,指定对人物的加成
},
{ // 装备2
"ID": "",
"Type": 0,
"UseSpace": 0,
"StarRating": 2,
"CharacterProperty": {}
}
//...
]翻译键:在ID字符串后加“_Name”是指定显示名称;在ID字符串后加“_Description”是指定显示描述。
装备星级:
2:普通,绿色
3:精致,蓝色
4:稀有,紫色
5:传说,橙色
6:特殊,红色
建议用5级封顶。
装备部件类型:
0:未指定,设定此值不会添加到游戏数据中
1:头部
2:躯干
3:腿部
5:奇物
设计提醒:装备系统的布局为3+2模式,其中的2是两件奇物;装备没有套装加成,也就是跟武器相似,仅提供数值加成,同理数值可以是负值。
添加角色:在根目录创建Character文件夹,所有的可战斗角色全部在这里;然后在其中创建Json文件,文件名随意,每一个角色单独一个文件。json 文件 定义模组基本信息和依赖信息
Cover.jpg 文件 在模组列表中显示的封面图
*.dll 文件 动态链接库,在清单文件中定义要加载哪些
<各种文件夹> 文件夹 存放不同类型内容的文件夹
在接下来的章节中详细了解
编写清单文件
将以下数据抄写到 Manifest.主体数据这一部分是主体结构,其中包含多个其他数据结构。请先直接把这一部分抄写于文件中:
{
"ID": "", // 角色对象名称
"StarRating": 4, // 角色的星级,最低4级,最高6级,请用5级封顶,6级应作为彩蛋或特殊内容
"ProfessionType": 0, // 职业类型,仅向玩家展示角色设计定位,不会影响其他内容
"PropertyData": {}, // 角色基本属性数据结构,设定初始值
"UseWeaponType": 0, // 使用的武器类型
"Skill_TB_Normal": [], // 回合制普通攻击的数据,类型:技能数据单级结构,列表形式
}"Skill_TB_Tactics": [], // 回合制战技的数据,类型:技能数据单级结构,列表形式 "Skill_TB_End": [], // 回合制终结技的数据,类型:技能数据单级结构,列表形式 "Skill_TB_NormalAddValue": 10, // 回合制的每次普通攻击能积攒多少技能槽,整数 "Skill_TB_TacticsCostValue": 10, // 回合制的每次战技要消耗多少技能槽,整数 "Skill_TB_EndCostValue": 50, // 回合制的每次终结技要消耗多少技能槽,整数 "Skill_RT_Normal": [], // 即时制普通攻击的数据,类型:技能数据单级结构,列表形式 "Skill_RT_Tactics": [], // 即时制战技的数据,类型:技能数据单级结构,列表形式 "Skill_RT_End": [], //即时制终结技的数据,类型:技能数据单级结构,列表形式
"Skill_RT_TimeSpeed_Millisecond": 500, // 即时模式的行动速度,毫秒,指每一次行动间隔的时间,同时也等于开始战斗后等待多久才打出第一次伤害
"Skill_RT_NormalToTacticsNumber": 2, // 即时模式中,执行几次普通攻击后执行战技
"Skill_RT_NormalToEnd_AddValue": 0.05, // 即时模式的每次普通攻击能够积攒的终结技槽,百分数小数形式
"Skill_RT_TacticsToEnd_AddValue": 0.1 // 即时模式的每次战技能够积攒多少终结技槽,百分数小数形式 "Talent1": [], // 第1个天赋数据,类型:天赋单级结构,列表形式 "Talent1Name": "", // 第1个天赋的显示名称,在角色翻译文件中指定键 "Talent2": [], // 第2个天赋数据,类型:天赋单级结构,列表形式 "Talent2Name": "", // 第2个天赋的显示名称,在角色翻译文件中指定键 "Talent3": [], // 第3个天赋数据,类型:天赋单级结构,列表形式 "Talent3Name": "", // 第3个天赋的显示名称,在角色翻译文件中指定键 "Story": [] // 角色资料,其中的键是条目名称,值是条目内容,在翻译文件中指定详细的文本,这里只是指向翻译文件 在角色翻译文件中ID 的值后跟 _Name来指定角色的显示名字。例如,DeWan_Name 这个键提供了本体剧情中的【德万】的名称显示。
职业类型:
未指定 = 0
生存 = 1
强攻 = 2
辅助 = 4
治疗 = 5
属性类型:
未指定 = 0
物理 = 1
法术 = 2
生化 = 3
神秘 = 4
物质 = 5
黑暗 = 6
技能类型:
未指定 = 0
回合制_对敌单体伤害 = 101
回合制_对敌相邻两位伤害 = 102
回合制_对敌相邻四位伤害 = 103
回合制_对敌全体伤害 = 104
回合制_对敌单体Buff = 111
回合制_对敌相邻两位Buff = 112
回合制_对敌相邻四位Buff = 113
回合制_对敌全体Buff = 114
回合制_对友单体治疗 = 121
回合制_对友相邻两位治疗 = 122
回合制_对友全体治疗 = 123
回合制_对友单体加盾 = 131
回合制_对友全体加盾 = 132回合制_友方单体增益=141
回合制_友方全体增益=142
即时制_敌方前排单体伤害=201
即时制_敌方前排两位伤害=202
即时制_敌方前排三位伤害=203
即时制_敌方前排四位伤害=204
即时制_敌方前排五位伤害=205
即时制_敌方全体伤害=209
即时制_敌方生命值百分比最低单体伤害=211
即时制_敌方防御力最低单体伤害=212
即时制_友方生命值百分比最低单体治疗=221
即时制_友方全体治疗=222
即时制_友方全体护盾=231
即时制_友方全体增益=241
基准数值类型
未指定=0
生命=1
攻击=2
防御=3
技能数据单级结构:这是单独一个等级的数据,实际使用是列表形式就是用方括号包含的数组,按照从上到下依次是每一个等级 { "技能内容": [ { // 此等级此技能的第1个动作,最多支持3个动作,多写的无效 "技能类型": 0, // 技能类型,指定要执行什么操作,注意此枚举值写错不会执行 "属性类型": 0, // 属性类型,如果选定的技能要打伤害,那么指定打出什么类型的伤害 "数值类型": 0, // 指定一个角色基本属性数据结构中的数值作为基础数值 "数值": 0.0, // 百分数小数形式,指定要乘以基础数值的一个百分比
"最终数值附加": 0 // 在最终数值(上面的相乘结果)上加上一个额外的数值
},
{}, // 第2个动作
{} // 第3个动作
],
"升级需求": [ // 升级到此等级需要消耗的材料。等级1不需要此对象,写了也不会生效 { "Key": "", // 物品ID "Value": 0 // 数量 } // 写太多会导致显示不下,但全都生效,不过真不建议写太多 ] } 天赋单级结构这是单独一个等级的数据,实际使用是列表形式,就是用方括号包含的数组,按照从上到下依次是每一个等级 { "TalentContent": {}, // 天赋内容,类型为角色基本属性数据结构 "UpgradeRequirements": {} // 升级到此等级需要消耗的材料,同理 } 天赋系统受限于技术问题,只能作为一个额外的基础属性加成存在,但可以指定到角色基本属性数据结构中的所有属性。推荐把天赋的升级材料设计得严苛一些,比如数量较多的材料或者难以获得的稀有材料。角色资料
角色资料的数据类型与前面升级材料的数据结构相似,像这样:
{
"Key": "", // 条目名称,在角色翻译文件中指定键
"Value": "" // 条目内容,在角色翻译文件中指定键
}
添加岗位
在根目录创建【Production System】文件夹,在其中创建名为【Job.json】文件
将以下数据抄写其中
[
{ // 这是一个岗位的完整数据
"ID": "", // 此岗位的对象名称
"ResourcesProducedPerHour": [ // 指定每个小时的每一个此岗位提供什么资源
{
"Key": "", // 物品的对象名称
"Value": 1.json 文件中并填写好其中的信息 { "ModName": "", //模组名称,显示在模组列表中 "Author": "", //作者 "Version": "", //版本 "UniqueID": "", //唯一ID,注意区分大小写 "Description" : "", //简要描述 "SupportedGameVersion": [], //支持的游戏版本,字符串数组,作为创意工坊标签的一部分 "UnSupportedGameVersion": [], //不支持的游戏版本,字符串数组 "AgeRating": "", //年龄分级,作为创意工坊标签的一部分,可选项:Everyone、Parent Guide、Aldult "Tag": [], //创意工坊标签主体,字符串数组,可选项查看文末注释 "Dependencies": [], //依赖项,这些UniqueID必须安装,字符串数组 "LoadDll": [] //要加载的 DLL 文件,从根目录算起,字符串数组 } // Tag5 // 提供数量,支持三位小数
}
],
"每小时资源消耗": [ // 指定每个小时该岗位消耗的资源
{
"键": "", // 物品的对象名称
"值": 1 // 消耗数量,支持三位小数
}
]
},
{} // 第二个岗位 ...
]
在语言文件夹的 Job.json 文件中ID 的值后跟 _Name 来指定岗位的显示名称
ID 的值后跟 _Description 来指定岗位的显示描述
技术细节游戏中岗位资源生产按照每小时计算一次,在正常情况下岗位会每天工作 8 小时,可以由玩家在决策中调整为最大 12 小时,最小 0 小时
需要注意的是:当程序计算岗位生产情况时,不会管距离上一次变动过去了多久,也就是说比如玩家在即将计算的前一瞬间调整了岗位安排,那么仍旧视为该岗位完整工作了 1 小时标签可选项如下,不含冒号,注意字符和没有头尾空格,否则不会生效 // Colony:殖民地;对殖民地进行添加或编辑 // Building & Work:建筑和工作 // Map:地图;对地图进行新增或编辑,其中的事件点等等 // Character:角色 // Weapon & Equipment:武器和装备 // Event & Mission:事件和任务;所有剧情 // Item:所有物品类型的,比如关键物资、制作材料、任务物品等 // Planting:特指可进行种植的消耗品 // Vehicle:载具 // Enemy & Combat:敌人和战斗;新增或编辑了敌人和战斗对局的 // Shop:商店 // Audio:添加或编辑了背景音乐或特效声音的 // Image:添加或编辑了图像资源的 编写提示UniqueID格式推荐:<作者名>.<模组名>,例如官方基础内容:Lake1059.FinalTown
重复的UniqueID不会扫描进列表!
当前游戏版本:Dev3
字符串数组的表达形式为:["字符串1", "字符串2", "字符串3"]
有的时候可能是列表数据,需要注意排序
添加封面图(可选)
将Cover.jpg 放置于根目录即可,注意这相当于设置创意工坊的物品封面图。强烈推荐使用正方形尺寸。不设置也是可以的。文件大小最好不要超过 1MB,否则容易上传失败。添加图片资源:游戏中的图片资源几乎只有地图格图标会用到。在模组根目录创建 Image 文件夹。将图片直接放置其中,其不含后缀的文件名将作为用来调用图片的名称。技术细节支持 SVG 矢量图,游戏会根据实际需要和当前 DPI 自动调整绘制分辨率。对于普通图片,仅支持 .添加音乐和音效:
音乐也就是游戏中的背景音乐,在根目录创建【Music】文件夹,然后直接将音乐文件放置其中。不含后缀的文件名将作为游戏内调用名称,支持【FLAC】、【WAV】、【MP3】格式。
音效是当玩家执行操作,例如按下按钮、触发情况等时播放的极短音频,在根目录创建【Sound】文件夹,然后直接将文件放置其中。不含后缀的文件名将作为游戏内调用名称,仅支持【WAV】格式,这些音频一般不超过一秒钟。
技术细节:
背景音乐在程序内仅记录文件路径,播放时从硬盘读取。
音效完整读入内存,所以请尽可能避免使用超过1秒钟的特效音。
字符串多语言请注意:游戏内文本强制使用多语言支持,因此你不能直接把文本包含在对象数据中;游戏采用多个字典对各类语言数据进行统一管理,以方便其他人制作翻译模组。
在模组根目录创建Language文件夹。
在其中创建语言文件夹:
zh:中文
en:英文
目前暂无支持其他语言的计划。
在这些语言文件夹中创建各Json文件,具体文件名会在对应内容中说明。
文件中的数据例如这样:
[ "123": "123123123", "3456": "6868536", "6575": "463252345" ]
其中键名称是指定文本的ID,在各种数据中调用;其中键的值就是对应的文本,要显示给玩家。
添加物品:在根目录创建Item文件夹,游戏内的所有物品(不包括武器和装备)全部在这里。在其中创建一个或多个Json文件,文件名随意,可以根据实际需要进行归纳。将以下数据抄写其中:
[ { // 物品信息1
"ID": "Coin", // 物品ID 用于调用
"Type": 1, // 类型
"UseSpace": 0.001, // 此物品的单件消耗多少空间,仅限3位小数
"Effects": [], // 消耗品专用,指定消耗品的效果,非消耗品指定无效
// "Effects": [{"Type": 1, "Value": 0.