-
What do you want to achieve? Keep it simple and clear!
I want to make a proper modular room generation system for my lethal company like game
-
What is the issue? Include screenshots / videos if possible!
basically, the module generates doors and openings to other rooms that are occupying a provided space in a table. The issue is that sometimes it doesn’t generate a doorway, completely blocking off rooms and even the entrance. Also, sometimes doorways are opened when there is no room there.
-
What solutions have you tried so far? Did you look for solutions on the Developer Hub?
Ive tried changing the code logic several times and rewriting it but i couldn’t find any useful solutions.
local module = {}
local incriment = 28
local rooms = game.ServerStorage.Rooms
local roomStorage = workspace.Game.Rooms
local occupiedSpaces = {}
local border = -2031.5
function module:Clear()
roomStorage:ClearAllChildren()
table.clear(occupiedSpaces)
end
local function getIndexFromValue(t, value)
for i, v in pairs(t) do
if v == value then
return i
end
end
end
function open(part:BasePart,bool:boolean)
if part then
local e ={
[true] = 1,
[false] = 0
}
part.Transparency = e[bool]
part.CanCollide = bool
part.CanTouch = bool
part.CanQuery = bool
end
end
local function isOccupied(cframe)
local position = cframe.Position
for _, occupied in pairs(occupiedSpaces) do
if (occupied.Position - position).Magnitude < 1 then
for i,v in pairs(workspace.Game.Rooms:GetChildren()) do
if v.PrimaryPart.Position == position then
return true
end
end
end
end
return false
end
function module:Generate(worldLimit:number)
local types = {"Factory"}
local randomType = types[math.random(1, #types)]
local seedInfo = {}
table.insert(seedInfo, getIndexFromValue(types, randomType))
table.insert(seedInfo, worldLimit)
local startingCFrame = workspace.Game.ImportantGameStuff.FirstGenerationPoint.CFrame
local offsets = {
["Left"] = Vector3.new(incriment, 0, 0),
["Right"] = Vector3.new(-incriment, 0, 0),
["Front"] = Vector3.new(0, 0, -incriment),
["Back"] = Vector3.new(0, 0, incriment),
}
local opposites = {
["Left"] = "Right",
["Right"] = "Left",
["Front"] = "Back",
["Back"] = "Front",
}
local function createRoom(cframe, firstRoom)
local validChecks = {"Front", "Left", "Back", "Right"}
if isOccupied(cframe) then
return
end
local gRooms = rooms:FindFirstChild(randomType)
if not gRooms or #gRooms:GetChildren() == 0 then
return
end
if #workspace.Game.Rooms:GetChildren() >= worldLimit then return end
local selectedRoom = gRooms:GetChildren()[math.random(1, #gRooms:GetChildren())]:Clone()
selectedRoom.Parent = roomStorage
selectedRoom:PivotTo(cframe)
if #workspace.Game.Rooms:GetChildren() < worldLimit then table.insert(occupiedSpaces, cframe) end
if selectedRoom:FindFirstChild("Nodes") then
for i,v in pairs(selectedRoom:FindFirstChild("Nodes"):GetChildren()) do
local n = game.ServerStorage.Node:Clone()
n.Parent = workspace.Nodes
n.CFrame = v.CFrame
end
end
print("create " .. tostring(cframe.Position))
local walls = {}
for i, v in pairs(selectedRoom:GetChildren()) do
if table.find(validChecks, v.Name) and v:IsA("Model") then
table.insert(walls, v)
end
end
local rWalls = {}
for i = 1, #walls do
local randomWall = walls[math.random(1, #walls)]
table.insert(rWalls, randomWall)
for i, g in pairs(walls) do
if g == randomWall then
table.remove(walls, i)
end
end
end
for i, v in pairs(rWalls) do
wait()
if v:FindFirstChild("DoorWay") then
if firstRoom then
if v.Name == "Back" then
continue
end
--v:FindFirstChild("DoorWay"):Destroy()
local offset = offsets[v.Name]
local nCFrame = cframe * CFrame.new(offset)
coroutine.wrap(function()
createRoom(nCFrame, false)
end)()
else
local offset = offsets[v.Name]
local nCFrame = cframe * CFrame.new(offset)
if nCFrame.Position.X <= border then
return
end
if isOccupied(nCFrame) then
if #workspace.Game.Rooms:GetChildren() >= worldLimit then return end
coroutine.wrap(function()
wait(0.3)
if math.random(1, 5) == 1 then
for i, d in pairs(workspace.Game.Rooms:GetChildren()) do
if not d then return end
if d.PrimaryPart.CFrame == nCFrame then
if not d then return end
if not v then return end
if d.Name == v.Parent.Name then
if d:FindFirstChild(opposites[v.Name]) then
for i,e in pairs(d:FindFirstChild(opposites[v.Name]):GetChildren()) do
if not e:IsA("BasePart") then return end
open(e,true)
end
for i,e in pairs(v:FindFirstChild(opposites[v.Name]):GetChildren()) do
if not e:IsA("BasePart") then return end
open(e,true)
end
else
warn("not found!")
for i,e in pairs(v:FindFirstChild(opposites[v.Name]):GetChildren()) do
if not e:IsA("BasePart") then return end
open(e,false)
end
end
else
if d:FindFirstChild(opposites[v.Name]) and not d:FindFirstChild(opposites[v.Name]):FindFirstChild("DoorWay")then
open(d:FindFirstChild(opposites[v.Name]):FindFirstChild("DoorWay"),true)
open(v:FindFirstChild("DoorWay"),true)
else
warn("no opposite")
open(v:FindFirstChild("DoorWay"),false)
end
end
end
end
else
for i, d in pairs(workspace.Game.Rooms:GetChildren()) do
if d.PrimaryPart.CFrame == nCFrame then
if not d then return end
if d:FindFirstChild(opposites[v.Name]) and d:FindFirstChild(opposites[v.Name]):FindFirstChild("DoorWay") then
open(d:FindFirstChild(opposites[v.Name]):FindFirstChild("DoorWay"),true)
open(v:FindFirstChild("DoorWay"),true)
else
warn("no door for this guy")
open(v:FindFirstChild("DoorWay"),false)
end
end
end
end
end)()
else
if #workspace.Game.Rooms:GetChildren() < worldLimit then
--v:FindFirstChild("DoorWay"):Destroy()
coroutine.wrap(function()
wait()
if #workspace.Game.Rooms:GetChildren() >= worldLimit then return end
local r = createRoom(nCFrame, false)
if not r then return end
if not r:FindFirstChild(opposites[v.Name]) then return end
if not r:FindFirstChild(opposites[v.Name]):FindFirstChild("DoorWay") then return end
open(r:FindFirstChild(opposites[v.Name]:FindFirstChild("DoorWay")),true)
end)()
end
end
end
else
warn("god")
end
end
return selectedRoom
end
local seed = ""
createRoom(startingCFrame, true)
table.insert(seedInfo, #roomStorage:GetChildren())
for i, v in pairs(seedInfo) do
if i == 1 then
seed = seed .. v
else
seed = seed .. " _ " .. v
end
end
return seed
end
return module