got a complicated one for you today guys. im totally stumped. Im making a random dungeon generator script, and i cant figure out how to tell LUA what room to lay down next. The rooms i made for the dungeon each have a different amount of exit parts, and there are different sized rooms as well. so a big or small room can have anywhere from 1-4 exits each. The problem im having is connecting these rooms. Heres what i got:
--ace12345678135 -- I have no idea what im doing, but this is about to get very, very complicated. local rooms = workspace["Room Templates"]:GetChildren() -- the room models local world = workspace.World-- this is a folder local placed = 0 -- keep track of how many rooms are placed local tracker1 = 1 -- to give each location part in a model a name math.randomseed(tick()) local RR = math.random(10,16) ------------------------------------------------------------------------------ for i = 1,RR,1 do -- section 1 label all parts locations to ready the next rooms to be added if placed == 1 then local createrooms = world.Room1:GetChildren() for _, v in pairs(createrooms) do if v.Name == "Part" then local newvar = Instance.new("Vector3Value", v) newvar.Name = tracker1 newvar.Value = v.CFrame.p tracker1 = tracker1 + 1 end end -- section 2, heres where it gets complicated. local mapname = workspace.World:GetChildren() for _, v in pairs(mapname) do if v.Name == "1:1 End" then --i gave up here. i realized that i would have to list all --compatible possibilities and put those into if statements --so i would be here for hours just listing possible rooms --maybe you know something i dont and can fix this but im stumped. end end placed = placed + 1 end ------------------------------------------------------------------------------ -- if you havent placed a room, place a room. if placed == 0 then local cell = rooms[math.random(#rooms)]:clone() cell.Parent = world cell.PrimaryPart = cell.Floor local movpos = Vector3.new(0,70,0) cell:MoveTo(movpos) placed = placed + 1 end end
there are no errors in this script, i just dont know how to tell the script what to do next without creating a plethera of "if" statements. any help is appreciated
Hey ace12345678135!
I can certainly relate with your troubles, because I have, in the past, made something similar myself! Making a procedural dungeon generator can be a whole lot of fun, but it's not without its challenges...
To start, let's move that room model into ServerStorage so that it's out of the way. That done, let's get started with the basics:
local RoomTemplates = game.ServerStorage:WaitForChild("Room Templates"):GetChildren(); -- A folder that will contain all rooms spawned. Easy to empty. local RoomFolder = Instance.new("Folder", game.Workspace); local StartRoom = game.ServerStorage["Room Templates"]:FindFirstChild("Room1"); local function AppendRoom(existingRoom, newRoom) local newRoom = newRoom:Clone(); newRoom:SetPrimaryPartCFrame(existingRoom.ExitPart.CFrame); newRoom.Parent = RoomFolder; return newRoom; end; -- Clear RoomFolder, create a new start room, and from the provided start room, append new rooms until we reach roomCount. local function GenerateDungeon(roomCount) RoomFolder:ClearAllChildren(); local lastRoom = StartRoom:Clone(); lastRoom.Parent = RoomFolder; for i = 1, roomCount do local chosenRoom = RoomTemplates[math.random(#RoomTemplates)]; local conditions = ( lastRoom and lastRoom:FindFirstChild("ExitPart") and chosenRoom.Name ~= "Room1" and chosenRoom.PrimaryPart and chosenRoom:FindFirstChild("ExitPart") -- Add conditions as needed. ); if (conditions) then lastRoom = AppendRoom(lastRoom, chosenRoom); end; end; end; if (StartRoom) then GenerateDungeon(math.random(10, 20)); end;
You will notice that instead of using MoveTo, I used a function called SetPrimaryPartCFrame. This was intentional. SetPrimaryPartCFrame works essentially the same way, but uses CFrame to position, which means that your models will be positioned where they belong without exception.
Another thing you may have noticed is that I use two different parts to position rooms. One named PrimaryPart, and another, ExitPart. PrimaryPart is actually a property of Model
that you can set to any part within the model. This is important. When you use SetPrimaryPartCFrame, it sets the position of that part, and moves the rest of the model to the same position relative to it. So, by setting a model's PrimaryPart CFrame to the CFrame of ExitPart, I effectively put the rooms together.
However, the positioning of PrimaryPart and ExitPart is crucial. PrimaryPart will be put in the same position as ExitPart, and the rest of the model will be placed around it. ExitPart of a room is where the door/hole/whatever of a certain room leads to another room. If PrimaryPart of the new room is where the entrance is, then the rooms will (if you positioned ExitPart and PrimaryPart correctly) fit together perfectly every time. To make positioning simple, make both the ExitParts and PrimaryParts of each room the same size, and place them in a consistent manner for each room in your game.
Having done that, simply set the PrimaryPart property of each room's Model, put them back into Room Templates
and run the game. If you forgot to set the PrimaryPart of a model, the script will give you an error letting you know. Additionally, your rooms' positioning might be a bit loopy at first (trust me, it takes a bit to get the positions right sometimes, if you're not careful!) due to incorrect rotation or slight imperfections of the positioning or one or both parts, but when done correctly, the rooms will always have a standardized way of fitting into each other. For each new room you make, simply give it a PrimaryPart to act as the placeholder for the entryway, and have an ExitPart for the place where the exit is.
The PrimaryPart name convention I used is because that is the name for, well, a Model's PrimaryPart
property. The name ExitPart, however, was made up. You could name it something else, but ExitPart seems pretty reasonable. Also note that PrimaryPart and ExitPart are placeholder parts. They do not need to be visible or collidable, since they only serve to help the rooms fit together consistently.
Now, I never did make a way for rooms to branch...
... that was intentional. There are multiple ways to do that, and I'm not sure what would best fit you. There is a point at which you'll be faced with problems like preventing rooms from running into each other and making the dungeon structure (semi-)reasonable. For now, tweak the existing game until you're satisfied that it will work consistently. Block the additional exits until you know how you want to work on additional paths. If you get stuck, though, feel free to message me.
It's worth noting that the above code was written completely from scratch and was not tested at all. It may or may not have problems, but I'm confident you'll be able to correct them if they turn up. Let me know if I made any mistakes, nonetheless. ;)
Have a good one, ace12345678135. Best of luck with your game, too!
Warm regards, tkcmdr