How to make a NPC Chat system with custom sound and camera manipulation!

Before starting create a dummy rig in a folder in workspace called NPCs, next add in a gui in startergui and customize it but make sure to add a promptlabel, linelabel, and a folder called sounds next add two sounds into the folder and call them click and talk then add a local script into the gui and paste these lines of code into it:

local RunService = game :GetService( “RunService” )
local UserInputService = game :GetService( “UserInputService” )
local Players = game :GetService( “Players” )
local DetectedNPC = nil
local Detected = false
local Chatting = false
local Skip = false
local Exit = false
local Player = Players.LocalPlayer
local Camera = game .Workspace.CurrentCamera
local Gui = script .Parent
local Sounds = Gui.Sounds
local PromptLabel = Gui.PromptLabel
local LineLabel = Gui.LineLabel
local Character = Player.Character or Player.CharacterAdded: Wait ()
local CharacterHumanoidRootPart = Character:WaitForChild( “HumanoidRootPart” )
local NPCS = game .Workspace:WaitForChild( “NPCS” )
UserInputService.InputBegan:Connect( function (Input)
if Input.KeyCode == Enum .KeyCode.X then
if Chatting == true then
Skip = true
Sounds.Click: Play ()
end
end
end )

UserInputService.InputBegan:Connect( function (Input)
if Input.KeyCode == Enum .KeyCode.Z then
if Chatting == true then
Exit = true
Sounds.Click: Play ()
end
end
end )

UserInputService.InputBegan:Connect( function (Input)
if Input.KeyCode == Enum .KeyCode.E then
if Detected == true then
local Lines = DetectedNPC:FindFirstChild( “Lines” )
if Lines then
Sounds.Click: Play ()
Chatting = true
Detected = false
LineLabel.Text = “”
PromptLabel:TweenSize( UDim2 .new( 0 , 0 , 0 , 0 ,), “Out” “Linear” , 0 . 2 )
LineLabel:TweenPosition( UDim2 .new( 0 , 0 , 0 . 8 , 0 ,), “In” “Linear” , 0 . 2 )
wait ( 0 . 5 )
for i, Line in pairs (Lines:GetChildren()) do
for i = 1 text do
LineLabel.Text = string.sub (Text, 1 , i)
Sounds.Talk: Play ()
if Skip == true then
Skip = false
LineLabel.Text = Text
b reak
end
if Exit == true then
b reak
end
end
wait ( 0 . 07 )
end
if Exit == true then
Exit = false
b reak
end
repeat wait () until Skip == true or Exit == true
Skip = false
end
Exit = false
Skip = false
PromptLabel:TweenSize( UDim2 .new( 0 , 0 , 0 , 0 ,), “Out” “Linear” , 0 . 2 )
LineLabel:TweenPosition( UDim2 .new( 0 , 0 , 1 . 2 , 0 ,), “Out” “Linear” , 0 . 2 )
wait ( 0 . 5 )
Chatting = false
Detected = false
end
end
end
end )

RunService.RenderStepped:Connect( function ()
if Detected == true and Chatting == false then
local Humanoid = DetectedNPC:FindFirstChild( “Humanoid” )
local HumanoidRootPart = Character:FindFirstChild( “HumanoidRootPart” )
if Humanoid and HumanoidRootPart then
Camera.CameraType = Enum .CameraType.Scriptable
Camera. CFrame = Camera. CFrame : Lerp (HumanoidRootPart. CFrame ***** CFrame . new (- 4 , 4 , - 7 ) ***** CFrame .fromOrientation( math . rad ( 215 ), 0 ), 0 . 07 )
end
else
Camera.CameraType = Enum .CameraType.Custom
end
end )

then add a folder into your rig and call it lines then add a string value called line1, for the value type what you want the npc to say.

then it should be done and working :slight_smile: (sorry if my code is messy I’m not that good)

5 Likes

Looks cool, but you might want to put the script in this format.

local RunService = game :GetService( “RunService” )
local UserInputService = game :GetService( “UserInputService” )
local Players = game :GetService( “Players” )
local DetectedNPC = nil
local Detected = false
local Chatting = false
local Skip = false
local Exit = false
local Player = Players.LocalPlayer
local Camera = game .Workspace.CurrentCamera
local Gui = script .Parent
local Sounds = Gui.Sounds
local PromptLabel = Gui.PromptLabel
local LineLabel = Gui.LineLabel
local Character = Player.Character or Player.CharacterAdded: Wait ()
local CharacterHumanoidRootPart = Character:WaitForChild( “HumanoidRootPart” )
local NPCS = game .Workspace:WaitForChild( “NPCS” )
UserInputService.InputBegan:Connect( function (Input)
if Input.KeyCode == Enum .KeyCode.X then
if Chatting == true then
Skip = true
Sounds.Click: Play ()
end
end
end )

UserInputService.InputBegan:Connect( function (Input)
if Input.KeyCode == Enum .KeyCode.Z then
if Chatting == true then
Exit = true
Sounds.Click: Play ()
end
end
end )

UserInputService.InputBegan:Connect( function (Input)
if Input.KeyCode == Enum .KeyCode.E then
if Detected == true then
local Lines = DetectedNPC:FindFirstChild( “Lines” )
if Lines then
Sounds.Click: Play ()
Chatting = true
Detected = false
LineLabel.Text = ""
PromptLabel:TweenSize( UDim2 .new( 0 , 0 , 0 , 0 ,), “Out” “Linear” , 0 . 2 )
LineLabel:TweenPosition( UDim2 .new( 0 , 0 , 0 . 8 , 0 ,), “In” “Linear” , 0 . 2 )
wait ( 0 . 5 )
for i, Line in pairs (Lines:GetChildren()) do
for i = 1 #Text do
LineLabel.Text = string.sub (Text, 1 , i)
Sounds.Talk: Play ()
if Skip == true then
Skip = false
LineLabel.Text = Text
b reak
end
if Exit == true then
b reak
end
end
wait ( 0 . 07 )
end
if Exit == true then
Exit = false
b reak
end
repeat wait () until Skip == true or Exit == true
Skip = false
end
Exit = false
Skip = false
PromptLabel:TweenSize( UDim2 .new( 0 , 0 , 0 , 0 ,), “Out” “Linear” , 0 . 2 )
LineLabel:TweenPosition( UDim2 .new( 0 , 0 , 1 . 2 , 0 ,), “Out” “Linear” , 0 . 2 )
wait ( 0 . 5 )
Chatting = false
Detected = false
end
end
end
end )

RunService.RenderStepped:Connect( function ()
if Detected == true and Chatting == false then
local Humanoid = DetectedNPC:FindFirstChild( “Humanoid” )
local HumanoidRootPart = Character:FindFirstChild( “HumanoidRootPart” )
if Humanoid and HumanoidRootPart then
Camera.CameraType = Enum .CameraType.Scriptable
Camera. CFrame = Camera. CFrame : Lerp (HumanoidRootPart. CFrame ***** CFrame . new (- 4 , 4 , - 7 ) ***** CFrame .fromOrientation( math . rad ( 215 ), 0 ), 0 . 07 )
end
else
Camera.CameraType = Enum .CameraType.Custom
end
end )

It will make it easier to copy.

4 Likes

Sorry it took me a while to respond but thanks for the advice, I will

2 Likes

Indent your code please and thank you

1 Like