Hello! I am currently building an NPC system for my game, and I want it to be fully modular. I am doing this by providing an NPC Name, Initial Message, Camera Instance (to tween the camera to), and a table with the dialouge choices/answers, which appears to not be detected. Below is the code, and I keep getting this error: 15:55:17.533 - Players.aidan1lol.PlayerGui.NPC.LocalScript:13: attempt to index nil with 'Choice1'
Heres the Serverside script, located inside the NPC.
local cd = script.Parent.ScriptablePart.ClickDetector local camPos = script.Parent.CamPos local head = script.Parent.Head local headNormal = script.Parent.NormalPos local headActive = script.Parent.FrontFacingPos local tInfo = TweenInfo.new(.6, Enum.EasingStyle.Quad, Enum.EasingDirection.InOut, 0, false, 0) local dialougeOptions = { -- THIS IS THE TABLE, IT IS NOT BEING SENT! Choice1 = "Where is the TIPR Control Room?"; Choice2 = "What do I do here?"; Answer1 = "You can find the TIPR Control Room in Sector C, to your right!"; Answer2 = "Look around, explore, and Experience the future of energy!" } local ts = game:GetService("TweenService") while wait() do -- Head animation script ts:Create(head, tInfo, {CFrame = headActive.CFrame}):Play() wait(math.random(6,15)) ts:Create(head, tInfo, {CFrame = headNormal.CFrame}):Play() wait(math.random(6,15)) end cd.MouseClick:Connect(function(plr) -- Fires NPC event when clicked game.ReplicatedStorage.NPC:FireClient(plr, "Welcome to the Energy Research Hub!", "Willow Batte", camPos, dialougeOptions) end)
Here is the Client script, which carries out the action. (This is where the error is!)
local ts = game:GetService("TweenService") local tInfo = TweenInfo.new(1, Enum.EasingStyle.Quad, Enum.EasingDirection.InOut, 0, false, 0) local inTween = ts:Create(script.Parent.Frame, tInfo, {Position = UDim2.new(0.067, 0,0.6, 0)}) local outTween = ts:Create(script.Parent.Frame, tInfo, {Position = UDim2.new(0.067, 0, 1, 0)}) local chatting = false game.ReplicatedStorage.NPC.OnClientEvent:Connect(function(msg, name, camInstance, choiceTable) -- NPC Event fired, carries Initial Message, Character name, camera instance to move to, and table with Choices/Answers if not chatting then wait(0.05) for _,v in pairs(workspace.NPCs:GetChildren()) do v.ScriptablePart.ClickDetector.MaxActivationDistance = 0 end print(choiceTable.Choice1) print(choiceTable.Choice2) local ogPos = workspace.Camera.CFrame -- Get original Camera position for use later script.Parent.Frame.DialougeChoice1.Text = choiceTable.Choice1 -- Set Choice Text script.Parent.Frame.DialougeChoice2.Text = choiceTable.Choice2 -- Set Choice Text workspace.Camera.CameraType = "Scriptable" -- Make camera Scriptable ts:Create(workspace.Camera, tInfo, {CFrame = camInstance.CFrame}):Play() -- Move Camera to Position script.Parent.Frame.NPCName.Text = name -- Set NPC Name chatting = true -- Enable this to disable dialouge buttons until fully ready to move on script.Parent.Frame.Message.Text = " " -- Empty msg text inTween:Play() -- Move NPC UI into Frame wait(1) for i = 1, #msg do -- TYPEWRITE MESSAGE script.Parent.Frame.Message.Text = string.sub(msg, 1, i) wait(0.025) end chatting = false -- Enable chat buttons script.Parent.Frame.DialougeChoice1.MouseButton1Click:Connect(function() if chatting == false then chatting = true for i = 1, #choiceTable.Answer1 do -- TYPEWRITE MESSAGE script.Parent.Frame.Message.Text = string.sub(choiceTable.Answer1, 1, i) wait(0.025) end chatting = false end end) script.Parent.Frame.DialougeChoice2.MouseButton1Click:Connect(function() -- Choice 2 selected if chatting == false then chatting = true for i = 1, #choiceTable.Answer2 do -- TYPEWRITE MESSAGE script.Parent.Frame.Message.Text = string.sub(choiceTable.Answer2, 1, i) wait(0.025) end chatting = false end end) script.Parent.Frame.GoodBye.MouseButton1Click:Connect(function() -- Exit NPC Dialouge outTween:Play() ts:Create(workspace.Camera, tInfo, {CFrame = ogPos}):Play() wait(1) workspace.Camera.CameraType = "Custom" for _,v in pairs(workspace.NPCs:GetChildren()) do v.ScriptablePart.ClickDetector.MaxActivationDistance = 32 end end) end end)
I don't really know if it will work or not. But, I'll recommend to keep MouseClick
Event above of while
loop. This is how your script might look :
local cd = script.Parent.ScriptablePart.ClickDetector local camPos = script.Parent.CamPos local head = script.Parent.Head local headNormal = script.Parent.NormalPos local headActive = script.Parent.FrontFacingPos local tInfo = TweenInfo.new(.6, Enum.EasingStyle.Quad, Enum.EasingDirection.InOut, 0, false, 0) local dialougeOptions = { -- THIS IS THE TABLE, IT IS NOT BEING SENT! Choice1 = "Where is the TIPR Control Room?"; Choice2 = "What do I do here?"; Answer1 = "You can find the TIPR Control Room in Sector C, to your right!"; Answer2 = "Look around, explore, and Experience the future of energy!" } cd.MouseClick:Connect(function(plr) -- Fires NPC event when clicked game.ReplicatedStorage.NPC:FireClient(plr, "Welcome to the Energy Research Hub!", "Willow Batte", camPos, dialougeOptions) end) local ts = game:GetService("TweenService") while wait() do -- Head animation script ts:Create(head, tInfo, {CFrame = headActive.CFrame}):Play() wait(math.random(6,15)) ts:Create(head, tInfo, {CFrame = headNormal.CFrame}):Play() wait(math.random(6,15)) end
Lemme know if it works!