饥荒联机版Mod开发——两种帽子(十)

饥荒联机版Mod开发——两种帽子(十)

  • 前言
  • 总览与下载
  • 动画
  • 代码
    • modmain
    • 露头类帽子
      • 基本的预设物框架
      • 穿戴
      • 可交易
      • 腐烂及可放冰箱
      • 总的代码
    • 不露头类帽子
      • 差异
      • 基本代码
      • 耐久
      • 其他功能
      • 总的代码
  • 官方参考代码
  • 传送门

前言

这期我们来聊聊饥荒中的帽子,根据显示的不同,分为露头类帽子(如花环),不露头类帽子(如高礼帽)。这两种帽子除了动画显示部分有所区别外,其他部分是相同的。为了节省制作动画的时间,我直接用花环和高礼帽的动画作演示。

总览与下载

饥荒联机版Mod开发——两种帽子(十)_第1张图片

除了动画和prefabs里的,其他可以前几期都有涉及,这里就不多赘述了。
源文件已添加到mods/~myhats.zip中
饥荒联机版开发
https://pan.baidu.com/s/1_-TPRdo86z8PNwK084N_3A?pwd=oc74

动画

两种类型的帽子,动画制作流程其实是一样的。

  1. 素材要放在swap_hat文件夹下
    饥荒联机版Mod开发——两种帽子(十)_第2张图片

  2. 名字要对应,前三张依次对应帽子的正面、侧面、后面贴图,最后一张是地上的贴图。
    饥荒联机版Mod开发——两种帽子(十)_第3张图片

  3. 双击右上角的图片,设置锚点。前三张的锚点对应的是带上帽子后的位置,这个需要多进游戏多试,最后一张的锚点是地面落地点。

饥荒联机版Mod开发——两种帽子(十)_第4张图片

饥荒联机版Mod开发——两种帽子(十)_第5张图片

  1. 制作扔地上的动画,注意名字,这对应三行代码的参数。
    (前几期都有涉及,不记得了回去复习下)
	inst.AnimState:SetBuild("mytophat") --scml名字自动打包成同名zip,同时也是这个参数
	inst.AnimState:SetBank("mytophat")  --对应sprite里右下角的第一层名字
	inst.AnimState:PlayAnimation("idle")	--第一个参数是动画名,对应sprite里右下角的第二层名字

饥荒联机版Mod开发——两种帽子(十)_第6张图片

代码

modmain

简单声明预设物文件,物品名,物品描述

GLOBAL.setmetatable(env,{__index=function(t,k) return GLOBAL.rawget(GLOBAL,k) end})	

PrefabFiles = {
    "myflowerhat",
    "mytophat"
}

STRINGS.NAMES.MYFLOWERHAT = "我的花帽"
STRINGS.CHARACTERS.GENERIC.DESCRIBE.MYFLOWERHAT = "这是花帽?"

STRINGS.NAMES.MYTOPHAT = "我的高礼帽"
STRINGS.CHARACTERS.GENERIC.DESCRIBE.MYTOPHAT = "这是高礼帽?"

露头类帽子

基本的预设物框架

下面这代码属于最基本的代码了,如果看不懂建议回去看第三期和第四期。

--prefabs/myflowerhat.lua

local assets = {
    Asset("ANIM", "anim/myflowerhat.zip"), --动画文件
    Asset("IMAGE", "images/inventoryimages/myflowerhat.tex"), --物品栏贴图 
    Asset("ATLAS", "images/inventoryimages/myflowerhat.xml")
}

local prefabs = {}

local function fn() 
    local inst = CreateEntity()

    inst.entity:AddTransform()
    inst.entity:AddAnimState()
    inst.entity:AddNetwork()

    MakeInventoryPhysics(inst)  --与地面碰撞
    MakeInventoryFloatable(inst) --可以飘在水上	

    inst.AnimState:SetBank("myflowerhat") 
    inst.AnimState:SetBuild("myflowerhat")
    inst.AnimState:PlayAnimation("idle")

    inst.entity:SetPristine()

    if not TheWorld.ismastersim then
        return inst
    end

    inst:AddComponent("inspectable") --可检查

    inst:AddComponent("inventoryitem") --物品组件
    inst.components.inventoryitem.imagename = "myflowerhat"
    inst.components.inventoryitem.atlasname = "images/inventoryimages/myflowerhat.xml"

	MakeHauntableLaunch(inst)   --可作祟
    
    return inst
