I am currently in the process of creating my first Roblox game, and I was wondering if the following ModuleScript is well-optimized and organized. If not, I would like some help to make the most out of it. I also want to add some additional features, but for now, optimizing it is my top priority.
The code essentially ensures that when calling the ‘Station.Generate()’ function, a station begins to generate from scratch. It starts by randomly selecting a main room to serve as a starting point, and then at each DoorPlace of that room, another room is generated, each passing through a filter with predefined rules, until the desired number of rooms is achieved. The ‘Station.Assemble()’ function positions the station in its final place.
I would like to know if there is a way to optimize the code so that it’s not a mess.
With regard to how I could improve the script to make it more efficient, I have already optimized it myself to the best of my abilities (as far as I know), so that’s why I came to ask for help.
Well, as I mentioned before, I would like to organize and optimize it. Additionally, I would like to add functionality to provide the Script with a room that is guaranteed to be generated in the station, as well as being able to confirm if there are enough rooms of a certain type (which I have considered doing using additional attributes or creating a new Module with room data).
Finally, here’s the code:
(sorry in advance for the comments in spanish)
local Station = {}
local ServerScriptService = game:GetService("ServerScriptService")
local Weight = require(ServerScriptService.Modules.Weight)
local random = Random.new()
local station = workspace.Map.Main.Station
local stationGenerate = workspace.Map.StationGenerate
local unusedPlaces = {}
local roomCount = 0 --Cantidad de habitaciones generadas
local waitTime = 0.5 --Tiempo de espera entre la generación de habitaciones
Station.rooms = 10 --Cantidad aproximada de habitaciones para generar
Station.stairsPossible = true --Si se pueden generar escaleras
Station.stairs = false --Si se generaron escaleras
function Station.GetRandom(isRoom, prevRoom) --Obtiene una habitación aleatoria
local roomPool = {}
if isRoom then
for i, room in pairs(workspace.Templates.Rooms:GetChildren()) do
-- [1] La habitación seleccionada DEBE ser diferente a la anterior
if room.Name == prevRoom.Name then
continue
-- [2] Si se pueden generar escaleras, comprobar que sean las unicas
elseif room.Name == "Stairs" and (not Station.stairsPossible or Station.stairs) then
continue
-- [3] Las tres primeras habitaciones tienen que tener más de dos puertas
elseif roomCount <= 3 and room:GetAttribute("Places") < 2 then
continue
-- [...] Si la habitación es apta para generarse, añadirla a la pool
else
table.insert(roomPool, room)
end
end
else
roomPool = workspace.Templates.Stations:GetChildren()
end
return Weight.GetObject(roomPool)
end
function Station.GenerateRoom(doorPlace)
local prevRoom = doorPlace.Parent.Parent
local chosenRoom = Station.GetRandom(true, prevRoom)
local newRoom = chosenRoom:Clone()
local doorTemplates = workspace.Templates.Doors
local door = doorTemplates.Door
local blockedDoor = doorTemplates.BlockedDoor
local doorPlaces = newRoom:FindFirstChild("DoorPlaces")
local placesList = doorPlaces:GetChildren()
newRoom:PivotTo(doorPlace.CFrame)
newRoom.Parent = stationGenerate
--Identificar si hay espacio para generar la habitación
for i, part in pairs(workspace:GetPartsInPart(newRoom.Hitbox)) do
if part.Name == "Hitbox" and not part:IsDescendantOf(newRoom) then
newRoom:Destroy()
print("collide!")
return
end
end
--Si la habitación es especial, registrarlo en su variable para que no se generen más
if newRoom.Name == "Stairs" then
Station.stairs = true
end
roomCount += 1
doorPlace:SetAttribute("HasRoom", true)
local newDoor = door:Clone()
newDoor:PivotTo(doorPlace.CFrame)
newDoor.Parent = newRoom
--Si la habitación tiene otras puertas, generar habitaciones en ellas
while #placesList > 0 and roomCount < Station.rooms do
local randomPlace = placesList[random:NextInteger(1, #placesList)]
task.wait(waitTime)
task.spawn(function()
Station.GenerateRoom(randomPlace)
end)
table.remove(placesList, table.find(placesList, randomPlace))
end
print("room generated!")
end
function Station.Generate()
local chosenRoom = Station.GetRandom(false)
local newRoom = chosenRoom:Clone()
local porch = workspace.Templates.Porches.Porch
local blockedDoor = workspace.Templates.Doors.BlockedDoor
local window = workspace.Templates.Windows.Window8x8
local doorPlaces = newRoom:FindFirstChild("DoorPlaces")
local placesList = doorPlaces:GetChildren()
station:ClearAllChildren()
Station.stairs = false
unusedPlaces = {}
roomCount = 0
newRoom:PivotTo(workspace.Map.StationGeneratePart.CFrame)
newRoom.Parent = stationGenerate
roomCount += 1
local newPorch = porch:Clone()
newPorch:PivotTo(newRoom.PrimaryPart.CFrame)
newPorch.Parent = stationGenerate
--Si la habitación tiene otras puertas, generar habitaciones en ellas
while #placesList > 0 and roomCount < Station.rooms do
local randomPlace = placesList[random:NextInteger(1, #placesList)]
task.wait(waitTime)
task.spawn(function()
Station.GenerateRoom(randomPlace)
end)
table.remove(placesList, table.find(placesList, randomPlace))
end
--Detectar si la estación terminó de generarse
local lastRoomCount = 0
while task.wait(waitTime * 2) do
if roomCount > lastRoomCount then --Si se generó una habitación
lastRoomCount = roomCount
elseif roomCount == lastRoomCount then --Si no se generó una habitación
print("the station has fully generated!")
break
end
end
--Identificar lugares no usados
for i, room in pairs(stationGenerate:GetChildren()) do
local places = room:FindFirstChild("DoorPlaces")
if not places then
continue
end
--Posicionar puertas bloqueadas
for i, place in places:GetChildren() do
for i, part in workspace:GetPartsInPart(place) do
if part.Parent.Name == "DoorPlaces" then
local newBlockedDoor = blockedDoor:Clone()
newBlockedDoor:PivotTo(place.CFrame)
newBlockedDoor.Parent = place.Parent.Parent
place:SetAttribute("Blocked", true)
part:Destroy()
print("blocked!")
end
end
end
for i, place in pairs(places:GetChildren()) do
local hasRoom = place:GetAttribute("HasRoom")
local blocked = place:GetAttribute("Blocked")
if not hasRoom and not blocked then
table.insert(unusedPlaces, place)
end
end
end
print("unused places identified!")
--Generar habitaciones necesarias
--Posicionar ventanas
for i, place in pairs(unusedPlaces) do
local room = place.Parent.Parent
local newWindow = window:Clone()
newWindow:PivotTo(place.CFrame)
newWindow.Parent = room
place:SetAttribute("Windowed", true)
print("windowed!")
end
print("station finished!")
end
function Station.Assemble()
local children = stationGenerate:GetChildren()
for i, child in pairs(children) do
child.Parent = station
end
station.PrimaryPart = station.Porch.PrimaryPart
station:PivotTo(workspace.Map.Main.StationPart.CFrame)
end
return Station