Need help with a mixing system

  1. What do you want to achieve?

I need a “mixing system” that mixes elements. I tried doing it but it doesn’t work.

  1. What is the issue?

What I made makes the wrong compound when mixing elements and sometimes doesn’t make anything.

  1. What solutions have you tried so far? Did you look for solutions on the Developer Hub?

I tried looking on the devforum but I didn’t know what to look for.

Script One (Local Script)

local Current -- is the current flask/beaker its a basepart

local Number = 0

local Number2 = 0

local Compound

for i,v in pairs(ElementsInContainer) do --This makes values of the elements in the 'Current' variable and it works
	if Storage:FindFirstChild(v.Name) then
		Storage[v.Name].Value += 1
	else
		local Clone = ElementValue:Clone()
		Clone.Parent = Storage
		Clone.Name = v.Name
		Clone.Value = 1
		Clone.Parent = Storage
	end
end

-- After this I don't know what to do. this is what I tried

for i,v in pairs(ElementsModule.Compounds) do
	for x,y in pairs(v.ComposedOf) do
		for z,t in pairs(Storage:GetChildren()) do
			if y.Name == t.Name then
               Compound = v.Name
			end
		end
	end
end

local a = ElementsModule.Compounds[Compound]
if a and Compound then
	for i,v in pairs(a.ComposedOf) do
		Number2 += v.Amount
	end
else
	return
end

print(Number, Number2, Compound)

if Number == Number2 then -- This is a very bad way of doing it because if a different compound also adds up to (lets say 5) it wont work
	print("Made Compound: "..Compound)
	MainModule.Spawn("Compounds", Compound, Current.Position)
end

Elements Module (Module Script)

local Elements = {
	Elements = {
		["Hydrogen"] = {
			Name = "Hydrogen",
			Symbol = "H",
			AtomicNumber = 1,
			AtomicMass = 1.0078,
			Color = Color3.fromRGB(255, 0, 0),
			PhysicalColor = Color3.fromRGB(100, 100, 100),
			Material = Enum.Material.Plastic,
			Reactors = {-- Reactors are just a visual thing
				[1] = "Oxygen",
			},
		},
		["Oxygen"] = {
			Name = "Oxygen",
			Symbol = "O",
			AtomicNumber = 8,
			AtomicMass = 15.999,
			Color = Color3.fromRGB(255, 178, 126),
			PhysicalColor = Color3.fromRGB(0, 50, 255),
			Material = Enum.Material.SmoothPlastic,
			Reactors = {
				[1] = "Hydrogen",
			},
		},
	},
	Compounds = {
		["Water"] = {
			Name = "Water",
			Symbol = "H₂O",
			AtomicMass = 18.02,
			Color = Color3.fromRGB(0, 100, 255),
			PhysicalColor = Color3.fromRGB(0, 100, 255),
			Material = Enum.Material.Glass,
			ComposedOf = {
				["Hydrogen"] = {Name = "Hydrogen", Amount = 2},
				["Oxygen"] = {Name = "Oxygen", Amount = 1},
			},
			Reactors = {},
		},
-- there are more compounds and elements but I only gave what's needed
	}
}

return Elements

Its supposed to make compounds based of what’s in the beaker/flask. if there is 2 Hydrogen and 1 Oxygen in there it makes water.

This is my first time making a topic so tell me if I’m doing something wrong :grinning:

5 Likes

This is a really cool idea. You can do this pretty easily by following these steps:

  1. Create a function Make(Beaker, Compound) that will attempt to make a new compound.

  2. In the Make function, for every element composing the compound, check if the beaker contains that element and if the amount inside the beaker is greater than or equal to the amount needed to make the compound.

  3. If that check evaluates to false, end the function.

  4. Otherwise, find the maximum amount of times you can remove the element from the beaker and insert that into an array.

  5. Find the minimum value inside that array, call it X.

  6. For every element that composes the compound, remove X times the amount needed to make the compound of that element from the beaker.

  7. Add X of the compound to the beaker.

  8. For every compound A, call Make(Beaker, A).

Here is a simplified version of your code that does exactly what I described above:

local Compounds = {
	['Water'] = {
		Name = 'Water',
		Composition = {
			{'Hydrogen', 2}, 
			{'Oxygen', 1} 
		}
	}
}

local Beaker = {
	['Hydrogen'] = 8,
	['Oxygen'] = 9  
}

