Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
COMMUNITY QUESTION

Holo Map ]] How to run multiple holo maps at the same time?

So, basically one part of this script will remove the clone of a current map and run a different map. The process goes as it follows, me : r2/map1 (map1 is loaded) me : r2/map2 (map1 is removed and map2 is loaded) What I want, me : r2/map1 (map1 is loaded) me : r2/map2 (map2 loaded) A part of the script below removes the current map when I say r2/(map) Anyway how to edit this?

Permission = {"PLAYER","PLAYER","PLAYER"} -- Players who can run/stop the maps.
RunText = "r2/" -- Text the Players have to say to run the maps. (MAP NAME AFTER)
StopText = "cl2/" -- Text the Players have to say to stop the maps. (MAP NAME AFTER)

game.Players.ChildAdded:connect(function(Player)
	Player.Chatted:connect(function(Chat)
		for i = 1, #Permission do
			if Player.Name == Permission[i] then
				if Chat:lower():sub(1,RunText:len()) == RunText then
					Map = game.ServerStorage:FindFirstChild(Chat.sub(Chat,1+RunText:len()))
					if Map ~= nil then
						for i,v in pairs(game.ServerStorage:GetChildren()) do
							if v:IsA("Model") then
								if game.Workspace:FindFirstChild(v.Name) then
									game.Workspace:FindFirstChild(v.Name):remove()
								end
							end
						end
						Map:Clone().Parent = game.Workspace
					end
				end
				if Chat:lower():sub(1,StopText:len()) == StopText then
					Map = game.ServerStorage:FindFirstChild(Chat.sub(Chat,1+StopText:len()))
					if Map ~= nil then
						Clone = game.Workspace:FindFirstChild(Chat.sub(Chat,1+StopText:len()))
						if Clone ~= nil then
							Clone:remove()
						end
					end
				end
			end
		end
	end)
end)

2 comments

0

please use Destroy() and not remove()

0

why?

1 answer

Improving Organization / Cleanup

  • It's a bad sign that you are indented 9 levels deep.
  • It's awful that you're using string methods using .. You can use # instead of :len().
  • You should use local variables for variables inside functions -- this actually matters a lot.
  • There's no reason to say ~= nil.
  • You should use :Remove() instead of :remove(), but anyway :Destroy() instead of :Remove().
  • You can use workspace instead of game.Workspace.

Applying these changes, we get this:

Permission = {"PLAYER","PLAYER2","PLAYER3"} -- Players who can run/stop the maps.
RunText = "r2/" -- Text the Players have to say to run the maps. (MAP NAME AFTER)
StopText = "cl2/" -- Text the Players have to say to stop the maps. (MAP NAME AFTER)

function speak(Chat)
	if Chat:lower():sub(1, #RunText) == RunText then
		local Map = game.ServerStorage:FindFirstChild(Chat:sub(1+#RunText))
		if Map then
			for _, v in pairs(game.ServerStorage:GetChildren()) do
				if v:IsA("Model") then
					if workspace:FindFirstChild(v.Name) then
						workspace:FindFirstChild(v.Name):Destroy()
					end
				end
			end
			Map:Clone().Parent = workspace
		end
	end
	if Chat:lower():sub(1, #StopText) == StopText then
		local Map = game.ServerStorage:FindFirstChild(Chat:sub(1+#StopText))
		if Map then
			local Clone = workspace:FindFirstChild(Chat:sub(1+#StopText))
			if Clone then
				Clone:Destroy()
			end
		end
	end
end

game.Players.ChildAdded:connect(function(Player)
	for _, authedName in pairs(Permission) do
		if authedName:lower() == Player.Name:lower() then
			Player.Chatted:connect(speak)
		end
	end
end)

Simplifying String Stuffs

There's a lot of repetition going on. Let's observe that we are processing messages in this way:

  • Does it start with x?
  • Then I need to use the remainder of the string.

Let's make a function that deals with that, then:

function afterPrefix(text, pre)
	if text:sub(1, #pre) == pre then
		return text:sub(#pre + 1)
	end
end

We can use afterPrefix to simplify the rest of the speak function. We should also probably break the speak up into different functions, one for each command -- since the commands have no overlap, it simplifies understanding.

function runCommand(cmd)
	local Map = game.ServerStorage:FindFirstChild(cmd)
	if Map then
		for _, v in pairs(game.ServerStorage:GetChildren()) do
			if v:IsA("Model") then
				if workspace:FindFirstChild(v.Name) then
					workspace:FindFirstChild(v.Name):Destroy()
				end
			end
		end
		Map:Clone().Parent = workspace
	end
end

function stopCommand(cmd)
	local Map = game.ServerStorage:FindFirstChild(cmd)
	if Map then
		local Clone = workspace:FindFirstChild(cmd)
		if Clone then
			Clone:Destroy()
		end
	end
end

function speak(Chat)
	local run = afterPrefix(Chat:lower(), RunText)
	if run then
		runCommand(run)
	end
	local stop = afterPrefix(Chat:lower(), StopText)
	if stop then
		stopCommand(stop)
	end
end

Question

runCommand very obviously deletes all of the current maps. Instead, we should just delete the current map. Instead of repeating ourselves, we can just invoke stopCommand.


function runCommand(cmd)
	stopCommand(cmd)
	local Map = game.ServerStorage:FindFirstChild(cmd)
	if Map then
		Map:Clone().Parent = workspace
	end
end

This discussion is preserved as it was. New answers, comments, and votes are closed.