How do I grab all recipes available?

I would like to make a cooking system where when you are within a certain radius, a menu opens with the certain food you can currently take.

The following modules are in play:

GameDataManager
CookingManager

The annoying part is, it doesn’t seem to work.
When I want to execute the module to see which specific foods is available, I want it to send back the string of the available foods.

The recipes are found in the gamedata so they are easily changeable and the checker is inside of cooking manager.

When attempting, it returns “Currently available: Tomato” even though that is not a food and isn’t the full list of ingredients there are.

The following image is me with a TOMATO and a LAVENDER in my backpack activating the checker using THIS script below (check below image)

local GameDataManager = require(game.ReplicatedStorage:WaitForChild("Modules").GameData)
local CookingManager = require(game.ReplicatedStorage:WaitForChild("Modules").CookingManager)


script.Parent.ClickDetector.MouseClick:Connect(function(plr)
	for i, v in pairs(CookingManager:CheckMaterials(plr)) do
		print("Can Cook:" .. v[i])
	end
end)

This is the recipes:

GameData.Recipes = {
	["Baked Potato"] = {
		"Lavender"
	},
	
	["Fancy Dinner"] = {
		"Tomato","Lavender"
	}
}

This is the checker to see if the user has the specific items and SHOULD return a table with strings of currently available meals like “Fancy Dinner” but doesn’t.

local Stations = workspace.Interactables.Stations:GetChildren()

local Recipes = GameDataManager.Recipes


function module:CheckMaterials(plr)
	for _, foodName in pairs(Recipes) do
		for i, foodIngredience in pairs(foodName) do
			
			local canCook = {}
			if plr.Backpack:FindFirstChild(foodIngredience) or plr.Character:FindFirstChild(foodIngredience) then
				table.insert(canCook,1,foodName)
			end
			
			return canCook
			
		end
	end
end

this resets the canCook table everytime it loops, so it will insert something into the table but reset it in the next loop/iteration, so best to keep it out of the loop

try this:

local canCook = {} -- make the table
function module:CheckMaterials(plr)
	for _, foodName in pairs(Recipes) do
		for i, foodIngredience in pairs(foodName) do
			
			if plr.Backpack:FindFirstChild(foodIngredience) or plr.Character:FindFirstChild(foodIngredience) then
				table.insert(canCook,1,foodName)
			end

			return canCook

		end
	end 
	local canCook = {} -- set it to none after loop ends
end

edit- removed an extra end

2 Likes

Alright, progress made!!

Now, it prints out Tomato & Lavender, but that’s not specifically what I want.
It also gives me an error from the clickdetector which executes it.


1 Like

try:

local canCook = {} -- make the table
function module:CheckMaterials(plr)
	for _, foodName in pairs(Recipes) do
		for i, foodIngredience in pairs(foodName) do
			
			if plr.Backpack:FindFirstChild(foodIngredience) or plr.Character:FindFirstChild(foodIngredience) then
				table.insert(canCook,1,foodName)
			end
		end
	end 
	return canCook
	local canCook = {} -- set it to none after loop ends
end


Received an error lacking an end

function module:CheckMaterials(plr)
	local canCook = {}
	for _, foodName in pairs(Recipes) do
		for i, foodIngredience in pairs(foodName) do

			if plr.Backpack:FindFirstChild(foodIngredience) or plr.Character:FindFirstChild(foodIngredience) then
				table.insert(canCook,1,foodName)
			end
		end
	end 
	return canCook
end

Why not just create the array in the method itself? That way each time it’s called a new array is created and you don’t need to empty the old one. Functions stop running after a return statement is executed so the “local canCook = {}” won’t run.

2 Likes

This is what I got back from that;
image

It no longer sees tomato as an option.

Alright, I took a bit of time to look at the logic (hadn’t previously), I believe the following should work.

local Stations = workspace.Interactables.Stations:GetChildren()

local Recipes = GameDataManager.Recipes