end

return Prefab("myflowerhat", fn, assets, prefabs)

穿戴

当然这么写还是无法穿戴的,控制物品可穿戴的核心组件是equippable,一般来说我们只要添加这个组件,设置装备的位置,装备/卸载时替换贴图即可。
细心观察你会发现,装备物品其实是一个起手动作结束后,直接换贴图的。

local function onequiphat(inst, owner) --装备的函数

    owner.AnimState:OverrideSymbol("swap_hat", "myflowerhat", "swap_hat")

    owner.AnimState:Show("HAT")
    owner.AnimState:Hide("HAIR_HAT")
    owner.AnimState:Show("HAIR_NOHAT")
    owner.AnimState:Show("HAIR")

    owner.AnimState:Show("HEAD")
    owner.AnimState:Hide("HEAD_HAT")

	--若有耐久组件,则开始扣耐久
    if inst.components.fueled ~= nil then
        inst.components.fueled:StartConsuming()
    end

end

local function onunequiphat(inst, owner) --解除帽子
    owner.AnimState:ClearOverrideSymbol("swap_hat")
    owner.AnimState:Hide("HAT")
    owner.AnimState:Hide("HAIR_HAT")
    owner.AnimState:Show("HAIR_NOHAT")
    owner.AnimState:Show("HAIR")

    if owner:HasTag("player") then
        owner.AnimState:Show("HEAD")
        owner.AnimState:Hide("HEAD_HAT")
    end

	--若有耐久组件,则停止扣耐久
    if inst.components.fueled ~= nil then
        inst.components.fueled:StopConsuming()
    end
end

local function fn()
	...
    if not TheWorld.ismastersim then
        return inst
    end
    ...
    inst:AddComponent("equippable") --装备组件
    inst.components.equippable.equipslot = EQUIPSLOTS.HEAD --装在头上
    inst.components.equippable:SetOnEquip(onequiphat) --装备
    inst.components.equippable:SetOnUnequip(onunequiphat) --解除装备
end

其中

  • owner.AnimState:OverrideSymbol(“swap_hat”, “myflowerhat”, “swap_hat”)
    表示用myflowerhat.scml动画中的swap_hat(后)文件夹中的图,替换owner中swap_hat(前)中的图。
    由于反解压不出第一个参数表示的透明图文件夹,所以一般我们只配置后两个参数。

  • owner.AnimState:Show(“HAT”)
    显示某个文件夹的图

  • owner.AnimState:Hide(“HAT”)
    隐藏某个文件夹的图

  • owner.AnimState:ClearOverrideSymbol(“swap_hat”)
    取消替换某个文件夹的图,即还原回来。

上面的装备和卸载函数基本是固定的,有新的功能直接在后面加上就好,前面的直接copy吧。

可交易

当然这只是完成了基本的装备/卸载,我们可以添加tradable组件,让它可以给猪人、兔人等

inst:AddComponent("tradable")   --可交易,给猪人等

腐烂及可放冰箱

其次,花帽加个腐烂做耐久就挺不错的。腐烂结束我们用一朵花来替换好了。

    inst:AddComponent("perishable") --腐烂的
    inst.components.perishable:SetPerishTime(TUNING.PERISH_FAST)  --6天的腐烂时间
    inst.components.perishable.onperishreplacement = "flower"   --设置腐烂后的替代物
    --inst.components.perishable:SetOnPerishFn(inst.Remove)     --如果不要替代物,可换为这句,腐烂后直接销毁
    inst.components.perishable:StartPerishing() --开始腐烂

当然还要在客户端那表示要显示腐烂度,以及可以放冰箱

	...
    
    inst:AddTag("show_spoilage") --加这个就有保鲜度动画
    inst:AddTag("icebox_valid")		--加这个就可以放进冰箱

    inst.entity:SetPristine()

    if not TheWorld.ismastersim then
        return inst
    end

总的代码

所以,总的代码如下

--prefabs/myflowerhat.lua

