Help with a map picker script

hello, i have made a script that picks out maps once a goal has been completed, but for some reason when the map is completed it doesn’t destroy the current one or load a random one at all.

basically what the code does is constantly check if all the buttons have been pressed, and if they have it should supposedly destroy the current map after 5 seconds (temporary time for testing purposes) and load a new one after another 5 seconds (also temporary)

local counter = 1

local chosenmap

function chooseSpawnPoints(spawnblocks) -- folder is the spawn parts folder we specified in the while loop

	local tableA = spawnblocks:GetChildren()

	local tableB = {} -- the Winner table

	local tabALength = #tableA

	local maxspawnblocks = math.random(1,tabALength)

	for i = 1,maxspawnblocks do

		local randomNumber = math.random(1,tabALength)-- choosen a random # within the tables max index. 

		local choosen = tableA[randomNumber] -- grab the value

		if choosen ~= nil then

			table.insert(tableB,choosen)-- insert the choosen spawn block into the winner table

			table.remove(tableA,randomNumber)-- remove from the spawn block table so we do not get it again


		end

	end

	return tableB 

end



local maps = game.ReplicatedStorage.maps:GetChildren() -- get a list of all the maps

local chosenMap = maps[math.random(1,#maps)]

chosenMap = chosenMap:Clone()

chosenMap.Parent = game.Workspace


local choosenblocks = chooseSpawnPoints(chosenMap.spawnblocks)  -- changed the function a bit. It needs a parameter which is the instance it will loop through

for i, block in pairs(choosenblocks) do
	local button = game.ReplicatedStorage.Button:Clone()

	button:SetPrimaryPartCFrame(CFrame.new(block.Position))
	button.Parent = game.Workspace.Buttons

	block:Destroy()
end

local buttonsPressed = game.Workspace.ButtonsPressed
local buttons = game.Workspace.Buttons:GetChildren()


buttonsPressed.Changed:Connect(function(property)
	if property == "Value" then
		if buttonsPressed.Value == #buttons then
			wait(5)
			chosenMap:Destroy()
			buttons:Destroy()

			wait(5)
			chosenMap:Clone()
			chosenMap.Parent = workspace
		end
	end
end)

there are no errors in output or anything when this happens, so i don’t know what’s causing this bug or why it’s happening

any help is appreciated

1 Like

You never changed what Chosen map was, so if chosen map is called MapA for example, it deletes MapA, waits 5 seconds, clones MapA.
I don’t see anywhere else in the script where it changes chosenMap because the first time chosenMap is given a value, it never goes back to that line of code again

this basically tells the game to pick out a random map, so shouldn’t the value of the variable chosenMap change every time?

Yes it should and you never changed it after the first time it does this, after it runs that code it won’t go back to it ever again because it’s not in a repeat / while loop so it will only run one time and continue going down the script

Try doing something like this :


local counter = 1

local chosenmap

function chooseSpawnPoints(spawnblocks) -- folder is the spawn parts folder we specified in the while loop

	local tableA = spawnblocks:GetChildren()

	local tableB = {} -- the Winner table

	local tabALength = #tableA

	local maxspawnblocks = math.random(1,tabALength)

	for i = 1,maxspawnblocks do

		local randomNumber = math.random(1,tabALength)-- choosen a random # within the tables max index. 

		local choosen = tableA[randomNumber] -- grab the value

		if choosen ~= nil then

			table.insert(tableB,choosen)-- insert the choosen spawn block into the winner table

			table.remove(tableA,randomNumber)-- remove from the spawn block table so we do not get it again


		end

	end

	return tableB 

end



local maps = game.ReplicatedStorage.maps:GetChildren() -- get a list of all the maps

local chosenMap = maps[math.random(1,#maps)]

chosenMap = chosenMap:Clone()

chosenMap.Parent = game.Workspace


local choosenblocks = chooseSpawnPoints(chosenMap.spawnblocks)  -- changed the function a bit. It needs a parameter which is the instance it will loop through

for i, block in pairs(choosenblocks) do
	local button = game.ReplicatedStorage.Button:Clone()

	button:SetPrimaryPartCFrame(CFrame.new(block.Position))
	button.Parent = game.Workspace.Buttons

	block:Destroy()
end

local buttonsPressed = game.Workspace.ButtonsPressed
local buttons = game.Workspace.Buttons:GetChildren()


buttonsPressed.Changed:Connect(function(property)
	if property == "Value" then
		if buttonsPressed.Value == #buttons then
			wait(5)
			chosenMap:Destroy()
			buttons:Destroy()

            chosenMap = maps[math.random(1,#maps)] — now we actually changed what chosenMap is as chosenMap is never updated again anywhere else in the script

			wait(5)
			chosenMap:Clone()
			chosenMap.Parent = workspace
		end
	end
end)

Try this instead:

local maps = game.ReplicatedStorage.maps:GetChildren() -- get a list of all the maps
local chosenMap = maps[math.random(1,#maps)]

local clonedMap = chosenMap:Clone()
clonedMap.Parent = game.Workspace

Okay, so your issue is the way in which the “.Changed” event works for “ValueBase” instances i.e; StringValue, BoolValue, IntValue, NumberValue etc. as opposed to how it works for other instance types.

The way in which “.Changed” works for standard instances is that the parameter received by the event represents the name (as a string type value) of the changed property which resulted in the event firing on the instance.

Now let’s take a look at a random “ValueBase” instance for comparison.

As we can see, its “.Changed” event only fires when its “Value” property changes, and the parameter received by this event represents the new value of the changed “Value” property which caused the event to fire on the instance, with this information your script needs to be changed to look like the following.

buttonsPressed.Changed:Connect(function(pressedCount)
	if pressedCount == #buttons then
		wait(5)
		chosenMap:Destroy()
		buttons:Destroy()

		wait(5)
		chosenMap:Clone()
		chosenMap.Parent = workspace
	end
end)

I’d also recommend replacing wait() with task.wait() for future work (but that’s just an efficiency preference).

Put it in a loop then if you want it to keep switching

i tried this, but it didn’t really do anything different. same result, maps not changing

i tried this, nothing different really happened. same result

i had put it in a while true do loop but that just crashed my studio entirely

because you didn’t add a wait(). Other then that, it shouldn’t have crashed

what i did with that loop was this pretty much

while true do
	buttonsPressed.Changed:Connect(function(property)
		if property == "Value" then
			if buttonsPressed.Value == #buttons then
				wait(5)
				chosenMap:Destroy()
				buttons:Destroy()

				chosenMap = maps[math.random(1,#maps)]

				wait(5)
				chosenMap:Clone()
				chosenMap.Parent = workspace
			end
		end
	end)
end

where should i add the wait()?

try while wait() do. That might work

i replaced the while true with a while wait() and nothing changed, map stays the same and doesn’t delete itself or generate a new one at all

Yeah, that shouldn’t be in a while true do loop, it should be on its own, can you provide the full script?

the full script is in the first post

local replicated = game:GetService("ReplicatedStorage")

local mapsFolder = replicated.maps
local maps = mapsFolder:GetChildren()

local button = replicated.Button
local buttonsPressed = workspace.ButtonsPressed
local buttonsFolder = workspace.Buttons
local buttons = buttonsFolder:GetChildren()

local clonedMap = nil

local function doRound()
	buttonsPressed.Value = 0
	local randomMap = maps[math.random(#maps)]
	local clonedMap = randomMap:Clone()
	clonedMap.Parent = workspace

	local blocks = clonedMap.spawnblocks:GetChildren()
	local randomAmount = math.random(#blocks)
	for i = randomAmount, 1, -1 do
		local pressed = false
		local button = button:Clone()
		button:PivotTo(blocks[i].CFrame)
		buttons.Touched:Connect(function()
			if pressed then
				return
			end
			
			pressed = true
			buttonsPressed.Value += 1
		end)
		button.Parent = buttonsFolder
		blocks[i]:Destroy()
	end
end

doRound()

buttonsPressed.Changed:Connect(function(pressedCount)
	if pressedCount == #buttons then
		task.wait(5)
		clonedMap:Destroy()
		doRound()
	end
end)

this script gives me this error in the output

What do the button instances represent? I was under the impression that they were BaseParts.