remote.OnServerEvent:connect(function(u)if IsCoupled.Value then IsCoupled.Value=false else Allow.Value=not Allow.Value Recolor()end end)IsCoupled.Changed:connect(function()if IsCoupled.Value==false then Decouple()end Recolor()end)function rotate(u,q)local h=Instance.new("\082\111\116\097\116\101")h.Part0=u h.Part1=q h.C0=CFrame.new()h.C1=q.CFrame:inverse()*u.CFrame h.Name="\067\111\117\112\108\101\114\082\111\116\097\116\101"return h end function rotateSpecial(u,q)local h=Instance.new("\082\111\116\097\116\101")h.Part0=u h.Part1=q h.C0=CFrame.new(0,0,-0.6)h.C1=CFrame.new(0,0,-0.6)*CFrame.Angles(0,math.pi,0)h.Name="\067\111\117\112\108\101\114\082\111\116\097\116\101"return h end function PGSRotates(u,q)local h=Instance.new("\080\097\114\116")h.CanCollide=false h.Transparency=1 h.FormFactor="\080\108\097\116\101"h.Size=Vector3.new()h.TopSurface="\083\109\111\111\116\104"h.BottomSurface="\083\109\111\111\116\104"local S=h:Clone()h.CFrame=u.CFrame S.CFrame=q.CFrame;(rotate(u,h)).Parent=u;(rotate(q,S)).Parent=q;(rotateSpecial(h,S)).Parent=h h.Parent=coupler.Parent S.Parent=coupler.Parent return h,S end function Couple(u,q)if PGS then u.CanCollide=false q.CanCollide=false R1,R2=PGSRotates(u,q)else MyWeld=weld(u,q)MyWeld.Parent=model end u.SoundClose:Play()end CoupledTo.Changed:connect(function()if CoupledTo.Value then local u=CoupledTo.Value:FindFirstChild("\067\111\117\112\108\101\114")if u and(CoupledTo.Value:FindFirstChild("\073\115\067\111\117\112\108\101\100")and(CoupledTo.Value.IsCoupled:IsA("\066\111\111\108\086\097\108\117\101")and CoupledTo.Value.IsCoupled.Value))then else return end local q=coupler:GetNetworkOwner()local h=u:GetNetworkOwner()local S=coupler:GetNetworkOwnershipAuto()local Y=u:GetNetworkOwnershipAuto()if coupler:CanSetNetworkOwnership()then coupler:SetNetworkOwner(nil)end if CoupledTo.Value.Coupler:CanSetNetworkOwnership()then coupler:SetNetworkOwner(nil)end Couple(coupler,u)if coupler:CanSetNetworkOwnership()then if S and Y then coupler:SetNetworkOwnershipAuto()elseif S then coupler:SetNetworkOwner(h)elseif Y then coupler:SetNetworkOwner(q)else coupler:SetNetworkOwner(q)end end wait()if PGS then WeldDisappear=coupler.ChildRemoved:connect(function(u)if u.Name=="\067\111\117\112\108\101\114\082\111\116\097\116\101"then Decouple()WeldDisappear:disconnect()end end)else WeldDisappear=MyWeld.AncestryChanged:connect(function()Decouple()WeldDisappear:disconnect()end)end else coupler.CanCollide=true end end)coupler.Touched:connect(function(u)if u.Parent and u.Name=="\067\111\117\112\108\101\114"then local q=u.Parent local h=q:FindFirstChild("\065\108\108\111\119")local S=q:FindFirstChild("\073\115\067\111\117\112\108\101\100")if h and S then if h.Value==true and(Allow.Value==true and(S.Value==false and IsCoupled.Value==false))then IsCoupled.Value=true S.Value=true CoupledTo.Value=q if q:FindFirstChild("\067\111\117\112\108\101\100\084\111")then q.CoupledTo.Value=model end end end end end)
-- alas poor coupler.ClickDetector.MouseClick:connect(function() ... end), I knew thee well

remote.OnServerEvent:connect(function(player)
	if IsCoupled.Value then
		IsCoupled.Value = false
	else
		Allow.Value = not Allow.Value
		Recolor()
	end
end)

IsCoupled.Changed:connect(function()
	if IsCoupled.Value == false then
		Decouple()
	end
	Recolor()
end)

function rotate(a, b)
	local weld = Instance.new("Rotate")
	weld.Part0 = a
	weld.Part1 = b
	weld.C0 = CFrame.new()
	weld.C1 = b.CFrame:inverse() * a.CFrame --use this because you get less floating point errors
	weld.Name = "CouplerRotate"
	return weld
