Dictionary Help (dialogue, items, etc)

I’m creating a small dialogue system from scratch, something simple, no options just little help from the NPCS, or whatever they are. I have two scripts, one is a local script (A) in the player that handles everything dialogue GUI. This is for a short horror game, for me and some friends.

A proximity prompt sents an event to the local script (A) which is this… (i put some helpful tips of my personal solutions to problems that may seem unconvential)

local players = game:GetService("Players")
local player = players.LocalPlayer

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

local gui_fire_event = rs:WaitForChild("Events"):WaitForChild("GUI")
local continue_event = rs:WaitForChild("Events"):WaitForChild("Continue")
local dialogue = require(rs:WaitForChild("Modules"):WaitForChild("dialogue")) -- finds the module script


-- text gui find

local textgui = player:WaitForChild("PlayerGui"):WaitForChild("Text")
local frame = textgui:WaitForChild("Frame")
local name_box = frame:WaitForChild("NameBox")
local text_box = frame:WaitForChild("TextBox")

-- tween positions

local pos_1_s = {Position = UDim2.new(0.125,0,0.721,0)} -- position of the gui up
local pos_1_e = {Position = UDim2.new(0.125,0,1.1,0)} - position of the gui downThis text will be hidden

-- stuff

local nextline = 0

gui_on = false
script_on = false

local function tween_p(tween) -- plays the tweening info
	tween:Play()
	tween.Completed:Wait()
	return
end


local function gui_show()
	if script_on == false then -- debounce
		script_on = true 
		local gui_info = TweenInfo.new(1, Enum.EasingStyle.Exponential, Enum.EasingDirection.In, 0, false)
		print("here")
		
		if gui_on == false then -- puts the gui up
			
			local temp_tween =  ts:Create(textgui.Frame, gui_info, pos_1_s)
			tween_p(temp_tween)
			
			
			gui_on = true
			print("done1")
		
		elseif gui_on == true then -- puts it down
			
			local temp_tween =  ts:Create(textgui.Frame, gui_info, pos_1_e)
			tween_p(temp_tween)
			
			
			gui_on = false
			print("done!2")
		end
		
		task.wait(0.5)	-- wait to prevent it going up and down
		
		script_on = false
	end
end

local function typewrite(text) -- simple typewriter script
	for i = 1, #text, 1 do
		text_box.Text = string.sub(text, 1, i)
		wait(0.05)
	end
end

--
-- continuation scripts
--

local db = false
local gui_up = false

local function onContinue(name, target) 
	
-- these three check if its theres a target, name, or if its down, ik its clunky.

	if target and target ~= "" then -- 
		target.Enabled = false
	end
	
	if name and name ~= "" then
		name_box.Text = name
	end
	
	if gui_up == false then
		gui_show()
		gui_up = true
	end
	
	local char = name_box.Text -- character name achieved from the event fire
	
	if db == false then
		db = true
		nextline += 1 -- changes the line of the dialogue
		local text = dialogue.Statue[tostring(char)][nextline] -- finds the dialogue
		if text ~= "benasss" then -- checks if it isnt the last code, as benasss is used to end  it
			print(text)
			typewrite(text)
		elseif text == "benasss" then -- detects the last line, and ends the script
			
			name_box.Text = " " -- scrapes the label clean for next time
			text_box.Text = " "
			
			nextline = 0 -- resets the line

			
			gui_show() -- puts down the gui
			gui_up = false 
			
		end	
		db = false
	end
end



continue_event.Event:Connect(onContinue) -- fire when the script is clicked/pressed E on the dialogue box
gui_fire_event.OnClientEvent:Connect(onContinue) -- fire when proximity prompt

Heres the short script that handles the proximity prompt:

local gui_event = game:GetService("ReplicatedStorage"):WaitForChild("Events"):WaitForChild("GUI")
local target = script.Parent -- the proximity prompt

local name = "Steve" -- this is just the name of the char, so the dialogue module script knows where it is. 

target.Triggered:Connect(function(plr)
	gui_event:FireClient(plr, name, target)
end)

And here’s the final script, the module script that houses all the dialogue:

local dialogue = {}

dialogue.Statue = {
	["Steve"] = { -- name of the target, which is created by the proximity prompt
		[1] = "Steve is so cool and majestic",
		[2] = "Steve is so cool and majestic and cooler!",
		[3] = "I love cake",
		[4] = "benasss"
	},
	
	["Paul"] = {
		[1] = "I lose my hofner bass guitar in this very scary cave...",
		[2] = "I know, I know, it will be dark... so have this... "
		[3] = "This handy dandy flashlight.. straight from Liverpool..." -- main question 1
	}
}

