[关闭]
@longfei 2016-12-14T05:42:36.000000Z 字数 12990 阅读 4239

制作手持武器

Don'tStarve Mod教程


实例下载

按下面流程制作的一个示范已经上传到了我的网盘,如果在制作过程中有什么疑问,可以参考。
实例下载

基本工具

mod tools
这是一个官方提供的工具合集,除了提供上传到创意工坊的功能之外,其他的介绍如下:

两条基本编程原则

制作手持武器--贴图

图片的具体需求:

2和3对大小要求不一样的原因是,放在地上的图片,是可以在spriter里调整大小的。
但3不能,3原本是多大,在游戏里就会显示出多大。我第一次做的时候选用64*64的图片来做3,结果实际显示的大小刚好有人物的拳头那么大。

在讲下面的内容之前,要补充一些下面会用到的说明:
一个在地图上(注意是地图上,放在物品栏里的不算)显示的实体,显示出来的是一个动画。
一个实体可以有多个动画,通过代码来控制播放。简单的比如一棵草,有三个动画:成熟、被采摘后,枯萎后。
对于一个实体的地图表现,以下这些参数是很重要的

现在可以来讲相应内容了。假设你已经用图片处理工具弄好了相应的图片。

然后就开始来正式制作一个MOD吧,这里仅仅讲单机版的。联机版的稍有不同但也没多大差别,聪明的人自然懂得举一反三。

手上动画和地上动画还有一个很大的区别,就是你在spriter里调节的大小、方向,是不会在手上显示出来的。你的图片里,武器朝向哪个方向,有多大,那么实际到了游戏就维持着相同的样子。所以如果你要改动在手上的武器朝向或大小,只能改图片。
你设定的图片控制点,就是人物的手持位置。比如我把控制点设置在了武器的尖头上,实际效果如下图:
这里写图片描述

如此,就完成了所有的美术准备,下一步就是代码了。

制作手持武器--代码篇

