currently im making a puzzle script and trying to distribute 11 keys through about 50 possible spawn locations using math.random. i tried to store the keys in a table and the spawn locations in another table then distribute them like that but i couldnt get it to work.
what i did is defined each 11 keys seperately, then stored the locations in a table and spawned them which works how i want, except that one of the locations will spawn 2+ keys and then the player cant pick them up.
is there a way to stop this from happening? each key is important (think of it like colored keys) and is used to open a door but i dont want them to double up (like red key and yellow key together) any ideas are appreciated!
here is how i store the locations, and how i spawn the keys. its not too effectient but it works lol
code:
local Locations = workspace.Lvl5NoteLocations
local Notes = ServerStorage.Lvl5Puzzle
local tbl = {}
for _,part in pairs(Locations:GetChildren()) do
table.insert(tbl, part.CFrame)
end
local Note1 = workspace:FindFirstChild(āIā)
local Note1Spawned = false
if not Note1 then
local Note1Clone = I:Clone()
Note1Spawned = true
Note1Clone.CFrame = tbl[math.random(#tbl)]
Note1Clone.Parent = workspace
end
Have you tried removing the location from the table after you use it using table.remove(tbl, index)? Your script only shows spawning one āNoteā so itās hard to see what the problem might be.
local LocationsTable = {}; -- Table of "Locations"
for _,Part in pairs(Locations:GetChildren()) do
table.insert(LocationsTable, Part.CFrame); -- Same as your script
end
for _,Key in pairs(<INSERT KEYS PATH>:GetChildren()) do -- Iterate through all of your "Keys"
local LocationIndex = math.random(1, #LocationsTable); -- Find a random "Location"
local newKey = Key:Clone() -- Create the new "Key"
newKey.CFrame = LocationsTable[LocationIndex];
newKey.Parent = workspace;
table.remove(LocationsTable, LocationIndex); -- Remove the Location from your table so it cannot be re-used
end
Iāve used <INSERT KEYS PATH>:GetChildren() assuming you have all of your keys as a child of a specific folder/model that you can iterate through, but it would be just as easy to replace this with a table of keys like you said youād already tried earlier.
Glad to hear itās working! Just for the benefit of yourself or anyone else who stumbles across this Iāll give a brief explanation:
Every time you iterate youāre using math.random on the table length. As the table length isnāt changing you have the possibility of repeating the same randomly generated number. In that circumstance it will index the same location that youāve already used and cause two keys to spawn on the same position.
Example:
local Table = {'one', 'two', 'three', 'four'}; -- Table has a length of 4 (as there is 4 values inside it)
local x = math.random(1, #Table); ---> Random number between 1 and 4, lets assume it picks 2
print(Table[x]) ---> "two"
local y = math.random(1, #Table); ---> Random number between 1 and 4, lets assume it picks 2 again
print(Table[y]) ---> "two"
If you remove the value from the table after every use:
local Table = {'one', 'two', 'three', 'four'}; -- Table has a length of 4 (as there is 4 values inside it)
local x = math.random(1, #Table); ---> Random number between 1 and 4, lets assume it picks 2
print(Table[x]) ---> "two"
table.remove(Table, x); -- Removes the 2nd value from the table
-- Table now looks like this:
local Table = {"one", "three", "four"};
local y = math.random(1, #Table); ---> Random number between 1 and 4, lets assume it picks 2 again
print(Table[y]) ---> "three" as the 2nd index of 'Table' is now "three"
local rand = Random.new()
rand:Shuffle(table)
for _, locator in table do
spawnAt(locator)
end
you can also maintain a logical āused portionā:
local usedCount = 0
for i = 1, #table do
local last = #table - usedCount
local index = math.random(1, last)
spawnAt(table[index])
table[index], table[last] = table[last], table[index] --swap to place it into used portion
usedCount += 1
end