So I have bit of weird problem. This is one section from my modulescript “DIAGHelper” which is a modulescript that handles dialogue system in my story game. I have other functions like TweenIn and TweenOut which would slide dialogue UI in-game in and out.
The real issue tho, I have this approach which is explained briefly in script. Upon joining, there’s automated intro dialogue (it have 10 lines in array), and when I clicked a object as trigger for random multiple-page dialogue sequence, it WOULDN’T work and have this bug where it would show the intro dialogue instead of the actual dialogue after clicking > button. This can be seen in clip below:
IT would get more nonsensical after more consecutive clicks which shows it’s probably skipping in index or something like that.
(I’m pretty sure this is probably scoping issue but I don’t know how to fix this)
Now if i change local dialogueIndex = 1 to local dialogueIndex = nil as to attempt close it after completion (as seen in the script with comment -- change to nil in second video example, this would happen:
What? It would work except there’s error in output and I don’t have any prior experience in modulescript, this is literally my first time because I am trying to learn from it and try something new. How would I fix this and is there any feedbacks any of you would have for me to improve upon my code?
--[[
So, we have DIAG Write function here.
p is for "paragraph", or aka single-page
where script would default to assuming there's no "room".
Room is multi-page, seen after beating room and
entering to next as to drive the story further.
]]
function DIAGHelper.Write(player,p,room)
if not (room == nil) then
local dialogueIndex = 1
local Pages = #Rooms[room]
DIAGHelper.TweenIn()
TX.Text = Rooms[room][dialogueIndex]
--print(dialogueIndex)
DIAG.GO.MouseButton1Down:Connect(function()
if dialogueIndex == Pages then
print("The end is reached.")
DIAGHelper.TweenOut()
dialogueIndex = 1 -- change to nil in second video example
return
end
dialogueIndex += 1
local dialogue = Rooms[room][dialogueIndex]
TX.Text = dialogue
end)
else
-- [Paragraph mode. Ignore.]
DIAGHelper.TweenIn()
TX.Text = p
DIAG.GO.MouseButton1Down:Connect(function()
DIAGHelper.TweenOut()
end)
end
end
The issue you’re describing is a classic state management problem — your dialogueIndex variable isn’t properly isolated between different dialogue sequences, so they’re interfering with each other.Here’s what’s happening: when you use local dialogueIndex = 1 at the module level or within a function that persists, clicking the button increments that same index across all dialogue contexts. When you switch from intro dialogue to your clicked-object dialogue, the index doesn’t reset, so it’s reading from the wrong position in the new array.The fix is straightforward — use a table to track state per dialogue sequence:lualocal DIAGHelper = {}local dialogueStates = {} -- Track active dialogues by IDfunction DIAGHelper:StartDialogue(dialogueArray, dialogueID) dialogueID = dialogueID or "default" -- Initialize state for this specific dialogue dialogueStates[dialogueID] = { index = 1, array = dialogueArray } self:DisplayDialogue(dialogueID)endfunction DIAGHelper:NextLine(dialogueID) dialogueID = dialogueID or "default" local state = dialogueStates[dialogueID] if not state then return end state.index = state.index + 1 if state.index > #state.array then -- Dialogue complete dialogueStates[dialogueID] = nil return end self:DisplayDialogue(dialogueID)endKey changes:- Each dialogue sequence gets its own unique ID (e.g., “intro”, “trigger_001”)- State is stored in a table keyed by that ID, not as a single global index- When dialogue completes, clean up that state entryWhen your button is clicked, call DIAGHelper:NextLine("trigger_001") instead of a generic function. This way, intro dialogue stays on its own index while triggered dialogues maintain theirs independently.If you’re managing multiple simultaneous dialogues, this also scales properly without conflicts.