How to make Player able to Chat again when Near NPC Without Problems?

hey guys

so today, i have a pretty annoying problem on my hands, and i want to see if anybody can help me out.

i have been trying to make a rpg chat based system, and its been going pretty well.

Its just that i’ve been trying to make it where when the player is done chatting to the npc, the chat resets, and you would be able to chat to the npc again. well, this was tried, but the attempt at it had failed really bad.

here is the attempt I had made to doing so (When the text says ‘Second Sentence’, that is the last sentence in the chat, then the player is supposed to press space to exit out, but instead the whole conversation just decides to repeat itself.) :

See that? it just keeps on repeating, and i hate the fact that it is doing that.

here is the code for chatting to the npcs:

local plr = game:GetService('Players').LocalPlayer
local chr = plr.Character or plr.CharacterAdded:Wait()
local TypewriteGraphic = plr.PlayerGui:WaitForChild('Typewriter')
local Typewriter = require(TypewriteGraphic.Frame.Typewriter)

local CanClick = TypewriteGraphic.Frame.CanClick
local Log = TypewriteGraphic.Frame.Typewriter.Log

local rootpart = chr:WaitForChild('HumanoidRootPart')
local UserInputService = game:GetService('UserInputService')
local RunService = game:GetService('RunService')

local detectednpc = nil
local persondetected = false

local counter = 0
local peoplefolder = workspace:WaitForChild('NPCS')

-- Start Chat --

UserInputService.InputBegan:Connect(function(input, process)
	if process then return end

	if (input.KeyCode == Enum.KeyCode.Space) then
		if persondetected then
			if detectednpc ~= nil then
				local attribute = detectednpc:GetAttribute('Person')
				local lines
				local maxlines
				
				if Log.Value ~= '' then
					TypewriteGraphic.Enabled = true
					coroutine.resume(coroutine.create(function()
						if plr.PlayerScripts:FindFirstChild('ControlScript') then
							local Controls = require(plr.PlayerScripts:WaitForChild('ControlScript'))
							Controls:Disable()
						elseif plr.PlayerScripts:FindFirstChild('PlayerModule') then
							local Controls = require(plr.PlayerScripts:WaitForChild('PlayerModule')):GetControls()
							Controls:Disable()
						else
							return nil
						end
					end))
				end

				if Log.Value == '' and CanClick.Value ~= false then
					CanClick.Value = false
					TypewriteGraphic.Enabled = false
					TypewriteGraphic.Frame.Text.Text = ''
					coroutine.resume(coroutine.create(function()
						if plr.PlayerScripts:FindFirstChild('ControlScript') then
							local Controls = require(plr.PlayerScripts:WaitForChild('ControlScript'))
							Controls:Enable()
						elseif plr.PlayerScripts:FindFirstChild('PlayerModule') then
							local Controls = require(plr.PlayerScripts:WaitForChild('PlayerModule')):GetControls()
							Controls:Enable(true)
						else
							return nil
						end
					end))
				end

				-- All lines of People In Game --
				-- Cat --

				if Log.Value == 'Cat1' and CanClick.Value ~= false and (attribute == 'Cat') then
					lines = detectednpc.Logs.FirstLog.Lines
					maxlines = detectednpc.Logs.FirstLog.Max.MaxLines

					-- Set person logs --
					CanClick.Value = false
					print(attribute)
					counter += 1
					print(counter)
					
					if counter == 1 then
						Typewriter:Typewrite(TypewriteGraphic.Frame.Text, lines.Line1.Value, attribute)
					end
					if counter == maxlines.Value - 1 then
						counter = 0
						detectednpc = nil
						persondetected = false
						Log.Value = ''
						Typewriter:Typewrite(TypewriteGraphic.Frame.Text, lines.Line2.Value, attribute)
					end
					
				end
			else
				warn('Cannot typewrite text, Unknown person.')
			end

		else
			return
		end
	end
end)

