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

How do you make a msgbox that will return true/false if the player chooses yes/no?

--Module (In ReplicatedStorage) --

local module = {}
module.showMSG = function(msgGUI) --< Inside the msgGUI, there's a textbutton called yes and a textbutton called no.

	msgGUI.Enabled = true


	msgGUI.Yes.MouseButton1Click:Connect(function() return true end)
	msgGUI.No.MouseButton1Click:Connect(function() return false end)
end
return module

---local script (Descendant of PlayerGui) --

local module = require(game:GetService("ReplicatedStorage").Module)

script.Parent.MouseButton1down:Connect(function()
	local processedModule = module.showMSG(game.Players.localPlayer.PlayerGui:FindFirstChild("msgbox"))
	if processedModule == true then
	print("Yahoo!")
	else
	print("Oh Noes!")
	end
end)

When I tested it out, it kept returning false when I called the module, when I did not even press any button. Is there a way to fix this?

Thank you.

1 answer

✓ Accepted answer

See this thread about returning values that do not yet exist.

The return on line 7 returns from the function on line 7, not the showMSG function.

You can't forcibly return from another function, because that function may no longer be running (or may be recursive, etc...)

There are roughly three broad options:

1. Blocking

Don't return until you have an answer.

This is a little awkward to do in ROBLOX for this particular case, but it's possible and not too bad with BindableEvents.

function showMSG(gui)
	gui.Enabled = true

	local event = Instance.new("BindableEvent")

	-- Listen for clicks
	local yesEvent = gui.Yes.MouseButton1Click:Connect(function()
		event:Fire(true)
	end
	local noEvent = gui.No.MouseButton1Click:Connect(function()
		event:Fire(false)
	end

	-- Await the first click
	local answer = event.Event:Wait()

	-- Stop caring about clicks to the buttons
	yesEvent:Disconnect()
	noEvent:Disconnect()

	-- Return the answer (`true` for Yes, `false` for No)
	return answer
end

local answer = showMSG(foo)
print("Player said", answer)

2. Promise / Future

Return an object that can be used to produce an answer.

The simplest way to do this is to return an event:

function showMSG(gui)
	gui.Enabled = true

	local event = Instance.new("BindableEvent")

	-- Listen for clicks
	local noEvent, yesEvent

	yesEvent = gui.Yes.MouseButton1Click:Connect(function()
		event:Fire(true)
		yesEvent:Disconnect()
		noEvent:Disconnect()
	end
	noEvent = gui.No.MouseButton1Click:Connect(function()
		event:Fire(false)
		yesEvent:Disconnect()
		noEvent:Disconnect()
	end

	-- Return an event.
	-- The caller of showMSG() must either :Wait() or :Connect()
	-- to get the result
	return event.Event
end

local answer = showMSG(foo):Wait()
print("Player said", answer)

3. Callback / Continuation

When you invoke showMSG, tell it to contact you later.

This is usually the least convenient way to write code because it leads to lots of functions nested into each other, but it is an option.

function showMSG(gui, callback)
	gui.Enabled = true

	local event = Instance.new("BindableEvent")

	-- Listen for clicks
	local noEvent, yesEvent

	yesEvent = gui.Yes.MouseButton1Click:Connect(function()
		yesEvent:Disconnect()
		noEvent:Disconnect()

		callback(true)
	end
	noEvent = gui.No.MouseButton1Click:Connect(function()
		yesEvent:Disconnect()
		noEvent:Disconnect()

		callback(false)
	end
end

showMSG(foo, function(answer)
	print("Player said", answer)
end)

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