Jump to content

Need help creating a smelter


Recommended Posts

So, I'm currently working on a mod that adds the smelter from ds hamlet and the iron ore, and I'm having trouble setting up the smelter component, but crashes whenever I press the smelt button in the ui. Please help!

smelter.lua component

local smelting = require "smelting"

local Smelter = Class(function(self, inst)
    self.inst = inst
	self = self
    
    self.issmelting = nil
    self.product = nil
    self.canharvest = nil

    self.smelttime = 0
    
    self.startsmeltingfn = nil
    self.donesmeltingfn = nil
    self.onharvest = nil

    self:Update(0, self, self.inst, self.issmelting, self.product, self.canharvest, self.smelttime)
end)

function Smelter:StartSmelting(doer, self, inst)
    self.issmelting = true
    self.product = nil
    
    if self.startsmeltingfn then
        self.startsmeltingfn(self.inst)
    end
    
    local ings = {}  

    for k, v in pairs (self.inst.components.container.slots) do
        table.insert(ings, v.prefab)
    end
    
    self.product, self.smelttime = smelting.CalculateSmelterRecipe(self.inst.prefab, ings)

    self.inst.components.container:Close()
    self.inst.components.container.canbeopened = false
	
    self:Update(0, self, self.inst, self.issmelting, self.product, self.canharvest, self.smelttime)
end

function Smelter:ResumeSmelting()
    self.issmelting = true

    if self.startsmeltingfn then
        self.startsmeltingfn(self.inst)
    end
    
    self.inst.components.container:Close()
    self.inst.components.container.canbeopened = false

    self:Update(0)
end

function Smelter:DoneSmelting()
    self.issmelting = nil
    self.canharvest = true
    
    if self.donesmeltingfn then
        self.donesmeltingfn(self.inst)
    end
    
    self.inst:AddTag("harvestable")
    
    self.inst.components.container.canbeopened = false

    self.inst.components.container:DestroyContents()
end

function Smelter:ResetSmelter()
    self.issmelting = nil
    self.product = nil
    self.canharvest = nil

    self.smelttime = 0
    
    self.inst.components.container.canbeopened = true

    self.inst:RemoveTag("harvestable")

    self.inst.components.container:DropEverything()
    
    if self.task then
        self.task:Cancel()
        self.task = nil
    end
end

function Smelter:Harvest(harvester)
    if self.canharvest then
        if self.onharvest then
            self.onharvest(self.inst)
        end

        if self.product then
            if harvester and harvester.components.inventory then
                local loot = SpawnPrefab(self.product)
                
                if loot then                    
                    loot.targetMoisture = 0
                    loot:DoTaskInTime(2*FRAMES, function()
                        if loot.components.moisturelistener then 
                            loot.components.moisturelistener.moisture = loot.targetMoisture
                            loot.targetMoisture = nil
                            loot.components.moisturelistener:DoUpdate()
                        end
                    end)
                    harvester.components.inventory:GiveItem(loot, nil, self.inst:GetPosition())
                end
            end
        end
        
        self:ResetSmelter()
        
        return true
    end
end

------------------------------------------------------------------------------------------------------
-- Update Functions

local function OnDoUpdate(inst, self, period)    
    --self:Update(period)
end

function Smelter:Update(dt, self, inst, issmelting, product, canharvest, smelttime)
    self.inst = inst
	self.issmelting = issmelting
    self.product = product
    self.canharvest = canharvest

    self.smelttime = smelttime
    if self.issmelting and not self.canharvest then
        self.smelttime = self.smelttime - dt
    
        if self.smelttime <= 0 then
            if self.product ~= nil then
                self:DoneSmelting()
            end
        end
    end
    
    if self.task == nil then
        self.task = self.inst:DoPeriodicTask(0.5, OnDoUpdate, nil, self, 0.5)
    end
end

------------------------------------------------------------------------------------------------------
-- Saving and Loading Functions

function Smelter:OnSave(self, inst)
    return
    {
        canharvest = self.canharvest,
        product = self.product,
        smelttime = self.smelttime,
        issmelting = self.issmelting,
        
    }
end

function Smelter:OnLoad(data)
    if data ~= nil then
        if data.product then
            self.product = data.product
        end
    
        if data.issmelting and data.smelttime ~= 0 then
            self.smelttime = data.smelttime
        
            self:ResumeSmelting()
        end
    
        if data.canharvest then
            self.inst:DoTaskInTime(2, function() self.inst:AddTag("harvestable") end)
        
            self:DoneSmelting()
        end
    end
    
    self:Update(0, self, self.inst, self.issmelting, self.product, self.canharvest, self.smelttime)
