Problem with coding the wire pipe puzzle

Hey,

I am making a famous “pipe puzzle” which looks like this:
IMG

And mine looks like this now:
IMG

The problem I am struggling with is that the wires keep turning on even if I do this:
Before:


After:
IMG

So even if I connect one pipe in the wrong direction, the upper ones still have power. The reason is that each one checks if there is power in the other, and if there is, it turns on. The pipes don’t care about how they are connected to others, as long as there is power. I have struggled with this issue for a long time and need your help to solve it. I can’t manage on my own. I’ve already tried everything.

And here is the code for one pipe. All the others are almost exactly the same.

local prox = script.Parent.Part.ProximityPrompt


local model = script.Parent.Part
local TweenService = game:GetService("TweenService")

local function rotateModel()
	local currentOrientation = model.CFrame
	local goalCFrame = model.CFrame * CFrame.Angles(math.rad(90), 0, 0)

	local tweenInfo = TweenInfo.new(
		1,
		Enum.EasingStyle.Quad,
		Enum.EasingDirection.Out 
	)

	local tween = TweenService:Create(model, tweenInfo, {CFrame = goalCFrame})
	tween:Play()
end

prox.Triggered:Connect(rotateModel)
while true do

	wait(.1)
	script.Parent.Part.Color = Color3.fromRGB(0,0,0)
	script.Parent.Connector.Color = Color3.fromRGB(0,0,0)
	script.Parent.Connector2.Color = Color3.fromRGB(0,0,0)
	local touchingParts = script.Parent.Connector:GetTouchingParts()
	local touchingParts2 = script.Parent.Connector2:GetTouchingParts()
	local touchingParts3 = script.Parent.no:GetTouchingParts()
	local touchingParts4 = script.Parent.no2:GetTouchingParts()
	local isTouchingLazer = false
	local isTouchingLazerF = false
	for _, part in ipairs(touchingParts) do
		if part.Name == "Union" or part:IsA("Part") and part.Parent ~= script.Parent and part.Transparency == 0 then
			if part.Parent:FindFirstChild("Part").Color == Color3.fromRGB(118, 197, 168) then
				isTouchingLazer = true
				break
				
			end
			
			
		end
	end
	for _, part in ipairs(touchingParts2) do
		if part.Name == "Union" or part:IsA("Part") and part.Parent ~= script.Parent and part.Transparency == 0 then
			if part.Parent:FindFirstChild("Part").Color == Color3.fromRGB(118, 197, 168) then
				isTouchingLazer = true
				break
			end

		end
	end


	if isTouchingLazer then
		script.Parent.Part.Color = Color3.fromRGB(118, 197, 168)
		script.Parent.Connector.Color = Color3.fromRGB(118, 197, 168)
		script.Parent.Connector2.Color = Color3.fromRGB(118, 197, 168)
		script.Parent.Union.Value.Value = true
	else
		script.Parent.Union.Value.Value = false
	end
end

If you need more information, don’t be afraid to ask. I just want to get rid of this problem.

4 Likes

Seems like you need to set a “source” part, as in the source of the water. Then, whenever a part is rotated, you could use nested if conditions to work backwards through all of the pipes that are connected to it, and if none of them are touching the source part, change the color back to black of all of the pipes.

2 Likes

Do you mean that the pipe codes check if the connected pipes are connected to each other in such a way that they are connected to a power source? I’m making electric pipes, not water pipes, but that doesn’t matter much. What would be the best way for me to implement this? I have thought about this before myself. I’m trying to make it so that pipes can be freely copied without needing to add anything to the codes anymore. The power source works so that when there is power in the pipe and it touches the starting bar, the starting bar gets power, and if any pipe touches it correctly, it gets power. In principle, I could make it easier, but then I’d have to keep coding constantly when making new puzzles. So, I want to be able to create new puzzles with copy & paste, and they should work immediately. I have almost got it working, but this is basically the only remaining problem for now.

1 Like

Upon looking deeper into the code it seems that you do not have any condition that sets isTouchingLazer back to false once it is set to true? As in, once the way to the source is broken, you do not have functionality that would set the isTouchingLazer to false?

2 Likes

The code sets isTouchingLazer to false before it checks if anything touches this pipe. The pipes turn black if there is no power attached to them.

