rimworld吧 关注:289,337贴子:5,306,847
  • 10回复贴,共1

Rimworld Mod xml教程 这可能是你见过的最细的MOD教程了

取消只看楼主收藏回复


基础篇 第一讲
你好!我是旋风。既然你看到了这个教程,想必你有成为一个mod制作者的兴趣。
我们常常把各类教程的作者比作一个引路人。在这里,我将教会你如何去制作一个简单的mod——而更重要的是,我希望能引导你走上探索制作方法的道路。
我私下带过不少新人,常见的问题有两点。一是在获得这“金手指”后,只是为了满足一时的快感去“魔改”,在mod中无脑地刷数据甚至堆0,导致劣质mod的泛滥。二是仅凭着一时的热血去制作mod,在遇到困难或者制作周期过长时便轻易地选择了放弃。
其实,我认为做mod的主要动力还是“自嗨”,毕竟只有让自己感到快乐的作品才能带给别人快乐;另一方面,一个作品就像自己的孩子,我们需要为其负责,并不断努力把他们打造成更优秀的作品。
从现在开始,除了一颗希望mod越来越好的心以外,什么要求都没有。
愿你获得启示。


IP属地:福建1楼2025-05-12 14:02回复
    基础篇 第二讲:MOD整体结构
    本课将讲述mod的组成部分及每个部分对应的编辑工具
    内容:
    About:管理mod的外在设置,内含:
    About.xml:编辑mod的名字,Id,作者,介绍,以及与其他mod的排序、需求、兼容性提示等设定。
    Preview.png:mod封面,用于游戏内与工坊处。
    Defs:mod新增内容的数据库。
    Assemblies:mod新增内容的程序集。
    Textures:存放mod新增的贴图。
    Sounds:存放mod新增的音频。
    Languages:存放语言包。
    工具:
    XML方面这里推荐三个工具
    Notepad++
    >文本式编辑器
    >良好的查找器和替换器
    >缺少实时错误检测
    >可以自动补全同一个文件内已经出现过的一串文本
    >无格式修正
    >简单朴素
    XML Notepad
    >表格式编辑器
    >没有文件内查找功能
    >自动编译,几乎无法出错
    >自动完成格式编辑
    >极易上手
    Visual Studio
    >文本式编辑器
    >优秀的查找器和替换器
    >可以同时管理一整套文件
    >实时检查错误
    >格式修正
    >能够编译各种语言
    >高级mod必备
    程序:反编译工具+代码编辑器
    (1).反编译工具
    制作mod程序集时会不可避免地需要研究游戏本身的程序,虽然可以去下载源代码
    但我个人更喜欢直接用反编译工具来辅助研究。
    dnSpy
    >UI与Visual Studio的风格一致
    >样式丰富
    >反编译“本地方法”、lambda表达式时会乱码
    >跳转代码方便快捷
    >喜欢把字段放在文件末尾
    >不再更新
    ILspy
    >UI别致
    >样式较少
    >反编译消耗时间长
    >能正常编译大部分代码
    >持续维护
    .代码编辑器
    每个程序员都有自己常用的编辑器,此处没有要求,能编译C#程序即可。教程中出现的,也是最常见的,为Visual Studio
    在早期制作mod时,无需下载程序相关软件;即使不制作程序集,你也能制作出包括武器,家具,衣服甚至派系的好mod,这是因为Rimworld本身的框架已经足够丰富。而只有当你不满足现状,且自身具备足够的面向对象编程经验与C#语言基础时,才有必要获取以上工具进行程序制作。
    本教程会适当使用反编译器来展示游戏框架的内容,同时我会附上代码讲解以方便没有任何编程基础的人也可以正常使用我的教程。


    IP属地:福建2楼2025-05-12 14:03
    收起回复
      2026-04-24 01:39:03
      广告
      不感兴趣
      开通SVIP免广告
      基础篇 第三讲:第一个MOD
      我相信各位一定急于做出自己的第一个mod,因此,我决定在开启我们的正式教学之前,让大家过一过瘾。
      我为大家准备了一份礼物,就放在我们的网盘里
      在下方百度网盘中找到“我们的第一份mod”下载并解压,我们能找到以下文件:
      >一套无内容的文件夹框架
      >一张枪械贴图FirstGun.png
      >一张封面贴图Preview.png
      >一个mod管理文件About.xml
      >一个枪械数据文件Weapon.xml
      来吧,让我们试试!
      首先,制作mod时请记得关闭其他mod,避免造成冲突影响mod制作【尤其是CE】
      其次,每次mod文件被修改,都需要将Rimworld进程完全关闭后再启动。
      配置mod属性
      将About.xml拖入mod中的Abouts文件夹
      使用xml编辑软件打开该文件,你可以看到我需要你修改的地方,例如第三行的
      <name>【为你的mod命名】</name>
      把这里的括号及其内部的内容替换为你想要写的东西:
      <name>我们的第一个mod</name>
      该文件内的其他东西请不要乱动,我们会在后方的章节内详细讲述其作用
      下一步,将Preview.png拖入Abouts文件夹
      现在,我们已经得到了一个没有任何内容,但能够被游戏识别的mod,你可以启动游戏来在mod列表中找到它。
      添加新内容
      将FirstGun.png拖入Texutures文件夹
      将Weapon.xml拖入Defs文件夹
      使用XML编辑器打开Weapon.xml,与刚才相同地,将我们给出的东西替换为你想要的内容,其他东西就不做修改。
      修改结束后,别忘了保存文件。
      完事后,你就可以在游戏中看到它了,赶紧体验一下吧!
      若你的游戏内容没有变化,请检查是否保存了文件,是否重启了游戏。


      IP属地:福建3楼2025-05-12 14:04
      收起回复
        我喜欢把XML形象地称为“数据库”,因为它为游戏提供了大量数据。一个数据包含其名字(参数名)和内容(参数)。每个参数名都在程序中被声明和应用,用简单易懂的话来说,就是我们必须按照程序给出的数据来制作。如果使用了一个程序中不存在的参数名,便会在进入游戏时报错,这点我们会在后期归纳报错时详细讲解。而数据的内容则按照一定的类型去完成,不符合类型地去填写内容往往会报错。若一个数据被程序提及,却没有被数据库提及,则使用程序给出的默认值。
        【注:这里的参数名其实被称为“标记”,每一个键值对被称为一个元素,但为了方便新手理解,我不引入相关的专业名词】
        每一个XML文件的第一行必定为
        <?xml version="1.0" encoding="utf-8"?>
        是XML文件的识别码。
        ①文本式编辑
        基本格式为:
        <参数名>参数</参数名>
        这里就像一个前后括号包着一个东西,所以需要十分注意“后括号”的"/"字符。我们称这种参数是一个简单的值的类型为“基础类型”。部分数据的参数不是简单的一个值,而可能由其他数据组成,形成“复合式”甚至“嵌套式”的结构,这是因为它们的类型为“复合类型”。
        <大参数名>
        <子参数A>A</子参数A>
        <子参数B>B</子参数B>
        </大参数名>
        <大参数名>
        <子参数C>C</子参数C>
        <子参数D>
        <孙参数>孙</孙参数>
        </子参数D>
        </大参数名>
        有极少数情况,我们不需要参数:
        <参数名></参数名>
        此时可以简写为:
        <参数名/>
        有时,在参数名处可以加上一些游戏预设的记号,此时请把记号置于前面的参数名处,格式为 记号名="记号内容" ,例:
        <参数名A Inherit="False">a</参数名A>
        【注:“记号”在XML中学术译名为属性】
        ②.注释
        注释写法为<!--注释内容-->,可以换行:
        <!--
        啊对对对
        -->
        不允许嵌套,如这么做是要报错的:
        <!--
        <!--啊错错错-->
        -->
        ③List结构
        在复合结构中,有一种特殊的数据类型(以后我会以“List类型”来形容它)。正常的复合结构,一个大数据所包括的小数据,每一个数据仅对应一个值。给一个数据对应多个值,或一个大数据内出现多次同一个数据是不被允许的,而List则能够解决这一问题。此处给出一个“人际关系”的例子,其中基础类型的参数,类型均为字符串,希望填写一个称呼,
        <人际关系>
        <妻子>夫人</妻子>
        <孩子>大儿子,二儿子</孩子>
        </人际关系>
        显然是错误的,程序会认为有一个孩子被称为“大儿子,二儿子”
        ==========================
        <人际关系>
        <妻子>夫人</妻子>
        <孩子>大儿子</孩子>
        <孩子>二儿子</孩子>
        </人际关系>
        “孩子”出现了两次,会导致程序报错
        =========================
        可能可以用这种方式解决:
        <人际关系>
        <孩子A>大儿子</孩子A>
        <孩子B>二儿子</孩子B>
        </人际关系>
        问题就在于,每多一个孩子,程序就要多规定一个新数据
        =========================
        List类似一堆同类型数据的有序集合体,能够让“一个”数据有“多个内容”。于是,若把“孩子”的类型设为“List类型”后:
        <人际关系>
        <妻子>夫人</妻子>
        <孩子>
        <li>大儿子</li>
        <li>二儿子</li>
        </孩子>
        </人际关系>
        此处的“孩子”显然成为了一个复合结构。其中每一个“li”数据被称为一个“元素”。事实上,这种元素可以被不断添加进list当中。
        List结构是允许嵌套的,下面是一段疯狂的代码:
        <list>
        <li>
        <li>文</li>
        <li>化</li>
        <li>有</li>
        <li>限</li>
        </li>
        <li>
        <li>公</li>
        <li>司</li>
        </li>
        </list>
        在mod制作中,数据类型由程序决定,xml作为一个数据库是没有办法修改的。制作者们不能自行将一个数据变为List类型,也不能以简单类型的方式来写一个List。在日后的学习过程中,我会给出它们的类型,需要仔细辨认。
        <list><li>A</li></list>
        单元素的list通常这么写,也可以换行
        ④父对象关系:ParentName,Name,Inherit记号
        数据库里有这堆东西:
        <人们>
        <人>
        <称呼>父亲</称呼>
        <年龄>47</年龄>
        <单位>文化有限</单位>
        <地址>蒸汽社区</地址>
        <姓>郑</姓>
        </人>
        <人>
        <称呼>儿子</称呼>
        <年龄>23</年龄>
        <地址>蒸汽社区</地址>
        <姓>郑</姓>
        </人>
        </人们>
        我们会发现儿子与父亲有许多相同点:地址和姓。而如果父子间的相同点越来越多,或出现了二儿子,三儿子等,一些相同的数据就会重复的出现。而我们想修改这个“家族”的姓时又要全翻一遍来修改。事实上,儿子的部分数据应当永远与父亲相同。
        我们使用“父对象”来实现这种“继承”的功能:
        <人们>
        <人 Name=”爹”>
        <称呼>父亲</称呼>
        <年龄>47</年龄>
        <单位>文化有限</单位>
        <地址>蒸汽社区</地址>
        <姓>郑</姓>
        </人>
        <人 ParentName=”爹”>
        <称呼>儿子</称呼>
        <年龄>23</年龄>
        <单位 Inherit=”False”/>
        </人>
        </人们>
        前面提到过,一个未被数据库提及的数据将被视为默认值。在此处,由于“儿子”未提及“地址”与“姓”,且其继承了“爹”的数据,所以“地址”和“姓”就会直接被视为是“父亲”的“地址”和“姓”,而儿子自己本身具有的“称呼”和“年龄”,这两个数据将直接覆盖其父对象的对应数据;特别的,此处的“单位”数据没有对应的参数,而是使用了“Inherit=false”标签,表示该数据不继承父对象。
        从上不难得出使用方法:
        Name=”A”,ParentName=”A”
        其中,整个数据库仅允许出现一个被命名为A的Name,其所标记的数据体就是一个父对象;而所有被标记为ParentName=”A”的数据体都将以被Name=”A”标记的为父对象。显然,一个数据体不允许将自己视为自己的父对象,但继承关系是允许被逐级嵌套的:
        <人们>
        <人 Name=”一代目”>
        <称呼>爷</称呼>
        <姓>郑</姓>
        <地址>天地</地址>
        </人>
        <人 ParentName=”一代目”,Name=”二代目”>
        <称呼>爹</称呼>
        <地址>蒸汽社区</地址>
        </人>
        <人 ParentName=”二代目”>
        <称呼>崽种</称呼>
        </人>
        </人们>
        输出第三代人的信息,姓氏会直接继承“一代目”的姓,而地址则继承更近的“二代目”,大家可以自行分析。
        特别地,当某个数据体中存在复合数据时,将会全部拆到基础类型,而不会把复合数据视为整体:
        <信息表>
        <信息卡 Name=”卡”>
        <代号>A</代号>
        <内容>
        <工资>14000</工资>
        <年终>2000</年终>
        <五险一金>1000</五险一金>
        </内容>
        </信息卡>
        <信息卡 ParentName=”卡”>
        <代号>B</代号>
        <内容>
        <工资>9000</工资>
        </内容>
        </信息卡>
        </信息表>
        这里的“内容”作为一个复合数据,将会被拆分为多个数据来分别继承(如果拆出来的也有复合那么继续拆直到全为基础),所以B实际上的内容为{工资:9000,年终:2000,五险一金:1000},如果希望B的内容仅为{工资:9000},那么应当对“内容”使用Inherit记号。这样一来,其余两项就会因没有被数据库提及而使用默认值。
        List类型由于其特殊的有序性,在继承时会按序合并父对象与子对象的数据内容。


        IP属地:福建4楼2025-05-12 14:07
        收起回复
          虽然应该有相当一部分玩家对我应该是比较熟悉的,但我觉得还是有必要证明一下自己的含金量.....总不能说什么东西都没有就跑来写教材,那样没有东西能证明自己的技术力,教程也会失去说服力

          代表作品是这个,统计数据如图所示

          我也是神州凶兽、预兆母树、石双双、艾叟坡达种系等项目的主程序
          我还发布过虐待收容实体、更好的研究列表、手术刀、战地续航、旋风绘卷科技等mod
          实际上这是一个几年前就开始更新的教程,由于一些原因一直未转过来
          我会在最近将教程内容陆续转至该贴,而后继续更新
          再次强调一下3楼的盘内有很重要的东西,有意向学习mod开发的小伙伴请务必获取。


          IP属地:福建69楼2025-05-12 22:49
          收起回复
            基础篇 第五讲:About文件
            About文件
            这是个mod的外在属性的管理器,内容包括其作者,mod名,工作版本等。这些属性最常在mod配置器【即mod列表】使用。而该文件即使在mod未被启用时也会加载。所以,写这个文件时要十分注意,它可能会导致一个未被启用的mod报错而彻底迷惑普通玩家。
            以下是机甲的about

            name:mod名字,为一个字符串【区分大小写,可以使用特殊字符和各种语言】不允许换行,允许与其他mod重名
            author:作者名字,为一个字符串
            authors:同上,为一个List
            packageId:mod的识别id。程序使用这段数据来识别mod,因此不允许与其他mod相同。当你本地mods或steam订阅mod中出现相同id,无论该mod是否被启用均会报错——除非它们一个是本地版,一个是steam版。
            它不区分大小写,仅允许出现英文,数字和小数点。我们常用的格式为:
            【作者英文名或steam名】.【mod英文名】
            以及
            【作者英文名或steam名】.【目录】.【mod英文名】
            supportedVersions:此处为mod的运行版本,是一个List。若该数据内所有元素均与当前游戏运行版本不匹配,则mod在列表中会变为黄名且后置。
            description:介绍,也是填文本,可以直接换行。
            modDependencies:非必须内容,依赖mod,即必须在该mod运行的情况下才能启用本mod。内含:
            >packageId:依赖mod的识别ID
            >displayName:显示的mod名
            >steamWorkshopUrl:steam创意工坊链接,为steam://url/CommunityFilePage/【工坊id】
            >downloadUrl:下载链接,直接一个HTML超链接。
            >以上的steamWorkshopUrl和downloadUrl可以直接不写。
            loadAfter、loadBefore:非必须内容,要求该mod的排序在其他mod前/后,为一个List,元素填其他mod的packageId
            incompatibleWith:非必须内容,要求该mod不允许与某些mod一起被启用,为一个List,元素填其他mod的packageId
            forceLoadBefore、forceLoadAfter:与上面的那俩相似,但其要求更强,游戏会强制满足该排序。
            descriptionsByVersion、modDependenciesByVersion、loadBeforeByVersion、loadAfterByVersion、incompatibleWithByVersion:非必须内容,是上面提到的“description、modDependencies、loadAfter、loadBefore、incompatibleWith”的“根据版本变化”的模式,在使用时先打版本数据,再打内容,比如:
            <incompatibleWithByVersion>
            <v1.3>
            <li>CETeam.CombatExtended</li>
            </v1.3>
            </incompatibleWithByVersion>
            意思是仅在1.3版本下与CE冲突


            IP属地:福建70楼2025-05-12 22:58
            回复
              基础篇 第六讲:Defs文件
              该文件夹用于存放defs文件,每个文件内会有一个或多个def数据体,以数据库的形式被程序读取来形成mod的新内容。
              Defs数据体有ThingDef,HediffDef,RecipeDef等的区分,不同的def对应不同的新内容,如刚才的三个分别对应新物品,新的健康状态和新的制作配方。
              Def的内容依附游戏已有的庞大框架,学习他们就是本教程的主体部分,从此我们将用其不断创造新内容来完成我们的mod。不同def以后会分别详细讲解,此章节我先介绍所有def共有的数据。
              <?xml version="1.0" encoding="utf-8" ?>
              <Defs>
              <DamageDef ParentName="Bomb">
              <defName>XFUnused_BombWithDirection</defName>
              <label>炸</label>
              </DamageDef>
              <DamageDef ParentName="Bomb">
              <defName>XFUnused_BombWithDirectionSecond</defName>
              <label>炸2</label>
              <workerClass>MParmorLibrary.Unused.DamageWorker_ExplosionWithDirection</workerClass>
              </DamageDef>
              </Defs>
              第一行是XML固定识别码,不可丢
              第二行是Defs,我们所有的def都要被这个东西包住(看第二行与最后一行)
              然后中间的就是每一个数据体了
              <defName/>
              该数据是一个def的基础,表示了一个def的识别名,就像身份证号一样,相同类型的def间defname必须不同,而不同类型间则可以相同。
              请注意,这里的单一性不只适用于你的项目,拿thingdef举例,所有已启用的mod中的所有thingdef都不允许重复,当然也不允许与原版的重复——毕竟原版本身就被视为一个mod。
              为了解决这种极易出现的bug,所有制作者均会在defname填写时加上一个独特的前缀,如游戏里“钢铁”的defname为”Steel”,那么我得项目里的新钢铁就可以这么写:
              <defName>XFMLI_Steel<defName>
              其中XF是“旋风”的缩写,MLI是“mod lesson instance”的缩写。
              当然,只要你有自己解决重名的方法,如何命名是无所谓的,但整体必须遵循仅由:1.大小写英文(defName是大小写敏感的) 2.数字 3.下划线 组成,且最后一个字不能为数字。而除了程序的这些硬性要求之外,我们还有一些自己的规范:
              由于不允许使用空格,在面对多个单词的时候有些人会选择使用下划线:
              <defName>XFMLI_Beautiful_flower_for_you</defName>
              其实显得过于冗长和散漫,我更推荐用“驼峰命名法”,而下划线应起到类似区分前缀后缀和本体的作用:
              <defName>XFMLI_BeautifulFlowerForYou</defName>
              将每个单词首字母大写,删去单词间的空格,就成了驼峰命名法。其中首字母大写的为:“大驼峰”,我们使用这种。
              首字母小写的为“小驼峰”,大多数的数据名均为这种类型,若制作时报错请检查拼写问题。
              <label>flower</label>
              <description>A flower for someone you love</description>
              以上数据中,label为显示名,description为介绍,两者的填写没有绝对要求,可以使用空格、汉字、特殊字符,但不允许使用{} [] <>。这类文本数据在使用翻译包时将可以被替换,我们会在后面学到。这两种数据允许重名,在部分def中他它们甚至不会被调用。而在需要调用它们的def中,缺少它们将会导致报错。
              补充一些没那么常用的
              descriptionHyperlinks:一个List,元素有特殊的填写格式,<def的种类>defName</def的种类>,比如路西法合剂:
              <descriptionHyperlinks>
              <HediffDef>LuciferiumHigh</HediffDef>
              <HediffDef>LuciferiumAddiction</HediffDef>
              </descriptionHyperlinks>
              游戏内效果

              modExtensions:泰南注释:Mod-specific data. Not used by core game code.是一个List,作用是填写一些dll留给xml的接口。教程里不会使用这个东西。


              IP属地:福建73楼2025-05-13 13:19
              收起回复
                基础篇 第七讲:翻译包文件
                翻译包存放在Language文件夹内,并使用预设好的名字来区分语言。
                以下是一些常用的语言的文件夹名:
                ChineseSimplified 简体中文
                ChineseTraditional 繁体中文
                English 英语
                Japanese 日语
                Russian 俄语
                一个翻译包分为两部分:对def内文本的翻译放入DefInjected文件夹,对dll内的翻译放入Keyed文件夹。对dll的翻译被称为Key,基本格式为:
                <key>文本</key>
                在整个游戏所有已启用的mod中不允许出现重复的key,否则排序靠后的将覆盖排序靠前的。
                若游戏使用的语言所对应的翻译包中缺少对应的key,或者干脆没有对应的翻译包,那么会从English包中查找并使用。
                由于我们目前不对程序,dll方面展开教学,Key的内容就到此为止,对于def的翻译是本章的主要部分。
                与defs不同:
                Defs区分一个def的类型是看它在数据库中出现时最外层的参数名,例如现在defs中有这样一个文件:
                <?xml version="1.0" encoding="utf-8" ?>
                <Defs>
                <ThingDef ParentName=”XFMLI_ThingParentA”>
                <defName>XFMLI_Flower</defName>
                <label>flower</label>
                <description>A beautiful flower</description>
                </ThingDef>
                </Defs>
                第一行为识别码,所有xml文件的必需,在作为例子的这个thingdef中,我使用了父对象来省略其他必要的数据填写,这样一来我们就更能将注意力集中在这三项研究对象上。
                我们注意到,defs中总是用一个参数名放在最外层来区分类型,显而易见的,此处的例子中的def类型为thingdef
                而翻译包并不采用这种形式,在这里我们通过文件夹的命名来区分其中的翻译文件所对应的def类型。对于上文的例子,我们如果要制作翻译,那么应当将文件置于下图的文件夹中:
                <?xml version="1.0" encoding="utf-8" ?>
                <languages>
                <XFMLI_Flower.label>花</XFMLI_Flower.label>
                <XFMLI_Flower.description>一朵美丽的花</XFMLI_Flower.description>
                </languages>
                基本格式为:
                <defName.数据路径>翻译文本</defName.数据路径>
                其中defname为你要翻译的def的defname。
                数据路径指的是从整个数据体最外层向里依次拆分复合数据直到到达翻译对象。一个文本的基本数据每级的参数名之间用小数点连接,再举一例:
                <数据体>
                <defName>X</defName>
                <复合A>
                <复合B>
                <基本C>this.</基本C>
                </复合B>
                </复合A>
                </数据体>
                其对应翻译为:
                <x.复合A.复合B.基本C>这个。</x.复合A.复合B.基本C>
                特别的在于list型复合数据,因为它拆分后是多个元素。也就是li。我们当然不能在路径中使用li,而应当使用索引器:用一个从0开始依次增加1的整数来依次指代元素。注意其从0开始数意味着第一个元素为0,第二个为1,依此类推。
                如:
                <list>
                <li>A</li>
                </list>
                即为<list.0>A</list.0>
                而除此之外,其实还有其他对list的元素的索引方式,如

                翻译文件直接用label来索引,注意索引到的是元素本身,所以依然需要一个label来指向其名字文本数据。

                在comps中,也常直接用Class名来指代,当然也可以用comps.0来指代。

                值得注意的是,对于父对象的翻译不会作用于子对象上,也就是说,即使子对象在继承后拥有与父对象完全相同的一个文本数据,你仍然要对它们分别翻译,而一个abstract=”true”的数据体其中的任何数据都是不允许被翻译的——当然,在正常情况下这种数据体也不存在defname。
                除此之外,原文本中若出现形如 {n}(n为整数)或 “TargetX”(X为大写字母)等,则需要保留他们在翻译文本中。
                <stringA>Use this by TargetA.</stringA>
                <stringB>The number is {0}.</stringB>
                对应的翻译为
                <stringA>让 TargetA使用这个。</stringA>
                <stringB>数字是{0}。</stringB>
                你可以自行安排它们在文本中的位置,在该文本实际出现在游戏中时,它们会自动被程序替换为其他东西。
                如果一个def没有找到对应的翻译,将直接使用def中的文本,而不是English翻译包。因此我鼓励大家在制作时以英文书写def中的文本,再用中文翻译来完成中文文本。


                IP属地:福建77楼2025-05-14 13:08
                回复
                  2026-04-24 01:33:03
                  广告
                  不感兴趣
                  开通SVIP免广告
                  基础篇 第八讲:以原版def为参照制作一个新的ThingDef
                  这里你们需要用到编辑器一步一步跟我操作:
                  在实际制作时,我们其实难以从零开始构思一个def所应有的所有数据,而有时原版提供的父对象也难以满足我们的全部需求。这时,我们会尝试在原版中找到与我们想制作的内容相近的成品,并将其复制加以修改以变成我们的作品。
                  我们将以原版中长剑为模板,制作一把伤害更高,攻速更慢的近战武器。
                  ①首先,我们在游戏中找到该参考对象,值得注意的是,能用不同制成的武器在名称中会出现材料名为前缀,应当自行排除这些前缀【如钢铁长剑,实际名称为“长剑”】。
                  接下来,我们在编辑器中打开查找功能,并选择“在文件中查找”(不同编辑器的表述可能不同),路径选择为简体中文翻译包(若没有,则前往RimWorld\Data\Core\Languages找到对应压缩包并解压),查找内容为“长剑”。
                  在此之后,应当会跳出所有提及长剑的文本,我们重点在thingdef的文件夹的查找结果中找到长剑,可能有以下结果:
                  <MeleeWeapon_LongSword.label>长剑</MeleeWeapon_LongSword.label>
                  根据第七章的内容,原版中长剑的defname即为MeleeWeapon_LongSword。
                  下一步,在RimWorld\Data\Core\Defs中搜索<defName>MeleeWeapon_LongSword</defName>,查询结果即为长剑的thingdef。
                  搜索使用的“文件夹内搜索”

                  <ThingDef ParentName="BaseMeleeWeapon_Sharp_Quality">
                  <defName>MeleeWeapon_LongSword</defName>
                  <label>longsword</label>
                  <description>The ancient weapon of kings, the longsword can be used for slashing or stabbing.</description>
                  <graphicData>
                  <texPath>Things/Item/Equipment/WeaponMelee/LongSword</texPath>
                  <graphicClass>Graphic_Single</graphicClass>
                  </graphicData>
                  <techLevel>Medieval</techLevel>
                  <weaponTags>
                  <li>MedievalMeleeAdvanced</li>
                  <li>LongSword</li>
                  </weaponTags>
                  <costStuffCount>100</costStuffCount>
                  <thingSetMakerTags><li>RewardStandardQualitySuper</li></thingSetMakerTags>
                  <statBases>
                  <WorkToMake>18000</WorkToMake>
                  <Mass>2</Mass>
                  </statBases>
                  <relicChance>2</relicChance>
                  <equippedAngleOffset>-65</equippedAngleOffset>
                  <stuffCategories>
                  <li>Metallic</li>
                  <li>Woody</li>
                  </stuffCategories>
                  <tools>
                  <li>
                  <label>handle</label>
                  <capacities>
                  <li>Blunt</li>
                  </capacities>
                  <power>9</power>
                  <cooldownTime>2</cooldownTime>
                  </li>
                  <li>
                  <label>point</label>
                  <capacities>
                  <li>Stab</li>
                  </capacities>
                  <power>23</power>
                  <cooldownTime>2.6</cooldownTime>
                  </li>
                  <li>
                  <label>edge</label>
                  <capacities>
                  <li>Cut</li>
                  </capacities>
                  <power>23</power>
                  <cooldownTime>2.6</cooldownTime>
                  </li>
                  </tools>
                  <recipeMaker>
                  <researchPrerequisite>LongBlades</researchPrerequisite>
                  <skillRequirements>
                  <Crafting>5</Crafting>
                  </skillRequirements>
                  </recipeMaker>
                  </ThingDef>
                  ②在我们自己的Defs里新建一个xml,并将识别码<?xml version="1.0" encoding="utf-8" ?>与我们搜索到的长剑的整个ThingDef扔进去;根据第六章的内容,为了不覆盖原版武器,defname必须要被修改,label和description也最好进行修改以进行区分。为了演示方便,这里不考虑制作翻译包,可以直接写入中文(实际操作中并不建议这样做)
                  ③修改数据
                  初学者们此时可以通过翻译软件翻译每一个数据名,并加以更改和测试来猜测。我们会在后面的章节逐一分析。对比游戏内数据和Defs内数据,并判断数据的对应关系也是一项很重要的技能。本章以“伤害更高,攻速更慢的近战武器。”为课堂例子,所以先给出一些数据名对应的数据内容:
                  <tools>
                  <li>
                  <label>handle</label>
                  <capacities>
                  <li>Blunt</li>
                  </capacities>
                  <power>9</power>
                  <cooldownTime>2</cooldownTime>
                  </li>
                  <li>
                  <label>point</label>
                  <capacities>
                  <li>Stab</li>
                  </capacities>
                  <power>23</power>
                  <cooldownTime>2.6</cooldownTime>
                  </li>
                  <li>
                  <label>edge</label>
                  <capacities>
                  <li>Cut</li>
                  </capacities>
                  <power>23</power>
                  <cooldownTime>2.6</cooldownTime>
                  </li>
                  </tools>
                  看到这里,根据第四章内容tools是一个List。里面的每一个元素都是一种攻击方式,图中从上到下分别是“剑柄”、“剑头”、“剑刃”。每一个元素内的power对应的该攻击方式的伤害,为整数;cooldownTime为冷却时间,即后摇,单位是秒,可以写小数。
                  我们可以把整个柄删去,实际上柄是拿来降低DPS,并提供钝器伤害的方式,但我们的巨剑不需要;然后将剑头和剑刃的伤害提高,冷却调高

                  然后进游戏测试一下吧!
                  千万要注意,修改的是我们复制出来的ThingDef,而不是原版Core的Defs里的数据,否则我们就是直接修改原版数据了!


                  IP属地:福建80楼2025-05-17 23:20
                  回复
                    基础篇 第九讲:Defs种类
                    该讲是22年3月写的 现在几乎用不了了 就不发了 需要的去三楼找吧


                    IP属地:福建82楼2025-05-23 13:49
                    回复


                      IP属地:福建87楼2025-06-02 11:57
                      回复