Skip to main content

Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
TagsGame Engines

Streamlining Dialogue Trees?

A topic by tinyfossil created 5 days ago Views: 106 Replies: 3
Viewing posts 1 to 4
(2 edits) (+1)

Hi All!

I wanted to see if anyone had suggestions on how I can streamline some of my dialogue scenes, the way I'm doing it works but is so clunky and makes it difficult to make adjustments to. Here is a sample scene from better context.

I hope this isn't too confusing or that I'm missing something huge here, but I started off thinking I could just use dd.ask[] inside dd.chat. But no matter how I did it that just wasn't working.

r:dd.ask["What were you looking for?"("You.","Love","What are you reading?","Nevermind...")]
if r~0
//dialogue scene
//g:dd.ask["1","2","3"]
//if g~1 I want to trigger alerts and toggle values
//else other dialogue if r~1
//And so on... 

So my solution was to make a ton of invisible fields and just have them evaluate them instead, but now I have 10 different fields to go between for one scene which is difficult to edit and debug:

r:dd.ask["What were you looking for?"("You.","Love","What are you reading?","Nevermind...")]
if r~0
    dd.say[ask.value]
    eval[field2.text () 1]
  else if r~1
     dd.say[ask3.value]
     dd.close[]
     pt.clear[]
else if r~2
    dd.say[ask4.value]
    dd.close[]
    pt.clear[]
else
    dd.say[ask5.value]
    ver1.toggle["none"]
end
dd.close[]
pt.clear[]
end
end
end

I hope this makes any sense, I think playing through the scene I attached will explain it better than I can articulate :')

Anything helps!

Developer(+3)

Well, if a dialog tree is complicated and contains many unique behaviors, the code may tend to be complicated. I do have a few suggestions that might help:

One thing I notice is that you're writing alternate conditional cases as "else if" instead of using the "elseif" keyword; the former nests conditionals (and requires a stack of matching "end"s) and the latter allows you to write a flatter sequence:

# nested:
if C1 B1 else if C2 B2 else if C3 B3 else B4 end end end
# flat:
if C1 B1 elseif C2 B2 elseif C3 B3 else B4 end

I don't recommend using eval[] on the text of fields to structure reusable pieces of code when you can help; it's usually clearer (and less surprising) to define functions and call them. Instead of:

eval[field2.text () 1]

You could consider

asklove[]

With a definition further down in your script:

on asklove do
 # ...
end

Instead of dispatching like so:

r:dd.ask[ ... ]
if r~0
 dd.say[ask0.value]
elseif r~1
 dd.say[ask1.value]
else
 dd.say[ask2.value]
end

It may be easier to index into a list of widgets:

dd.say[(ask0,ask1,ask2)[r].value]

This doesn't necessarily work when, as in your case, each response has somewhat different logic behind it, but it might be possible to abstract some of those differences into custom dialogizer commands, like the "!light" and "!dark" commands you're using to adjust dialog box styles. Even better might be to use semantically relevant widget names so it's easier to remember what's happening where:

dd.say[(askAboutLove,askAboutYou,askAboutReading,iHaveToGo)[r].value]

I took a crack at reworking the script in the "button1" widget in your example deck, applying some of the above ideas:

on click do
 o.size:180,0
 o.pos:"pos2"
 o.osound:"click"
 o.asound:"click"
 o.tsound:("talk1","moan2","talk3")
 o.speed:3
 dd.style[o]
 dd.open[deck o]
 dd.say[script.value]
 r:dd.ask["What were you looking for?"
  ("You.","Love","What are you reading?","Nevermind...")
 ]
 dd.say[(ask,ask3,ask4,ask5)[r].value]
 if r~0 askyou[] end
 dd.close[]
 pt.clear[]
end
on askyou do
 r:dd.ask["Sarah: and now the site doesn't get much traffic."
  ("Why did it go down?","You do seem like you'd have a low satisfaction score","*say nothing*")
 ]
 dd.say[(ask6,ask2,ask5)[r].value]
 if r~0
  trigger.value:1
  alert["SARAH gave you 'archive artifact'"]
 end
end

You could consider further simplifying the askyou[] function here by making the "give artifact" bit into a custom command, and just having something like

!giveartifact

In the text of the "ask6" field. With askyou[] simplified further, you might just inline it:

on click do
 o.size:180,0
 o.pos:"pos2"
 o.osound:"click"
 o.asound:"click"
 o.tsound:("talk1","moan2","talk3")
 o.speed:3
 dd.style[o]
 dd.open[deck o]
 dd.say[script.value]
 r:dd.ask["What were you looking for?"
  ("You.","Love","What are you reading?","Nevermind...")
 ]
 dd.say[((ask,ask3,ask4,ask5)[r]).value]
 if r~0
  r:dd.ask["Sarah: and now the site doesn't get much traffic."
   ("Why did it go down?","You do seem like you'd have a low satisfaction score","*say nothing*")
  ]
  dd.say[((ask6,ask2,ask5)[r]).value]
 end
 dd.close[]
 pt.clear[]
end

Make sense? Does that help at all?

(+2)

Yes very very helpful! Anything that makes it less chaotic helps tremendously <3 

Thank you!

Developer(+1)

Here's another idea: define this helper function in the deck-level script:

on qa ...x do
 a:raze table 2 window 1 drop x
 r:dd.ask[first x keys a]
 dd.say[(range a)[r].value]
 r
end

It takes a prompt and then alternating pairs of choices and references to the field containing the ensuing scene, allowing you to write that main script like:

on click do
 o.size:180,0
 o.pos:"pos2"
 o.osound:"click"
 o.asound:"click"
 o.tsound:("talk1","moan2","talk3")
 o.speed:3
 dd.style[o]
 dd.open[deck o]
 dd.say[script.value]
 r:qa["What were you looking for?"
  "You."                  ask 
  "Love"                  ask3
  "What are you reading?" ask4
  "Nevermind..."          ask5
 ]
 if r~0
  qa["Sarah: and now the site doesn't get much traffic."
   "Why did it go down?"                                  ask6
   "You do seem like you'd have a low satisfaction score" ask2
   "*say nothing*"                                        ask5
  ]
 end
 dd.close[]
 pt.clear[]
end

Anywhere your code has repetitive patterns, there's a chance that a helper function could make things more concise and easier to edit.