PID: 78036181
————————————————写在前面————————————————
1. 本教程基于SPT-AKI2.3.0版本制作,理论上在2.3.1版本可以使用。
2. 教程内一切内容都基于个人理解,如有谬误还请指出,不胜感激。
3. 这条我不知道写啥了,但我感觉三行对齐会显得比较好看…………
————————————————还是碎碎念————————————————
站内的服务端MOD教学已经停止更新,思考了一段时间后还是决定出个教学……由于我本人也是个半桶水,并不是专业的程序员,讲解过程可能存在一些概念上的错误,还请谅解。这篇教程不止使用模板,旨在讲解制作、修改的思路以及基于我个人理解对于服务端本身以及部分文件的结构剖析,如果有错误还希望各位大佬指出(鞠躬)。
注1:请确保你已经阅读过此篇文章:逃离塔科夫离线版服务端MOD制作教程
注2:请确保你已经阅读过此篇文章:服务端MOD制作教程,初级版
注3:强烈建议使用VSCode进行开发,软件请自备
注3:本教程可能需要一定的js基础知识,这个也请自备……
————————————————基础讲解————————————————
首先让我们来看一个什么都没有的空壳MOD
packge.json是Mod信息,mod.js中对mod进行实例化并将mod主体指向Class1.js,Class1里目前什么都没有,我在mod.js中插入了一个console语句用于在载入时输出信息。
可以看到控制台成功输出了信息,表示mod已经加载。
(以下内容默认你已经读过了注释中的两篇文章,并有了一定的理解,当然后面我会放出本教程用到的一切工程以及具体方法,不懂没关系,照做就对了(笑)。)
众所周知呢,在js中,万物皆是对象。而实际上在Mod制作的过程中我们所需要进行的修改也是基于对象的。
举个栗子:
此处的DatabaseServer.tables读取的是服务端数据结构,此处的Client.templates.items即表示database/templates/items(有过修改服务端经验的朋友应该知道这是什么),我们使用console语句将items输出到控制台。
可以看到控制台在疯狂刷新,将整个items文件输出到了控制台……显然这样毫无头绪,让我们换个方式:
这次只有简单的一行信息了,控制台告诉我们,item的类型是一个对象。
让我们看看items的文件结构:
可以看到,items里的每一个属性以物品ID命名,而而内容就是物品的详细数据,通过查询ID索引,我们找到Salewa血包的ID,并通过属性名访问。
可以看到控制台输出了Salewa的全部物品数据。
顺便输出一下类型,我们可以看到,在items里,SalewaID这个属性的内容也是一个对象。
接下来我们试着修改Salewa的使用次数:
使用次数这个属性在_props里,我们通过语句访问将使用次数更改为800
可以看到前后对比,接下来进游戏验证一下。
可以看到确实生效了,而对于其他文件的修改、调整,也是同样的方法。
————————————————进阶部分————————————————
Part.1: 向游戏添加一个商人。
我们在Mod根目录新建一个名为traders的文件夹,在traders目录下创建名为MyTraders的文件夹。
从原版任意一个商人(database/traders/ID)目录中复制base、assort和questassort三个json文件到MyTraders文件夹下,打开base.json。
其中base是商人基础信息,assort是商人的售卖列表,而questassort表示的是通过任务解锁的交易。
修改base中的_id为MyTraders,这里是唯一ID,每一个商人不可重复。
那么怎么让游戏内加载这个商人呢,还记得开头的话吗?js中,万物皆是对象。
将traders目录作为变量定义,使用for循环将其作为一个对象遍历,对于其中的每一个属性Traders,将其赋值给DatabaseServer.traders[Traders]。
进入游戏可以看到,这里已经多了一个商人,但是却缺少了详细信息。
我们来到对应的汉化文件位置(database/locates/global/ch)。
按照之前的思路,我们应该自己创建一个目录,然后创建json,并且向里面写入相似的内容,然后使用for循环向对象添加内容……like this
但是——想一想我们前面说的,js里万物皆是对象。
那么有没有办法让我们省去这个创建目录、文件的过程呢,对于这种需要的字符串不多、调用部分也不多的东西,显然是可以的。
在base中插入一个新的属性description,并输入对应的值,然后将nickname和location分别修改,为你的商人在语言文件的trading属性里创建一个空对象,并对其对应的属性进行赋值(FirstName和FullName游戏内似乎并没有用到,如果感觉不妥在base中创建对应属性赋值即可)。
效果完美。
如果想要自定义商人头像的话,则需要使用ImageRouter加载图片资源,这里我随意制作了一张图片作为商人头像。
关于商人的具体信息呢,请在base中自行对照修改。
那么商人本身的部分到此结束,我们来讲一讲售卖物品。
Part.2: 自定义商人出售的物品。
这里我用一个空的assort文件作为演示说明。
很显然,assort文件也是一个对象,里面有items数组和barter_scheme、loyal_level_items两个对象一共三个属性。
接下来我会编写四个例子来进行说明:
第四个例子比较特殊,首先我们来看前三个例子:
items中,_id是每一个交易项目的ID,依然不可重复;_tpl是交易的物品的ID,parentId和slotId这里暂且不讲,对于普通物品止直接填写hideout即可;upd属性中我们可以看到有四个属性,其中BuyRestrictionMax是限制购买的数量,BuyRestriction也和限制购买有关系,但我能力有限,实在不知道啥意思,反正这里填0就可以,StackObjectsCount表示商人的存货数量,UnlimitedCount则决定了这个物品是否是无限量供应的,如果不提供这项属性,则物品将在被买空后断货。
接下来让我们来看barter_scheme
barter_scheme是一个对象,其包含的每一个属性即为items里每一个交易项目对应的ID,而内容则是交易所需的物品,参数简单明了,count表示数量,_tpl表示交易所需的物品,例子3则是需要多个物品进行兑换的情况。
最后的属性loyal_level_items就更简单了:它的每一条属性依然对应交易项目的ID,参数值则是需求的商人好感等级,1-4。
接下来让我们把目光放到特殊的例子4上:这个例子向你展示了如何让商人出售完整枪械。
可以看到这里稍微有所不同,下面的一大堆不包含upd属性的即是这把枪上的配件,因为我是直接从枪匠的assort中复制而来,我也不知道这把枪对应的物品是啥……不过这并不妨碍讲解。
如你所见,_id、_tpl这两个属性依然表示ID和物品本身,但是与之不同的是parentId和slotId,parentId。
每一个部件的parentId指向需要安装在的物品的位置,也就是对应的交易项目ID;每一个部件的slotId指向的是部件所对应的安装栏位。
我们先保存文件,进入游戏查看一下效果:
原来是格洛克……我说怎么没枪托(叹)
接下来要讲的是,如何从无到有为商人添加一把完整的枪械,显然,通过自己查找对应ID进行手动编辑的方式无比繁琐……那么有没有什么更加方便、快捷的方法呢?
答案当然有,让我们来到武器预设页面。
这里用黑DT作为例子,打开预设,把它改装成你想要的样子组装,我就随便改改了。
接下来我们退出游戏,找到你的存档文件,位置在游戏根目录/user/profiles,找到你的存档文件并打开,搜索黑DT的ID,找到对应的物品,搜索其ID。
不难发现,其中一部分物品的parentId指向了黑DT本身,结合前文,我们通过查找parentID和_ID,把对应的部件整理、复制到一个单独的文件中,删除多余属性并修改ID。
然后用我们修改完的”黑DT本体1″替换掉例子4,查看一下效果,务必注意多余逗号可能产生的格式错误。
可以看到效果非常好。
看到这里想必你已经学会如何添加一个新的商人了,此处便不再过多赘述,接下来让我们进入下一个也是最复杂的环节——任务。
Part.3: 为商人编写任务
由于任务文件结构较为复杂,我的精力也比较有限,这部分内容我会以后再细讲,我会在最后放出的工程文件里编写两个示范性任务作为参考,有能力的同学可以自己研究,这部分内容会在日后进行补全。
Part.4: 创造自己的物品、Buff组
相信看到这里的你,对于如何添加物品文件已经有了自己的想法,其实这个过程已经和超级模组的独立物品步骤相似。
比如我们想要添加一个使用次数为30次的独立手术包,搜索ID,将野战手术包的数据完整复制到items.json中并更改ID,name,shortname和desc等参数。
将使用次数修改为30,将物品进行加载。
打个Logger来查看物品是否正常加载:
可以看到物品已经正常加载(前面的代码有一部分错误,我进行了修改)
由于游戏内无法通过控制台给予物品,我们通过为商人添加交易项的方式把双倍速手术包添加到新商人的出售列表中,过程不再截取。
效果很完美。
接下来讲讲怎么添加自定义的buff组,首先按照上面所说的复制一根绿针。
创建globals.json,内容如下:
为服务端对象添加内容,将超级回血针的buff组调用修改为你创建的buff组。
可以看到buff组已经正常起效。
————————————————自言自语————————————————
从下午三四点写到现在,勉强是把这个教程完成了。也算是给了自己一个交代,关于任务的部分我会在日后补完。
写到现在,恍惚间才发觉这篇教程似乎并不适合零基础的新人,而对于已经对mod开发有所了解的人,似乎又有点食之无味;我也不知道我后面抱着什么样的心态将这篇教程结尾,也许只是为了满足自己吧,希望这篇乱七八糟的教程能够帮到更多想要创作属于自己的东西的人。更加简洁的mod模板也会在之后进行重新整理、发布。
在这么短的时间里,从对塔科夫提起兴趣,到发现离线社区,再到自己一步步从独立物品发展到服务端mod,期间离不开诸多大佬的帮助,而我也在这个过程中学到了很多东西,然而当我完成自己的mod后,创作的热情却在日益消退。
所以我才会写下这篇教程,希望它能够帮到更多的人,更多有着想法却被知识所困的人。
起码在我对塔科夫的热情彻底消退之前,我想留下点什么证明自己来过。
——千叶玲花,于2022年7月17日
————————————————相关链接————————————————
如何制作独立bundle文件:https://sns.oddba.cn/28688.html
基础服务端mod教学:https://sns.oddba.cn/16676.html
SPT-AKI-2.3.0版本原始服务端数据及源码下载:https://dev.sp-tarkov.com/SPT-AKI/Server/src/tag/2.3.0
本Mod用到的工程文件:
链接:https://pan.baidu.com/s/1MYPG3Y-GDcECgMl0VNZBGw
提取码:MHWI
最后,感谢你看到这里。
————————————————支持链接————————————————
隐藏内容需要付费才可以看见
多谢分享,真的辛苦!特别感谢!!!
真棒棒,我学习下