end

return Smelter

 

modded_actions.lua

local State = GLOBAL.State
local Action = GLOBAL.Action
local FRAMES = GLOBAL.FRAMES
local Action = GLOBAL.Action
local require = GLOBAL.require
local ACTIONS = GLOBAL.ACTIONS
local TheInput = GLOBAL.TheInput
local TimeEvent = GLOBAL.TimeEvent
local SpawnPrefab = GLOBAL.SpawnPrefab
local TOOLACTIONS = GLOBAL.TOOLACTIONS
local EventHandler = GLOBAL.EventHandler
local ActionHandler = GLOBAL.ActionHandler 
local CONTROL_ACTION = GLOBAL.CONTROL_ACTION
local MOUSEBUTTON_LEFT = GLOBAL.MOUSEBUTTON_LEFT
local CONTROL_CONTROLLER_ACTION = GLOBAL.CONTROL_CONTROLLER_ACTION

require("components/quagmire_map")

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------	
-- ACTIONS
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------	

-- Smelting

AddAction(
	"SMELT",
	"Smelt",
	function(act)
		if act.target and act.target.components.smelter then
			act.target.components.smelter:StartSmelting(act.doer)
			
			return true
		end
	end)
	
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------	
-- COMPONENT ACTIONS
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------	
	
-- Smelting

AddComponentAction("SCENE", "smelter", function(inst, doer, actions, right)
	if inst:HasTag("hasingot") then
		table.insert(actions, ACTIONS.HARVEST)
	end
end)

 

Edited by bnutters
being more specific
Link to comment
Share on other sites

It would be good if you also posted the error you get when clicking on the button.

Looking at your code I can see that you also have the argument self in your StartSmelting function, which will be nil as your action doesn't give this argument. Which in turn means that all self variables and functions will be nil, which will probably cause the crash you are experiencing.

--Change this
function Smelter:StartSmelting(doer, self, inst)
--to this
function Smelter:StartSmelting(doer)

 

Link to comment
Share on other sites

9 hours ago, Monti18 said:

It would be good if you also posted the error you get when clicking on the button.

Looking at your code I can see that you also have the argument self in your StartSmelting function, which will be nil as your action doesn't give this argument. Which in turn means that all self variables and functions will be nil, which will probably cause the crash you are experiencing.


--Change this
function Smelter:StartSmelting(doer, self, inst)
--to this
function Smelter:StartSmelting(doer)
 

 

  When I plug that in, the game doesn't crash this time, but smelter smelts indefinitely when I start smelting

Link to comment
Share on other sites

Add print statements with the variable values in each function that that follows the StartSmelting function and check where it stops. Then try to find out why it stops. If you're not able to find out why, post again with the code block where the print statements stop :)

Link to comment
Share on other sites

On 11/3/2021 at 2:05 AM, Monti18 said:

Add print statements with the variable values in each function that that follows the StartSmelting function and check where it stops. Then try to find out why it stops. If you're not able to find out why, post again with the code block where the print statements stop :)

After intense research and procrastination, Thanks to your help I was able to get the smelter to finish smelting and actually smelt at a given time! There's just one more thing. The smelter when it is finished will do the pour animation but the product afterwards doesn't show on the smelter, and the player is incapable of harvesting the smelter afterwards.

Edited by bnutters
i somehow sent the reply unfinished without even realizing
Link to comment
Share on other sites

my smelter component:
 

local smelting = require "smelting"

local Smelter = Class(function(self, inst)
    self.inst = inst
	self = self
    
    self.issmelting = nil
    self.product = nil
    self.canharvest = nil

    self.smelttime = 0
    
    self.startsmeltingfn = nil
    self.donesmeltingfn = nil
    self.onharvest = nil

    self:Update(self, self.inst, self.issmelting, self.product, self.canharvest, self.smelttime)
end)

