Jump to content

Introduction to some Components


Mobbstar

Recommended Posts

Prefabs, components, stategraphs, what does all of that mean?! I just want X to Y when Z!

And for that matter, you'll find a regularly expanded guide to various much-needed components and related things below! Make sure to read the [other guides] too!

 

Since the syntax highlighter isn't good for Lua, my code-snippets will use the following format: generic replace_this - comment/note - highlighted (important) 

 

If you have questions, reply! But if you need assistance with your mod, make a new topic instead!

 

Content:

General
Armor
Beard

Burnable
Container
Cookable
Dapperness
Eater
Edible
Equippable
Finite Uses
Harvestable
Health
Hunger
Insulator
Inventory-Item
Perishable
Pickable

Propagator
Repairable
Sanity-Aura
Talker
Tool
Tradable
Useable Item
Workable

Light

 


 

General

 

(assuming you are familiar with very basic Lua)

 

A component is a bunch of prepared code which every prefab can get. Usually components describe a single property of that prefab, allowing for all kinds of creative combinations. Still confused about those words? [Wots the diff?]

 

To use a component, you first need to add it to your prefab:

inst:AddComponent("MyComponent")

 

Then you can customize the exact details:

inst.components.MyComponent.maxvalue = 100

inst.components.MyComponent:SetSomething(true)

 

If the component is used actively, you can now access that components function when you need them, or set functions the component executes for you:

inst.components.MyComponent:BeFun() --prepared function

inst.components.MyComponent.befunfn = BackflipFn --set a function

 

This is theory though, choose a component below to see examples that make sense! Or - even better - look at the game data!

 

Armor

 

This component makes your item armor, reducing all or certain types of damage dealt to the player. Sadly, this component also implies durability.

 

important Variables:

tags: table -- armor with tags only has an effect if the attack has an identical tag.

onfinished: function -- fires just before the component removes the armor. Theoretically you could use this to make a replacement item or try to reset the condition.

ontakedamage: function -- when the armor takes damage

 

important Functions:

InitCondition(amount, absorb_percent) --how many hits the armor takes, and how well it does that

SetCondition(amount) -- change the current durability

 

Example: (from hats.lua, thulecite crown)

 

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

 

This component gives your creature a magnificant beard. Insulation and sanity from shaving oneself is hard-coded.

 

important Variables:

callbacks: table -- insert the days at which the beard changes state, including a function

prize: string -- the prefab name of the 'beardhair'

bits: number -- how much 'beardhair' the beard drops when shaved

canshavetest: function -- a way to limit shaving, return both a boolean and a 'reason'

onreset: function -- fires when shaving or ressurrecting

 

important Functions:

Reset() -- puts you back at day 0

 

