Help with burger cooking script

  1. What do you want to achieve?
    I am trying to make a script that will “cook” food items when they are placed onto the grill.

  2. What is the issue?
    I am having trouble with using coroutines to change a counter variable which acts as the cooking time for the food item to change its cooking state (raw, slightly cooked, well done, burnt, etc.)

-- This script handles cooking the food items.
--


--	Services

local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local ServerStorage = game:GetService("ServerStorage")
local CollectionService = game:GetService("CollectionService")





--	Initialize variables

local sandwichesModule = require(ServerStorage:WaitForChild("Module_Scripts"):WaitForChild("Sandwiches"))

local gameSceneFolder = game.Workspace:WaitForChild("Scene")
local kitchenFolder = gameSceneFolder:WaitForChild("Kitchen")
local grillFolder = kitchenFolder:WaitForChild("Grill")

local activeSandwichItemsFolder = kitchenFolder:WaitForChild("ActiveSandwichItems")

--local patty = gameSceneFolder:WaitForChild("Sandwich_Items"):WaitForChild("Patty")



local grillPart = script.Parent
local grillHitbox = grillPart:WaitForChild("Hitbox")


local grillTouchConn
local grillTouchEndConn


local partsOnGrill = {}

local grilling = false

local amountTime = 0



--	Functions

-- This function "cooks" the food items, changing its Time_Left, Cooking_State, and Cooking_Time attributes
local function cookingTimer(object) -- The coroutines will make use of this
	--local amountTime
	
	local objectCurrentCookTime = object:GetAttribute("Time_Left")
	local objectStartCookTime = object:GetAttribute("Cooking_Time") * 60
	
	if objectCurrentCookTime == 0 then
		amountTime = objectStartCookTime
	else
		amountTime = objectCurrentCookTime
		--object:SetAttribute("Time_Left", amountTime)
	end
	
	--if object then
	--	amountTime = object:GetAttribute("Cooking_Speed") * 60
	--end
	
	
	print("Testing")

	while true do
		
		if not object:GetAttribute("Cooking") then
			object:SetAttribute("Time_Left", amountTime)
			break
		end
		
		--print("Grilling value = " .. tostring(grilling))
		
		--print("Time left: " .. amountTime)
		
		amountTime = amountTime - 1
		
		if amountTime <= 0 then
			amountTime = objectStartCookTime
			
			object:SetAttribute("Cooked_State", object:GetAttribute("Cooked_State") + 1)
		end
		
		RunService.Heartbeat:Wait()
		--RunService.PreSimulation:Wait()
	end
end


local newCoroutine = coroutine.create(cookingTimer)

local delayCounter = 0


local function grillItems()
	while true do
		if delayCounter > 10 then
			delayCounter = 0
			
			local touchingParts = grillHitbox:GetTouchingParts()
			
			-- When food item goes on grill
			for index, foodItem in pairs(touchingParts) do
				if CollectionService:HasTag(foodItem, "Sandwich_Items") then
					
					-- If food item doesn't exist in memory table
					
					local foundExactItem = false
					
					for index, item in pairs(partsOnGrill) do
						if item == foodItem then
							foundExactItem = true
						end
					end
					
					if foundExactItem == false then
						partsOnGrill[#partsOnGrill+1] = foodItem
					end
					
					local newCoroutine = coroutine.create(cookingTimer)
					
					if coroutine.status(newCoroutine) == "dead" then
						print("Dead coroutine")
						newCoroutine = coroutine.create(cookingTimer)
					end

					if foodItem:GetAttribute("Cooking") == false then
						foodItem:SetAttribute("Cooking", true)

						local success, result = coroutine.resume(newCoroutine, foodItem)
					
						if success == false then
							warn(result)
						end
					end
					
				end
			end
			
			
			-- When food item comes off grill
			for index, foodItem in pairs(partsOnGrill) do
				if CollectionService:HasTag(foodItem, "Sandwich_Items") then
					
					local foundExactItem = false
					
					for index, item in pairs(touchingParts) do
						if item == foodItem then
							foundExactItem = true
						end
					end
					
					if foundExactItem == false then
						foodItem:SetAttribute("Cooking", false)
						table.remove(partsOnGrill, index)
					end
				end
			end
		else
			delayCounter = delayCounter + 1
		end
		
		RunService.Heartbeat:Wait()
	end
end


-- When a sandwich item is removed from the ActiveSandwichItemsFolder or is destroyed, remove it from the memory table 
activeSandwichItemsFolder.ChildRemoved:Connect(function(itemRemoved)
	warn("Spawned")

	if itemRemoved:IsA("BasePart") or itemRemoved:IsA("UnionOperation") then
		if CollectionService:HasTag(itemRemoved, "Sandwich_Items") then
			for index, foodItem in pairs(partsOnGrill) do
				if index == itemRemoved then
					table.remove(partsOnGrill, index)
				end
			end
			
		end
	end
end)


---- When a food item hits the grill
grillTouchConn = grillHitbox.Touched:Connect(function(otherPart)
	print("Touched")
end)

grillItems()

This script makes use of a table that acts as memory (partsOnGrill) to compare which food items are still touching the grill, and stops it from cooking (Setting the attribute “Cooking” to false) if it is no longer on the grill.

It seems that, even though the for loop goes through each food item that’s on the grill, only the item that touched first gets its values changed. Also, based on how many parts are on the grill, only one will receive changes in its values, but times over. i.e: if there are 3 parts on the grill, the one part will cook 3x as fast as usual.

As you can see, based on the color, only the patty in the middle cooked at all. And now it’s burnt.

  1. What solutions have you tried so far?

Before, I had it set up to create one coroutine and it worked great. But only if there’s one part on the grill. I changed it to make a new coroutine for each item, and resume in an attempt to cook the items with multi-threading. But it seems something is interferring with that.

2 Likes

I tried something else, and got it all figured out! Instead of using a for loop to iterate through all of the food items and then resuming a coroutine for each part, I called only one coroutine and passed a table with all of the touching parts. So that way, inside of just one coroutine, I was able to set up a for loop to iterate through all of the food parts and change each one’s Time_Left value, as one while loop runs.