Hey, I’m looking to pull a model from a table based on the number in the table and do things with it. I’m new to tables, and don’t know much other than what the DevWiki provides.
Specifically variables chosenSpawn and newRoom are causing me issues, not too sure how to pull the model from the table using the index I defined as a variable. I suspect that there’s simply a method hiding before my eyes but I can’t find the answer. Seems to be a fundamental for table usage.
It’s important to note that there is already entries in the ‘roomSpawn’ table due to the way the first room generates in a seperate part of the script, as well as the different rooms being indexed in ‘rooms’ as well.
Also feedback for other parts of my code is appreciated as well.
This is my code, this and the error log that shows after.
function createRoom()
print("ok")
local chosenRoom = math.random(1,table.getn(roomSpawn)) -- 'randomly' a number between 1 to # of spawns available (tabled on generation)
print(chosenRoom)
local chosenSpawn = roomSpawn.chosenRoom -- looking to pull the model from the table based on chosenRoom
local newRoomNumber = math.random(1, table.getn(rooms)) -- 'randomly' a number between 1 to # rooms (tabled from a folder)
print(newRoomNumber)
local newRoom = rooms.NewRoomNumber:Clone() -- looking to clone the chosen room from the list
newRoom.Parent = dungeonModel -- parents to the dungeon model
newRoom:SetPrimaryPartCFrame(chosenSpawn) -- sets the rooms orientation and pos to the spawn point
chosenSpawn:Destroy() -- destroys spawn to prevent it from being used again
table.remove(roomSpawn,table.find(chosenRoom)) -- removes spawn point from table to prevent it from being used again
print("room created")
for i, v in pairs(newRoom:GetChildren()) do -- loops through children of new room
if v:IsA("BasePart") and v.Name == "SPAWN" then -- finds spawn(s) for new rooms
table.insert(roomSpawn, v) -- inserts new spawn(s) into spawntable
print("spawn integrated")
end
end
end
function generation()
for i = 1,Limit,1 do
wait(0.1)
createRoom()
end
end
01:47:07.200 ▶ Spawn Indexed to roomSpawn (x4) - Server - RoomMaker:38
01:47:08.834 ok - Server - RoomMaker:49
01:47:08.834 4 - Server - RoomMaker:51
01:47:08.835 1 - Server - RoomMaker:54
01:47:08.835 ServerScriptService.RoomMaker:55: attempt to index nil with 'Clone' - Server - RoomMaker:55
01:47:08.835 Stack Begin - Studio
01:47:08.835 Script 'ServerScriptService.RoomMaker', Line 55 - function createRoom - Studio - RoomMaker:55
01:47:08.835 Script 'ServerScriptService.RoomMaker', Line 73 - function generation - Studio - RoomMaker:73
01:47:08.835 Script 'ServerScriptService.RoomMaker', Line 80 - Studio - RoomMaker:80
01:47:08.836 Stack End - Studio
TL;DR: I’m trying to find how to pull a model from a table based on the index, with the index being a variable.
clicking on what’s printed in the error log for what spawn is selected highlights it in explorer, so I’d imagine this is a successful integration.
edit: this only applies for a seperate part script that prints as it inserts into the table.
I’m a little confused as to how your hierarchy is laid out. Is it just a folder with different rooms in it and these rooms have different parts which should have more rooms connected to them?
I don’t think you would need an external table as you can just use :GetChildren().
local rooms = game:GetService('ServerStorage'):WaitForChild('Rooms')
local function createRoom() -- make sure functions are local as I am pretty sure they allocate less memory
local chosenRoom = math.random(1,#roomSpawn)
print(chosenRoom)
local chosenSpawn = roomSpawn:GetChildren()[chosenRoom] -- this will take the child whose index is chosenRoom
local newRoomNumber = math.random(1, #rooms)
print(newRoomNumber)
local newRoom = rooms:GetChildren()[newRoomNumber]:Clone()
newRoom.Parent = dungeonModel
newRoom:SetPrimaryPartCFrame(chosenSpawn)
chosenSpawn:Destroy()
print("room created")
for i, v in pairs(newRoom:GetChildren()) do
if v:IsA("BasePart") and v.Name == "SPAWN" then
print("spawn integrated")
end
end
end
In short, yes. The rooms are kept in a folder in ServerStorage, and indexed into the “rooms” table via this code:
local ServerStorage = game:GetService("ServerStorage")
local RoomsHere = ServerStorage:WaitForChild("Rooms")
for i, v in pairs(RoomsHere:GetChildren()) do
if v:IsA("Model") and v.Name ~= "spawnRoom" then
--print("Spawn Indexed to roomSpawn")
table.insert(rooms, v)
--print(roomSpawn)
end
end
Alright. I’m still a bit confused but I tried to add some comments on parts I am not 100% sure on and maybe some to help you understand where I’m going with things haha.
for i,v in pairs(roomsHere:GetChildren()) do -- so this is generated first
if v:IsA('Model') and v.Name ~= 'spawnRoom' then
rooms[#rooms + 1] = v
end
end
local function createRoom(index)
local chosenRoom = math.random(1,#roomSpawn) -- not sure what roomSpawn is, probably the amount of spawns in the room?
local chosenSpawn = roomSpawn[chosenRoom] -- use square brackets to index tables with a variable/number
local newRoomNumber = math.random(1, #rooms)
local newRoom = rooms[newRoomNumber]:Clone()
newRoom.Parent = dungeonModel
newRoom:SetPrimaryPartCFrame(chosenSpawn)
chosenSpawn:Destroy()
table.remove(roomSpawn, chosenRoom) -- since we already have a number that is between 1 and # roomSpawn, we don't have to use table.find
for i,v in pairs(newRoom:GetChildren()) do
if v:IsA('BasePart') and v.Name == 'SPAN' then
roomSpawn[#roomSpawn + 1] = v
end
end
end
local function generation()
for i = 1,limit do -- also, no need to specify the step here as it's 1 by default
wait(.1)
createRoom(i)
end
end
My thought process when creating the system was to have two tables; one for the places rooms can spawn (spawnpoints as BaseParts) and the other for the rooms (Models), the code that puts the rooms in a table is in my previous post, and the process of spawning the first room puts some spawn points for rooms in a table. Spawning a room puts the spawn points from that respective room in a table as seen in my original post.
Here’s my code for spawning the origin room:
function createSpawn()
local newspawn = SpawnRoom:Clone()
newspawn.Parent = spawnParent
newspawn:SetPrimaryPartCFrame(spawnOrigin)
for i, v in pairs(newspawn:GetChildren()) do
if v:IsA("BasePart") and v.Name == "SPAWN" then
print("Spawn Indexed to roomSpawn")
table.insert(roomSpawn, v)
end
end
end
This code block with some minor changes was successful, thank you! I was unaware of the functionality of square brackets, as I am still fairly new to scripting. I’m going to dissect the given code in comparison to my own, and hopefully improve my original script to match yours so it’s not straight up plagarism haha.
I’ll be back in one moment once I understand the changes.
Basically, the reason why using a period doesn’t work is because it is looking for a child or property whose name is “chosenRoom”, “NewRoomNumber” etc…
You can also use brackets to index things whose indexes are instances, tables etc
local t = {}
local t2 = {
[t] = 'table';
}
print(t2.t) -- this would be nil because no entry exists whose index is "t"
print(t2[t]) -- this would be 'table' because the index is the table object
Same thing with instances
local t = {
[workspace] = 'cool the index is the workspace'
}
print(t.workspace) --> nil
print(t[workspace]) --> nil
Basically, doing table.string is the same as doing table[‘string’].
Only upside to using brackets for names is that you can use spaces (which is very uncommon if not nonexistent in professional cases).
local part = workspace['this part has a name with spaces']
local part2 = workspace.this part has a name with spaces --> would error with something like expected function call because it's basically the same as doing
local part2 = workspace.this
part
has
a
name
with
spaces
-- or
local part2 = workspace.this
nil
nil
nil
nil
nil
nil
-- because the variables, part, has, a, name, with, and spaces are all nil if that makes sense
Thanks for the lesson! I was entirely unaware, when I absolutely had to refer to a child with spaces in the name before I’d use a WaitForChild("") - which has obvious issues in itself.
After understanding and modifying my base code, it successfully generates in the way I’d expect. Now I’ve only to code the doors between rooms becoming destroyed when a room is created, and preventing a spawn location from being used when already inside the room, however that’ll have to be for a future date as it’s 3am local time and I’ve work in the morning. Hopefully I won’t have to make another post requesting assistance on that topic, LOL.