Attempt to index number with 'TypeRate'

  1. What do you want to achieve? Keep it simple and clear!
    Hey, I am trying to make a dialogue system for a side project.
  2. What is the issue? Include screenshots / videos if possible!
    I keep getting this error message, and I have tried just about everything in my power to fix it, but it works to no avail.

    2023-12-28 16-46-05
  3. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
    I have tried reading online solutions, though there was nothing that I could find applicable.
    After that, you should include more details if you have any. Try to make your topic as descriptive as possible, so that it’s easier for people to help you!

Here is my client script:

local TweenService = game:GetService("TweenService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local TalkEvent = ReplicatedStorage:WaitForChild("TalkEvent")




local main = script.Parent.Main
local choicesFrame = main.ChoicesFrame
local nameLabel = main.NameFrame.Label
local dialogLabel = main.DialogFrame.Label
local choicesTemplate = script.ChoiceTemplate

local cameraFrame = main.CameraFrame


local currentNPC = nil
local storedChoices = {}

local function typeWrite(text, label, info)
	label.Text = ""
	
	for i, v in text:split("") do
		label.Text = label.Text..v 
		task.wait(info.TypeRate.Value) -- 1200bpm, variable can change
		
	end
	
end

local function endDialog(info)
	for i, child in pairs(choicesFrame:GetChildren()) do
		-- Clears out choices from previous dialogue
		if child:IsA("TextButton") then
			child:Destroy()
		end
	end
	
	typeWrite(info.LeaveMessage, dialogLabel, info.TypeRate)
	
	task.wait(0.5)
	
	currentNPC.HumanoidRootPart.ProximityPrompt.Enabled = true
	task.wait(1)
	main.Visible = false
	nameLabel.Text = ""
	dialogLabel.Text = ""
	storedChoices = {}
	currentNPC = nil
		
end

local function nextDialog(info, lastChoice)
	for i, child in pairs(choicesFrame:GetChildren()) do
		-- Clears out choices from previous dialogue
		if child:IsA("TextButton") then
			child:Destroy()
		end
	end
	
	local dialog 
	if lastChoice then 
		if lastChoice.Next then
			dialog = info.Dialog[lastChoice.Next]
			else 
			endDialog(info)
		end
	else 
		dialog = info.Dialog[1]
	end
	
	if not dialog then return end
	
	typeWrite(info.LeaveMessage, dialogLabel, info.TypeRate)
	
	if dialog.Choices and (#dialog.Choices > 0 or #storedChoices > 0 ) then
		for i, choice in pairs(storedChoices) do
			local clone = choicesTemplate:Clone()
			clone.Parent = choicesFrame
			clone.Name = choice.Text 
			clone.Label.Text = choice.Text
			
			clone.MouseButton1Click:Connect(function()
			storedChoices[i] = nil
			nextDialog(info, choice)
			end)
		end
		for i, choice in pairs(dialog.Choices) do
			local clone = choicesTemplate:Clone()
			clone.Parent = choicesFrame
			clone.Name = choice.Text 
			clone.Label.Text = choice.Text
			
			if choice.Follow == true then
				storedChoices[i] = choice
			end

			clone.MouseButton1Click:Connect(function()
				storedChoices[i] = nil
				nextDialog(info, choice)
			end)
		end
		
		local leaveButton = choicesTemplate:Clone()
		leaveButton.Parent = choicesFrame
		leaveButton.Name = "Leave"
		leaveButton.Label.Text = "Goodbye"
		
		leaveButton.MouseButton1Click:Connect(function()
			-- Ends the conversation + removes the dialogue 
			endDialog(info)
			
		end)
		
	else
		task.wait(1)
		
		if dialog.Next then
			nextDialog(info, dialog)
			else 
			-- Ends the conversation
			endDialog(info)
		end
	end
end

TalkEvent.OnClientEvent:Connect(function(npc, info, cameraCF)
	if currentNPC == nil and npc then
		currentNPC = npc 
		nameLabel.Text = npc.Name 
		dialogLabel.Text = ""
		storedChoices = {}
		
		for i, child in pairs(choicesFrame:GetChildren()) do
			-- Clears out choices from previous dialogue
			if child:IsA("TextButton") then
				child:Destroy()
			end
		end
		if cameraCF then
			npc.HumanoidRootPart.ProximityPrompt.Enabled = false
			
			local camera = Instance.new("Camera")
			local CFrameValue = Instance.new("CFrameValue")
			camera.CameraType = Enum.CameraType.Scriptable
			camera.Parent = cameraFrame
			camera.CFrame = cameraCF 
			
		end
		
		main.Position = UDim2.new(0, 0, 1, 0)
		main.Visible = true
		
		main:TweenPosition(UDim2.new(0, 0, 0, 0))
		
		task.wait(1)
		nextDialog(info, nil)
		
	end
end)

Here is my Info module script:

local Info = {}

Info.LeaveMessage = "Goodbye"
Info.CameraDistance = 3
Info.TypeRate = 0.05

Info.Dialog = {
	[1] = {Text = "Hello, how are you?";
		Choices = { 
			[1] = {Text = "Bad"};
			[2] = {Text = "I'm great, how are you?"; Next = 2}; 
			
			
		}
	};
	[2] = {Text = "I'm decent, thanks for asking";
		Choices = { 
			[1] = {Text = "What's your name?"; Next = 3, Follow = true};
			[2] = {Text = "What's your favorite color?"; Next = 4, Follow = true}; 
		}
	};
	[3] = {Text = "My name is dummy";
		Choices = {
			
		};
	};
	[4] = {Text = "Yellow";
		Choices = {};
	}
	
}

return Info

(there’s another server script used, but i don’t think that it’s needed here)
Thanks in advance for reading this :slight_smile:

4 Likes

in line 26, it must be task.wait(info.Value) i think

1 Like

What is info then, is it a value? or what type of object is it?

1 Like

if i’m not mistaken (i’m a bit rusty), info is the name of the module in the modulescript

2 Likes

image
image
You already accessed TypeRate

you tried to do info.TypeRate.TypeRate.Value

1 Like

if info is inside module it should be like this:

info.TypeRate

if info is not a value but variable

1 Like

info is just the name of the module where i put the values such as TypeRate, CameraDistance and LeaveMessage
honestly the script is probably very messy as i followed a tutorial and was adjusting it for my own needs

1 Like

do i just do ‘task.wait(TypeRate.Value)’ then?

@0786ideal i tried doing that, but it gave the same results

1 Like

change line 40 to typeWrite(info.LeaveMessage, dialogLabel, info)
i think that should fix it

1 Like

sadly enough nothing changed, i think that the problem is in line 26 specifically, which in turn breaks everything else

2 Likes

maybe give us more info, if you would give us a screen of how scripts are placed and what module and main script does, then we should solve your problem

1 Like

@0786ideal here’s the roblox file:
rpg test game.rbxl (92.7 KB)
There are 3 scripts:

  1. a normal script called ‘Server’ which handles everything server-side, such as you clicking the proximity prompt, in Workspace.NPCs.Server
  2. a module called ‘Info’ script in Workspace.NPCs.TestNPC, which just has the basic data unique to any specific NPC (basically just the text that he says, how fast he says it, and how far the ViewportFrame camera from him will be, for future tweaking)
  3. a local script called ‘Client’, in StarterGui.TalkGui (this handles everything client-side, such as the text appearing one-by-one as an effect, you answering the npc, leaving the conversation, etc.)
    I also tried having some basic documentation in the scripts, though it’s probably still quite messy, as I was changing some elements that I took from a tutorial.
    anyway thanks for trying to help me man

i just realized that a friend of mine deleted the spawnpoint, so you’re probably gonna have to place one next to the npc, sorry in advance bro