G’day devs! I’ve been trying to make a Visual Novel Module System (Which could also be used for Dialogue Systems) that will make some tedious tasks easier.
(I still haven’t decided if I should release it or keep it for personal use)
What I currently need help with:
- Improvement in both performance and simplifying the local script side
- Features/Ideas (Mainly how Visual Novels do it)
Do note that I for now only need ideas/feedback on the visual novel service’s dialogue, this still doesn’t include screen VFX or MSX as they will be in a separate module script and can be run using the command runner function.
Local Script Code
local DialogueModule = require(game:GetService("ReplicatedStorage").DialogueModule)
local Dialogue = DialogueModule.CoreFunctions
local Settings = require(game:GetService("ReplicatedStorage").DialogueModule.SettingsModule)
local DialogueArea = script.Parent.DialogueArea
local TxtLabel = DialogueArea.Template.TxtTemplate
local UIS = game:GetService("UserInputService")
local Types = Settings.Type()
local FunctionListTemplate = {
{
["Dialogue"] = {"Aaron", "X-Ray 09"},
["ChangeTxtColor"] = function()
local x = Settings.TextSettings()
x.TxtColor = Color3.fromRGB(37, 161, 255)
return x
end,
},
{
["Dialogue"] = {"I'll just go back to my wonderful nap.", "Tactical airstrike in bound"},
["ChangeTxtColor"] = function()
local x = Settings.TextSettings()
x.TxtColor = Color3.fromRGB(255, 64, 67)
return x
end,
},
{
["Dialogue"] = {"Alpha-1", "air support"},
["ChangeTxtColor"] = function()
local x = Settings.TextSettings()
x.TxtColor = Color3.fromRGB(134, 255, 41)
return x
end,
},
{
["Dialogue"] = {"Alpha-1"},
["ChangeTxtColor"] = function()
local x = Settings.TextSettings()
x.TxtColor = Color3.fromRGB(0, 229, 255)
return x
end,
},
}
local FunctionListTemplate222 = {
{
["Dialogue"] = {"Aaron", "X-Ray 09"},
["ChangeTxtColor"] = function()
warn("EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE")
end,
},
}
local t = 0
local Characters = {
["Character1"] = {
["CharName"] = "Aaron",
["CharID"] = workspace.Aaron,
["CharDesc"] = "",
},
["Character2"] = {
["CharName"] = "Bryan",
["CharID"] = workspace.Bryan,
["CharDesc"] = "",
},
["Character3"] = {
["CharName"] = "S m i l e",
["CharID"] = "rbxassetid://1803736786",
["CharDesc"] = "",
},
}
--[[
local txtcmdlist = Dialogue.CmdSchedule(Statement1, FunctionListTemplate, "Fill")
Dialogue.NewCharacter(Characters["Character2"], "rbxassetid://16265865392")
Dialogue.GenerateText(Statement1, Settings.TextSettings(), txtcmdlist, 1)
Dialogue.TypeWriter(Statement1)
]]
local CurrentlyRunning = false
local db = false
local function Reset()
db = true
Dialogue.EndDialogue()
t = 0
db = false
CurrentlyRunning = false
end
local Cooldown = false
local function CooldownFunc()
task.spawn(function()
if Cooldown == false then
Cooldown = true
wait(1)
Cooldown = false
end
end)
end
Dialogue.LaunchDialogueModule(script.Parent.Parent, script.Parent.DialogueArea, script.Parent.CharacterFrame, script.Parent.Parent.NameFrame, script.Parent.Parent.ChoicesFrame)
UIS.InputBegan:Connect(function(inp)
if inp.KeyCode == Enum.KeyCode.Two then
Dialogue.SkipTypeWriting()
end
if Cooldown == true then return end
if inp.KeyCode == Enum.KeyCode.RightBracket then
CooldownFunc()
if db == true then return end
if CurrentlyRunning then Reset() return end
CurrentlyRunning = true
db = true
local Target = script.Parent.DialogueArea:FindFirstChild("CharacterFrame[2]")
if Target then Target:Destroy() end
Dialogue.StartDialogue()
Dialogue.NewDialogue("Tactical airstrike in bound! This is Alpha-1, We request air support!!! HQ come in!", {["TxtFunctionList"] = FunctionListTemplate}, Characters["Character2"], {["AnimationPose"] = "rbxassetid://16265865392"})
if Dialogue.DialogueWait("10", true) then return end -- 2
Dialogue.ContinueDialogue(" HQ? HQ? Aaron! AAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAA AAAAAAAA AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAA AAAAAAAAAAAAAA AAAAAAAAAA AAAAAAAAAAAAA AAAAAAA",{["TxtFunctionList"] = FunctionListTemplate}, Characters["Character2"], {["AnimationPose"] = "rbxassetid://16265872688"})
if Dialogue.DialogueWait("25", true) then return end -- 5
Dialogue.NewDialogue("Wait, huh?", {["TxtFunctionList"] = FunctionListTemplate}, Characters["Character1"], {["AnimationPose"] = "rbxassetid://16265869308"})
if Dialogue.DialogueWait(10, true) then return end -- 2
Dialogue.NewDialogue("HQ I repeat, Tactical airstrike in bound, we need air support! ", {["TxtFunctionList"] = FunctionListTemplate}, Characters["Character2"], {["AnimationPose"] = "rbxassetid://16265865392"})
if Dialogue.DialogueWait(5, true) then return end -- 5
Dialogue.NewDialogue("Uhm...", {["TxtFunctionList"] = FunctionListTemplate}, Characters["Character1"], {["AnimationPose"] = "rbxassetid://16265869308"})
local Mad = Settings.TextSettings()
Mad.TxtColor = Color3.fromRGB(255, 67, 70)
local ChoicesText = {
{
["ChoiceTxt"] = "Go back to sleep.",
["OutputKey"] = "Sleep",
["TxtSettings"] = Mad,
},
{
["ChoiceTxt"] = "Help an ally!",
["OutputKey"] = "War",
},
}
Dialogue.GenerateChoices(ChoicesText, 3)
Dialogue.ChoicesTransition("Entrance")
Dialogue.ChoicesSelection(function(callbackResult)
if ChoicesText[1]["OutputKey"] == callbackResult then
Dialogue.ChoicesTransition("Exit")
Dialogue.ContinueDialogue(" This ain't my problem. I'll just go back to my wonderful nap.",{["TxtFunctionList"] = FunctionListTemplate}, Characters["Character1"], {["AnimationPose"] = "rbxassetid://16265872688"})
if Dialogue.DialogueWait(2, true) then return end
Dialogue.NewDialogue("Aaron went back to sleep.",{["TxtFunctionList"] = FunctionListTemplate})
CurrentlyRunning = false
db = false
elseif ChoicesText[2]["OutputKey"] == callbackResult then
Dialogue.ChoicesTransition("Exit")
Dialogue.NewDialogue("Aaron stood up and got towards the radio.", {["TxtFunctionList"] = FunctionListTemplate})
if Dialogue.DialogueWait(3, true) then return end
Dialogue.NewDialogue("This is HQ, X-Ray 09, we're sending air support right away!",{["TxtFunctionList"] = FunctionListTemplate}, Characters["Character1"], {["AnimationPose"] = "rbxassetid://16265872688"})
CurrentlyRunning = false
db = false
else
warn("Tried to call nil")
end
end)
end
if inp.KeyCode == Enum.KeyCode.LeftBracket then
Reset()
if Cooldown == false then
CooldownFunc()
Reset()
end
end
end)
Current Features
- Responsive UI (This has a custom responsive UI for the texts)
- Extremely customizable text in dialogue
- Command based on word/phrase/sentence reference (This can be repeated and set a limit)
- Supports both 2D and 3D Characters (it can even be a whole group of 3D characters and if it is a humanoid it supports animation poses or full on animations on general)
- Choices that can branch out
- Extremely customizable punctuation
- Can change emotions/pose (Aka it doesn’t do the character opening transition every time you want to change the emotion/pose)
- Ability to skip dialogue
- ability to continue the dialogue without resetting the previous dialogue
- Cross-platform support (including console)
Current System work in progress:
- Extremely Customizable UI animation/tweening.