--[[

-- Continue Chat --

UserInputService.InputBegan:Connect(function(input, process)
	if process then return end
	
	if (input.KeyCode == Enum.KeyCode.Return and persondetected and not chatting) then
		
	end
end)

]]

RunService.RenderStepped:Connect(function(dt)
	if not persondetected then
		for i, person in pairs(peoplefolder:GetChildren()) do
			local PersonHumanoid = person:FindFirstChild("Humanoid")
			local PersonRootPart = person:FindFirstChild("HumanoidRootPart")
			detectednpc = person

			if PersonHumanoid and PersonRootPart then
				if (PersonRootPart.Position - rootpart.Position).magnitude < 5 then
					persondetected = true
					Log.Value = detectednpc:GetAttribute('LogType')
					print('in range')
					return
				end
			end
		end
	end
	if persondetected then
		for i, person in pairs(peoplefolder:GetChildren()) do
			local PersonHumanoid = person:FindFirstChild("Humanoid")
			local PersonRootPart = person:FindFirstChild("HumanoidRootPart")

			if PersonHumanoid and PersonRootPart then
				if (PersonRootPart.Position - rootpart.Position).magnitude > 5 then
					persondetected = false
					print('away')
					return
				end
			end
		end
	end
end)

all i want to do is make it where when the whole conversation is over with, the player could be able to chat to the npc again, and as many times as they need or want to, and i just cant figure out how to do it. Maybe you guys could help me out? Please and thank you. Let me know if you need any more info onto what im talking about

I feel like this part is clashing with eachother. When the maxlines.Value == 2 and your counter is on 1. It will pass the first if statement, but then also the second one which resets everything. I guess its supposed to do this but maybe change the reset if statement and put it at the front of the function and don’t check with maxlines.Value - 1 but just the value without subtracting one.

Same thing happens unfortunately. i dont know if giving you a place file would help you more with what im trying to do or not

Yeah i can try to fix it in your place file.

apologies for the wait, was busy doing something else, anyways here is the place file

type writer thing.rbxl (80.2 KB)

Okay i updated your script. I added an if statement after incrementing the counter to see if it hit the limit, and then reset the frame again and the variables. Also made some extra helper functions to make it a bit easier.

local plr = game:GetService('Players').LocalPlayer
local chr = plr.Character or plr.CharacterAdded:Wait()
local TypewriteGraphic = plr.PlayerGui:WaitForChild('Typewriter')
local Typewriter = require(TypewriteGraphic.Frame.Typewriter)

local CanClick = TypewriteGraphic.Frame.CanClick
local Log = TypewriteGraphic.Frame.Typewriter.Log

local rootpart = chr:WaitForChild('HumanoidRootPart')
local UserInputService = game:GetService('UserInputService')
local RunService = game:GetService('RunService')

local detectednpc = nil
local persondetected = false

local counter = 0
local peoplefolder = workspace:WaitForChild('NPCS')

-- Start Chat --
local function EnableMovement()
	coroutine.resume(coroutine.create(function()
		if plr.PlayerScripts:FindFirstChild('ControlScript') then
			local Controls = require(plr.PlayerScripts:WaitForChild('ControlScript'))
			Controls:Enable()
		elseif plr.PlayerScripts:FindFirstChild('PlayerModule') then
			local Controls = require(plr.PlayerScripts:WaitForChild('PlayerModule')):GetControls()
			Controls:Enable(true)
		else
			return nil
		end
	end))
end

local function DisableMovement()
	coroutine.resume(coroutine.create(function()
		if plr.PlayerScripts:FindFirstChild('ControlScript') then
			local Controls = require(plr.PlayerScripts:WaitForChild('ControlScript'))
			Controls:Disable()
		elseif plr.PlayerScripts:FindFirstChild('PlayerModule') then
			local Controls = require(plr.PlayerScripts:WaitForChild('PlayerModule')):GetControls()
			Controls:Disable()
		else
			return nil
		end
	end))
end