local assets = {
    Asset("ANIM", "anim/myflowerhat.zip"), --动画文件
    Asset("IMAGE", "images/inventoryimages/myflowerhat.tex"), --物品栏贴图 
    Asset("ATLAS", "images/inventoryimages/myflowerhat.xml")
}

local prefabs = {}

local function onequiphat(inst, owner) --装备的函数

    owner.AnimState:OverrideSymbol("swap_hat", "myflowerhat", "swap_hat")

    owner.AnimState:Show("HAT")
    owner.AnimState:Hide("HAIR_HAT")
    owner.AnimState:Show("HAIR_NOHAT")
    owner.AnimState:Show("HAIR")

    owner.AnimState:Show("HEAD")
    owner.AnimState:Hide("HEAD_HAT")

    if inst.components.fueled ~= nil then
        inst.components.fueled:StartConsuming()
    end

end

local function onunequiphat(inst, owner) --解除帽子
    owner.AnimState:ClearOverrideSymbol("swap_hat")
    owner.AnimState:Hide("HAT")
    owner.AnimState:Hide("HAIR_HAT")
    owner.AnimState:Show("HAIR_NOHAT")
    owner.AnimState:Show("HAIR")

    if owner:HasTag("player") then
        owner.AnimState:Show("HEAD")
        owner.AnimState:Hide("HEAD_HAT")
    end

    if inst.components.fueled ~= nil then
        inst.components.fueled:StopConsuming()
    end
end

local function fn() 
    local inst = CreateEntity()

    inst.entity:AddTransform()
    inst.entity:AddAnimState()
    inst.entity:AddNetwork()

    MakeInventoryPhysics(inst)  --与地面碰撞
    MakeInventoryFloatable(inst) --可以飘在水上	

    inst.AnimState:SetBank("myflowerhat") 
    inst.AnimState:SetBuild("myflowerhat")
    inst.AnimState:PlayAnimation("idle")

    inst:AddTag("hat")
    inst:AddTag("show_spoilage") --加这个就有保鲜度动画
    inst:AddTag("icebox_valid")		--加这个就可以放进冰箱

    inst.entity:SetPristine()

    if not TheWorld.ismastersim then
        return inst
    end

    inst:AddComponent("inspectable") --可检查

    inst:AddComponent("inventoryitem") --物品组件
    inst.components.inventoryitem.imagename = "myflowerhat"
    inst.components.inventoryitem.atlasname = "images/inventoryimages/myflowerhat.xml"

    inst:AddComponent("equippable") --装备组件
    inst.components.equippable.equipslot = EQUIPSLOTS.HEAD --装在头上
    inst.components.equippable:SetOnEquip(onequiphat) --装备
    inst.components.equippable:SetOnUnequip(onunequiphat) --解除装备
    inst.components.equippable.dapperness = TUNING.DAPPERNESS_MED --设置回san值

    inst:AddComponent("perishable") --腐烂的
    inst.components.perishable:SetPerishTime(TUNING.PERISH_FAST)  --6天的腐烂时间
    inst.components.perishable.onperishreplacement = "flower"   --设置腐烂后的替代物
    --inst.components.perishable:SetOnPerishFn(inst.Remove)     --如果不要替代物,可换为这句,腐烂后直接销毁
    inst.components.perishable:StartPerishing() --开始腐烂

    
    inst:AddComponent("tradable")   --可交易,给猪人等

    MakeHauntableLaunch(inst)   --可作祟

    return inst
end

return Prefab("myflowerhat", fn, assets, prefabs)

不露头类帽子

差异

这两种帽子的差异主要是装备函数里对AnimState的调用显示,即Show,Hide的部位。卸载函数是一样的。

--露头
local function onequiphat(inst, owner) --装备的函数

    owner.AnimState:OverrideSymbol("swap_hat", "myflowerhat", "swap_hat")

    owner.AnimState:Show("HAT")
    owner.AnimState:Hide("HAIR_HAT")
    owner.AnimState:Show("HAIR_NOHAT")
    owner.AnimState:Show("HAIR")

    owner.AnimState:Show("HEAD")
    owner.AnimState:Hide("HEAD_HAT")

    if inst.components.fueled ~= nil then
        inst.components.fueled:StartConsuming()
    end

end

