I implemented a Lua dialogue system for another video game and thought you might be interested in knowing how it works. It's pretty flexible.
Here's the URL where I discuss it briefly:
http://forums.relicnews.com/showthread.php?263962-Multiple-choice-menuHere's what the code looks like:
DialogueScripts =
{
none =
{
-- the text that appears in the dialogue window (i.e. what the named actor says to the player)
maintext = "You must select a named ship before initiating dialogue.",
-- the respone buttons you may choose from
options =
{
-- once per response
{
-- the text that appears on the response button
buttontext = "Close",
-- the code that gets executed when you click on the response button
buttonaction = function ()
CloseDialogueWindow()
end,
},
},
},
a1 =
{
maintext = "Talk to Shipyard Nabaal first.",
options =
{
{
buttontext = "Okay!",
buttonaction = function ()
CloseDialogueWindow()
end,
},
},
},
a2 =
{
maintext = "Goodbye as well.",
options =
{
{
buttontext = "Okay!",
buttonaction = function ()
CloseDialogueWindow()
end,
},
},
},
b1 =
{
maintext = "I am Shipyard Nabaal. My friend Captain Soban is unfortunately not very talkative.",
options =
{
{
buttontext = "Okay!",
buttonaction = function ()
HasTalkedToElohim = 1
UpdateDialogueStatus("ElohimGroup")
end,
},
},
},
b2 =
{
maintext = "Now that we've spoken, I must say goodbye.",
options =
{
{
buttontext = "Okay!",
buttonaction = function ()
HasSaidGoodbyeToElohim = 1
CloseDialogueWindow()
end,
},
},
},
}
ActorsScripts =
{
-- actor "none" used as a fallback if something goes wrong
none = function ()
-- tells the game that the "none" dialogue script should be spawned
DialogueStatus.current = "none"
end,
-- actor "Soban"
SobanGroup = function ()
-- if you've already spoken to actor Elohim, proceed to script "a2"
if (HasSaidGoodbyeToElohim == 1) then
DialogueStatus.current = "a2"
-- else, stick with "a1"
else
DialogueStatus.current = "a1"
end
end,
-- actor Elohim
ElohimGroup = function ()
-- if you've already spoken to actor Elohim, proceed to script "b2"
if (HasTalkedToElohim == 1) then
DialogueStatus.current = "b2"
-- else, stick with "b1"
else
DialogueStatus.current = "b1"
end
end,
}
What happens is:
1. The ActorsScripts table contains code for each actor (e.g. the named important people, Elohim and Soban) that gets executed when a particular actor is selected and dialogue is initiated. For instance, if you are speaking to the actor Soban then the SobanGroup code is executed. This code determines which dialogue script is should be spawned depending on an arbitrary set of global quest variables (e.g. HasTalkedToElohim, HasSaidGoodbyeToElohim).
2. The DialogueScripts table contains the spoken text strings that appear in the dialogue window and response buttons. It also contains the code that gets executed when you click on one of the responses. This code usually advances the global quest variables to a newer state so that duplicate responses are not initiated.
Sorry if my explanation is confusing...

Because I was lazy the code example I provided only contains a single response to each message. But, more than one response is of course possible.
Also, I omitted the code that alters the physical display window and shows the actual dialogues to the player.
Lastly, you should notice the "none" entries in both tables. This is in case a non-named (i.e. unimportant) actor is selected by accident or due to a bug. I.e. the code falls back to "none" when something goes wrong.
[edit]
Removed some code from the example that wasn't really necessary to show.