local isTouchingLazer = false
local isTouchingLazerF = false
1 Like

Ah yeah, I missed that, sorry. I suppose if you’d like something that you could use in most puzzles, you should have a for loop that gathers info on how many pipes there are in the puzzle. Then, whenever a pipe is rotated, run another for loop that checks every connection the pipe has, and if it isn’t directly connected to the source, turn it to black? Basically, you would run a for loop and check every connection of every pipe that’s directly or indirectly connected to the rotated pipe, and then turn isTouchingLazer back to false if the rotation broke off the connection to the source.

2 Likes

I don’t completely understand what you mean. I thought that each pipe’s code checks the pipe connected to it (let’s call this A) and then the pipes connected to B, and so on, until it encounters an object named Lazer. It would always check all the objects in one list, where it would store all the connected pipes or something like that. If none of the pipes in this chain is touched by an object named Lazer, then all the pipes in the chain turn off.

I tried using Boolean values just now, so that when it is ‘true,’ there is power in the other pipe, and it takes the same value itself. If it is ‘false,’ there is no power and it turns off because it takes the same value.
However, this is pointless because if any connected pipe has ‘true,’ then this pipe also gets ‘true,’ regardless of whether the pipes are connected in such a way that the power could reach the end from the generator through the pipes.

This is really difficult. Apparently, some people have managed to do this in Roblox Studio, but I can’t really ask them for help. I tried watching Unity tutorials because I am quite good at using Unity, but they use pipes that are always the same, regardless of whether water flows through them or not.

1 Like

I’m a little confused. Do you have a way of checking whether any pipe has a direct path to the source through other pipes? As in, if the pipe somewhere in the middle suddenly gets disconnected, it and the pipes after it will turn black. If so, can you send me that part of the code?

Well here is my all codes:

Begin part’s:

while true do
	wait(.1)
	script.Parent.Part.Color = Color3.fromRGB(0,0,0) 
	local touchingParts = script.Parent.Union:GetTouchingParts()
	local isTouchingLazer = false

	for _, part in ipairs(touchingParts) do
		if part.Color == Color3.fromRGB(118, 197, 168) and part.Name == "Lazer" then
			isTouchingLazer = true
			break
		end
	end

	if isTouchingLazer then
		script.Parent.Part.Color = Color3.fromRGB(118, 197, 168)
		script.Parent.Part.Value.Value = isTouchingLazer
		script.Parent.Union.Value.Value = true
	else
		script.Parent.Union.Value.Value = false
	end

end

And here is the V or L-shape pipe’s code:

local prox = script.Parent.Part.ProximityPrompt


local model = script.Parent.Part
local TweenService = game:GetService("TweenService")
local isTouchingLazer = false
local isTouchingLazerF = false
local function rotateModel()
	
	local currentOrientation = model.CFrame
	local goalCFrame = model.CFrame * CFrame.Angles(math.rad(90), 0, 0)

	local tweenInfo = TweenInfo.new(
		1,
		Enum.EasingStyle.Quad,
		Enum.EasingDirection.Out 
	)


	script.Parent.Part.Color = Color3.fromRGB(0,0,0)  
	script.Parent.Connector.Color = Color3.fromRGB(0,0,0)
	script.Parent.Connector2.Color = Color3.fromRGB(0,0,0)
	
	local tween = TweenService:Create(model, tweenInfo, {CFrame = goalCFrame})
	tween:Play()
	script.Parent.Part.Color = Color3.fromRGB(0,0,0)  
	script.Parent.Connector.Color = Color3.fromRGB(0,0,0)
	script.Parent.Connector2.Color = Color3.fromRGB(0,0,0)
	tween.Completed:Connect(function()
		if isTouchingLazer and script.Parent.Union.Value.Value == true then
			script.Parent.Part.Color = Color3.fromRGB(118, 197, 168)
			script.Parent.Connector.Color = Color3.fromRGB(118, 197, 168)
			script.Parent.Connector2.Color = Color3.fromRGB(118, 197, 168)
		else
			script.Parent.Union.Value.Value = false
		end
	end)
end