--不露头
local function onequiphat(inst, owner) --装备的函数
    owner.AnimState:OverrideSymbol("swap_hat", "mytophat", "swap_hat")
 
    owner.AnimState:Show("HAT")
    owner.AnimState:Show("HAIR_HAT")
    owner.AnimState:Hide("HAIR_NOHAT")
    owner.AnimState:Hide("HAIR")

    if owner:HasTag("player") then
        owner.AnimState:Hide("HEAD")
        owner.AnimState:Show("HEAD_HAT")
    end

    if inst.components.fueled ~= nil then
        inst.components.fueled:StartConsuming()
    end

end

基本代码

所以最基本的不露头的帽子的代码如下。

local assets = {
    Asset("ANIM", "anim/mytophat.zip"), --动画文件
    Asset("IMAGE", "images/inventoryimages/mytophat.tex"), --物品栏贴图 
    Asset("ATLAS", "images/inventoryimages/mytophat.xml")
}

local prefabs = {}

local function onequiphat(inst, owner) --装备的函数
    owner.AnimState:OverrideSymbol("swap_hat", "mytophat", "swap_hat")
 
    owner.AnimState:Show("HAT")
    owner.AnimState:Show("HAIR_HAT")
    owner.AnimState:Hide("HAIR_NOHAT")
    owner.AnimState:Hide("HAIR")

    if owner:HasTag("player") then
        owner.AnimState:Hide("HEAD")
        owner.AnimState:Show("HEAD_HAT")
    end

    if inst.components.fueled ~= nil then
        inst.components.fueled:StartConsuming()
    end

end

local function onunequiphat(inst, owner) --解除帽子
    owner.AnimState:ClearOverrideSymbol("swap_hat")
    owner.AnimState:Hide("HAT")
    owner.AnimState:Hide("HAIR_HAT")
    owner.AnimState:Show("HAIR_NOHAT")
    owner.AnimState:Show("HAIR")

    if owner:HasTag("player") then
        owner.AnimState:Show("HEAD")
        owner.AnimState:Hide("HEAD_HAT")
    end

    if inst.components.fueled ~= nil then
        inst.components.fueled:StopConsuming()
    end
end

local function fn()
    local inst = CreateEntity()

    inst.entity:AddTransform()
    inst.entity:AddAnimState()
    inst.entity:AddNetwork()

    MakeInventoryPhysics(inst)
    MakeInventoryFloatable(inst) --可以飘在水上	

    inst.AnimState:SetBank("mytophat") 
    inst.AnimState:SetBuild("mytophat")
    inst.AnimState:PlayAnimation("idle")

    inst:AddTag("hat")

    inst.entity:SetPristine()

    if not TheWorld.ismastersim then
        return inst
    end

    inst:AddComponent("inspectable") --可检查

    inst:AddComponent("inventoryitem") --物品组件
    inst.components.inventoryitem.imagename = "mytophat"
    inst.components.inventoryitem.atlasname = "images/inventoryimages/mytophat.xml"

    inst:AddComponent("equippable") --装备组件
    inst.components.equippable.equipslot = EQUIPSLOTS.HEAD --装在头上
    inst.components.equippable:SetOnEquip(onequiphat) --装备
    inst.components.equippable:SetOnUnequip(onunequiphat) --解除装备

    MakeHauntableLaunch(inst)   --可作祟

    return inst
end

return Prefab("mytophat", fn, assets, prefabs)

耐久

要添加耐久度,需要使用fueled组件,设置使用情况,耐久度,即耐久使用结束后的回调。

    inst:AddComponent("fueled") --耐久
    inst.components.fueled.fueltype = FUELTYPE.USAGE
    inst.components.fueled:InitializeFuelLevel(TUNING.FEATHERHAT_PERISHTIME)    --8天
    inst.components.fueled:SetDepletedFn(inst.Remove)

其他功能

    inst:AddComponent("waterproofer")   --防水
    inst.components.waterproofer:SetEffectiveness(TUNING.WATERPROOFNESS_SMALL)

    inst:AddComponent("insulator")  --绝缘
    inst.components.insulator:SetInsulation(TUNING.INSULATION_MED)

    inst:AddComponent("armor")  --防具
    inst.components.armor:InitCondition(TUNING.ARMOR_SLURTLEHAT, TUNING.ARMOR_SLURTLEHAT_ABSORPTION)