function module:CheckMaterials(plr)
	local canCook = {}
	for _, foodName in pairs(Recipes) do
		for _, foodIngredient in pairs(foodName) do
			local backpack = plr.Backpack
			local char = plr.Character
			if backpack:FindFirstChild(foodIngredient) or char:FindFirstChild(foodIngredient) then
				if not table.find(canCook, foodName) then
					table.insert(canCook, foodName)
				end
			else
				table.remove(canCook, table.find(Recipes, foodName))
			end
		end
	end
	return canCook
end
2 Likes

Sadly wasn’t the result but the logic made sense (at least to me)
It gave me this outcome. The warning is from this script which executes it, also shown earlier:

local GameDataManager = require(game.ReplicatedStorage:WaitForChild("Modules").GameData)
local CookingManager = require(game.ReplicatedStorage:WaitForChild("Modules").CookingManager)


script.Parent.ClickDetector.MouseClick:Connect(function(plr)
	for i, v in pairs(CookingManager:CheckMaterials(plr)) do
		print("Can Cook:" .. v[i])
	end
end)

Screenshot by Lightshot (pasting image didnt work for some reason)

It’s possible that canCook returns an empty table (if no recipes are found). Thus when you iterate over it from the main script the error arises as an attempt is made to concatenate nil with a string value.

local Stations = workspace.Interactables.Stations:GetChildren()

local Recipes = GameDataManager.Recipes


function module:CheckMaterials(plr)
	local canCook = {}
	for _, foodName in pairs(Recipes) do
		for _, foodIngredient in pairs(foodName) do
			local backpack = plr.Backpack
			local char = plr.Character
			if backpack:FindFirstChild(foodIngredient) or char:FindFirstChild(foodIngredient) then
				if not table.find(canCook, foodName) then
					table.insert(canCook, foodName)
				end
			else
				if table.find(canCook, foodName) then
					table.remove(canCook, table.find(Recipes, foodName))
				end
			end
		end
	end
	print(#canCook)
	return canCook
end

Try this, it’ll print the length of canCook before returning it.

2 Likes

image

For reference, what I want it to do is to look into the game data recipes and see if they have the valid tools for the specific meal.

This is what the table looks like.
image

Yeah, I see what you’re trying to do and that output indicates to me that the method in the module has been fixed as both recipes are being collected.

	for i, v in pairs(CookingManager:CheckMaterials(plr)) do

line 7 that’s bugged

local GameDataManager = require(game.ReplicatedStorage:WaitForChild("Modules").GameData)
local CookingManager = require(game.ReplicatedStorage:WaitForChild("Modules").CookingManager)

script.Parent.ClickDetector.MouseClick:Connect(function(plr)
	for i, v in pairs(CookingManager) do
		print("Can Cook:" .. v)
	end
end)

Make A Recipes Module

local Recipes = {
	
	["Baked Potato"] = {
		"Lavender"
	},

	["Fancy Dinner"] = {
		"Tomato","Lavender"
	}
}

return Recipes
script.Parent.ClickDetector.MouseClick:Connect(function(plr)
	for i, v in pairs(CookingManager:CheckMaterials(plr)) do
		print("Can Cook:" .. v)
	end
end)

You just need to grab the values from the array which is being returned from the method.

2 Likes

print("Can Cook:" .. v[) this bit would error.

2 Likes

CookingManager:CheckMaterials(plr)

This function is what returns so I don’t think thats the issue. The recipes also return when you do GameData.Recipes so I don’t think it would make a difference.

This is what I originally did and this error was the outcome and the reason I added [i] to it of that:image

image
It Is

local GameDataManager = require(game.ReplicatedStorage:WaitForChild("Modules").GameData)
local CookingManager = require(game.ReplicatedStorage:WaitForChild("Modules").CookingManager)


script.Parent.ClickDetector.MouseClick:Connect(function(plr)
	for i, v in pairs(CookingManager:CheckMaterials(plr)) do
		print("Can Cook:" .. i)
	end
end)

My bad, it’s the field which stores the name of the recipe.