Jump to content

Instant crock pot cook for custom character


Recommended Posts

I haven't seen any other forum posts that had answers to this question so I decided to make one.

I'm trying to port a mod from DST to singleplayer that featured a character being instantly able to cook with the crock pot.

I tried the following code but it didn't do anything in game.

 

-- Fast Cooker
COOK.fn = function(act, ...)
    local result = old_cook_fn(act)
    local stewer = act.target.components.stewer
    if result and stewer ~= nil and act.doer.prefab == "vanilla" then
        local fn = stewer.task.fn
        stewer.task:Cancel()
        fn(act.target, stewer)
    end
end

 

any help would be appreciated

 

modmain.lua

vanilla.lua

chocola and vanilla ds.zip

Link to comment
Share on other sites

Hi Danielance.  I got your code to work in my own files.
I've done work with the GLOBAL.ACTIONS.COOK.fn function before with my own personal project, enough to know its limitations.  Here is the limitation:  in terms of crockpots and warly's portable cookpot, this function will only call when you RIGHT-CLICK on a ready-to-cook crockpot or portablecookpot to make it cook.  It will NOT call when you press the "Cook" button in the crockpot interface/UI where you can put the four ingredients.  Because ACTIONS.COOK.fn does not trigger inherently in the code when you click the "Cook" button in the UI, our scripts overriding the ACTIONS.COOK.fn will not trigger.  Which makes me wonder, if this code did work in DST for the "Cook" button as well, maybe I should go look and see what the differences are between the two games' actionhandlers..

So if you do press that button, rather than right-clicking on the crockpot, it will appear as if nothing is happening.  Cooking in the other method will instantly cook the recipe, as you'd like.

To make it act just like in DST is another story:

previewDS_wonder4.jpg


Edit:  So if we want to make it do the same in DS, we will have to reverse engineer what Klei did to make the action handler/ actionpicker do that.  In DST, in the containers.lua, there is a function here that calls the GLOBAL.ACTIONS.COOK.fn

function params.cookpot.widget.buttoninfo.fn(inst)
    if inst.components.container ~= nil then
        BufferedAction(inst.components.container.opener, inst, ACTIONS.COOK):Do()
    elseif inst.replica.container ~= nil and not inst.replica.container:IsBusy() then
        SendRPCToServer(RPC.DoWidgetButtonAction, ACTIONS.COOK.code, inst, ACTIONS.COOK.mod_name)
    end
end

And in Don't Starve, here is the widgetbutton function:
local widgetbuttoninfo = {
    text = STRINGS.ACTIONS.COOK.GENERIC,
    position = Vector3(0, -165, 0),
    fn = function(inst)
        inst.components.stewer:StartCooking()    
    end,
    
    validfn = function(inst)
        return inst.components.stewer:CanCook()
    end,
}

So theoretically, all we have to do is 1) modify this code to push an event that the character can listen for, where we can run our scripts, or 2) modify this code to call the GLOBAL.ACTIONS.COOK.fn, where our overriding of that function will run our scripts.

What I decided to do was modify the code to push an event that triggers the code I want to run.  Here is what I did:

--modmain.lua
local require = GLOBAL.require
local ACTIONS = GLOBAL.ACTIONS

local function CookPotPostInit(inst)
    print("CookPotPostInit called")
    local preFn = function(inst)
        print("preFn called")
        if inst.components.container~=nil then
            return inst.components.container.opener
        end
        return false
    end
    local oldFn = inst.components.container.widgetbuttoninfo.fn
    local newFn = function(inst, opener)
        print("newFn called")
        opener:PushEvent("oncookstewer", {target = inst})
    end
    inst.components.container.widgetbuttoninfo.fn = function(inst)
        print("widgetbuttoninfo.fn called")
        local opener = preFn(inst) --this function grabs the instance of the player before the container closes
        oldFn(inst) --the original function, so that we won't have to modify the script later if the devs change this script
        if opener~=false then
            newFn(inst, opener) --push the event that we need to run our scripts
        end
    end
end

AddPrefabPostInit("cookpot", CookPotPostInit) --call the function that modifies the cookpot

AddPrefabPostInit("portablecookpot", CookPotPostInit) --if for whatever reason, warly's cookpot is in the world, you can use this code for his portable cookpot, too.

--modmain.lua, this code is for if you also want vanilla's ability to work when right-clicking on the cookpot to make it cook
local CookFnOld = ACTIONS.COOK.fn

local function CookStewerFnNew(act)
        print("CookStewerFnNew called")
        act.doer:PushEvent("oncookstewer", {target = act.target})
end

ACTIONS.COOK.fn = function(act)
    print("ACTIONS.COOK.fn called")

    local result = CookFnOld(act)
    if result == true then
        print("CookFnOld returned true")
        if act.target.components.stewer then
            CookStewerFnNew(act)
        end
    end
    return result
end


--vanilla.lua
--in the fn, same function where you set stats, soundsname, tags, etc.
inst:ListenForEvent("oncookstewer", OnCookStewer)

--new function higher up in vanilla.lua
local function OnCookStewer(inst, data)
    print("OnCookStewer called")
    local target = data.target
    if target.components.stewer then
        print("target.components.stewer is true")
        local stewer = target.components.stewer
        local fn = stewer.task.fn
        stewer.task:Cancel()
        fn(target, stewer)
    end
end

 

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