prox.Triggered:Connect(rotateModel)
while true do

	wait(.1)
	script.Parent.Part.Color = Color3.fromRGB(0,0,0)  
	script.Parent.Connector.Color = Color3.fromRGB(0,0,0)
	script.Parent.Connector2.Color = Color3.fromRGB(0,0,0)
	local touchingParts = script.Parent.Connector:GetTouchingParts()
	local touchingParts2 = script.Parent.Connector2:GetTouchingParts()
	local touchingParts3 = script.Parent.no:GetTouchingParts()
	local touchingParts4 = script.Parent.no2:GetTouchingParts()
	isTouchingLazer = false
	isTouchingLazerF = false
	for _, part in ipairs(touchingParts) do
		if part.Name == "Union" or part:IsA("Part") and part.Parent ~= script.Parent and part.Transparency == 0 then
			if part.Parent:FindFirstChild("Part").Color == Color3.fromRGB(118, 197, 168) then
				isTouchingLazer = true
				script.Parent.Union.Value.Value = part.Parent.Union.Value.Value
				break
				
			end
			
			
		end
	end
	for _, part in ipairs(touchingParts2) do
		if part.Name == "Union" or part:IsA("Part") and part.Parent ~= script.Parent and part.Transparency == 0 then
			if part.Parent:FindFirstChild("Part").Color == Color3.fromRGB(118, 197, 168) then
				isTouchingLazer = true
				script.Parent.Union.Value.Value = part.Parent.Union.Value.Value
				break
			end

		end
	end

	
	if isTouchingLazer and script.Parent.Union.Value.Value == true then
		script.Parent.Part.Color = Color3.fromRGB(118, 197, 168)
		script.Parent.Connector.Color = Color3.fromRGB(118, 197, 168)
		script.Parent.Connector2.Color = Color3.fromRGB(118, 197, 168)
	else
		script.Parent.Union.Value.Value = false
	end
end

Hm. What do you think about making two different tables. One table would hold all pipes that were connected towards the source, directly or over other pipes, and the other table would hold all pipes that aren’t connected to the source. So when you connect a pipe to the source, add it to the connectedPipes table and remove it from disconnectedPipes table. Then, when you rotate a different pipe and connect it to some other pipe, you check the connectedPipes table for all of the pipes connected to it. If none of the pipes are in the connectedPipes table, then the pipe you just rotated also stays in the disconnectedPipes table. I’ll write some pseudecode below to explain and you can try to fit it into your code.

Make a module called pipeManager and add it to the folder with your pipes
In the module do this:

local pipeManager = {}
local sourceBlock = script.sourceBlock

local connectedPipes = {}
local disconnectedPipes = {}

function pipeManager.checkConnectedPipes(rotatedPipe, touchingPipe)
   if table.find(connectedPipes, touchingPipe) or rotatedPipe isTouchingSourceBlock then
       table.insert(connectedPipes, rotatedPipe)
       if table.find(disconnectedPipes, rotatedPipe) then
           table.remove(disconnectedPipes, rotatedPipe)
       end
   else
       if not table.find(connectedPipes, touchingPipe) and table.find(connectedPipes, rotatedPipe) then
           table.insert(disconnectedPipes, rotatedPipe)
           table.remove(connectedPipes, rotatedPipe)
       end
   end
end


return pipeManager

Then in your pipes scripts, to access this function you will do

local pipeManager = require(script.Folder.pipeManager)

Then, whenever you rotate a pipe you will do this function for every pipe touching it:

pipeManager.checkConnectedPipes(rotatedPipe, touchingPipe1)

pipeManager.checkConnectedPipes(rotatedPipe, touchingPipe2)

and so on...

That’s a lot of code, try to implement it within your pipes and feel free to ask if you need any help.

1 Like

Woah… That’s a lot of code… okey, let me try… I’ll tell you when I’m done. I have to do other things too before I am done

1 Like

Well, it’s working now! I created 2 new boolean values that indicate when the power is on and when someone is rotating a pipe. I also made a minor adjustment for when they rotate. Now, each pipe’s color changes to this → 118, 197, 169 instead of this → 118, 197, 168
:D.

Entire code:

