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