end

function rotateSpecial(a, b)
	local weld = Instance.new("Rotate")
	weld.Part0 = a
	weld.Part1 = b
	weld.C0 = CFrame.new(0, 0, -0.6)
	weld.C1 = CFrame.new(0, 0, -0.6) * CFrame.Angles(0, math.pi, 0)
	weld.Name = "CouplerRotate"
	return weld
end

function PGSRotates(coupler1, coupler2)
	local R1 = Instance.new("Part")
	R1.CanCollide = false
	R1.Transparency = 1
	R1.FormFactor = "Plate"
	R1.Size = Vector3.new()
	--R1.CanCollide = false
	R1.TopSurface = "Smooth"
	R1.BottomSurface = "Smooth"
	local R2 = R1:Clone()
	R1.CFrame = coupler1.CFrame
	R2.CFrame = coupler2.CFrame
	rotate(coupler1, R1).Parent = coupler1
	rotate(coupler2, R2).Parent = coupler2
	rotateSpecial(R1, R2).Parent = R1
	R1.Parent = coupler.Parent
	R2.Parent = coupler.Parent
	return R1, R2
end

function Couple(coupler, otherCoupler)
	if PGS then
		coupler.CanCollide = false
		otherCoupler.CanCollide = false
		R1, R2 = PGSRotates(coupler, otherCoupler)
	else
		MyWeld = weld(coupler, otherCoupler)
		MyWeld.Parent = model
	end
	coupler.SoundClose:Play()
end

CoupledTo.Changed:connect(function()
	if CoupledTo.Value then
		--the network ownership means the couplers won't freak out when you couple
		local otherCoupler = CoupledTo.Value:FindFirstChild("Coupler")
		if
			otherCoupler
			and CoupledTo.Value:FindFirstChild("IsCoupled")
			and CoupledTo.Value.IsCoupled:IsA("BoolValue")
			and CoupledTo.Value.IsCoupled.Value
		then
			--continue
		else
			return
		end
		local owner = coupler:GetNetworkOwner()
		local otherOwner = otherCoupler:GetNetworkOwner()
		local ownerAuto = coupler:GetNetworkOwnershipAuto()
		local otherOwnerAuto = otherCoupler:GetNetworkOwnershipAuto()
		if coupler:CanSetNetworkOwnership() then
			coupler:SetNetworkOwner(nil)
		end
		if CoupledTo.Value.Coupler:CanSetNetworkOwnership() then
			coupler:SetNetworkOwner(nil)
		end
		Couple(coupler, otherCoupler)
		if coupler:CanSetNetworkOwnership() then
			if ownerAuto and otherOwnerAuto then
				coupler:SetNetworkOwnershipAuto()
			elseif ownerAuto then
				coupler:SetNetworkOwner(otherOwner)
			elseif otherOwnerAuto then
				coupler:SetNetworkOwner(owner)
			else
				coupler:SetNetworkOwner(owner)
			end
		end
		wait()
		if PGS then
			WeldDisappear = coupler.ChildRemoved:connect(function(it)
				if it.Name == "CouplerRotate" then
					Decouple()
					WeldDisappear:disconnect()
				end
			end)
		else
			WeldDisappear = MyWeld.AncestryChanged:connect(function()
				Decouple()
				WeldDisappear:disconnect()
			end)
		end
	else
		coupler.CanCollide = true
	end
end)

coupler.Touched:connect(function(TouchedPart)
	if TouchedPart.Parent and TouchedPart.Name == "Coupler" then --make sure the part still exists and that it is called "Coupler" (a good indicator)
		local OtherCoupler = TouchedPart.Parent
		local OtherAllow = OtherCoupler:FindFirstChild("Allow") --make sure this is a coupler by looking for the value that says we can couple
		local OtherIsCoupled = OtherCoupler:FindFirstChild("IsCoupled") --make sure this is a coupler by looking for the value that says it is coupled
		if OtherAllow and OtherIsCoupled then
			if
				OtherAllow.Value == true
				and Allow.Value == true
				and OtherIsCoupled.Value == false
				and IsCoupled.Value == false
			then
				IsCoupled.Value = true
				OtherIsCoupled.Value = true
				CoupledTo.Value = OtherCoupler
				if OtherCoupler:FindFirstChild("CoupledTo") then
					OtherCoupler.CoupledTo.Value = model
				end
			end
		end
	end
end)