local function Reset()
	counter = 0
	detectednpc = nil
	persondetected = false
	Log.Value = ''
	TypewriteGraphic.Enabled = false
	TypewriteGraphic.Frame.Text.Text = ''
	CanClick.Value = true
	EnableMovement()
end

UserInputService.InputBegan:Connect(function(input, process)
	if process then return end

	if (input.KeyCode == Enum.KeyCode.Space) then
		if persondetected then
			if detectednpc ~= nil then
				local attribute = detectednpc:GetAttribute('Person')
				local lines
				local maxlines
				
				if Log.Value ~= '' then
					TypewriteGraphic.Enabled = true
					DisableMovement()
				end

				if Log.Value == '' and CanClick.Value ~= false then
					print()
					CanClick.Value = false
					TypewriteGraphic.Enabled = false
					TypewriteGraphic.Frame.Text.Text = ''
					EnableMovement()
				end

				-- All lines of People In Game --
				-- Cat --

				if Log.Value == 'Cat1' and CanClick.Value ~= false and (attribute == 'Cat') then
					lines = detectednpc.Logs.FirstLog.Lines
					maxlines = detectednpc.Logs.FirstLog.Max.MaxLines
					print(counter, maxlines.Value)
					
					-- Set person logs --
					CanClick.Value = false
					counter += 1
					print(counter)
					
					if counter == maxlines.Value then
						Reset()
						return
					end
					
					if counter == 1 then
						Typewriter:Typewrite(TypewriteGraphic.Frame.Text, lines.Line1.Value, attribute)
					end
					if counter == maxlines.Value - 1 then
						Typewriter:Typewrite(TypewriteGraphic.Frame.Text, lines.Line2.Value, attribute)
					end
				end
			else
				warn('Cannot typewrite text, Unknown person.')
			end

		else
			return
		end
	end
end)

--[[

-- Continue Chat --

UserInputService.InputBegan:Connect(function(input, process)
	if process then return end
	
	if (input.KeyCode == Enum.KeyCode.Return and persondetected and not chatting) then
		
	end
end)

]]

RunService.RenderStepped:Connect(function(dt)
	if not persondetected then
		for i, person in pairs(peoplefolder:GetChildren()) do
			local PersonHumanoid = person:FindFirstChild("Humanoid")
			local PersonRootPart = person:FindFirstChild("HumanoidRootPart")
			detectednpc = person

			if PersonHumanoid and PersonRootPart then
				if (PersonRootPart.Position - rootpart.Position).magnitude < 5 then
					persondetected = true
					Log.Value = detectednpc:GetAttribute('LogType')
					print('in range')
					return
				end
			end
		end
	end
	if persondetected then
		for i, person in pairs(peoplefolder:GetChildren()) do
			local PersonHumanoid = person:FindFirstChild("Humanoid")
			local PersonRootPart = person:FindFirstChild("HumanoidRootPart")

			if PersonHumanoid and PersonRootPart then
				if (PersonRootPart.Position - rootpart.Position).magnitude > 5 then
					persondetected = false
					print('away')
					return
				end
			end
		end
	end
end)
1 Like

Thank you so much man, your a life saver. this has been stressing me out since 3pm in the afternoon :sob:

Glad i could help! I saw that there was one more line in your Logs folder, if you also want that line to display then you can move the if statement that resets everything before the line that increments the count. You can also index the line with the current counter so you don’t have to hardcode anything, just have to keep the names the same.

if Log.Value == 'Cat1' and CanClick.Value ~= false and (attribute == 'Cat') then
					lines = detectednpc.Logs.FirstLog.Lines
					maxlines = detectednpc.Logs.FirstLog.Max.MaxLines
					print(counter, maxlines.Value)
					
					if counter == maxlines.Value then
						Reset()
						return
					end
					
					-- Set person logs --
					CanClick.Value = false
					counter += 1
					print(counter)
					
					Typewriter:Typewrite(TypewriteGraphic.Frame.Text, lines["Line"..counter].Value, attribute)
				end
1 Like

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