function Smelter:StartSmelting(doer)
    self.issmelting = true
    self.product = nil
	print("StartSmelting")
    
    if self.startsmeltingfn then
        self.startsmeltingfn(self.inst)
    end
    
    local ings = {}  

    for k, v in pairs (self.inst.components.container.slots) do
        table.insert(ings, v.prefab)
    end
    
    self.product, self.smelttime = smelting.CalculateSmelterRecipe(self.inst.prefab, ings)

    self.inst.components.container:Close()
    self.inst.components.container.canbeopened = false
	
    self:Update(self, self.inst, self.issmelting, self.product, self.canharvest, self.smelttime)
end

function Smelter:ResumeSmelting()
    self.issmelting = true

    if self.startsmeltingfn then
        self.startsmeltingfn(self.inst)
    end
    
    self.inst.components.container:Close()
    self.inst.components.container.canbeopened = false

    self:Update(0)
end

function Smelter:DoneSmelting()
    self.issmelting = nil
    self.canharvest = true
    
    if self.donesmeltingfn then
        self.donesmeltingfn(self.inst)
    end
	
	print("FinishedSmelting")
    
    self.inst:AddTag("harvestable")
    
    self.inst.components.container.canbeopened = false

    self.inst.components.container:DestroyContents()
end

function Smelter:ResetSmelter()
    self.issmelting = nil
    self.product = nil
    self.canharvest = nil

    self.smelttime = 0
    
    self.inst.components.container.canbeopened = true

    --self.inst:RemoveTag("harvestable")

    self.inst.components.container:DropEverything()
    
    if self.task then
        self.task:Cancel()
        self.task = nil
    end
end

function Smelter:Harvest(harvester)
    print("Harvesting metal")
		if self.onharvest then
			self.onharvest(self.inst)
		end
		self.done = nil
		if self.product then
			if harvester and harvester.components.inventory then
				local loot = nil
				loot = SpawnPrefab(self.product)
					harvester.components.inventory:GiveItem(loot, nil, Vector3(TheSim:GetScreenPos(self.inst.Transform:GetWorldPosition())))
					self.inst:RemoveTag("harvestable")
				end
			end
			self.product = nil
			self.spoiltargettime = nil

			if self.spoiltask then 
				self.spoiltask:Cancel()
				self.spoiltask = nil
			end
			
			self:ResetSmelter()
			
		
		if self.inst.components.container and not self.inst:HasTag("flooded") then		
			self.inst.components.container.canbeopened = true
		end
		
		return true
	end

------------------------------------------------------------------------------------------------------
-- Update Functions

local function OnDoUpdate(inst, self, period)    
    --self:Update(period)
end

function Smelter:Update(self, inst, issmelting, product, canharvest, smelttime)
    self.inst = inst
	self.issmelting = issmelting
    self.product = product
    self.canharvest = canharvest

    self.smelttime = smelttime
    if self.issmelting and not self.canharvest then
		inst:StartThread(function()
		repeat
			Sleep(1)
			self.smelttime = self.smelttime - 1
		until self.smelttime <= 0
		print("Am I even smelting to begin with?",issmelting)
		print("Smeltin' for",smelttime,"second(s)!")
		print("Product we're smeltin' here:",product)
    
        if self.smelttime <= 0 then
            if self.product ~= nil then
                self:DoneSmelting()uuuuu
            end
		end
		end)
    end
    
    if self.task == nil then
        self.task = self.inst:DoPeriodicTask(0.5, OnDoUpdate, nil, self, 0.5)
		--print("CurrentlySmelting")
    end
end

------------------------------------------------------------------------------------------------------
-- Saving and Loading Functions

function Smelter:OnSave(self, inst)
    return
    {
        canharvest = self.canharvest,
        product = self.product,
        smelttime = self.smelttime,
        issmelting = self.issmelting,
        
    }
end

function Smelter:OnLoad(data)
    if data ~= nil then
        if data.product then
            self.product = data.product
        end
    
        if data.issmelting and data.smelttime ~= 0 then
            self.smelttime = data.smelttime
        
            self:ResumeSmelting()
        end
    
        if data.canharvest then
            self.inst:DoTaskInTime(2, function() self.inst:AddTag("harvestable") end)
        
            self:DoneSmelting()
        end
    end
    
    self:Update(0, self, self.inst, self.issmelting, self.product, self.canharvest, self.smelttime)
end

return Smelter

For some reason, it never actually says the harvest function is done in the logs when I harvest it in-game, so my character says "I can't do that.", and the game crashes when beginning a new day because of line 168

Edited by bnutters
being more specific
Link to comment
Share on other sites

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
 Share

×
  • Create New...