对了上面的TUNING.XXX可以在tuning.lua中找到,一般是个数字

总的代码

--prefabs/mytophat.lua

local assets = {
    Asset("ANIM", "anim/mytophat.zip"), --动画文件
    Asset("IMAGE", "images/inventoryimages/mytophat.tex"), --物品栏贴图 
    Asset("ATLAS", "images/inventoryimages/mytophat.xml")
}

local prefabs = {}

local function onequiphat(inst, owner) --装备的函数
    owner.AnimState:OverrideSymbol("swap_hat", "mytophat", "swap_hat")
 
    owner.AnimState:Show("HAT")
    owner.AnimState:Show("HAIR_HAT")
    owner.AnimState:Hide("HAIR_NOHAT")
    owner.AnimState:Hide("HAIR")

    if owner:HasTag("player") then
        owner.AnimState:Hide("HEAD")
        owner.AnimState:Show("HEAD_HAT")
    end

    if inst.components.fueled ~= nil then
        inst.components.fueled:StartConsuming()
    end

end

local function onunequiphat(inst, owner) --解除帽子
    owner.AnimState:ClearOverrideSymbol("swap_hat")
    owner.AnimState:Hide("HAT")
    owner.AnimState:Hide("HAIR_HAT")
    owner.AnimState:Show("HAIR_NOHAT")
    owner.AnimState:Show("HAIR")

    if owner:HasTag("player") then
        owner.AnimState:Show("HEAD")
        owner.AnimState:Hide("HEAD_HAT")
    end

    if inst.components.fueled ~= nil then
        inst.components.fueled:StopConsuming()
    end
end

local function fn()
    local inst = CreateEntity()

    inst.entity:AddTransform()
    inst.entity:AddAnimState()
    inst.entity:AddNetwork()

    MakeInventoryPhysics(inst)
    MakeInventoryFloatable(inst) --可以飘在水上	

    inst.AnimState:SetBank("mytophat") 
    inst.AnimState:SetBuild("mytophat")
    inst.AnimState:PlayAnimation("idle")

    inst:AddTag("hat")

    inst.entity:SetPristine()

    if not TheWorld.ismastersim then
        return inst
    end

    inst:AddComponent("inspectable") --可检查

    inst:AddComponent("inventoryitem") --物品组件
    inst.components.inventoryitem.imagename = "mytophat"
    inst.components.inventoryitem.atlasname = "images/inventoryimages/mytophat.xml"

    inst:AddComponent("equippable") --装备组件
    inst.components.equippable.equipslot = EQUIPSLOTS.HEAD --装在头上
    inst.components.equippable:SetOnEquip(onequiphat) --装备
    inst.components.equippable:SetOnUnequip(onunequiphat) --解除装备
    inst.components.equippable.dapperness = TUNING.DAPPERNESS_LARGE --设置回san值

    inst:AddComponent("fueled") --耐久
    inst.components.fueled.fueltype = FUELTYPE.USAGE
    inst.components.fueled:InitializeFuelLevel(TUNING.FEATHERHAT_PERISHTIME)    --8天
    inst.components.fueled:SetDepletedFn(inst.Remove)

    inst:AddComponent("waterproofer")   --防水
    inst.components.waterproofer:SetEffectiveness(TUNING.WATERPROOFNESS_SMALL)

    inst:AddComponent("insulator")  --绝缘
    inst.components.insulator:SetInsulation(TUNING.INSULATION_MED)

    inst:AddComponent("armor")  --防具
    inst.components.armor:InitCondition(TUNING.ARMOR_SLURTLEHAT, TUNING.ARMOR_SLURTLEHAT_ABSORPTION)

    inst:AddComponent("tradable")   --可交易

    MakeHauntableLaunch(inst)   --可作祟

    return inst
end

return Prefab("mytophat", fn, assets, prefabs)

官方参考代码

prefabs/hats.lua

传送门

→饥荒联机版Mod开发——衣服(十一)
←饥荒联机版Mod开发——制作栏(九)

你可能感兴趣的:(饥荒Mod开发,lua,开发语言)