Jump to content

Recommended Posts

Hi Don't Starve modders,

 

I keep coding a mod with a friend and we have an idea for a custom character.
He will be able to craft a special item (like Wigfrid with her helmet and spear).

 

But the action of this item is a bit special and nothing similar exist in the game.

I need to create something which will heal all the stats (hunger, sanity and health), just like the healing salve does.

 

But I can't use a "healer" component because we can only set the health amount.

 

So I decided to create my own component and my own action.

 

First the item :

 

item.lua

local function fn(Sim)	local inst = CreateEntity()	local trans = inst.entity:AddTransform()	local anim = inst.entity:AddAnimState()    MakeInventoryPhysics(inst)        inst.AnimState:SetBank("spider_gland_salve")    inst.AnimState:SetBuild("myitem")    inst.AnimState:PlayAnimation("idle")    inst:AddComponent("stackable")	inst.components.stackable.maxsize = TUNING.STACK_SIZE_SMALLITEM    inst:AddComponent("inspectable")        inst:AddComponent("inventoryitem")    inst.components.inventoryitem.atlasname = "images/inventoryimages/myitem.xml"		inst:AddComponent("characterspecific")    inst.components.characterspecific:SetOwner("mycharacter")		inst:AddComponent("mycomponent")    inst.components.smokable:SetAmounts(-5, -5, 2)	    return instend

My custom component :

local MyComponent = Class(function(self, inst)    self.inst = inst	self.hunger = 0	self.sanity = 0    self.health = 0end)function MyComponent:SetAmounts(hunger, sanity, health)	self.hunger = hunger	self.sanity = sanity    self.health = healthendfunction MyComponent:CollectInventoryActions(doer, actions)    if doer.components.hunger and doer.components.sanity and doer.components.health then        table.insert(actions, ACTIONS.USE)    endendfunction MyComponent:Use(target)    if target.components.hunger and target.components.sanity and target.components.health then        target.components.hunger:DoDelta(self.hunger)		target.components.sanity:DoDelta(self.sanity)		target.components.health:DoDelta(self.health,false,self.inst.prefab)        if self.inst.components.stackable and self.inst.components.stackable.stacksize > 1 then            self.inst.components.stackable:Get():Remove()        else            self.inst:Remove()        end        return true    endendfunction MyComponent:CollectUseActions(doer, target, actions)    if target.components.health and target.components.hunger and target.components.sanity then        table.insert(actions, ACTIONS.USE)    endendreturn MyComponent

And in modmain.lua I created my custom action (named "USE") :

local require = GLOBAL.require--require "class"require "bufferedaction"local STRINGS = GLOBAL.STRINGSlocal ACTIONS = GLOBAL.ACTIONSlocal Action = GLOBAL.Actionlocal USE = Action()USE.id = "USE"USE.str = "Use"USE.fn = function(act)    if act.invobject and act.invobject.components.mycomponent then        local target = act.target or act.doer    	return act.invobject.components.mycomponent:Use(target)    endend AddAction(USE)  GLOBAL.ACTIONS.USE = USE

I have my item in my stuff, i can see that a right click does the "use" action, but when i click on it, nothing happen.

 

If I use :

local USE = Action(1, true)

instead, I can use my item but there is no animation like a healing salve would do.

 

Sorry for the long post and maybe grammar errors (I'm not an english native speaker).

I'm still looking for a solution but I have no more ideas...

 

Thanks in advance,

 

Inward

You're not adding an action handler to the character's stategraph.

 

local ActionHandler = GLOBAL.ActionHandlerAddStategraphActionHandler("wilson", ActionHandler(USE, "dolongaction"))
As an aside, you're putting prefab-specific code inside a component, which makes the component much less robust (see the reason that you have to make your own component in the first place; Klei's "healer" component is not great, they should have made a generic component and used callbacks to do the healing [there is "useableitem" but it's not flexible enough either, it's written to handle variable length uses]).

I'd suggest making a component something like:

local GenericUseableItem = Class(function(self, inst)    self.inst = inst    self.onusefn = nil    self.canusefn = nil    self.validtargetfn = nil    self.action = ACTIONS.USEend)function GenericUseableItem:Use(target, doer)    if self.onusefn then        self.onusefn(self.inst, target, doer)    endendfunction GenericUseableItem:CanBeUsedBy(doer)    if self.canusefn then        self.canusefn(self.inst, doer)    else        return true    endendfunction GenericUseableItem:CanBeUsedOn(target, doer)    if not self:CanBeUsedBy(doer) then        return false    elseif self.validtargetfn then        return self.validtargetfn(self.inst, target, doer)    else        return true    endend-- for targeting somethingfunction GenericUseableItem:CollectUseActions(doer, target, actions)    if self:CanBeUsedOn(target, doer) then        table.insert(actions, self.action)    endend-- for using while in an inventoryfunction GenericUseableItem:CollectInventoryActions(doer, actions)    if self:CanBeUsedBy(doer) then        table.insert(actions, self.action)    endend return GenericUseableItem
then the prefab-specific code would all go in your prefab file and the component would be useful for more things than just healing health/sanity/hunger at once.

Example usage:

--in your prefab filelocal function canbeused(inst, target, doer)    return target and target.components.health and target.components.hunger and target.components.sanityendlocal function onused(inst, target, doer)    if canbeused(inst, target, doer) then        target.components.hunger:DoDelta(-5)        target.components.sanity:DoDelta(-5)        target.components.health:DoDelta(2,false,inst.prefab)        if inst.components.stackable and inst.components.stackable.stacksize > 1 then            inst.components.stackable:Get():Remove()        else            inst:Remove()        end        return true    endend-- in the prefab's fn function    inst:AddComponent("genericuseableitem")    inst.components.genericuseableitem.canusefn = canbeused    inst.components.genericuseableitem.validtargetfn = canbeused    inst.components.genericuseableitem.onusefn = onused
I'd also probably stay away from the action id "USE" because it seems extremely likely to be implemented either by the game or by other mods in the future which will cause conflicts (one overwriting the other). Could prefix it with your mod name or something like that just to make sure it won't step on anything in the future. Edited by squeek

Hi everyone,

I have a last problem for my character and I just can't find a solution...

 

I would like to increase the difficulty of the Don't Starve experience by losing health when the sanity is 0, like when the hunger is 0.

I already created a function for the "sanitydelta" event :

local function onsanitychange(inst, data)	local sanity = inst.components.sanity.current	local bonus = 100 - sanity			inst.components.combat.min_attack_period = TUNING.WILSON_ATTACK_PERIOD / (1 + (bonus / 100))		inst.components.locomotor.walkspeed = (TUNING.WILSON_WALK_SPEED * (1 + ((bonus/3) / 100) ))	inst.components.locomotor.runspeed = (TUNING.WILSON_RUN_SPEED * (1 + ((bonus/3) / 100)))		if sanity <= 0 then	--lose health per second	    elseif sanity > 0 then    --cancel the health loss    endend
local fn = function(inst)
 
inst:ListenForEvent("sanitydelta", onsanitychange)
 
end

 

I don't know how to replace the comments on this code, or if I should do it here.

Maybe I could create a tag on my character, then override the Sanity:OnUpdate(dt) function and create a Sanity:IsLosingMind() (or something like this), override the HealthBadge:OnUpdate(dt) function (to display the arrow when losing health) and check with the tag with that's my character or not.

 

I tried all day but I couldn't find a good result.

 

If someone could help me for this, it would be awsome.

 

Thanks in advance,

 

Inward

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
  • Create New...