cataclysmdda吧 关注:21,008贴子:330,033
  • 9回复贴,共1

新人向|无基础情况下如何从0开始写MOD

取消只看楼主收藏回复

(忘记是哪个大佬的图了,有记得的记得说一下)


IP属地:山东来自Android客户端1楼2022-06-16 14:22回复
    很多人入坑都是因为CDDA极高的自由度与极好的操作手感[雾]
    作为开放式生存游戏,MOD一直都是不可缺少的一环,但是CDDA因为目前较弱的MOD支持和偏小众的游戏定位使得它现在并没有足够媲美它本身的MOD群体。
    吧里已经有大佬发过MOD的教学贴,但是更像是经验分享这一类,幸存者基地那里倒是有不错的教程,不过鸽了好久了。
    所以打算开个MOD教程贴,教一下如何入门。


    IP属地:山东来自Android客户端2楼2022-06-16 14:22
    收起回复
      一、制作一个更好的背包
      打开我们的游戏根目录/data,在通常情况下,我们只需要使用到这两个文件夹里的东西:

      第一个json 我们会去里面查找游戏物品的源码
      第二个mods则是我们的mod存放的位置,我们也会常常去其中借鉴其他mod的处理方式
      (由于是教学,借鉴也是真的借鉴,以后出现在教学里的mod都会写明原作者,希望没有版权纠纷)
      我们除此之外还需要一个能打开json的文本编辑器,我用的Notepad++,也可以sublme text,甚至记事本也可以。为了顺手,我就用Notepad++了。
      那好,我们现在有了游戏本体、文本编辑器以及一个想法——制作一个更好的背包
      那我们首先要知道,背包在代码层面什么样子?
      那我们去物品浏览器搜索一下


      我们发现,背包的ID是backpack,(要注意的是,并不是所有物品的id都是它的英文名)
      我们去Notepad++里搜索一下
      打开Notepad++里的文件中查找

      然后从这里找到之前提到的data文件夹

      目标自然是背包的id

      查完以后有很多很多项,我们要找那个id:“backpack”的

      很好,在这里!

      双击打开,我们现在找到了背包的源码


      IP属地:山东4楼2022-06-16 15:13
      收起回复
        把光标点到id前面的”{“上,可以发现符号变红了,我们用滚轮划到下面,发现另一个“}”也变红了,这两个括号内的内容就是这个id为backpack的物品的代码了,我们把他复制下来,放到你自己的json里
        (创建方式为,新建一个文本文档,把拓展名改为“.json”)
        虽然有一些基础的朋友到这里已经明白了,但既然是小白教学,咱们就傻瓜式一点,打开翻译,我们把整段代码翻译一下:(为了方便阅读,我就放到了文本文档里)

        那我们理想中的背包应该是什么样子的?要有一个大空间,要体积够小、重量更轻,更方便制作。
        那好,我们先解决大空间。
        通过翻译,我们很容易就找到,代码里面更跟储物空间扯上关系的,就只有一条条"pocket_type": "CONTAINER",属性
        我们删除其余的"pocket_type": ,只留下那个最大的,也就是:
        "pocket_data": [
        {
        "pocket_type": "CONTAINER",
        "max_contains_volume": "25 L",
        "max_contains_weight": "30 kg",
        "max_item_length": "40 cm",
        "moves": 300
        },
        ]
        它明显不那么够大,我们给带单位的加几个0,
        "pocket_data": [
        {
        "pocket_type": "CONTAINER",
        "max_contains_volume": "25000 L",
        "max_contains_weight": "30000 kg",
        "max_item_length": "40000 cm",
        "moves": 300
        },
        ]
        (为什么不给moves加呢,因为这个属性是代表了对行动的影响,数值越大你越难把东西取出来,面对未知属性改如何查找我们很后面才会讲,这里只是满足一下大家的好奇心)
        那我们继续,依照相同的方法,我们把背包的重量和体积改小
        "weight": "63 g",
        "volume": "1 L",
        制作方法,我们在这里还找不到,那就说明不在这里,我们先放放,先这样子。
        好!现在已经修改的差不多了,既然是mod,那必然要改一个id,我就叫“goodbeibao"好了,描述也改一下,就叫“嘿嘿哈哈↑↑↓↓←→←→BABA繁华卍落尽π”好了
        保存,退出!
        (特别注意:文件里面必须以”[{“开头,以“}]”结尾,如果格式不对会报错,如:
        DEBUG : Error: Json error: data/mods/一个更好的背包/goodbeibao.json:21:8: comma not allowed at end of array
        "max_item_length": "40000 cm",
        "moves": 300
        },
        ^
        ],
        "warmth": 6,
        FUNCTION : bool main_menu::new_character_tab()
        FILE : src/main_menu.cpp
        LINE : 949
        VERSION : ac85e55


        大家从一些其他的教程中也知道了,mod必须有个“modinfo.json”文件来说明这个mod的信息,那我们也要创建一个,信息如下:

        (这里除了前两项以外,别的都可以自由发挥,具体的大家去翻译一下就好)
        好!现在就基本全了,这个样子:

        我们把文件夹拖进mods里面,然后开启游戏试一下

        可以看到mod已经正确被识别了。
        让我们进去看一下,很好,没有丝毫意外的进去了

        由于我们还没设计如何获得这个物品,不过为了避免大家好奇,我通过特殊手段给大家看一下我们这个背包

        非常成功!


        IP属地:山东6楼2022-06-16 16:36
        收起回复
          二、如何设置制作配方
          经过昨天的研究,我们有了一个mod的雏形,但是我们目前还无法获得这里面的物品。
          这次就来解决它!
          在CDDA这个游戏中,我们最常用的物资获取方式有三种:出生自带、地图刷新、&里合成。
          第一种我们放到人物职业章来讲
          第二种放到地形地貌讲过以后再单开一章
          这次讲最简单的,合成!

          虽然大家可能都知道,合成配方是"type" : "recipe",但我们还是要假装不知道来讲。
          那我们在不知道具体信息在什么地方的时候,就要用好现有的每一个信息。
          我们的思路仍然从背包开始,既然我们要找背包的配方,那么想当然应该要找”backpack“,但是直接搜backpack会出来各种背包的变种。
          那不妨试试带引号,毕竟按道理我们之前看到的代码都是【”类型“:”内容“】的格式,理应配方也是【”产出“:”背包“】这种。

          不过,虽然推测十分合理,但是我们并没有搜到想要的结果,无奈只能在backpack的281个结果中去找
          经过不懈的努力,我们发现这个result很像我们要找的东西(明明就是好吧~~)

          我们点进去看一下:

          看起来非常像我们需要的代码,不过为了保险起见,我们翻译一下:

          看来没错了!
          我们把东西放到之前的goodbeibao.json中(也可以新建一个json,不过因为教学文件的代码不多,我就直接都放一起了。这里补充一句,在目前的CDDA中,除了mod信息以外的代码,都可以以任意顺序放在任意命名的JSON中,以后不再说这个问题,大家有需要自己分文件就好。)

          注意两个{之间要用英文逗号隔开,末尾的}与]之间不能有符号
          同样的,我们改改数据:
          {「结果」:「背包」,
          “类型”:“配方”,「活动水平」:「轻_运动」,
          【类别】:“CC战甲”,
          “子类别”:“CSC装甲_存储”,
          “使用的技巧”:“裁缝”,
          【难度】:3,“时间”:“10 h”,
          “自动学习”:没错,“可逆”:真,
          "使用":[ ["剪裁_尼龙_拼布",3 ],["拉链_大号",2 ] ],
          "熟练程度":[ { "熟练程度":"教授封闭" },{ "熟练程度":"教授封闭防水" } ]},
          最主要的,我们的result应该指向我们的goodbeibao而不是原本的backpack,
          其次,配方也要改一下,就.....一个拉链好了!(用拉链把东西存起来,很合理的好吧~~)
          难度什么的都降到1,熟练度看不懂先不管,最后变成这个样子:
          {
          "result": "goodbeibao",
          "type": "recipe",
          "activity_level": "LIGHT_EXERCISE",
          "category": "CC_ARMOR",
          "subcategory": "CSC_ARMOR_STORAGE",
          "skill_used": "tailor",
          "difficulty": 1,
          "time": "1 s",
          "autolearn": true,
          "reversible": true,
          "using": [ [ "fastener_large", 1 ] ],
          "proficiencies": [ { "proficiency": "prof_closures" }, { "proficiency": "prof_closures_waterproofing" } ]
          }
          然后,保存,进去游戏看一下
          很好,非常成功!


          IP属地:山东12楼2022-06-17 14:47
          收起回复
            接下来让我们延申一下,虽然后面的"proficiencies"我们很容易就猜出来是专长效果,但我们不妨借此来思考一下,面对未知的词条应该如何解决?
            就比如
            "recoil": 1400,
            "proportional": { "price": 0.7, "dispersion": 1.1 }
            "shot_spread": 1,
            这些都是些仅凭翻译无法确定作用的代码。(其实完全可以凭借经验判断,经验欠缺也可以在游戏里查看词条,不过因为是教学,就用这些比较简单的词目了)
            那依然以"proficiencies"为例,我们先去文件搜索一下这个词条:

            于是我们发现,大多数条目中都是类似的结构
            那我们转为搜索其中的某个条目,比如“prof_leatherworking_basic”
            我们查到了如下结果,其中有一个以id开头的很让人在意

            点击去看一下
            {
            "type": "proficiency",
            "id": "prof_leatherworking_basic",
            "category": "prof_tailoring",
            "name": { "str": "Principles of Leatherworking" },
            "description": "You've got a basic familiarity with how to work with leather, furs, hides, and similar materials.",
            "can_learn": true,
            "default_time_multiplier": 1.5,
            "default_fail_multiplier": 1.5,
            "time_to_learn": "4 h"
            }
            不错,看来我们找到了我们想要的,不过距离我们的目标还差一点点,我们需要的是任意更改自己的mod中的"proficiencies"而不仅仅是删除不用的,那么我们就需要知道其他的"proficiencies",去之前的搜索结果里一个一个找固然是个办法,可我们为什么不直接搜索呢?
            我们来搜索一下"type": "proficiency",

            一共有15个文件共125个条目(与你装的mod的数量有关)
            通过对比我们很容易发现,每个"type": "proficiency",都在不同的以技能名命名的JSON,所以以此推论,我们需要电子学的第一个专长,那么我们就打开electronics.json去找到prof_elec_soldering,将它加入我们的配方中,也就是:

            打开游戏我们看一下效果:

            非常成功!!


            IP属地:山东13楼2022-06-17 15:50
            收起回复
              三、如何从优秀的作品中学习
              ——————————————————————
              本次使用的教学mod是mod创作基地里下载的教学mod
              【[军用无人机][EN]Military_UAV】
              作者为:
              "authors": [ "Aunt_Su | 苏大妈#7831" ],
              "maintainers": [ "Aunt_Su | 苏大妈#7831" ],
              未有作者授权、我也不认识他
              但mod里也没说不让拿来当教材
              总而言之,我们开始吧!
              ——————————————————————
              我们现在有着一个非常优秀的mod,我们想学习其中的技巧方法化为己用,我们该怎么做呢?
              首先,先看一下mod的文件构成:

              一共有三个文件,其中两个是我们所知道的:
              一个XXXX.json是mod本体
              一个modinfo.json是mod的说明信息
              另一个32x32.png我们没有见过,猜测是贴图文件,那么我们先打开看看:

              很明显,是无人机的贴图
              【很好!我们可以从这个mod中学习至少一部分的贴图使用方法!】
              那继续看其他文件,这里建议先modinfo,因为这个文件通常不会太大,而且里面的mod介绍可以更好的帮助我们去理解mod的内容
              那我们打开看看:

              里面除了我们熟知的
              "type": "MOD_INFO",
              以外,还有一个
              "type": "mod_tileset",
              这个东西我们没见过,而且单词我们也不认识,那么我们翻译一下:


              经过翻译,我们发现我们仍然不知道这是什么东西
              那就用老办法——不管了,爱咋咋地
              我们继续看
              下一行是compatibility,也就是兼容,后面跟了一些模组名称
              也就是说,这一句表示它(这个mod)所兼容的其他mod
              下一句是一个明显的大括号,经过之前的经验,括号内的应该是一系列同一种东西

              可以发现,里面的语句排列整齐,fg分别从0到7,一共八种
              可旋转的属性被标为了false
              我们再去数一下贴图文件,一共8个,与这里的八种相互匹配
              所以这个极大概率就是贴图的使用方法
              那让我们仔细看看
              里面先是给了一个id,然后跟着一个名为fg的参数,最后跟着是否可以旋转
              那我们去另一个文件里找一找相关id
              搜索结果很让人惊讶
              "id": "Tactical_Pad"和"id": "Tactical_Pad_on"是可以搜索到的
              但是"id": "overlay_wielded_Tactical_Pad"和 "id": "overlay_wielded_Tactical_Pad_on"是搜索不到的
              而且这个mod只有三个文件,那么【真実はいつも一つ】!——CDDA是可以识别id前加overlay_wielded_的
              对比之前的图片

              很明显,带overlay_wielded_的条目,是缩放的样子。
              那么我们得到一个知识:
              缩略图是"type": "mod_tileset",且里面的词条以fg相表示,贴图存在外面(作为对比,look like词条是存在json内部的),贴图条目中以overlay_wielded_表示另一个视角,这个视角的翻译是“放置行驶的”。

              那我们继续看另一个被我们叫做mod本体的JSON

              仅仅是第一页,我们就发现了两个不认识的type
              "type": "item_action",和 "type": "tool_quality",
              这两个相对简单,就交给大家当作业了
              这里提两个东西,一个是这个//和//2
              一个是str
              两个东西没什么难度,学过编程的都知道,//是注释,str是字符串
              这里给没学过的解释一下,//和//2不同是因为要区分这两个注释,如果同一个{}中有两个以上的注释,那么理所应当的是//2、//3、//4等等等等,具体上限多少不清楚,你可以自己试试。
              而用str是因为,不能在str以外的数据格式中用空格,想用空格就必须str,否则会报错
              (这时候你可能就要问了,在 "volume": "300 ml",中300和ML之间不就有空格吗?emmm,这个真的很难清晰的解释一下,因为有字节这个东西,不去正经学一下很难理解。简单的来说,这里的空格起到的不是空格的作用。好比你把橡木装在了桃木箱里,那它就是一箱橡木,而不是“橡木、桃木混合箱”)
              (此外,description在定义上就是str的数据类型,无需再加)
              好!我我们继续!

              这里面
              "price_postapoc": 1500000,一看就是价值的某一个分支,具体是什么对我们影响不大,有相关需求的制作者可以自己去研究研究
              "to_hit": -1,这个词条比较奇怪,因为它后面是一个负数,但是我们只要去游戏里面看一下就可以发现

              它是命中-1
              其他的都可以通过对比游戏内与游戏外的数值来确定
              (先到这里吧,这个mod跟我的版本不匹配,装进去以后就一直报错,整了一下午才整明白"type": "mod_tileset",现在需要单独一个json,否则会提示id不对author不对description不对一堆不对,他还就是不提示mod_tileset不对,全改了一遍以后发现shape的现在是必须添加,而死亡效果的格式改了。。。。总之给别人修了一堆BUG,吐了吐了)
              剩下的之后再说,这个mod到这里才讲了三分之一。
              孬!
              非常非常!


              IP属地:山东14楼2022-06-19 21:18
              收起回复
                自己顶自己!
                (今天有些事,今天不更了吼)


                IP属地:山东来自Android客户端15楼2022-06-20 12:00
                回复
                  好,我们继续。
                  " class="BDE_Image" onload="EditorUI.resizeImage(this, 560)" unselectable="on"/>

                  对于前面部分的词条,我们大多都认识

                  这些我就不解释了,大家自己研究
                  我们继续
                  "use_action": [
                  "EINKTABLETPC",
                  "CAMERA",
                  {
                  "menu_text": "Activate Tactical tablet",
                  "//": "启动战术平板",
                  "type": "transform",
                  "target": "Tactical_Pad_on",
                  "need_charges": 2,
                  "need_charges_msg": "Low battery, cannot start!",
                  "//2": "电量低,无法开机!",
                  "active": true,
                  "msg": "You've activated the tactical tablet.",
                  "//3": "你启动了战术平板."
                  }
                  ]
                  这个词条我们可以通过作者在其中的注释知道是具体的操作(其实看那个use就知道了。。。)
                  但为什么会有这么奇怪的格式?
                  我们之前的经验都是
                  “属性”:[“词条1”,"词条2"]
                  或者
                  "属性":[{"属性1":"词条1","属性2":"词条2","属性3":"词条3"}]
                  从来没有"属性":["词条1",{"属性2":"词条2"}]这种
                  那让我们搜索一下”EINKTABLETPC“

                  有几个跟我们的情况一样,我们点进去看一下

                  好像是一个打开手机MP3的操作,但是经过翻译,我们发现"use_action":条目中的几乎所有词条都无法翻译成汉语,那老办法———不管了,爱咋咋地
                  如果之后没有其他办法,我们再回来啃这块硬骨头
                  我们去那个id文件看一下,经验告诉我应该大有收获

                  很好!啥也没有!
                  我们只能去看看有没有办法高清楚它的意思
                  我们把这些词条逐一拿去翻译
                  "MP3_ON", "PORTABLE_GAME", "EINKTABLETPC", "EBOOKSAVE", "EBOOKREAD"
                  "WATCH", "TRADER AVOID", "ALARMCLOCK", "USE_UPS", "NO_UNLOAD", "NO_RELOAD", "WATER_BREAK"
                  得到
                  “MP3_打开”、“便携_游戏”、“EINKTABLETPC”、“电子书保存”、“电子书阅读”,
                  “观察”、“交易者回避”、“警报锁”、“使用UPS”、“无卸载”、“无重装”、“断水”

                  这条路也不通,我们就再换个思路,从
                  "type": "item_action",
                  "id": "EINKTABLETPC",
                  "name": { "str": "Use SD-Card apps" }
                  入手,猜测一下它是做什么用的
                  我们知道,这个东西的名字叫做“使用储存卡的应用”
                  并且经过搜索,整个游戏只在这里出现过一次sd卡
                  那说明并不是什么引用,而是这三行确确实实的就是这个词条的全部
                  我们需要一个测试mod,就用之前的背包好了,把这个词条加进去(具体过程不写了,大家自行脑补一期内容),我们去游戏里看一下

                  原来是表示里面有内存卡
                  所以我们只要添加了这个词条,无论什么东西都会有内存(一个有内存卡的背包,啧啧啧)
                  同理,如果加了EBOOKREAD这个词条,那么哪怕是一口锅,也可以看电子书
                  好!我们继续
                  我们已经知道了EINKTABLETPC是指这个东西有内存卡,那么CAMERA自然就是相机了
                  那便剩下了这部分

                  我们去搜索一下没见过的词条,比如menu_text

                  东西还是不少的
                  不过我们发现大部分的menu_text中都是不一样的,结合这个词本身的意思(菜单文本)
                  想必各位已经有了答案
                  那我们继续看type,先搜索一下

                  大量的几乎一样的文本,说明这个是固定用法
                  那我们去翻译一下
                  {
                  " menu_text ":"激活战术平板",
                  "//": "启动战术平板",
                  "类型":"转换",
                  "目标":"战术_垫_开",
                  need _ charges:2
                  " need_charges_msg ":"电池电量低,无法启动!",
                  "//2": "电量低,无法开机!",
                  “主动”:真,
                  “msg”:“你已经激活了战术平板。”,
                  "//3": "你启动了战术平板."
                  }
                  看来大家都明白了,这个
                  "type": "transform",
                  是表示这个东西将要经过转换
                  "target":后面应该是跟转换的对象
                  为了验证,我们搜索一下"target":后面的内容

                  就在这个文件中,我们找到了这样一串代码想必到现在大家已经能够看懂了
                  (为一没说过的可能有些难度的就是copy-from,这个词条的意思是指这个东西的其他属性与copy-from所指向的东西的属性一致,通过我之前讲过的方法不难知道,就不带大家一起了
                  那么这串代码的最后部分
                  "pocket_data": [
                  {
                  "pocket_type": "MAGAZINE_WELL",
                  "rigid": true,
                  "holster": true,
                  "max_contains_volume": "20 L",
                  "max_contains_weight": "20 kg",
                  "item_restriction": [ "medium_battery_cell", "medium_plus_battery_cell", "medium_atomic_battery_cell", "medium_disposable_cell" ]
                  }
                  经过背包那里的经验,这个很明显是一个口袋,硬的,且有一个holster属性(这个属性也很有意思,感兴趣的可以自己去研究研究),容积不大
                  只有一行是我们无法确定的,那先翻译一下
                  “物品限制”:[“中号电池”、“中号加电池”、“中号原子电池”、“中号一次性电池”


                  IP属地:山东18楼2022-06-21 15:22
                  收起回复
                    嘿嘿嘿嘿,我们继续
                    继续看大佬的mod文档

                    这些词目大家都差不多知道,我们就着重讲比较新颖的
                    像这个revert_to,就是指的这个东西在用光电量以后会变回所指向的东西,类似于死亡动作。
                    而且值得注意的是,怪物身上也可以使用这个词条,大家按照我之前教的方法就能弄明白,就不带大家演示了。
                    又像item_restriction便是指的物品限制,即:只有这些物品可以放到里面
                    target这个此比较复杂,不过大家知道这个是指的目标对象即可,像这里:本身的type是动作,target指向之前的无人机,意思当然是对这个无人机发出这个动作(当然,我们可以说是无人机发出的这个动作,这取决于你是怎么理解的)
                    另外,补充一下:对于换行符\r和回车符\n,楼主自己的测试结果是\n作用于换行,\r似乎作为了空格,但是空格可以直接打上去。所以大家不用纠结回车符还是换行符,需要的时候都加上就好了。
                    经过前面的学习,这些东西真是一点难度有没有啊!!
                    那我们加快节奏

                    这里有一个我们没见过的
                    "drop_action": {
                    "target": "Military_UAV_MAP_KEY_act",
                    "target_charges": 1,
                    "moves": 3000,
                    "active": true,
                    "type": "transform"
                    },
                    再最后带着大家分析一遍,以后这种根据已知例子求过程的就不再讲了
                    老样子,先搜索

                    结果非常少,我们可以一个一个看
                    先看第一个

                    这个里面说,你可以甩出酸液来
                    我们看看 下一个

                    孬!几乎一模一样
                    那我们去试试搜索子条目"type": "emit_actor"

                    毫无结果,仅仅指向了它自己
                    那我们只好试图自己用眼睛瞅出答案来,我们来瞅瞅
                    "drop_action": {
                    "target": "Military_UAV_MAP_KEY_act",
                    ........
                    我们发现,这里的drop_action指向了另一个id。我们去找一下

                    通过眼瞅这些代码,我们知道:
                    这是一个工具(TOOL)
                    属于武器weapons(category这个词条的用法大家可以毋需关注,不过为了大家好奇心依然简要讲一下:好比一个“苹果”,你知道它是苹果,那么想当然的它有汁水,因为你知道“苹果”这个东西。那么假设一个东西叫“阿斯顿奥丁阿瑟东跌幅高达ABCDE”,你不知道这是什么,但是我告诉你这是水果,那么你也立马会理解“它有汁水”这个事。这个category同样如此,它是武器,那么自然具有武器的通用属性,自然可以出现在武器出现的地方(不是指的物品刷新)。另外,配方中的制作类别并不是这个词条,大家不要搞错了)
                    它还有一个类型是cast_spell的动作,经过我们翻译我们可以知道,这个动作是施法
                    那我们去找一下它施了什么法

                    几乎没有难度,就不带着大家翻译了
                    (给大家留个作业,最后这个魔法能量源是干什么用的?
                    那我们继续

                    这里有一些groups,我不打算讲这些东西,虽然它对mod有很大提升,但是里面的类似权重这些东西对于没有接触过程序编写的朋友来说可能有些难理解。
                    我们继续往下看

                    我们发现,这个mod作者将无人机做成了一个monster,来执行侦察功能
                    这是一个非常好的思路,我们可以把脱离小@的东西,无论是工具还是武器装备,都可以做成monster的形式
                    更甚者,我们可以尝试做一个移动堡垒,或者护体真气(这两者似乎都有人做了
                    .
                    .
                    那么,第一部分的内容讲解完毕。之后会再讲一些其他方面的东西,有关方法的部分就是这些了。
                    最后总结一下,拿到东西先搜索,搜索过后就翻译,翻译不行就搜索下位词条,都不行就再去看原文档,最后找到某词条的用法。
                    .
                    .
                    好!非常成功!


                    IP属地:山东20楼2022-06-27 17:48
                    收起回复