local prox = script.Parent.Part.ProximityPrompt
local turn = script.Parent.Parent.turn
local shut = script.Parent.Parent.shut
local model = script.Parent.Part
local TweenService = game:GetService("TweenService")
local isTouchingLazer = false
local isTouchingLazerF = false
local function rotateModel()
	prox.Enabled = false
	turn.Value = true
	local currentOrientation = model.CFrame
	local goalCFrame = model.CFrame * CFrame.Angles(math.rad(90), 0, 0)

	local tweenInfo = TweenInfo.new(
		1,
		Enum.EasingStyle.Quad,
		Enum.EasingDirection.Out 
	)


	script.Parent.Part.Color = Color3.fromRGB(0,0,0)  
	script.Parent.Connector.Color = Color3.fromRGB(0,0,0)
	script.Parent.Connector2.Color = Color3.fromRGB(0,0,0)
	
	local tween = TweenService:Create(model, tweenInfo, {CFrame = goalCFrame})
	tween:Play()
	script.Parent.Part.Color = Color3.fromRGB(0,0,0)  
	script.Parent.Connector.Color = Color3.fromRGB(0,0,0)
	script.Parent.Connector2.Color = Color3.fromRGB(0,0,0)
	tween.Completed:Connect(function()
		turn.Value = false
		prox.Enabled = true
	end)
	
end

prox.Triggered:Connect(rotateModel)
while true do

	wait(.1)
	script.Parent.Part.Color = Color3.fromRGB(0,0,0)  
	script.Parent.Connector.Color = Color3.fromRGB(0,0,0)
	script.Parent.Connector2.Color = Color3.fromRGB(0,0,0)
	local touchingParts = script.Parent.Connector:GetTouchingParts()
	local touchingParts2 = script.Parent.Connector2:GetTouchingParts()
	local touchingParts3 = script.Parent.no:GetTouchingParts()
	local touchingParts4 = script.Parent.no2:GetTouchingParts()
	isTouchingLazer = false
	isTouchingLazerF = false
	for _, part in ipairs(touchingParts) do
		if part.Name == "Union" or part:IsA("Part") and part.Parent ~= script.Parent and part.Transparency == 0 then
			if part.Parent:FindFirstChild("Part").Color == Color3.fromRGB(118, 197, 168) then
				isTouchingLazer = true
				script.Parent.Union.Value.Value = part.Parent.Union.Value.Value
				break
				
			end
			
			
		end
	end
	for _, part in ipairs(touchingParts2) do
		if part.Name == "Union" or part:IsA("Part") and part.Parent ~= script.Parent and part.Transparency == 0 then
			if part.Parent:FindFirstChild("Part").Color == Color3.fromRGB(118, 197, 168) then
				isTouchingLazer = true
				script.Parent.Union.Value.Value = part.Parent.Union.Value.Value
				break
			end

		end
	end

	
	if isTouchingLazer and script.Parent.Union.Value.Value == true then
		script.Parent.Part.Color = Color3.fromRGB(118, 197, 168)
		script.Parent.Connector.Color = Color3.fromRGB(118, 197, 168)
		script.Parent.Connector2.Color = Color3.fromRGB(118, 197, 168)
	else
		script.Parent.Union.Value.Value = false
	end
	if turn.Value == true then
		if isTouchingLazer then
			script.Parent.Part.Color = Color3.fromRGB(118, 197, 169)
			script.Parent.Connector.Color = Color3.fromRGB(118, 197, 169)
			script.Parent.Connector2.Color = Color3.fromRGB(118, 197, 169)
		else
			script.Parent.Part.Color = Color3.fromRGB(0,0,0)  
			script.Parent.Connector.Color = Color3.fromRGB(0,0,0)
			script.Parent.Connector2.Color = Color3.fromRGB(0,0,0)
		end

	end
	if shut.Value == false then
		script.Parent.Part.Color = Color3.fromRGB(0,0,0)  
		script.Parent.Connector.Color = Color3.fromRGB(0,0,0)
		script.Parent.Connector2.Color = Color3.fromRGB(0,0,0)
	end
end

Should we just call it a day and leave it at that? It looks a bit messy because some pipes don’t turn off or on at the same time as the others. Well, it’s now shutting off pipes when the connection is broken. :D.

Glad to hear you got it to work! If you wanna leave it like so, just make sure that the player can’t rotate another pipe until they are all done changing colors, otherwise you might run into more errors. Other than that, feel free to post again if you need any more help!

Thanks for your support! :).
This was hard to fix

1 Like

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