首先我们要给这个新武器起个名字,就叫myitem吧。

  1. name = "My item example" --Mod的名字
  2. description = "A simple item example" --Mod描述
  3. author = "LongFei" --作者名
  4. version = "0.1" --Mod版本
  5. forumthread = ""--MODklei论坛的下载地址,没有可以留空,但不可删除
  6. api_version = 6--modAPI版本
  7. --priority = -9999 --mod的启动优先级,越低的越晚启动,一般不用设置,除非和其他MOD有冲突需要调整
  8. dont_starve_compatible = true--以下几句,都是设置兼容性的,分别对应DSROG,SWDST
  9. reign_of_giants_compatible = true
  10. shipwrecked_compatible = true
  11. dst_compatible = false
  12. icon_atlas = ""--mod的图标设置
  13. icon = ""--mod的图标图片
  1. PrefabFiles = {
  2. "myitem",--PrefabFiles是一张注册表,是用来向游戏注册prefab的,所有的新设定的prefab都必须在这里注册。如果你有多个prefab,就在中间用逗号隔开。prefab在某种意义上可以说是饥荒世界的原子,武器也算是一个prefab,所以也要注册。
  3. }
  1. local assets=
  2. {
  3. Asset("ANIM", "anim/myitem_build.zip"),--这个是放在地上的动画文件
  4. Asset("ANIM", "anim/swap_myitem_build.zip"), --这个是手上动画
  5. Asset("ATLAS", "images/inventoryimages/myitem.xml"),--物品栏图标的xml
  6. Asset("IMAGE", "images/inventoryimages/myitem.tex"),--物品栏图标的图片
  7. }
  8. --目前我还弄不清楚下面这代码的具体意义,但就先这样空着吧,不能随意乱删,因为有一定的格式要求
  9. local prefabs =
  10. {
  11. }
  12. local function OnEquip(inst, owner) --当你把武器装备到手上时,会触发这个函数
  13. owner.AnimState:OverrideSymbol("swap_object", "swap_myitem_build", "swap_myitem")--这句话的含义是,用swap_myitem_build这个文件里的swap_myitem这个symbol,覆盖人物的swap_object这个symbolswap_object,是人物身上的一个symbolswap_myitem_build,则是我们之前准备好的,用于手持武器的buildswap_myitem就是存放手持武器的图片的文件夹的名字,mod tools自动把它输出为一个symbol
  14. owner.AnimState:Show("ARM_carry") --显示持物手
  15. owner.AnimState:Hide("ARM_normal") --隐藏普通的手
  16. end
  17. local function OnUnequip(inst, owner)
  18. owner.AnimState:Hide("ARM_carry") --隐藏持物手
  19. owner.AnimState:Show("ARM_normal") --显示普通的手
  20. end
  21. local function fn()--这个函数就是实际创建物体的函数,上面所有定义到的函数,变量,都需要直接或者间接地在这个函数中使用,才能起作用
  22. local inst = CreateEntity()--创建一个实体,常见的各种inst,根源就是在这里。
  23. local trans = inst.entity:AddTransform()--给实体添加转换组件,这主要涉及的是空间位置的转换和获取
  24. local anim = inst.entity:AddAnimState()--给实体添加动画组件,从而实体能在游戏上显示出来。
  25. MakeInventoryPhysics(inst)--给实体设定为"物品"的物理属性,这是一个写在data\scripts\standardcomponents里的标准函数,类似的还有MakeCharacterPhysics,就是设定"人物"的物理属性,基本上所有会动的生物,都会有MakeCharacterPhysics
  26. anim:SetBank("myitem_bank")--设置实体的bank,此处是指放在地上的时候,下同
  27. anim:SetBuild("myitem_build")--设置实体的build
  28. anim:PlayAnimation("idle")--设置实体播放的动画
  29. inst:AddComponent("inventoryitem")--添加物品栏物品组件,只有有了这个组件,你才能把这个物品捡起放到物品栏里。
  30. inst.components.inventoryitem.imagename = "myitem" --物品栏图片的名字
  31. inst.components.inventoryitem.atlasname = "images/inventoryimages/myitem.xml"--物品栏图片的xml文件。为什么会有这么两句呢?在单个文件下也许会迷惑,但如果换成一个张大图就容易理解了。举个例子,游戏的操作界面,HUD,你可以在data\images下找到HUD.tex,用textool打开就会看到是一整张大的图片,包含了整个操作界面的所有图片,xml就是用来切割分块这张大的图片,并分别给它们重新命名的,新的命名就会被前面的imagename 使用。
  32. inst:AddComponent("equippable")--添加可装备组件,有了这个组件,你才能装备物品
  33. inst.components.equippable:SetOnEquip( OnEquip ) -- 设定物品在装备和卸下时执行的函数。在前面定义的两个函数是OnEquipOnUnequip里,我们主要是围绕着改变人物外形设定了一些基本代码。 在装上的时候,会让人物的持物手显示出来,普通手隐藏,卸下时则反过来。需要注意的是,OnEquipOnUnequip都是本地函数,要想让它们发挥作用,就必须要通过这里的组件接口来实现。
  34. inst.components.equippable:SetOnUnequip( OnUnequip )
  35. return inst
  36. end
  37. return Prefab("common/inventory/myitem", fn, assets, prefabs)--最后,返回这个实体到modmain里注册。Prefab这个函数,第一个参数只需要看最后一个/后面的部分,视为这个prefabIDfn则是上面定义的fn,是这个物品的创建函数,assets,对应上面的assets,主要是用于注册美术资源,如果你在这里注册了相应的美术资源,就不需要在modmain里再注册一次。prefabs,目前还未明确具体的作用。

把装备添加到制作栏

为了让你的新装备不依赖于控制台产生,就需要给它设定一定的生成方式。这里只介绍最简单的一种,就是给装备设置一个Recipe,让它能被制作。

联机和单机在这个地方,总体上差不多,但细节会有变化,要分开来说明。首先从单机版开始。

在单机里,添加Recipe,是通过定义一个Recipe类的实例来实现的。
lua本身没有类这个概念,在饥荒里,类是通过函数来实现的,Recipe类的构造函数就是Recipe函数。

