Jump to content

How to add a custom action to a tool and item


Recommended Posts

I want a tool to only work on 1 item no chopping no digging no hammering no mining just this new action "operate" I want it to be similar to mining but I don't want it to work on rocks just this one item... I've been at this for the past week now with no success! I've got stategraph postinits and the action written down and both the item and the tool have ACTION.OPERATE but idk why it's not working...?

does anyone know how to do this and can they explain how it works for me? thank you

 

EDIT: I'd add code but tbh I don't feel like adding in 100-200 lines of code that are sitting all over the place in 5 different files! and besides I want every single step presented to me so I can go off of that! and it'll be a tutorial for future peoples to see

Link to comment
Share on other sites

Step one: build an action (as seen in actions.lua)

You can do that from modmain.lua

You'll need to set the id and string manually for this one, or it will display as "ACTION"

 

Step two: when to trigger the action (as seen in... many components)

You'll need a dummy component for this part. Don't question it. Dummy is your friend.

It needs a "Collect[...]Action" function. Look at other components for examples

Keep in mind to set an "if [cond] then" in that function, or else the action will be at all times. You probably want to test for the tool being "equipped" or "in inventory".

Attach the component to the specific targets. You can probably attach it to the tool too, but I never tried that.

 

I can't give you sample code yet, since both mods I made custom actions for aren't released.

Link to comment
Share on other sites

Step one: build an action (as seen in actions.lua)

You can do that from modmain.lua

You'll need to set the id and string manually for this one, or it will display as "ACTION"

 

Step two: when to trigger the action (as seen in... many components)

You'll need a dummy component for this part. Don't question it. Dummy is your friend.

It needs a "Collect[...]Action" function. Look at other components for examples

Keep in mind to set an "if [cond] then" in that function, or else the action will be at all times. You probably want to test for the tool being "equipped" or "in inventory".

Attach the component to the specific targets. You can probably attach it to the tool too, but I never tried that.

 

I can't give you sample code yet, since both mods I made custom actions for aren't released.

could you PM me an example of a dummy component? I'm a weirdo that understands code alot better than english! and english is my only language... :I

Link to comment
Share on other sites

Actions are incredibly unintuitive.  Here's an example:

 

modmain.lua:

SLAP = GLOBAL.Action(0, true)SLAP.str = "Slap"SLAP.id = "SLAP"SLAP.fn = function(act)    if act.target.components.slappable then        act.doer.SoundEmitter:PlaySound("dontstarve_DLC001/creatures/catcoon/swipe") --I'm sure there's a better sound somewhere         act.target.components.slappable:DoSlap(act.doer)    end    return trueendAddAction(SLAP)AddPrefabPostInit("evergreen", function(inst) inst:AddComponent("slappable") end)

components\slappable.lua:

local Slappable = Class(function(self, inst)    self.inst = instend)function Slappable:DoSlap(slapper)    print("This was printed via the component because my owner got slapped")    print(self.inst, "slapped by: ", slapper)endfunction Slappable:CollectSceneActions(doer, actions)    --What good is trying to slap when you have a shovel in your hand?    if not doer.components.inventory.equipslots.hands then        table.insert(actions, ACTIONS.SLAP)    endendreturn Slappable

NOTE: This creates an "instant" action.  As such, it completes without making you walk to the target.  Which makes no sense in the context of slapping.  To make it non-instant, remove the arguments from GLOBAL.Action().  Note that if you do this, you need to then add an ActionHandler to wilson's stategraph that handles ACTIONS.SLAP.

Link to comment
Share on other sites

Ok... I've read all this stuff many times and even looked through many files many times and reread them over and over and over and over again and again and again and again it's getting VERY frustrating for me!

 

What I'm trying to do is get my operating tool to operate on the patient the same way an axe chops a tree or a pickaxe mines a rock or a shovel digs a berry bush etc.

 

from the looks of it these tools (axe, shovel, net, hammer, pickaxe) do not need a custom component they just need "tool" which I did...

 

here's my code to show what I've got

 

action fn

