介绍一些组件
原文:[Introduction to some Components]
(http://forums.kleientertainment.com/topic/47542-introduction-to-some-components)
翻译: @czfshine
Prefabs(预设物), Components(组件), Stategraphs(状态图), 这一些名词意味着是什么呢?我希望它们像XYZ一样简单。
目录:
- 介绍一些组件
- 目录
- General一般
- Armor护甲
- Beard胡子
- Burnable可燃的
- Container容器
- Cookable烹饪
- Dapperness衣衫褴褛
- Eater吃者
- Edible可食用的
- Equippable可装备的
- Finite Uses耐久
- Harvestable收获
- Health生命
- Hunger饥饿
- Insulator保暖
- Inventory-Item可存放
- Perishable腐败
- Pickable可采摘
- Propagator传播算子
- Repairable可修理
- Sanity-Aurasan光环
- Talker话语者
- Tool工具
- Tradable交易
- Useable Item可使用的
- Workable能工作的
- Light亮
General(一般)
假设你已经熟悉基本的Lua
一个组件(component)是一些为预设件(prefabs)准备的代码,
通常组件是来描述一个单一的属性(例:生命,饥饿,攻击),
允许在一个预设件上用各种各样的创意组合各种组件,
仍然困惑于这段句话吗?去看它们的不同点
要使用一个组件,你首先需要将它添加到你的预设件:
inst:AddComponent("MyComponent")
然后你可以自定义具体的细节:
inst.components.MyComponent.maxvalue = 100
inst.components.MyComponent:SetSomething(true)
如果组件有提供,当你需要时你可以访问该组件的某个函数,或给组件设置一组函数:
inst.components.MyComponent:BeFun() --prepared function
inst.components.MyComponent.befunfn = BackflipFn --set a function
这些只是理论,选择看下面一些有意义的例子! 或者最好直接去看游戏数据!
Armor(护甲)
这个组件可以使你的盔甲,具有减少玩家全部或某些类型的伤害的功能.
遗憾的是,该组件还意味着有耐久性。
重要的变量
tags
:
标签——盔甲标签只有一个效果,可以抵御有一个的相同的标签的攻击。
(table)
onfinished
:
移除护甲–理论上你可以使用这个更换装备或重置属性。
(function)
ontakedamage
:
当受到伤害时触发
重要的函数
InitCondition(amount, absorb_percent)
初始化护甲,设置耐久度(num amount ),减伤百分比(num absorb_percent)
SetCondition(amount)
设置耐久度(num amount )
例子
hats.lua
local function ruinshat_proc(inst, owner) -- forcefield when hit
inst:AddTag("forcefield")
inst.components.armor:SetAbsorption(TUNING.FULL_ABSORPTION)
[....]
inst.components.armor.ontakedamage = function(inst, damage_amount)
if owner then
local sanity = owner.components.sanity
if sanity then
local unsaneness = damage_amount * TUNING.ARMOR_RUINSHAT_DMG_AS_SANITY
sanity:DoDelta(-unsaneness, false)
end
end
end
inst.active = true
owner:DoTaskInTime(TUNING.ARMOR_RUINSHAT_DURATION, function()
[...]
if inst:IsValid() then
inst:RemoveTag("forcefield")
inst.components.armor.ontakedamage = nil
inst.components.armor:SetAbsorption(TUNING.ARMOR_RUINSHAT_ABSORPTION)
owner:DoTaskInTime(TUNING.ARMOR_RUINSHAT_COOLDOWN, function() inst.active = false end)
end
end)
end
local function tryproc(inst, owner)
if not inst.active and math.random() < TUNING.ARMOR_RUINSHAT_PROC_CHANCE then
ruinshat_proc(inst, owner)
end
end
local function ruins_onunequip(inst, owner)
[...]
owner:RemoveEventCallback("attacked", inst.procfn)
end
local function ruins_onequip(inst, owner)
[....]
inst.procfn = function() tryproc(inst, owner) end
owner:ListenForEvent("attacked", inst.procfn)
end
local function ruins()
local inst = simple()
inst:AddComponent("armor")
inst.components.armor:InitCondition(TUNING.ARMOR_RUINSHAT, TUNING.ARMOR_RUINSHAT_ABSORPTION)
inst.components.equippable:SetOnEquip(ruins_onequip)
inst.components.equippable:SetOnUnequip(ruins_onunequip)
return inst
end
Beard(胡子)
这个组件使你的生物有胡子,绝燃和剃须必须自己编码。
重要变量
callbacks
:
回调表–插入每天胡子的变化状态,一个函数
(table)
prize
:
剃须奖励物品名,通常是“beardhair”
(string)
bits
:
奖励数量
(num)
canshavetest
:
限制能否剃须,返回布尔值与原因
(fn [ret] bln,str)
onreset
:
重置函数,(例:被火烧毁)
(fn)
重要函数
Reset()
–重置,状态回到零天
例子
beefalo.lua
local function GetStatus(inst)
if inst.components.follower.leader ~= nil then
return "FOLLOWER"
elseif inst.components.beard and inst.components.beard.bits == 0 then
return "NAKED"
end
end
local function fn(Sim)
[....]
local hair_growth_days = 3
inst:AddComponent("beard")
-- assume the beefalo has already grown its hair
inst.components.beard.bits = 3
inst.components.beard.daysgrowth = hair_growth_days + 1
inst.components.beard.onreset = function()
inst.sg:GoToState("shaved")
end
inst.components.beard.canshavetest = function() if not inst.components.sleeper:IsAsleep() then return false, "AWAKEBEEFALO" end return true end
inst.components.beard.prize = "beefalowool"
inst.components.beard:AddCallback(0, function() -- same as callbacks[0] = function()
if inst.components.beard.bits == 0 then
anim:SetBuild("beefalo_shaved_build")
end
end)
inst.components.beard:AddCallback(hair_growth_days, function() --do that for every individual state
if inst.components.beard.bits == 0 then
inst.hairGrowthPending = true --for stategraph
end
end)
[...]
return inst
end
Burnable(可燃的)
该组件允许你的预设物可以点燃和燃烧。这并不包括蔓延! (参见propagator(传播算子))
--注意,对于标准的物品,可以使用
MakeSmallBurnable(inst, time, offset)
MakeMediumBurnable(inst, time, offset)
MakeLargeBurnable(inst, time, offset)
--对于标准的动物,可以使用
MakeSmallBurnableCharacter(inst, sym, offset)
MakeMediumBurnableCharacter(inst, sym, offset)
MakeLargeBurnableCharacter(inst, sym, offset)
重要的变量
burntime
:
默认nil
– 要多长时间完全燃烧
(num)
onignite
:
默认nil
–当着火时调用
(fn)
onextinguish
:
默认nil
– 当不再着火时调用
(fn)
onburnt
:
默认nil
– 当燃烧完成时调用
(fn)
canlight
:
默认true
–能否被点燃
(bln)
burning
:
–是否在燃烧
(bln)
重要的函数
AddBurnFX(prefab, offset, followsymbol)
–增加特效
SetFXLevel(level, percent)
–改变火的强度
Ignite(immediate)
– 立即燃烧
Extinguish()
–停止燃烧
例子
firepit.lua
local function onignite(inst) --when you make a fire, you can cook
if not inst.components.cooker then
inst:AddComponent("cooker")
end
end
local function onextinguish(inst) --remember to un-do the cooking!
if inst.components.cooker then
inst:RemoveComponent("cooker")
end
end
local function fn(Sim)
[...]
inst.components.burnable:AddBurnFX("campfirefire", Vector3(0,.4,0) ) --the firepit has its own fx
inst:ListenForEvent("onextinguish", onextinguish) --this isn't the optimal way to do it, but it works too
inst:ListenForEvent("onignite", onignite)
inst.components.fueled:SetUpdateFn( function() --fueled component handles consumption
if GetSeasonManager() and GetSeasonManager():IsRaining() then
inst.components.fueled.rate = 1 + TUNING.FIREPIT_RAIN_RATE*GetSeasonManager():GetPrecipitationRate()
else
inst.components.fueled.rate = 1
end
end)
end
注意:firepit
不会在烧焦时明确的移除它自己,不像campfire
,如上面所说的,fueled
组件会帮你处理细节.
Container(容器)
这个组件可以让你的预设物可以接受主角给予物品(就像锅子或箱子一样),此外还有一个库存(inventory
)组件,但是那个十分适合角色。
重要的变量
numslots
:
默认0
——你的预设物能够接受多少项目
(num)
widgetslotpos
:
在这里设置的格子的位置(相对位置)
(table (Vector3))
canbeopened
:
默认true
——能否打开
(bln)
acceptsstacks
:
默认true
–不接受整堆的物品
(bln)
type
:
默认”chest”
——不能同时打开两个相同类型的箱子
(str)
widgetanimbank / widgetanimbuild
:
视觉背景
(str)
widgetpos
:
(相对屏幕)的位置
( Vector3)
side_align_tip
:
未知的效果,但需要
(num)
itemtestfn
:
能否进入
(fn)
widgetbuttoninfo
:
这是一个交互式按钮
(table( widget))
onopenfn / onclosefn
:
当打开/关闭时调用,只有在这个物品里有效
(fn)
重要的函数
IsFull()/IsEmpty()
–返回true 或 false
DropEverything()
– 把箱子里的所有物品弹出
DestroyContents()
– 销毁里面所有的物品
GiveItem(item, slot, src_pos, drop_on_fail, skipsound)
–把物品给予给箱子,注意参数item是一个实例
GetItemInSlot(slot)
–返回slot里的实例
Close()
–关闭
FindItems(fn)
– 返回能够导致fn返回true的项目
Has(item, amount)
– 返回是否具有该数量的物品
ConsumeByName(item, amount)
– 删除指定数量的项目
例子
cookpot.lua
local slotpos = { Vector3(0,64+32+8+4,0), --this table has the four slots' positions in form of Vector3(x,y,z)
Vector3(0,32+4,0),
Vector3(0,-(32+4),0),
Vector3(0,-(64+32+8+4),0)}
local widgetbuttoninfo = { --the cook button (optional)
text = "Cook",
position = Vector3(0, -165, 0),
fn = function(inst) --when clicked
inst.components.stewer:StartCooking()
end,
validfn = function(inst) --can it be clicked?
return inst.components.stewer:CanCook()
end,
}
local function itemtest(inst, item, slot) --test whether the item is cookable
if cooking.IsCookingIngredient(item.prefab) then
return true
end
end
local function onopen(inst) --some fancy stuff
inst.AnimState:PlayAnimation("cooking_pre_loop", true)
inst.SoundEmitter:PlaySound("dontstarve/common/cookingpot_open", "open")
inst.SoundEmitter:PlaySound("dontstarve/common/cookingpot", "snd")
end
local function onclose(inst) --more fancy stuff
if not inst.components.stewer.cooking then
inst.AnimState:PlayAnimation("idle_empty")
inst.SoundEmitter:KillSound("snd")
end
inst.SoundEmitter:PlaySound("dontstarve/common/cookingpot_close", "close")
end
local function fn(Sim)
[...]
inst:AddComponent("container")
inst.components.container.itemtestfn = itemtest --can it take that item?
inst.components.container:SetNumSlots(#slotpos) --how many slots must it consider?
inst.components.container.widgetslotpos = slotpos --where shall it display those slots?
inst.components.container.widgetanimbank = "ui_cookpot_1x4" --background
inst.components.container.widgetanimbuild = "ui_cookpot_1x4"
inst.components.container.widgetpos = Vector3(200,0,0) --where is the entire GUI?
inst.components.container.side_align_tip = 100 --??? just set it anyways
inst.components.container.widgetbuttoninfo = widgetbuttoninfo --this is needed for a button
inst.components.container.acceptsstacks = false --it wants only four ingredients!
inst.components.container.type = "cooker" --let chests open parallel to it
inst.components.container.onopenfn = onopen --for that fancy stuff
inst.components.container.onclosefn = onclose
end
Cookable(烹饪)
该组件能够让你的物品能够被烹饪。
重要的变量
product
:
煮熟时得到什么物品
(str或fn)
oncooked
:
在煮熟时调用。
(fn)
例子
local function defaultfn()
local inst = commonfn()
[...]
inst:AddComponent("cookable")
inst.components.cookable.product = "tallbirdegg_cooked"
return inst
end
Dapperness(衣衫褴褛)
顾名思义,给物品一个不整洁的标签,可以按一定的速度减少人物的san值.
重要的变量
dapperness
:
默认 0 速度
(num)
dapperfn
:
每当减少时调用
(fn)
例子
sweatervest.lua
local function fn(Sim)
[...]
inst:AddComponent("dapperness")
inst.components.dapperness.dapperness = TUNING.DAPPERNESS_MED
return inst
end
Eater(吃者)
让你的预设物(通常是一个标准的动物)可以食用带有Edible(可食用的)组件的物品。
重要的变量
strongstomach
:
默认false,是否可以吃有毒的东东
foodprefs
:
所有能过吃的物品列表
(table )
oneatfn
:
当食用时调用
(fn)
lasteattime
:
上一次吃东东是什么时候
(num(GetTime() ))
ignoresspoilage
:
默认false,忽略变质
(bln)
caneattest
:
指定什么可以吃(返回true时)
(fn)
重要的函数
TimeSinceLastEating()
–类似lasteattime,你可以用它来确定什么时候可以开始吃.
基本的食物类型
GENERIC,
VEGGIE,
MEAT,
INSECT,
SEEDS,
WOOD,
ELEMENTAL (矿物),
HORRIBLE (你不想知道的)
例子
local function OnEat(inst, food) --these are special food-effects
if food.components.edible
and food.components.edible.foodtype == "MEAT" --edible food has these types too
and inst.components.werebeast
and not inst.components.werebeast:IsInWereState() then
if food.components.edible:GetHealth() < 0 then --monster meat does bad stuff
inst.components.werebeast:TriggerDelta(1)
end
end
if food.components.edible and food.components.edible.foodtype == "VEGGIE" then --poop
local poo = SpawnPrefab("poop")
poo.Transform:SetPosition(inst.Transform:GetWorldPosition())
end
end
local function fn(Sim)
[...]
inst:AddComponent("eater")
inst.components.eater:SetOmnivore() -- all standard foodtypes besides wood, elemental and horrible
inst.components.eater:SetCanEatHorrible() --add horrible
inst.components.eater.strongstomach = true -- can eat monster meat
inst.components.eater:SetOnEatFn(OnEat)
return inst
end
Edible(可食用的)
能够让你的物品(通常是标准的物品)可以被食用。
重要的变量
healthvalue
:
默认10
–增加的生命
hungervalue
:
默认10
–增加的饥饿
sanityvalue
:
默认 0
–增加的san
foodtype
:
默认”GENERIC”
–孰能孰否
例子
custom
local function fn(Sim)
[...]
inst.components.edible.foodtype = "MyFoodType" --there's default ones in eater.lua
inst.components.edible.healthvalue = -10 --can hurt
inst.components.edible.hungervalue = 0
inst.components.edible.sanityvalue = 40
inst.components.edible.stale_health = 2 --you can set multiplier, in this case it hurts twice as much
return inst
end
Equippable(可装备的)
能够让你的物品(通常是一个标准的装备)可以被持有或者穿戴,当然,你需要一个可交互的动画来显示。
重要的变量
equipslot
:
默认EQUIPSLOTS.HANDS
装备位置
(EQUIPSLOTS.*)
equipstack
:
默认false
是否需要投掷(像吹箭)
(bln)
isequipped
:
装备是否正在装备(只读)
(bln)
onequipfn/onunequipfn
:
默认nil,
在装备时或者卸装时调用
(fn)
walkspeedmult
:
默认nil,
加快或减慢穿戴者
(num)
例子
axe.lua
local function onequip(inst, owner) --visual stuff
owner.AnimState:OverrideSymbol("swap_object", "swap_axe", "swap_axe")
owner.AnimState:Show("ARM_carry")
owner.AnimState:Hide("ARM_normal")
end
local function onunequip(inst, owner) --visual stuff
owner.AnimState:Hide("ARM_carry")
owner.AnimState:Show("ARM_normal")
end
local function fn(Sim)
[...]
inst:AddComponent("equippable")
--don't need equipslot, as it is hands by default
inst.components.equippable:SetOnEquip(onequip) --always remember to set your functions
inst.components.equippable:SetOnUnequip(onunequip)
end
Finite Uses(耐久)
限定物品(通常是一个标准的装备)的使用次数。
重要的变量
total
:
默认100
–最大使用次数
current
:
默认100
– 当前还剩多少
onfinished
:
当耐久完了之后调用(注意,不会自动的删除它本身,你要显式调用)
重要的函数
Use(num)
设置当前耐久
SetConsumption(action, uses)
设置各种行动所需的耐久度
例子
local function onfinished(inst) --remember, it doesn't dissappear per default
inst:Remove()
end
local function fn(Sim)
[...]
inst:AddComponent("finiteuses")
inst.components.finiteuses:SetMaxUses(TUNING.AXE_USES) --does the same as total = ...
inst.components.finiteuses:SetUses(TUNING.AXE_USES) --it loads the saved usage afterwards, does the same as current = ...
inst.components.finiteuses:SetOnFinished( onfinished) --does the same as onfinished = ...
inst.components.finiteuses:SetConsumption(ACTIONS.CHOP, 1) --it loses durability for chopping
return inst
end
Harvestable(收获)
可以让你的组件可以生产物品。
重要的变量
produce
:
默认0
–当前拥有多少物品
(num)
growtime
:
默认nil
多长时间
product
:
默认nil
生产什么
maxproduce
:
默认1
可以容纳多少产品
重要的函数
SetUp(product, max, time, onharvest, ongrow)
初始化
Grow()
立刻生长完成
StartGrowing(time)\StopGrowing()
开始\停止生长
例子
beebox.lua
local function onchildgoinghome(inst, data) --when the bees come home...
if data.child and data.child.components.pollinator and data.child.components.pollinator:HasCollectedEnough() then --and they bring pollen...
if inst.components.harvestable then
inst.components.harvestable:Grow() --make honey
end
end
end
local function fn(Sim)
[...]
inst:AddComponent("harvestable")
inst.components.harvestable:SetUp("honey", 6, nil, onharvest, updatelevel)
inst:ListenForEvent("childgoinghome", onchildgoinghome) --when the bees bring pollen...
return inst
end
Health(生命)
为你的事物(通常是标准的动物或人物)增加一个生命属性。
如果该事物拥有combat(攻击)组件的话,这个是必须的.
重要的变量
minhealth
:
默认0
– 如果设置这个变量>0,你的动物将不会死亡。
invincible
:
默认false
– 无敌模式
vulnerabletoheatdamage
:
默认true
– 能否被烧伤
fire\_damage\_scale
:
默认1
– 烧伤的比例
nofadeout
:
默认false
– 动画效果,死亡时是否直接删除而不会躺下
absorb
:
0
–天生的护甲值
canmurder
:
true
– 能否被谋杀
murdersound
:
string
– 当死亡时声音路径
canheal
:
true
– 能否治疗
redirect
:
function
– 在治疗或受伤时调用(重新定义如何受伤或治疗)
重要的函数
SetMaxHealth(amount)
– 设置最大值
DoDelta(amount, overtime, cause, ignore_invincible)
–更改状态
Kill()
– 杀死它
例子
slurper.lua
local function fn(Sim)
[...]
inst:AddComponent("health")
inst.components.health:SetMaxHealth(200)
inst.components.health.canmurder = false -- can't kill, eventhough it's in the inventory
return inst
end
Hunger(饥饿)
可以让你的事物(通常是一个标准的动物或者人物)获得饥饿的属性,这个整个饥荒游戏的中心慨念
重要的变量
max
:
默认100
– 你的事物能够食用多少的物品
hungerrate,hurtrate
:
默认1
– 饥饿的速度
burning
:
默认 true
– 是否会饿
period
:
默认1
– 减低饥饿值的间隔
例子
smallbird.lua
local function GetStatus(inst)
if inst.components.hunger then
if inst.components.hunger:IsStarving(inst) then
return "STARVING"
elseif inst.components.hunger:GetPercent() < .5 then
return "HUNGRY"
end
end
end
local function GetPeepChance(inst) --they get louder to show their hunger
local peep_percent = 0.1
if inst.components.hunger then
if inst.components.hunger:IsStarving() then
peep_percent = 1
elseif inst.components.hunger:GetPercent() < .25 then
peep_percent = 0.9
elseif inst.components.hunger:GetPercent() < .5 then
peep_percent = 0.75
end
end
return peep_percent
end
local function fn(Sim)
[...]
inst:AddComponent("hunger")
inst.components.hunger:SetMax(TUNING.SMALLBIRD_HUNGER)
inst.components.hunger:SetRate(TUNING.SMALLBIRD_HUNGER/TUNING.SMALLBIRD_STARVE_TIME)
inst.components.hunger:SetKillRate(TUNING.SMALLBIRD_HEALTH/TUNING.SMALLBIRD_STARVE_KILL_TIME)
return inst
end
Insulator(保暖)
让你的物品(通常是一个标准的装备)拥有保暖功能。可以降低temperature(温度)组件对人物的影响。
重要的变量
insulation
:
默认 0
–整个组件就是这个变量.
例子
sweatervest.lua
inst:AddComponent("insulator")
inst.components.insulator.insulation = TUNING.INSULATION_SMALL
Inventory-Item(可存放)
可以让你的物品可以被捡起存放进物品栏。通常这个组件不需要任何的设置,一切保持默认最好。
重要的变量
canbepickedup
:
默认true
– 能够被捡起
onpickupfn
:
function
– 当被捡起时调用
cangoincontainer:
true
–能够进入容器
keepondeath:
false
– 对于十分重要的角色项目或许有用?
imagename
在物品栏的图片名称
atlasname
图片的图集文件
ondropfn
掉落时调用
参数为 inst它本身
onpickupfn
捡起时调用
onputininventoryfn
放入物品栏时调用
重要的函数
GetContainer()
返回拥有物品栏或者容器的实例
要返回它本身使用GetContainer().inst
ChangeImageName(newname)
改变图片
例子
heatrock.lua
local function UpdateImages(inst, range) --this is called by another component
inst.currentTempRange = range
inst.components.inventoryitem:ChangeImageName("heat_rock"..tostring(range))
[...]
end
local function inst()
[...]
inst:AddComponent("inventoryitem") -- usually all you need to do...
return inst
end
Perishable(腐败)
让你的物品会随着时间的推移慢慢的腐败,
注意,这个组件不会删除物品本身,除非你给它设置一个替换物
重要的变量
perishtime:
– 要多长时间才会完全的腐败
number
perishfn:
当腐败后调用(在替换之前)
function
onperishreplacement:
替换物,可为空
string
重要的函数
IsFresh(),IsStale(),IsSpoiled()
–返回true 或 false取决于当前的百分比
GetPercent()
返回一个介于0到1 之间的数字
SetPercent(percent)
设置百分比
ReducePercent(amount)
减低百分比
StartPerishing(),StopPerishing()
开始/结束 腐败
例子
petals.lua
local function fn(Sim)
local inst = CreateEntity()
[...]
inst:AddComponent("perishable")
inst.components.perishable:SetPerishTime(TUNING.PERISH_FAST)
inst.components.perishable:StartPerishing()
inst.components.perishable.onperishreplacement = "spoiled_food"
return inst
end
Pickable(可采摘)
这个组件类似Harvestable,不过可以移植.
重要的变量
regentime:
再生需要多长时间
number
product:
劳动果实
string
onregenfn,onpickedfn,makeemptyfn,makefullfn,makebarrenfn,ontransplantfn:
当这些事件发生时调用
functions
max_cycles,cycles_left:
– 在缺肥前可以采摘多少
numbers
caninteractwith:
–能否采摘
boolean
numtoharvest:
–每次采摘有多少果实
number
quickpick:
是否需要快速的采摘
boolean
重要的函数
FinishGrowing()
立即可收获
Pause(),Resume()
暂停/恢复 生长
SetUp(product, regen, numbertoharvest)
初始化
IsBarren()
返回需不需要果实
MakeBarren()
需要肥料!
例子
carrot.lua
local function onpickedfn(inst)
inst:Remove()
end
local function fn(Sim)
[....]
inst:AddComponent("pickable")
inst.components.pickable.picksound = "dontstarve/wilson/pickup_plants" --you can define a sound
inst.components.pickable:SetUp("carrot", 10)
inst.components.pickable.onpickedfn = onpickedfn
inst.components.pickable.quickpick = true -- carrots are picked quickly, not by fumbling around
return inst
end
grass.lua
local function ontransplantfn(inst) --it starts off barren when planted
if inst.components.pickable then
inst.components.pickable:MakeBarren()
end
end
local function onregenfn(inst) --fancy stuff
inst.AnimState:PlayAnimation("grow")
inst.AnimState:PushAnimation("idle", true)
end
local function makefullfn(inst)
inst.AnimState:PlayAnimation("idle", true)
end
local function makebarrenfn(inst)
inst.AnimState:PlayAnimation("idle_dead")
end
local function onpickedfn(inst)
inst.SoundEmitter:PlaySound("dontstarve/wilson/pickup_reeds")
inst.AnimState:PlayAnimation("picking")
if inst.components.pickable and inst.components.pickable:IsBarren() then
inst.AnimState:PushAnimation("idle_dead")
else
inst.AnimState:PushAnimation("picked")
end
end
local function makeemptyfn(inst)
inst.AnimState:PlayAnimation("picked")
end
local function fn(Sim)
[....]
inst:AddComponent("pickable")
inst.components.pickable.picksound = "dontstarve/wilson/pickup_reeds" --you can define a sound
inst.components.pickable:SetUp("cutgrass", TUNING.GRASS_REGROW_TIME)
inst.components.pickable.onregenfn = onregenfn --remember to set your funtions
inst.components.pickable.onpickedfn = onpickedfn
inst.components.pickable.makeemptyfn = makeemptyfn
inst.components.pickable.makebarrenfn = makebarrenfn
inst.components.pickable.makefullfn = makefullfn
inst.components.pickable.max_cycles = 20 --grass can be picked twenty times (that's a lot)
inst.components.pickable.cycles_left = 20
inst.components.pickable.ontransplantfn = ontransplantfn
return inst
end
Propagator(传播算子)
可以让你的物品可以传播火和热,即使它是不可燃的.
注意:可以使用
MakeSmallPropagator(inst)
MakeLargePropagator(inst)
改变传播速度
重要的变量
flashpoint:
100
–当它点燃
currentheat:
0
–有多烫
decayrate:
1
冷却速度单位每秒
propagaterange:
3
–火能传播多远
heatoutput:
5
–热量损失速度 每秒
damages:
false
–火能否伤害人物
damagerange:
3
–火伤害距离
acceptsheat:
false
能否传播给另外的物品
onflashpoint:
nil
–点燃时调用
重要的函数
Delay(time)
–延时
StartSpreading() StopSpreading()
– 开始/停止传播热量
AddHeat(amount)
加热
Flash()
点燃
Repairable(可修理)
这个组件可以让你的物品(通常是一个标准的装备)可以在使用后修理,恢复耐久.
通常需要一个类似生命的组件来配合,如 Workable, Perishable ,都有这样的效果.
重要的变量
repairmaterial:
–需要的材料(不是预设物的名字)
string
announcecanfix:
–在人物查看时是否可以知道可修理
boolean
onrepaired:
–修理时调用
function
例子
walls.lua
local function onrepaired(inst)
if data.buildsound then --these functions are within a function for all types of walls, hence data
inst.SoundEmitter:PlaySound(data.buildsound)
end
makeobstacle(inst) --assure the wall is an obstacle when it gets repaired
end
local function fn(Sim)
[....]
inst:AddComponent("repairable")
if data.name == "ruins" then
inst.components.repairable.repairmaterial = "thulecite"
else
inst.components.repairable.repairmaterial = data.name --wood, stone or hay
end
inst.components.repairable.onrepaired = onrepaired
return inst
end
Sanity-Aura(san光环)
可以影响附近人物的san值,这个组件十分容易使用,在装备上时自动调用,参考
dapperness.
重要的变量
aura:
0
–速率 每秒
num
aurafn:
用来限制影响的范围
penalty:
0
减少或增加多少san
Talker(话语者)
可以让你的事物(人物或者动物)可以说话,表现为在上方有一行字符.
重要的函数
ShutUp()
停止说,做另外一些重要的事情.
Say(script, time, noanim)
说一些话
script 可以 一个string或者table,包括另外两个变量.
例子
custom
local function greet(inst)
inst.components.talker:Say("Good morning!")
end
local function fn(Sim)
[...]
inst.ListenForEvent("daytime",greet)
return inst
end
Tool(工具)
可以让你的物品(通常是装备)可以增加一些工具的功能.
通常与 worker,workable 这两个组件相关.
重要的函数
SetAction(act, effectiveness)
–设置你的装备能干啥,当 effectiveness = nil是删除这一行动.
例子
axe_pickaxe.lua
local function fn(Sim)
[...]
inst:AddComponent("tool")
inst.components.tool:SetAction(ACTIONS.CHOP, 1.33)
inst.components.tool:SetAction(ACTIONS.MINE, 1.33)
return inst
end
Tradable(交易)
这个组件可以让你的物品可以和交易员交易,当然你也可以设置一个黄金价格.
例子
custom
local function fn(Sim)
[...]
inst:AddComponent("tradable")
inst.components.tradable.goldvalue = 3 --the pigking buys this
inst:AddComponent("equippable")
inst.components.equippable.equipslot = EQUIPSLOTS.HEAD --pigmen can wear this
inst.components.equippable:SetOnEquip( onequip ) --pretend this is for visual appearance
inst.components.equippable:SetOnUnequip( onunequip )
return inst
end
Useable Item(可使用的)
这个组件可以让你的人物使用带有这个组件的物品,效果取决于你让他干什么,当别的组件不能满足时,才使用这个.
重要的变量
onusefn
在人物开始使用时调用
onstopusefn
在人物停止使用时调用
caninteractfn
限制人物是否可以使用
例子
hats.lua
local function stopusingbush(inst, data)
local hat = inst.components.inventory and inst.components.inventory:GetEquippedItem(EQUIPSLOTS.HEAD)
if hat and not (data.statename == "hide_idle" or data.statename == "hide") then
hat.components.useableitem:StopUsingItem()
end
end
local function onequipbush(inst, owner)
[...]
inst:ListenForEvent("newstate", stopusingbush, owner) --automatic event by stategraph
end
local function onunequipbush(inst, owner)
[...]
inst:RemoveEventCallback("newstate", stopusingbush, owner)
end
local function onusebush(inst)
local owner = inst.components.inventoryitem.owner
if owner then
owner.sg:GoToState("hide")
end
end
local function bush()
local inst = simple()
inst:AddTag("hide")
inst.components.inventoryitem.foleysound = "dontstarve/movement/foley/bushhat"
inst:AddComponent("useableitem")
inst.components.useableitem:SetOnUseFn(onusebush)
inst.components.equippable:SetOnEquip( onequipbush )
inst.components.equippable:SetOnUnequip( onunequipbush )
return inst
end
Workable(能工作的)
这个组件可以让你的物品(通常是装备)可以挖,锤,砍,…..
重要的变量
onwork,onfinish:
–在对应事件发生时调用
functions
action:
ACTIONS.CHOP
动作
workleft:
10
时间
savestate:
false
是否保存状态
重要的函数
Destroy(destroyer)
–销毁
SetWorkLeft(work)
–手动设置工作
例子
tree_marsh.lua
local function chop_down_tree(inst, chopper)
[...]
inst.components.workable:SetWorkAction(ACTIONS.DIG) --now it can no longer be chopped, but dug
inst.components.workable:SetOnFinishCallback(dig_up_stump)
inst.components.workable:SetWorkLeft(1)
end
local function fn(Sim)
[...]
inst:AddComponent("workable")
inst.components.workable:SetWorkAction(ACTIONS.CHOP)
inst.components.workable:SetWorkLeft(10)
inst.components.workable:SetOnWorkCallback(chop_tree) --this plays an animation
inst.components.workable:SetOnFinishCallback(chop_down_tree) --this makes a stump
[...]
return inst
end
Light(亮)
这不是一个组件,但是行为很像,所以在这里介绍它.
使用
inst.entity:AddLight()
重要的函数
SetIntensity(percent)
–强烈度
SetRadius(number)
– 光照多远
SetFalloff(percent)
–消退速度
Enable(boolean)
–开关
SetColour(r, b, g)
–设置颜色
例子
mininglantern.lua
local function turnon(inst) -- enable light
inst.Light:Enable(true)
inst.AnimState:PlayAnimation("idle_on")
[...]
end
local function turnoff(inst) --disable light
inst.Light:Enable(false)
inst.AnimState:PlayAnimation("idle_off")
[...]
end
local function fuelupdate(inst) --calculate brightness using math functions
local fuelpercent = inst.components.fueled:GetPercent()
inst.Light:SetIntensity(Lerp(0.4, 0.6, fuelpercent))
inst.Light:SetRadius(Lerp(3, 5, fuelpercent))
inst.Light:SetFalloff(.9)
end
local function fn()
[...]
inst.entity:AddLight() --light is not a component
inst.Light:SetColour(180/255, 195/255, 150/255) --clever way you can use the rbg-system
fuelupdate(inst)
end