-- First we define a function that will spawn in substances into the beaker.
local function Put(Substance, Amount)
	local Amount = Amount or 1 
	-- If amount is not specified, use 1.
	Beaker[Substance] = (Beaker[Substance] or 0) + Amount
	-- If the substance is not in the beaker, use 0. Add 'Amount' to what is already in the beaker.
end

local function Remove(Substance, Amount)
	local Amount = -Amount or -1
	-- If the amount is not specified, use -1. Here we use negative numbers to remove from the beaker.
	Put(Substance, Amount)
	-- We can just reuse the function from before instead of making a new one since a + (-b) = a - b.
	Beaker[Substance] = math.max(0, Beaker[Substance])
	-- Just make sure that we never have negative amounts of substance in the beaker.
end

local function Make(Compound)
	local MaxAmounts = {}
	
	for _, Element in pairs(Compound.Composition) do
		-- For every element composing this compound,
		local Name, Amount = Element[1], Element[2]
		if (Beaker[Name] and Beaker[Name] >= Amount) then
			-- If this element is in the beaker and the amount inside it is larger or equal to the amount needed, then
			local Max = math.floor(Beaker[Name] / Amount)
			-- Find the maximum amount of times you can remove 'Amount' from this element in the beaker.
			table.insert(MaxAmounts, Max)
			-- Add this maximum value to a table of maximum values called MaxAmounts
		else
			return
			--  If the element is not in the beaker or there isn't enough of it, this compound can't be made.
		end
	end
	local Mix = math.min(table.unpack(MaxAmounts))
	-- Find the maximum amount of times we can make this compound.
	
	for _, Element in pairs(Compound.Composition) do
		-- For every element composing this compound,
		local Substance, Amount = Element[1], Element[2]
		Remove(Substance, Mix * Amount)
		-- Remove the amount of this element needed to make the compound.
	end
	Put(Compound.Name, Mix)
	-- Add the compound to the beaker.
end

local function Mix()
	for _, Compound in pairs(Compounds) do
		-- For every compound,
		Make(Compound)
		-- Try to make it.
	end
end

Mix()

print(Beaker) --> { ['Hydrogen'] = 0, ['Oxygen'] = 5, ['Water'] = 4 }

Mix()
-- We can now mix whenever we want to update the beaker. 
-- Because nothing changed in the beaker since the last mix, nothing should change.

print(Beaker) --> { ['Hydrogen'] = 0, ['Oxygen'] = 5, ['Water'] = 4 }

I also recommend trying to make this object oriented somehow. Maybe make a Beaker object with :Put(Substance) and :Remove(Substance) methods, maybe make a Substance object, which Element and Compound inherit from, and you can build up from there.

1 Like

How do I get what compound was made from it

How will the script know which one to spawn

1 Like

You can modify the Put() function to do whatever you want. The Put() function would be called for every new substance that gets added in. I don’t know how your code works, but I guess this function in your case would be MainModule.Spawn("Compounds", ...).

1 Like

I tried messing around with it and I made this.

for i,v in pairs(ElementsModule.Compounds) do
	print(Beaker[v.Name])
	if Beaker[v.Name] then
	   print("Made compound: "..v.Name)
    end
end

but it prints nil.

I need it to give me the name of the compound it made so the script can spawn it.
that’s why I made that code.


The example says water but it says nil when I print it.

1 Like

Like I said in my post, the example I sent does not solve your specific case, instead it solves the more general problem.

  1. Make a function to get the amount of all elements inside your beaker and save the result to a dictionary of type {[Substance] : Amount}, call that dictionary T (you’d obviously find a better name for this table, but just for demonstration purposes…)

  2. Make a function Put(Substance, Amount) that spawns in any amount of a substance into the beaker.

  3. Make a function Remove(Substance, Amount) that removes any amount of a substance from the beaker.

  4. Now you make the Mix() function from the last example using your custom Put(...) and Remove(...) functions. Use T as the variable I called Beaker in my example.


I can’t really spoon-feed you the actual code you’d use because I don’t know exactly how your system works.
For example, I’m not sure how your beaker actually works, because there is no information on that in your original question, but that is not a problem because the information you gave is exactly the information that is needed to solve the main problem.

1 Like

I think I get it now let me test this out

1 Like

It works! thank you helping me :happy3:

2 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.