Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
0

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

Asked by 7 years ago
Edited 7 years ago

--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

Log in to vote
0
Answered by
BlueTaslem 18071 Moderation Voter Administrator Community Moderator Super Administrator
7 years ago

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)

Ad

Answer this question