InvokeClient Yield Result Help

Hello, I’ve been trying to make a dialogue script that is setup using InvokeClient() using a local variable. The normal script for it works perfectly fine except for one issue, I want to make it so that in a server script, when a click detector is fired, the script will not continue to pass the other lines until the InvokeClient receives a value that does not equal nil.

Server Script

local cd = script.Parent

cd.MouseClick:Connect(function(player)
	local yes = game.ReplicatedStorage.Requests.clientRequest:InvokeClient(player,"dial",{
		Speaker = "Test";
		Dialogue = "lol this a test";
		One = "ok";
		Two = "lmao"
	})
end)

Local Script

elseif(request == "dial") then
			local gui = assets.SpeakerGui:Clone(); gui.Parent = pGui; local frame = gui.Frame; local dialogue = frame.Dialogue; local speaker = frame.Frame.Speaker; local responses = frame.Responses
			dialogue.Text = ""; speaker.Text = ""; responses.Option1.Text = a1["One"]; responses.Option2.Text = a1["Two"]
			typeWrite(speaker,a1["Speaker"],false); 
			task.delay(2,function()
				typeWrite(dialogue,a1["Dialogue"],true)
				task.wait(1)
				responses.Option1.Active =true; responses.Option2.Active = true
				for i,v in pairs(responses:GetChildren()) do
					if(typeof(v) == "Instance") and(v:IsA("TextButton")) then
						local pos = v.Position
						v.Activated:Connect(function()
							gui:Destroy()
							return v.Name
						end)
						v.MouseEnter:Connect(function()
							v:TweenPosition(pos + UDim2.new(0,0,0.2,0),Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,0.2,true)
						end)
						
						v.MouseLeave:Connect(function()
							v:TweenPosition(pos,Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,0.2,true)
						end)
					end
				end
			end)
		end

You have a couple nested functions that cannot return out of. You need to avoid :Connect and task.delay to get your return value. Since you have multiple options you will have to create a bindable event to wait on one of many events. Use task.wait(2) instead of task.delay(2,

local waitAny = Instance.new("BindableEvent")
for i,v in pairs(responses:GetChildren()) do
    v.Activated:Once(function()
        waitAny.Event:Fire(v.Name)
    end)
    -- etc ...
end

local responseActivated = waitAny.Event:Wait() -- will give the v.Name from waitAny
waitAny:Destroy()
gui:Destroy()
return responseActivated

Look into using RemoteEvents instead. You should not use RemoteFunctions for invoking the client.

RemoteFunctions: Don’t use InvokeClient

2 Likes