在海难DLC下,Recipe函数有以下变量:self, name, ingredients, tab, level, game_type, placer, min_spacing, nounlock, numtogive, aquatic, distance。非海难DLC,则是以下变量,name, ingredients, tab, level, placer, min_spacing, nounlock, numtogive。
其中第一个变量self是定义一个类都必须有的变量self,代表了这个类本身,只在定义类的时候有用。通过类的构造函数定义类的实例,只需要填后面的变量就行了。前面4个变量name,ingredients,tab,level比较重要,只讲解这部分的含义,后面的变量,nounlock是说是否会像古代科技那样,即使制造了一次也无法解锁相应科技栏,默认为否。numtogive则是说一次制造给几个物品。其它的,请自己查找Recipe.lua和Recipes.lua下的代码了解具体含义。另外,单机的Recipe没有buildertag,所以如果你希望你的专属物品只能被你的专属人物制造的话,应该把这部分的代码写入人物的构造函数里而不是写在modmain里。

  1. Ingredient("lotus_leaf", 1, "images/inventoryimages/lotus_leaf.xml")
  1. RECIPETABS['SAMANSHA_TAB'] = {str = "SAMANSHATAB", sort=999, icon = "samansha_tab.tex", icon_atlas = "images/samansha_tab.xml"}

在填完上面4个基本参数之后还不够,单机的Recipe函数,不接收被制作物品的xml路径,所以你需要先用一个变量来接收Recipe函数的返回值(物品的Recipe表),然后给这个表的atlas元素赋值图片路径。一个例子如下:

  1. --用一个局部变量deerhatRecipe 接收Recipe函数的返回表,然后给表中的atlas元素赋上对应的xml路径。
  2. local deerhatRecipe = Recipe("deerhat", {deerhorn, deerhat_1}, RECIPETABS.SAMANSHA_TAB, TECH.MAGIC_TWO)
  3. deerhatRecipe.atlas = "images/inventoryimages/deerhat.xml"

联机版比起单机版,在这方面的支持更为给力。从上面单机版麻烦新制作栏添加方法以及图片xml路径设定就可以看出,官方原本是没打算让玩家添加新的可制作物品的。但联机版则受到官方鼓励。他们给出了mod用的两个函数:AddRecipeTab和AddRecipe。

添加新的制作栏,不需要像单机那样在RECIPETABS表里添加新元素了,我们有mod专用的函数:AddRecipeTab,变量依序为rec_str, rec_sort, rec_atlas, rec_icon, rec_owner_tag,分别代表制作栏名称,制作栏优先级(决定你的制作栏会被放在左侧边栏的第几个位置),制作栏图片的xml地址,制作栏图片的名字,会显示该制作栏的人物需要拥有的tag。
一个例子如下:

  1. AddRecipeTab("samansha", 999, "images/hud/samansha_tab.xml", "samansha_tab.tex", "samansha")

AddRecipe函数的变量,与联机版的Recipe函数,在去掉Recipe的第一个变量self之后,是完全相同的。
所有的变量,依序是name, ingredients, tab, level, placer, min_spacing, nounlock, numtogive, builder_tag, atlas, image。
前面讲过的前4个参数,在这里的用法是一样的。而新增的后面三个参数builder_tag, atlas, image,则是方便了我们MOD制作。中间的placer,minspacing是为了可放置的建筑物设计的,此处暂且略过不提。

  1. --中间有好几个nil,是因为这些参数可以不填
  2. AddRecipe("lotus_umbrella", {lotus_leaf}, samansha_tab, TECH.SCIENCE_ONE, nil, nil, nil, nil, "samansha","images/inventoryimages/lotus_umbrella.xml","lotus_umbrella.tex")

以上两个函数,都属于mod API,所以必须要写在modmain里,否则无法运行,会报错。

至此,专属武器的基本框架就算制作完成了。想要测试效果的,可以打开MOD后,进入游戏,在控制台里输入c_give("myitem"),便可获得该武器,或者根据你自己配置的Recipe,在制作栏里将其制作出来。下一篇讲如何给武器添加一些常用的功能,以及打造自己的个性武器。