Example: (from 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

 

This component allows your prefab to ignite and burn. This does not include fire spread! (see propagator)

Notice that you can use  MakeSmallBurnable(inst, time, offset) ,  M  akeMediumBurnable(inst, time, offset)  and  MakeLargeBurnable(inst, time, offset)  for standard objects, and  MakeSmallBurnableCharacter(inst,  sym, offset) , MakeMediumBurnableCharacter(inst, sym, offset) and MakeLargeBurnableCharacter(inst, sym, offset) for standard creatures.

 

important Variables:

burntime: default = nil -- how long it takes to burn entirely

onignite: default = nil -- function when the prefab catches fire

onextinguish: default = nil -- function when the prefab is no longer on fire

onburnt: default = nil -- function when the prefab reached its burntime (includes onextinguish)

canlight: default = true -- whether a lighter can light the prefab

burning: --am I on fire?

 

important Functions:

AddBurnFX(prefab, offset, followsymbol) -- for advanced effects

SetFXLevel(level, percent) -- for when you need an inferno or a candle

Ignite(immediate) -- catch fire, immediate only affects the fx

Extinguish() -- stop the fire

 

Example: (from firepit.lua)

 

local function onignite(inst) --when you make a fire, you can cook
    if not inst.components.cooker then
        inst:AddComponent("cooker")
    end
e
nd

 

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

 

Notice that the firepit doesn't remove itself when burnt, unlike the campfire. As mentioned above, the fueled component handles most things.

 

Container

 

This component allows your prefab to hold items given to it, and all related shizzwaz. There is also an inventory component, but that is very adapted to characters.

 

important Variables:

numslots: default = 0 -- how many items your prefab accepts

widgetslotpos: table -- here you need to set the position (relative to the widget position) of the individual slots, using Vector3()

canbeopened: default = true -- for when you want to lock your treasure away

acceptsstacks: default = true -- the crockpot, for example, does not accept stacks

type: default = "chest" -- can't open two of the same type at the same time

 

widgetanimbank/widgetanimbuild: string -- the visual background to the widget

widgetpos: Vector3() -- where (relative to the center of the screen) the widget is

side_align_tip: number -- unknown effect, but needed (maybe soft following of camera?)

itemtestfn: function -- what can go in?

widgetbuttoninfo: table -- this is for an interactive button, like the crockpot has

onopenfn/onclosefn: function -- these fire when opened/closed, only parameter is inst

 

important Functions:

IsFull()/IsEmpty() -- returns true or false

DropEverything() -- scatters the contents all around the prefab

DestroyContents() -- consume all items inside

GiveItem(item, slot, src_pos, drop_on_fail, skipsound) -- give an item ('item' is the instance, not the name!)

GetItemInSlot(slot) -- returns the actual instance

Close() -- shut it

FindItems(fn) -- returns a table with all items that cause 'fn' to return true

Has(item, amount) -- return true/false and the amount (amount is required!)

ConsumeByName(item, amount) -- removes that many items which have that prefab name

 

Example: (from 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

 

This component allows your item to be cooked on a firepit.

 

important Variables:

product: string or function -- the prefab name of the cooked item

oncooked: function -- fires when cooked

 

Example: (from tallbirdegg.lua)

 

local function defaultfn()
    local inst = commonfn()
    [...]

 

    inst:AddComponent("cookable")
    inst.components.cookable.product = "tallbirdegg_cooked"

    return inst
end

 

Dapperness

 

This component is used to improve or wreck the owners state of sanity. It's handled by 'sanity'. Do not confuse this component with the variable dapperness in 'sanity'!

 

important Variables:

dapperness: default = 0 -- the rate

dapperfn: function -- interactive sanity if you want it

 

Example: (from sweatervest.lua, that's the ragged vest)

 

local function fn(Sim)

    [...]

 

    inst:AddComponent("dapperness")
    inst.components.dapperness.dapperness = TUNING.DAPPERNESS_MED


    return inst
end

 

 

Eater

This component allows your prefab to eat [Edible] items.

 

important Variables:

strongstomach: default = false -- whether the prefab can eat poisonous foods normally

foodprefs: table -- all the types of dinner your prefab can feast on

oneatfn: function -- fires when eating

lasteattime: GetTime() value -- if you want to compare when your creature last ate, use this

ignoresspoilage: default = false -- for robots who like to wear a fedora

caneattest: function -- further specify what can and cannot be eaten

 

important Functions:

TimeSinceLastEating() -- similiar to lasteattime, you can use this to determine the time without a new meal

 

Standard-Foodtypes:

GENERIC, VEGGIE, MEAT, INSECT, SEEDS, WOOD, ELEMENTAL (minerals), HORRIBLE (you don't want to know...)

 

Example: (from pigman.lua)

 

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

 

This component makes your prefab food.

 

important Variables:

healthvalue: default = 10 -- how much health it gives

hungervalue: default = 10 -- how much it feeds

sanityvalue: default = 0 -- by how much it raises sanity

foodtype: default = "GENERIC" --who can eat this and who can't

 

Example: (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

 

This component makes your prefab wearable or holdable. You need a swap anim to get the visual working.

 

important Variables:

equipslot: default= EQUIPSLOTS.HANDS --where to equip it

equipstack: default = false --required for blowdarts and such

isequipped: default = false --whether the prefab is equipped, read-only!

onequipfn/onunequipfn: default = nil -- for things that only do stuff when worn

walkspeedmult: default = nil -- speed up or slow down the wearer

 

Example: (from 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

 

This component limits the lifespan of the prefab.

 

important Variables:

total: default = 100 -- set the maximal uses

current: default = 100 -- how many uses does it have now? 

onfinished: function -- what to do when you're done (it doesn't break by itself!)

 

important Functions:

Use(num) -- use by that many uses

SetConsumption(action, uses) --what action takes durability, and how much?

 

Example: (from axe.lua)

 

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

 

This component allows your prefab to produce something that can then be taken.

 

important Variables:

produce: default = 0 -- how much the prefab holds at the moment

growtime: default = nil -- how long it takes to produce

product: default = nil -- what the prefab produces

maxproduce: default = 1 -- how much the prefab can hold

 

important Functions:

SetUp(product, max, time, onharvest, ongrow) -- declare all variables and set some functions at once!

Grow() -- for when you're impatient

StartGrowing(time) -- if you don't give a specific time, it'll use growtime

StopGrowing() -- cancel the outstanding growth task

 

Example: (from 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

 

This component adds life and death to your prefab. Required for combat component.

 

important Variables:

minhealth: default = 0 -- if you raise this, your prefab can't die

invincible: default = false -- take a break from dying in battle

vulnerabletoheatdamage: default = true -- whether your prefab can burn alive

fire_damage_scale: default = 1 -- how devastating fire is

nofadeout: default = false -- turn this on to let the prefab stay there, rather than washing out

absorb: default = 0 -- natural armor

canmurder: default = true -- when in inventory

murdersound: string -- soundpath for inventory-murder

canheal: default = true -- when the player tries to use healing items on the prefab

redirect: function -- for when you really need to calculate damage/healing differently

 

important Functions:

SetMaxHealth(amount) -- initialize health

DoDelta(amount, overtime, cause, ignore_invincible) -- heal/hurt

Kill() -- put it out of its misery

 

Example: (from 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

 

This component lets your prefab starve over time. That's the entire game concept in a single component.

 

important Variables:

max: default = 100 -- how much your prefab can eat

hungerrate,hurtrate: default = 1 -- how fast you starve

burning: default = true -- whether your prefab gets hungry

period: default = 1 -- in how big steps hunger calculates

 

Example: (from 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

 

This components is used with 'temperature' to slow down the wearers temperature fluctuations (or at least the cooling out part, idk about RoG).

 

important Variables:

insulation: default = 0 --that is literally the whole component

 

Example: (from sweatervest.lua, that's the ragged vest)

 

inst:AddComponent("insulator")
inst.components.insulator.insulation = TUNING.INSULATION_SMALL

 

Inventory-Item

 

This component allows your prefab to be picked up and stashed away. Generally this component doesn't need any specification.

 

important Variables:

canbepickedup: default = true -- for when your thing is really sticky

onpickupfn: function -- fires when picked up, parameters are inst and picker_inst

cangoincontainer: default = true -- for when your thing is really sticky, say a mobile :razz:

keepondeath: default = false -- maybe useful for very important character items

imagename -- the image when in an inventory or container

atlasname -- atlas for your tex file

ondropfn -- fires when dropped on the ground, only parameter is inst

onpickupfn -- fires when picked up, parameter is inst

onputininventoryfn -- fires when put in inventory...

 

important Functions:

GetContainer() -- returns the container/inventory component of the owner (for the owner instance, use GetContainer().inst)

ChangeImageName(newname) -- change the appearance of your item

 

Example: (from 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

 

This component makes your prefab decompose over time. This does not imply removing the prefab unless you set a replacement!

 

important Variables:

perishtime: number -- how long it takes to perish in total

perishfn: function -- fires when perishing (before the replacement)

onperishreplacement: string -- whether and what remains when perished

 

important Functions:

IsFresh(),IsStale(),IsSpoiled() -- return true or false, depending on the current percent

GetPercent() -- returns a value between 1 and 0

SetPercent(percent) -- percent must be between 1 and 0

ReducePercent(amount) -- subtracts that many percent of total perishtime from the remaining perishtime

StartPerishing(),StopPerishing() -- control whether the prefab spoils at all

 

Example: (from 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

 

This component is oddly similiar to [Harvestable], but when transplanted, can barren after being picked too often.

 

important Variables:

regentime: number -- how long it takes to regrow

product: string -- the fruit of labour

onregenfn,onpickedfn,makeemptyfn,makefullfn,makebarrenfn,ontransplantfn: functions --fire at those events

max_cycles,cycles_left: numbers -- how often the prefab can be picked before barrening

caninteractwith: boolean -- control whether it can be picked

numtoharvest: number -- set this if you want several items for each pick

quickpick: boolean -- for when you need it fast and painless

 

important Functions:

FinishGrowing() -- for when you're impatient

Pause(),Resume() -- for when you need a break

SetUp(product, regen, numbertoharvest) -- three in one!

IsBarren() -- returns true or false

MakeBarren() -- for when you want to request fertilizer

 

Example: (from 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

 

Example: (from 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

 

This component allows fire (heat) to spread onto and from the prefab (even if it isn't burnable)

Notice that you can use MakeSmallPropagator(inst) or MakeLargePropagator(inst) for standard propagating (and afterwards change stuff if you want to).

 

important Variables:

flashpoint: default = 100 --when it "ignites"

currentheat: default = 0 --how hot is it?

decayrate: default = 1 --how quickly it cools (per seconds)

propagaterange: default = 3 --how far the fire can spread

heatoutput: default = 5 --how much heat (per seconds) the prefab emits while spreading

damages: default = false --whether the fire hurts

damagerange: default = 3 --how far the fire damages (if at all)

acceptsheat: default = false -- whether fire can spread to the prefab

onflashpoint: default = nil -- fires when it "ignites"

 

important Functions:

Delay(time) -- prevent taking heat for a while

StartSpreading() -- make the prefab spread heat

StopSpreading() -- self-explainatory

AddHeat(amount) -- increase the heat

Flash() -- force "ignition"

 

Repairable

 

This component allows your prefab to accept items and transform after a certain amount.

Keep in mind that this component requires either health, [Workable] or [Perishable] to have an effect.

 

important Variables:

repairmaterial: string -- the material required (not the prefab name)

announcecanfix: boolean -- whether the player character mentions this component on inspecting

onrepaired: function -- fires when given items

 

Example: (from 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

 

This component raises or lowers the sanity of nearby people. It is very easy to use. For the effect when equipped, look into dapperness!

 

important Variables:

aura: default = 0 --set this as the rate (per seconds)

aurafn: --limit the people who are affected

penalty: default = 0 -- reduce the maximal sanity temporarily

 

Talker

 

This component allows your prefab to talk. Talk as in "text above it and some annoying sounds".

 

important Functions:

ShutUp() -- stop talking, for when doing more important things

Say(script, time, noanim) -- say something, script is a string or a table which includes the other two variables

 

Example: (custom)

 

local function greet(inst)

    inst.components.talker:Say("Good morning!")

end

 

local function fn(Sim)

    [...]

   

    inst.ListenForEvent("daytime",greet)

 

    return inst

end

 

Tool

 

This component makes your handheld items tools (related to worker and workable components).

 

important Functions:

SetAction(act, effectiveness) -- set what the tool can and can't, effectiveness = nil removes that action

 

Example: (from 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

 

This component simply indicates that an item can be traded to traders. You can also set a gold value.

 

Example: (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

 

This component allows the player to use your prefab. What it does it up to you. This is useful for when there is no other fitting component.

 

important Variables:

onusefn -- this happens when the player uses it

onstopusefn -- this happens when the player stops

caninteractfn -- this allows you to limit the players ability to use it

 

Example: (from hats.lua, bushhat)

 

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

 

This component lets your prefab be mined, hammered, chopped, dug....

 

important Variables:

onwork,onfinish: functions -- fire at those events

action: default = ACTIONS.CHOP -- how it can be worked

workleft: default = 10 -- how often it can be worked still

savestate: default = false -- for when it is really important to stay broken

 

important Functions:

Destroy(destroyer) -- for basehassler and such

SetWorkLeft(work) -- manually set the work left

 

Example: (from 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

 

This isn't even a component, but acts a lot like one. Thus, I'll explain it in the same manner. Maybe I'll add images to visualize the differences.

 

add using inst.entity:AddLight()

 

important Functions:

SetIntensity(percent) -- how intense and bright the light is

SetRadius(number) -- how far the light shines

SetFalloff(percent) -- higher percent mean more rapid fading (after radius)

Enable(boolean) -- if the boolean is true, the light turns on, if it is false, it turns off but keeps its properties

SetColour(r, b, g) -- red/blue/green are percent values

 

Visual Example:

 

Example: (from 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

 

Of course you can just enable it at all times, or at fixed brightness. You can use the common rbg system using divisions like above, to implement easily pickable colours (for example using [colourpicker])

Link to comment
Share on other sites

Thanks , this will be useful for my project!

 

It's my pleasure! I keep adding onto this thread, showing others how to use components and what components there are, and even learn new methods myself, but eventually this page is just going to break the Klei servers :p

Link to comment
Share on other sites

You should definitely ask moderators to link this to the sticky list before it gets lost in here. I'm not sure what's the state of ds wiki or the modding resources on, I admit I never looked. I suppose it can't hurt tho - it's easier to format and maintain.

 

I... I already forgot about this thread...

 

If the admins add this to the guides thread once they're back in office, that'd be amazing.

 

EDIT: Wait, does the DS wiki have a modding section?

 

Can you explain other components that may be useful. I feel those were gear towards custom creation. CAn you explain some components that can be useful for making custom characters maybe. or is that something different.

 

I pick the next components by going over the list and checking some components I've heard or used before :razz: Do you have any components in mind?

Link to comment
Share on other sites

To name a few, Health, Hunger, Sanity(in general). I feel The component Combat could be use for on hit effects and hallucination could be used something other than the character going insane.

 

Im kinda looking at the code and trying to understand what is it callling for or defining. I feel like it should be self explanatory but I guess Lack of sleep or plain ignorance is keeping me from it.

 

 

 

Wait, does the DS wiki have a modding section?

 

It does Here.

 

Also, Does these thing pertain to DST. I feel the coding might be slightly different because of my other post.

 

My mistake and i cant read apparently 

Link to comment
Share on other sites

To name a few, Health, Hunger, Sanity(in general). I feel The component Combat could be use for on hit effects and hallucination could be used something other than the character going insane.

 

I added Health and Hunger (and a few extras ;)). Maybe I still wind up going over Sanity or Combat tonight. The forums seem to not like that a lot, I'll try some time later.

 

It does Here.

 

Also, Does these thing pertain to DST. I feel the coding might be slightly different because of my other post.

 

I wasn't talking about DST, but the DS wikia, a different website. It's rather messy and unorganized, and all in all not much better than this.

Link to comment
Share on other sites

FYI, I found out why couldn't extend this lately... It's too much and blows up the Klei servers every time I try :p

 

But seriously, I can't add the important components left because it's too much. Maybe I wind up moving this to the DS wikia (if I can get some support), but for now it'll stay as it is.

Link to comment
Share on other sites

@Mobbstar

Firstly, this has been very helpful, great work. Whenever I need to know about a component, I search it here second to the corresponding lua file.

 

May I add them to the unofficial API Docs?

 

I would appreciate that.

 

Sadly I had to stop expanding the list and amending the explanations because the post was too long. May I get permissions to contribute to the unofficial APID?

 

(btw, it took me a while to realise it's Don't Starve only)

 

EDIT: Maybe you could make (or invite me to) a PM?

Link to comment
Share on other sites

I'm editing characters for my Friend and me.

I would like to know how i can add an effect to a character to gain sanity when another player is nearby

and for another character to gain sanity when it's raining

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

Please be aware that the content of this thread may be outdated and no longer applicable.

×
  • Create New...