ACTIONS.OPERATE.fn = function(act)
    if act.target.components.workable and act.target.components.workable.action == ACTIONS.OPERATE then
        local numworks = 1
 
        if act.invobject and act.invobject.components.tool then
            numworks = act.invobject.components.tool:GetEffectiveness(ACTIONS.OPERATE)
        elseif act.doer and act.doer.components.worker then
            numworks = act.doer.components.worker:GetEffectiveness(ACTIONS.OPERATE)
        end
        act.target.components.workable:WorkedBy(act.doer, numworks)
    end
    return true
end

 

stategraph crap

local G = GLOBAL

local ACTIONS = G.ACTIONS
AddStategraphActionHandler("SGwilson", G.ActionHandler(ACTIONS.OPERATE, 
function(inst) 
if not inst.sg:HasStateTag("preoperate") then 
if inst.sg:HasStateTag("operating") then
return "operate"
else
return "operate_start"
end
end 
end))
 
AddStategraphState("SGwilson", G.State{
name = "operate_start",
tags = {"preoperate", "working"},
onenter = function(inst)
inst.components.locomotor:Stop()
inst.AnimState:PlayAnimation("pickaxe_pre")
end,
 
events = {G.EventHandler("animover", function(inst) inst.sg:GoToState("operate") end)}
})
    
AddStategraphState("SGwilson", G.State{
name = "operate",
tags = {"preoperate", "operating", "working"},
onenter = function(inst)
inst.sg.statemem.action = inst:GetBufferedAction()
inst.AnimState:PlayAnimation("pickaxe_loop")
end,
 
timeline = {
G.TimeEvent(9*G.FRAMES, function(inst) 
inst:PerformBufferedAction() 
inst.sg:RemoveStateTag("preoperate") 
inst.SoundEmitter:PlaySound("dontstarve/wilson/hit")
end),
 
G.TimeEvent(14*G.FRAMES, function(inst)
 
if (TheInput:IsControlPressed(CONTROL_SECONDARY) or
  TheInput:IsControlPressed(CONTROL_ACTION) or TheInput:IsControlPressed(CONTROL_CONTROLLER_ALTACTION)) and 
inst.sg.statemem.action and 
inst.sg.statemem.action.target and 
inst.sg.statemem.action.target:IsActionValid(inst.sg.statemem.action.action, true) and 
inst.sg.statemem.action.target.components.workable then
inst:ClearBufferedAction()
inst:PushBufferedAction(inst.sg.statemem.action)
end
end),
},
events = {
G.EventHandler("unequip", function(inst) inst.sg:GoToState("idle") end ),
G.EventHandler("animover", function(inst) 
inst.AnimState:PlayAnimation("pickaxe_pst") 
inst.sg:GoToState("idle", true)
end )
}      
})

 

Seems like everything's in order... right? WRONG because when I click on that patient with my tool the guy just walks on up to him and stands there doing nothing!!!!

 

also, yes I have worked with actions a lot before! this mod now has 4 custom actions and 3 of them work perfectly! but this one... THIS ONE IS BEING PURE EVIL!!!!!!

 

please answer with a legitimate response within the next 12 hours I'm trying to rush out the next update

(because everything else is already ready to be uploaded)

Link to comment
Share on other sites

@Fidooop, when you put your mouse over the patient, does it say "operate"? If not, you might need to have a collect_actions function within a custom component that adds "OPERATE" to the list of do-able actions on the patients.

 

Does your tool prefab call 

tool:SetAction(ACTIONS.OPERATE, effectiveness)

-

 

And do the patients' prefabs call

workable:SetWorkAction(ACTIONS.OPERATE)

and

workable:SetOnWorkCallback(on_work_fn)

-

 

Also, try throwing in a few print statements to see where it gets stuck?

Link to comment
Share on other sites

thank you @corrosive for helping me out! turns out the only reason causing the error was my postinits going to SGwilson instead of wilson....  heh... HEHEH... HEHEHEHEHEHEHAHAHAHAHAHAAHAHAHA 

 

good april fools day prank KLEI!!!!! O_O

 

Now I just need to figure out why the hell putting the new heart into bab if his container is closed crashes the game! :grin:

EDIT: oh... I fixed it lol that was easy

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...