Need help with procedural hallway generation

I need some help with this code. A problem is that it leaves gaps in the walls.

Either it deletes the “Connect” attachment, so it can’t place a wall at the end of a hallway, or it deletes a side-wall (on the side of a hallway) and just doesn’t place a hallway there? You can see the former in the video below.

local repS = game:GetService("ReplicatedStorage")
local anchorRoom = game.Workspace:WaitForChild("AnchorRoom")
local spots = {}

local loaded = 0 --amount of hallways loaded
local final = 1000 --requested number of hallways

--self explanatory
function randomRoom()
	local number = math.random(1, 1000)

	if number >= 1 and number <= 750 then
		return repS:FindFirstChild("Hallway")
	elseif number >= 751 and number <= 950 and anchorRoom.Name ~= "SmallIntersection" then
		return repS:FindFirstChild("SmallIntersection")
	elseif number >= 951 and number <= 1000 and anchorRoom.Name ~= "LargeRoom" then
		return repS:FindFirstChild("LargeRoom")
	else
		return repS:FindFirstChild("Hallway")
	end
end

--allows for hallways to loop back in on eachother
local function getOverlappingParts(attachment, params)
	local overlap
	local overlapList = game.Workspace:GetPartBoundsInRadius(attachment.WorldCFrame.Position, 1.5, params)
	for _, v in pairs(overlapList) do
		if v:IsA("BasePart") and v.Name == "Wall" then
			overlap = v
			break
	else
			overlap = nil
		end
	end
	return overlap
end


--Basically, the end of every hallway segment has an attachment that shows where there are open spots for new hallway segments.
--Hallways have 1, intersections 3, rooms 1

for i = 1, final, 1 do
	task.wait()
	table.clear(spots)
	for i,v in pairs(game.workspace:GetDescendants()) do
		if v:IsA("Attachment") and v.Name == "Connect" then
			table.insert(spots, v)
		end
	end
	
	--Chooses a random open spot from the list
	local attachment = spots[math.random(1, #spots)]
	local attachmentPos = attachment.WorldCFrame
	
	--Clones a random room
	local roomClone = randomRoom():Clone()
	
	--Overlap parameters
	local overlap = OverlapParams.new()
	overlap:AddToFilter(roomClone:GetDescendants())
	
	--Positions the cloned room (not yet in workspace)
	roomClone:PivotTo(attachmentPos*CFrame.Angles(0, math.rad(180) ,0))
	local parts = game.workspace:GetPartsInPart(roomClone.PrimaryPart, overlap) --Checks to see if it is overlapping/touching any current hallways or rooms
	
	--If it isn't, then it brings the cloned room in workspace and deletes the attachment (prevents other rooms from spawning there)
	if #parts == 0 and roomClone.name ~= "Wall" then
		roomClone.Parent = game.Workspace
		anchorRoom = roomClone
		attachment:Destroy()
	else --Basically the code below allows the hallways to loop back in on itself, and to also connect with other hallways.
		local overlappingWall = getOverlappingParts(roomClone.BasePart:FindFirstChild("Connect"), overlap)
		if overlappingWall ~= nil then
			overlappingWall:Destroy()
			local hallway = repS.Hallway:Clone()
			roomClone:Destroy()
			hallway.Parent = game.Workspace
			hallway:PivotTo(attachmentPos*CFrame.Angles(0, math.rad(180) ,0))
			anchorRoom = hallway
			attachment:Destroy()
			hallway.BasePart:FindFirstChild("Connect"):Destroy()
		else
			local wall = repS:FindFirstChild("Wall"):Clone()
			wall:PivotTo(attachmentPos*CFrame.Angles(0, math.rad(90) ,0))
			wall.Parent = game.Workspace
			attachment:Destroy()
		end
			end
	
		
	
	repS.UpdateLoad:FireAllClients(i)
	loaded=i
end

--Fill any open ends by placing a wall

for i,v in pairs(workspace:GetDescendants()) do
	if v:IsA("Attachment") and v.Name == "Connect" then
		local wall = repS:FindFirstChild("Wall"):Clone()
		wall:PivotTo(v.WorldCFrame*CFrame.Angles(0, math.rad(90) ,0))
		wall.Parent = game.Workspace
		v:Destroy()
	end
end

--Code below is for randomized spawn locations of players. Every intersection has a spawn part

local spawnSpots = {}

for i,v in pairs(game.Workspace:GetDescendants()) do
	if v.Name == "SpawnSpot" then
		table.insert(spawnSpots, v)
	end
end

repS.UpdateLoad.OnServerEvent:Connect(function(player)

	local character = player.Character
	local randomSpawn = spawnSpots[math.random(1, #spawnSpots)]

	character:MoveTo(randomSpawn.Position)


end)

Video:

2 Likes