return dialogue

Quick Look of the Dialogue:

Quick Look at my “Explorer”:

image

I’m fairly new to module scripts, and in general receiving data from them, creating dialogue systems, and also in general sort of scripting, thats why I’m providing the entire script system.

So the main questions:

  1. Is how would I change the dictionary to have it so that in “Paul [3]” it would give a flashlight to the user

  2. How could I better optimise the system so that it doesnt break, crash, etc…

  3. If theres any unnecessary code, or simplier ways to implement them

  4. How would I make it so that, I don’t have to use the keyword, “benasss” to stop the dialogue from progressing, as right now, I use it to tell the main localscript to stop the code and put the gui down.

I would appreciate any sort of help. :heart: :heart: :heart:

(sorry for any typos/spelling)

2 Likes

so, One thing at a time

For the benasss thing, you can instand of detecting a certain word, you can see if the nextline is bigger to the amount of the lines in the dialogue table.

Why?

I noticed that you started with the line 0, since there is no need for that, replace to 1 and we will only add the nextline after being written to make it more logical : )

How?

if db == false then
	db = true
	local text = dialogue.Statue[tostring(char)][nextline] -- finds the dialogue

	if nextline  <= #dialogue.Statue[tostring(char)] then -- checks if the nextline is less or equal than the amount of lines off the dialogue table
		print(text)
		typewrite(text)
        nextline += 1 -- changes the line of the dialogue
	else
		name_box.Text = " " -- scrapes the label clean for next time
		text_box.Text = " "

		nextline = 1 -- resets the line

		gui_show() -- puts down the gui
		gui_up = false 
	end	
	db = false
end

Note: Remember to delete the benasss thing from the dialogues and change nextline to 1

Now to give a flashlight when the index of Paul is 3 is actually pretty simple

First of all the function to give the flashlight, you can put it after all the variables on the local script:

local FlashLight = --Your path to the flashlight

local function GiveFlashLight()
   local newFlashLight = FlashLight:Clone()
   newFlashLight.Parent = player.Backpack
end

now Inside of the piece of the code that I did at the beggining add this:

if db == false then
	db = true
	local text = dialogue.Statue[tostring(char)][nextline] -- finds the dialogue

    if tostring(char) == "Paul" and nextline == 3 then -- if the dialogue is Paul and we are at the index 3
        GiveFlashLight() --Call Function
    end

	if nextline  <= #dialogue.Statue[tostring(char)] then -- checks if the nextline is less or equal than the amount of lines off the dialogue table
		print(text)
		typewrite(text)
        nextline += 1 -- changes the line of the dialogue
	else
		name_box.Text = " " -- scrapes the label clean for next time
		text_box.Text = " "

		nextline = 1 -- resets the line

		gui_show() -- puts down the gui
		gui_up = false 
	end	
	db = false
end

Tell me if you have any errors

1 Like

Hello, thanks for the help!

Since I made the post, I have done some changes to the script but it’s all relatively the same (i seperated the guI_show() funciton into two, because it was really unreliable and it would be easier to make just two).

I’ll totally implement the “benasss” solution to the script, as that’s really helpful, thank you.

However, for the flashlight part, is there any less congestive way to implement? I’m planning to reuse it in future projects and was wondering if theres like a way I could store it in the module, and then write a script that would find the flashlight (or any item in question) in replicated storage and just dispense it. I’ve done it with finding the NPC’s char and subsequent lines, but was wondering how to implement it with the items. I will use it just for this game cause I only need it for the NPC, but would appreciate any further help. Thank you! :heart: :heart: :heart:

Its almost the same, you can create a folder with the Tools in replicatedStorage and put the module in ServerScriptService to prevent hackers from getting the tools, in the module

local ToolsFolder = --Your path to the tools Folder

local module = {}

module.ReturnTool = function(player, toolWanted) --ToolWanted is a string
    local Tool = ToolsFolder:FindFirstChild(toolWanted) --Check for a tool with the name of tollWanted
    if Tool then -- if the tool exists
        local NewTool = Tool:Clone()
        NewTool.Parent = player.Backpack
    end
end

return module

You can use a remoteEvent on the client to call this function

Server:

local Remote = --Your path
local Module = -- Your path to the module

Remote.OnServerEvent:Connect(function(player, tool) --tool is a string
    Module.ReturnTool(player,tool)
end)

And then you can call it anywhere on the client by firing the function and putting the tool you want

Client:

local Remote = --Your path

Remote:FireServer("FlashLight") --needs to have the same name as the tool on the folder
1 Like

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