给武器设置伤害和特殊功能

接上一篇的最后,现在,做好了一把手持装备雏形的我们,要给这个装备设置伤害和特殊功能,使它能够当成一把武器来使用。要实现这一步,首先要了解,饥荒里的prefab和component的区别。

一个prefab,可以有多个组件,每个组件负责不同的功能。而添加组件,是通过AddComponent来完成的。比如说接着上一篇最后部分构造函数的代码。

  1. local function fn()
  2. local inst = CreateEntity()
  3. local trans = inst.entity:AddTransform()
  4. local anim = inst.entity:AddAnimState()
  5. MakeInventoryPhysics(inst)
  6. anim:SetBank("myitem_bank")
  7. anim:SetBuild("myitem_build")
  8. anim:PlayAnimation("idle")
  9. inst:AddComponent("inventoryitem")--这就是一个组件,添加'物品栏物品'这个组件,让这个prefab能够放在物品栏里。下面两行则是设置这个组件的一些参数,代表着它在物品栏中的图片表示。
  10. inst.components.inventoryitem.imagename = "myitem"
  11. inst.components.inventoryitem.atlasname = "images/inventoryimages/myitem.xml"
  12. inst:AddComponent("equippable")--这个组件是可装备组件,只有添加了这个组件,才能让物品可被装备。下面两行分别表示设置这个函数在被装备和被卸下时触发的函数。一般都会用这两个函数来设置人物的外观变化(比如把武器显示在人的手上)
  13. inst.components.equippable:SetOnEquip( OnEquip )
  14. inst.components.equippable:SetOnUnequip( OnUnequip )
  15. return inst
  16. end

那么,接下来就要设置武器的伤害和功能了。游戏本身赋予的组件相当丰富,几乎所有道具的功能,都是通过组件实现的。不同的道具,可能只在组件参数设置上有所区别。比如说黄宝石法杖能召唤晨星,绿宝石法杖能分解建筑,但它们都是通过spellcaster组件来实现这个功能的,只是对应的法术实现函数不一样罢了。

武器的属性,是由weapon组件实现的。只要添加两条代码,即可设置攻击力

  1. inst:AddComponent("weapon")
  2. inst.components.weapon:SetDamage(damage)--设置武器的攻击力damage

武器还有一个耐久度属性,这个是通过finiteuses属性来完成的。初始化设置的,一般会添加这三条代码

  1. inst:AddComponent("finiteuses")--添加有限耐久组件,按次数算
  2. inst.components.finiteuses:SetMaxUses(MaxUse)--设置最大耐久MaxUse
  3. inst.components.finiteuses:SetUses(CanUse)--设置当前耐久CanUse

然后,我们可以给武器添加一些特别的功能,这个可以参考其他道具来做。比如说火把有个Lighter组件,通过这个组件就可以点火。橙宝石法杖有个blinkstaff组件,通过这个组件我们就能实现瞬移。
当你想要实现某个游戏中已有道具的功能,或者对这个功能做些许改动的时候,就可以先通过饥荒英文WIKIA找到你想要的道具对应的prefab字符串ID,(即Wikia里写的Debug Spawn),然后从这个字符串ID去搜索同名文件,进而找到这个道具的构造函数所在,在构造函数中,搜索AddComponent,找到你想要的功能对应的组件。
下面列一个表给出一些常见的组件,以及它们常用于哪些物品,有什么用途。

组件名 范例 解释
tool axe 工具组件,像砍树、挖矿这些活动,都是通过向相应的工具(斧子,镐子)添加这个组件,并修改一些组件参数来实现的
shaver razor 刮胡子组件,有了这个就可以刮威尔逊的胡子以及牛毛了。
trap trap 陷阱组件,有了这个,就可以把兔子困在陷阱里了。
waterproofer umbrella 防水组件,有了这个,就可以给人物增加防雨能力,当防雨百分比>=100%时,就达到了完全防水的效果

其它的就不多说了,想要实现特殊功能,就自己去查找相应的代码吧。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注