I need help with my dialoge module!

I am making a module script that can make any text with options, with any text tree.

Here is what it looks like so far:

I have made it so there can be a riddle and one of the questions can be the correct answer and a custom function of the user’s choice will be fired, however I am trying to make it a textbox question.

I have made all the code except I am stuck on finding out when the player has stopped typing, and it checks if the answer is correct. Could you help me?

Here is a video of what it currently looks like:

Lastly here is the code, please keep in mind this is suppose to be very moduler and can be used by anyone including you.

-- ModuleScript: DialogueModule
-- Made by @The_codeMachine

local module = {}

function module.CreateDialogueSystem(agentName, agentImageId, player, correctAnswer, onCorrectAnswer)
	local DialogueSystem = {}

	local dialogueGui = player.PlayerGui.DialougeGui.BackgroundFrame

	local InformationBoxFrame = dialogueGui:WaitForChild("InformationBoxFrame")
	local AgentImage = InformationBoxFrame:WaitForChild("AgentImage")
	local AgentNameLabel = InformationBoxFrame:WaitForChild("AgentName")

	local TextBackgroundFrame = dialogueGui:WaitForChild("TextBackgroundFrame")
	local ChatText = TextBackgroundFrame:WaitForChild("ChatText")

	local OptionsFrame = dialogueGui:WaitForChild("OptionsFrame")
	local OptionTemplate = OptionsFrame:WaitForChild("OptionTemplate")
	
	local AnswerTextBox = dialogueGui:WaitForChild("AnswerTextBox")

	local lastClickTime = 0
	local typewriterInProgress = false
	local lastDisplayedText = ""

	function DialogueSystem.TypeWriterEffect(text, delay)
		typewriterInProgress = true
		for i = 1, #text do
			if not typewriterInProgress then
				break
			end
			ChatText.Text = text:sub(1, i)
			wait(delay)
		end
		typewriterInProgress = false
	end

	function DialogueSystem.DisplayDialogue(dialogue)
		-- Display agent information
		AgentImage.Image = "rbxassetid://" .. agentImageId
		AgentNameLabel.Text = agentName

		for i, optionButton in pairs(OptionsFrame:GetChildren()) do
			if optionButton:IsA("TextButton") and optionButton.Visible ~= false then
				optionButton:Destroy()
			end
		end

		-- Check if it's a textbox question
		--local isTextboxQuestion = dialogue.isTextboxQuestion or false

		-- Check if there are options
		if dialogue.options then
			-- Display options using OptionTemplate
			for option, nextDialogue in pairs(dialogue.options) do
				local newOption = OptionTemplate:Clone()
				newOption.Parent = OptionsFrame
				newOption.Text = option
				newOption.Visible = true
				newOption.MouseButton1Click:Connect(function()
					local currentTime = tick()
					if currentTime - lastClickTime < 0.3 then  -- Check for double-click within 0.3 seconds
						-- Skip the typewriter effect and display the entire text
						ChatText.Text = dialogue.text or ""
					else
						if nextDialogue then
							if option == correctAnswer then
								-- Check if the selected option is the correct answer
								if onCorrectAnswer then
									onCorrectAnswer()

									-- Check if it's a textbox question
									--[[local isTextboxQuestion = nextDialogue.isTextboxQuestion or false
									if isTextboxQuestion then
										OptionsFrame.Visible = false
										AnswerTextBox.Visible = true

										-- Use UserInputService.InputEnded instead of FocusLost
										local inputService = game:GetService("UserInputService")
										local connection
										connection = inputService.InputEnded:Connect(function(input, isProcessed)
											if input.UserInputType == Enum.UserInputType.MouseButton1 then
												connection:Disconnect()  -- Disconnect the event after it's handled
												local userAnswer = AnswerTextBox.Text
												if userAnswer == correctAnswer then
													-- Handle correct answer
													if onCorrectAnswer then
														onCorrectAnswer()
													end
												end
												-- Clear the TextBox
												AnswerTextBox.Text = ""
												-- Continue with the dialogue or handle as needed
												dialogueGui.Visible = false
											end
										end)
										return -- Stop further execution for this option
									end--]]
								end
							end
							
							local isTextboxQuestion = nextDialogue.isTextboxQuestion or false
							if isTextboxQuestion then
								OptionsFrame.Visible = false
								AnswerTextBox.Visible = true
								
								-- Use UserInputService.InputEnded instead of FocusLost
								local inputService = game:GetService("UserInputService")
								local connection
								connection = inputService.InputEnded:Connect(function(input, isProcessed)
									if input.UserInputType == Enum.UserInputType.MouseButton1 then
										connection:Disconnect()  -- Disconnect the event after it's handled
										local userAnswer = AnswerTextBox.Text
										if userAnswer == correctAnswer then
											-- Handle correct answer
											if onCorrectAnswer then
												onCorrectAnswer()
											end
										end
										-- Clear the TextBox
										AnswerTextBox.Text = ""
										-- Continue with the dialogue or handle as needed
										dialogueGui.Visible = false
									end
								end)
								
								return -- Stop further execution for this option
							end
							
								
							-- If it's not a textbox question or a correct answer, hide the TextBox
							if not isTextboxQuestion then
								AnswerTextBox.Visible = false
								OptionsFrame.Visible = true								
							end

							DialogueSystem.DisplayDialogue(nextDialogue)
						else
							-- End of dialogue or handle as needed
							dialogueGui.Visible = false
						end
					end
					lastClickTime = currentTime
				end)
			end
		end

		-- Make the GUI visible with a Tween
		dialogueGui.Visible = true
		dialogueGui.Position = UDim2.new(0, 0, 1, 0)  -- Initial position below the screen
		dialogueGui:TweenPosition(UDim2.new(0, 0, 0, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.5, true)

		-- Apply typewriter effect to ChatText
		if dialogue.text and dialogue.text ~= lastDisplayedText then
			DialogueSystem.TypeWriterEffect(dialogue.text, 0.05)  -- Adjust delay as needed
		end
	end

	return DialogueSystem
end

return module

Here is where I need help with:

local inputService = game:GetService("UserInputService")
local connection
connection = inputService.InputEnded:Connect(function(input, isProcessed)
if input.UserInputType == Enum.UserInputType.MouseButton1 then
       connection:Disconnect()  -- Disconnect the event after it's handled
       local userAnswer = AnswerTextBox.Text
	if userAnswer == correctAnswer then
	-- Handle correct answer
	if onCorrectAnswer then
		onCorrectAnswer()
	end
end
-- Clear the TextBox
	AnswerTextBox.Text = ""
-- Continue with the dialogue or handle as needed
dialogueGui.Visible = false
						

Thank you for your time! :slight_smile:
If you need to contact me for more information, please do!
@The_codeMachine

1 Like

Well first, I would try disconnecting the function after the func finishes, add a debounce if the event fires more than once.

Secondly, this code doesn’t make sense.

Let me know if this helped…

1 Like

Oh, that code checks if there is a OnCorrect Answer function, in the varibles of the module when fired, if so fire it, if it is the correct function.

Also I am a big fan of you, with you fixing all those people’s problem, I’m glad it is you that is helping me!

I will try to add what you said, and will contact you when I do!

I believe what you’re looking for is

TextBox.FocusLost:Connect(function()end)

This should activate when the player clicks out or when they press enter.

Sorry, it does not seem to even print anything, here is what I put down:

AnswerTextBox.FocusLost:Connect(function()
        print(11)
        local userAnswer = AnswerTextBox.Text
	if userAnswer == correctAnswer then
		-- Handle correct answer
		if onCorrectAnswer then
			onCorrectAnswer()
		end
    end
end)

It does not print 11.

You’re going to have to break point it, you have too many nested if statements it could be one of those conditional statements that are not allowing it to get to that specific code.

Did you verify that everything else worked? That the conditional statements above it are working properly?

Yes I did verify that all work but for some reason the Lost Focus function will not play in this module script. :frowning:

Focuslost can only be called from the client, whatever the player fills in the Textbox will be empty for the server.

The solution would be to use RemoteEvents or make your module only work in localscripts

If I understand everything correctly, you want to make a TextLabel where the player can type their answer. A possibility could be to check for the UserInputService for when the Enter button is pressed. This can fire a function from the event that will send the answer that the player wrote in the TextLabel to the module. In the module, you can check for the condition to be the same as the required answer. I can show you a rough sketch;

LocalScript

UserInputService.InputBegan:Connect(function(input, gameProcessedEvent)
	if input.KeyCode == Enum.KeyCode.Return then
		local userAnswer = AnswerTextBox.Text
		module.DialogueSystem.PlayerAnswer(userAnswer) --//Path correctly
	end
	AnswerTextBox.Text = " "
end)
	

ModuleScript

function DialogueSystem.PlayerAnswer(answer)
	if string.find(string.lower(answer), "<correct answer>") then --//Make sure it's lowercase
		return print("Good job.")
	else
		return print("Terrible.")
	end
end)

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.