星露谷物语吧 关注:472,107贴子:2,881,859

【CP】Content Patcher交流帖

只看楼主收藏回复

本交流帖的内容主要以使用Content Patcher开发mod为主,如果是使用Content Patcher和其他的CP mod有问题,请到mod作者那里或另开贴询问。
如果你玩星露谷喜欢打mod,那你很可能已经碰到了一些是以 [CP] 为开头的mod文件,它们是调用了Content Patcher功能的mod。Content Patcher英文缩写是CP,所以用 [CP] 来标识。

Content Patcher可以更改游戏的数据、图像和地图,而无需替换XNB文件。
可以根据游戏中的许多细节进行动态更改,如位置、天气、日期、节日或活动、配偶、关系、您是否拥有Joja会员资格等。
与XNB mod不同,这些内容包可以进行自动更新检查和兼容性检查,易于安装和卸载,自动支持本地化,不太可能发生冲突,也不太可能因游戏更新而中断。
因为没找到交流的地方,就在这里发个帖,让想开发cp mod的人相互学习交流一下。
该mod的N网尾号为1915,发帖时使用版本为1.30.4(对,在这几天之后 [CP] 2.0就要跟着星露谷1.6来了(对对,就是因为1.6迟迟不来我才发的这个帖子))


IP属地:河北1楼2024-03-15 16:20回复
    一、前置准备
    1.游戏本体
    2.SMAPI
    3.Content Patcher(n网尾号1915)
    4.可以编辑文本的软件,比如记事本
    5.拆包后的游戏素材
    为了能在编辑结束后测试调试,前四项是必须。
    而第五项是为了帮助你能找到你想要替换的素材的位置,一般而言也是必须。
    贴吧中有很多拆包教程,n网中也有很多,如何拆包在这里就不作过多说明了。
    举个实际的例子,假如你想将替换海莉的头像为潘姆。
    那么你需要做两件事,一个是准备好替换后的图像,另一个就是要找到海莉的头像在哪里。
    如果你有解包后的文件,你能清楚地知道这个文件的地址是Portraits/Haley

    那么只需写上这么两行,海莉的头像就会变成潘姆。

    游戏的画面就像这样,艾米丽和潘姆吵架.jpg


    IP属地:河北2楼2024-03-15 16:50
    收起回复
      二、主要文件
      楼上已经展示过了,只需要写很少的东西就能XNB需要替换文件才能实现功能。但是光凭那两行代码还是不够的,还需要一点配套的文件。
      1.mod文件夹
      新建一个文件夹,用你mod的名称命名文件夹,可以在前面加上 [CP] 便于识别,但是不加也完全没问题。
      之后在该文件夹中创建另一个文件夹,取名为assets(资产的复数形式)
      2. 使用记事本创建一个文件,将文件改名为manifest.json。
      复制默认格式,按照说明依次修改。(防吞楼此处放的图片版,便于复制的文字版在楼下)

      里面的内容对应改成你的内容就行,建议是和里面的格式保持一致。
      比如name行的Your Mod Name,在此处填写的形式最好是 Wo De Mod,而不是WoDeMod或者Wodemod。
      最后的两行文字一定不要改,第一次写cp mod无法正常运行,很有可能就是不小心动了这里。
      3.使用记事本创建一个文件,将文件改名为content.json
      向里面添加如下内容,一个任何功能都不实现的cp mod就制作完毕了。


      IP属地:河北3楼2024-03-15 17:34
      回复
        manifest.json
        {
        "Name": "Your Mod Name",
        "Author": "Your Name",
        "Version": "1.0.0",
        "Description": "One or two sentences about the mod.",
        "UniqueID": "YourName.YourModName",
        "UpdateKeys": [], // when you release the mod, see https://stardewvalleywiki.com/Modding:Modder_Guide/APIs/Upd
        "ContentPackFor": {
        "UniqueID": "Pathoschild.ContentPatcher"
        }
        }


        IP属地:河北4楼2024-03-15 17:35
        回复
          content.json
          {
          "Format": "1.29.0",
          "Changes": [
          // your changes will go here
          ]
          }


          IP属地:河北5楼2024-03-15 17:36
          回复
            按照步骤走下来,打开你的mod文件夹应该是这样。

            为了方便后续制作mod,你可以将这几个文件压缩。之后需要的时候解压就可以直接开始制作新的mod了。
            现在,让我们开始看看 [CP] 能做些什么


            IP属地:河北6楼2024-03-15 18:28
            回复
              三、主要功能
              1.Load
              使用 load 功能,将会把目标文件替换成你所提供的文件。
              官方(指的是这个 Content Patcher mod 的作者,后面通称官方)给出的示例如下:

              可以看到 load 功能需要3个基本项
              action(行动):load
              target(目标):被替换的文件路径
              fromFile(从……文件):assets/你的文件.文件后缀
              只要这样修改,就会实现替换功能。


              IP属地:河北7楼2024-03-15 18:39
              回复
                举几个具体例子来方便理解。
                首先是刚才潘姆海莉的例子。
                1. 打开你的 content.json 文件,文件内部应该和3楼最后一张图片或者5楼一致。与//那行平齐的添加代码:"Action": "Load",(最后的逗号别忘了加,而且所有标点是英文的)。完成后的样子应该是这样

                2. 从拆包的游戏文件中找到海莉肖像的位置为 Portraits/Haley.png ,所以第二行写上:"Target": "Portraits/Haley",
                。完成之后是这样的

                3. 找海莉图像的时候顺带找到了潘姆的图像,复制一份将其放到你mod文件夹中的assets文件夹里

                第三行就加上:"FromFile": "assets/Pam.png"就可以了。由于这是这个mod的最后一行,因此不用加逗号。
                之后将你整个mod的文件夹,放入到平时下载要放到的mods文件夹里,就可以开始测试了。
                测试成功的应该是这样

                你可能注意到会有这样图像缺失的空白的地方,这是因为海莉的肖像有12张,而潘姆只有5张。这里用到了后面的肖像,所以显示空白。因此在使用素材进行load替换的时候,一定要主要素材数量的相互对应。


                IP属地:河北8楼2024-03-15 19:06
                收起回复
                  再举一个常用的替换地图的例子。
                  打开拆包后的文件夹,然后打开Maps文件,我们可以看到里面有很多tmx文件,这些文件是星露谷物语的地图文件。如何打开和编辑地图文件在吧里有教程,在这里同样不作过多说明。

                  我们做个简单的,把河流农场和荒野农场互换。这两个文件名如下,各复制一份放到asset文件夹中。

                  如果你理解了上个例子,你完全可以自己写出这个替换的代码。但是写不出来,也不要紧,我们再来一遍。
                  首先是要用的功能,还是 load。
                  所以第一行是"Action": "Load",
                  第二行是被替换的文件,我们先替换荒野农场。找到文件为Maps/Farm_Combat.tmx ,所以第二行是"Target": "Maps/Farm_Combat",
                  第三行是我们提供的文件,是放在assets文件夹里面的河流农场,所以第三行是"FromFile": "assets/Farm_Fishing.tmx"
                  而另一个农场也是相同的步骤来完成,完整的代码应该是这样的:

                  这里说明一下哪里该有逗号哪里不该有逗号,看下面的图。"2"这一行后面还有"3"这一行,所以字母A处应该有逗号。而"3"后面没有内容,这个行为已经做完了,所以字母B处没有逗号。同理数字"6"所在行的最后也没有逗号。
                  而字母C处后面有逗号,D后面没有逗号,这是因为123构成了第一个行为这个整体,在它后面还有由456构成的第二个整体行为。123后面有456,而456后面再没有东西了,所以不加逗号。

                  进入游戏后可以发现我们选择了河流农场,但使用的是荒野农场的地形。


                  IP属地:河北9楼2024-03-15 19:44
                  收起回复
                    2.EditData
                    可以添加、编辑或删除条目;重新排序列表中的条目;或编辑条目中的单个字段。
                    官方给出的代码是使玩家出售的咖啡价格变成300:

                    可以看到EditData同样由3个基本项来实现。
                    action:EditData(编辑数据)
                    target:目标文件地址
                    操作类型:作用范围和作用效果


                    IP属地:河北10楼2024-03-16 10:08
                    收起回复
                      理解load操作后,EditData的前两项的 action 和 target 与之前完全相同没什么说的,但这个第三项要稍微复杂一些。
                      总共有四种操作:
                      Fields:更改一条数据中的部分内容
                      Entries:增加、删除、更改一整条数据中的内容。该功能虽然包含了上一条功能,但是为了兼容性考虑,官方建议在Fields能完成的请况下尽量使用Fields。
                      MoveEntries:对于有顺序的数据,更改它们的顺序。
                      TextOperations:对现有的数据进行更改。
                      第四种操作比较复杂,后面单独去讲。先使用其他三种来理解EditData这个操作。


                      IP属地:河北11楼2024-03-16 10:57
                      回复
                        首先是一个Fields的例子,把防风草种子的玩家出售价格改成0:
                        第一行肯定是这个操作的名称:"Action": "EditData",
                        第二行要知道防风草种子价格存在哪,通过拆包资源知道:"Target": "Data/ObjectInformation",
                        第三行要使用Fields进行操作,就得找到防风草种子然后知道价格是哪个。
                        首先在星露谷英文 wiki 的Modding: Items/Object sprites里面找到防风草种子编号是472

                        然后在Modding: Items找到防风草种子的分类是Objects,里面解释了每个"/"分割的部分里面都是什么,从而得知防风草种子售价是在第二个。

                        也就是说,这个就是我们要改的目标

                        所以第三个是"Fields":
                        (指定防风草种子)"472":
                        (价格是第二个数据段,但编号是从0不是1开始,所以是1)1: "0"
                        之后再加上必要的符号,完整的代码应该是这样:

                        (那个红字是记事本报错,不用管它)
                        进入到游戏可以看到,玩家想要出售的防风草种子的价格变成了0,而皮埃尔受此影响种子售价也变成了1。


                        IP属地:河北12楼2024-03-16 11:27
                        回复
                          之后是使用Entries的例子。
                          我们完全可以用Entries做到和刚才一模一样的事情,只要把第三行操作由Fields变成了Entries,然后把472后面整段复制过来,然后把第二个数据从10变成0即可。
                          完整的代码如下:

                          进游戏发现价格变化正确,但是种子的名称变成了英文。
                          这就是官方推荐能使用Fields解决,就别使用Entries的原因。

                          除了更改,Entries还可以添加和删除。
                          添加与刚才的更改操作完全一样,就是填的目标不是已存在的就行。
                          比如说不能是已经存在的472,随便填个2222、3333、7777都会新添一个序号为对应数字的项。
                          删除操作则是让这一项的值为null(关键字"空的")即可。示例代码如下:

                          进游戏的效果:


                          IP属地:河北13楼2024-03-16 11:59
                          回复
                            而MoveEntries官方没有过于详细的说明,我也没想到能够如何使用这个功能,这里就带过了。


                            IP属地:河北14楼2024-03-16 14:33
                            回复
                              接下来主要说一下TextOperations。
                              从描述上看,看似这个功能与Fields功能一致,其实不然。拿官方的例子来说:

                              这个改动使得村民最爱的礼物上增加了127和128两项,这样看上去根本没有TextOperations出场的必要。

                              其实不然。这仅仅只是在不加任何其他mod的情况下的结果,只有原版和这个mod存在时会是这个结果。
                              而一旦有其他mod用同样的方法修改了这一项,那么结果必然是不对的。
                              所以此时轮到TextOperations出场了。这样的代码可以实现给所有人的最爱的礼物添加上127和128:

                              可以看到TextOperations使用方式有所不同。
                              除了本身的操作名为TextOperations,之后它还需要4部分构成:
                              Operation:操作
                              Target:目标项
                              Value:变化的值
                              Delimier:分隔符,有" ", "\", "^"这三种,默认为"\"或"^"(Data/Achievements文件)
                              Operation:总共有append(添加在最后)、prepend(添加在最前)、RemoveDelimited(删除分割符)三种操作。
                              使用append或者prepend操作会使目标项被添加对应的值,并使用规定的分隔符分隔;
                              而使用RemoveDelimited会删除掉对应的分隔符类型。
                              拿上面的图举例:
                              如果使用append的结果就会是
                              "Universal_Love": "74 446 797 373 279 127 128"
                              如果使用prepend的结果就会是
                              "Universal_Love": "127 128 74 446 797 373 279"
                              如果使用RemoveDelimited的结果会是
                              "Universal_Love": "74446797373279"


                              IP属地:河北15楼2024-03-16 16:00
                              收起回复