Adding scenes into dialogue based on previous choices?

Hello everyone!

I'm working on a game currently and I've run into a bit of a head scratcher. Essentially what I'm trying to accomplish is this: I want the player to enter conversation with an NPC, the NPC will ask them a small handful of questions. The (lengthy) conversation will then progress. Then, later on, I would like to have the player's answers come back in the conversation. I figure the easiest way is have them use flags but what I'm having an issue of if having the dialogue tree not turn into a nightmare of boxes in the Quest editor.

When doing the "If object player has flag" y/n rather than having to post the entire conversation under both the Yes and No answers but with the addition of the couple of extra text boxes of dialogue, my idea was to use functions to insert them and then continue the conversation. I tried that and it almost works but the problem is I can't get it to work for more than one line of dialogue. Instead of waiting for the function to finish and then proceeding, after the first wait in the function quest immediately continues with the initial dialogue.

    <object name="Test">
      <inherit name="editor_object" />
      <look type="script">
        msg ("1 I am an apple seller")
        wait {
          msg ("2 I hear you like apples")
          wait {
            ShowMenu ("3 Do you like red apples?", Split("Yes;No", ";"), false) {
              if (result="Yes") {
                msg ("4 YesRed")
                SetObjectFlagOn (player, "Red")
              }
              else if (result="No") {
                msg ("NoRed")
              }
              wait {
                msg ("5 I have some apples")
                wait {
                  if (GetBoolean(player, "Red")) {
                    Redtest
                  }
                  msg ("8 Have a nice day")
                }
              }
            }
          }
        }
      </look>
    </object>
  </object>

And here is the function, very simple.

    msg ("6 Since you like red apples here is a red apple")
    wait {
      msg ("7 I hope you enjoy")
      wait {
      }
    }
  </function>

So the intent is for the dialogue to go
1 I am an apple seller
(wait for keypress)
2 I hear you like apples
(wait)
3 (ask question) Do you like red apples?
4 YesRed
(wait)
5 I have some apples
(Wait, then If player said yes and has flag, show line 6 from the function)
6 Since you like red apples here is a red apple
(wait and show line 7 from the function)
7 I hope you enjoy
(wait, return to line 8 from the main dialogue)
8 Have a nice day

Instead, what it's doing is

1 I am an apple seller
(wait for keypress)
2 I hear you like apples
(wait)
3 (ask question) Do you like red apples?
4 YesRed
(wait)
5 I have some apples
(wait, then if players said yes previously and has flag shows lines 6 from the function & 8 from the main dialogue simultaneously)
6 Since you like red apples here is a red apple
8 Have a nice day
(wait show line 7 from the function)
7 I hope you enjoy

I hope that made some sense. So yeah, I'm basically just trying to do dialogue easier and have choices that have results later in the conversation and not immediately without having to copy the entire conversation after every single If box. I also struggle (and this is an ongoing issue so advice is VERY welcome) with large conversations becoming incredibly cumbersome and either too big for the screen in the editor or causing the editor to crash. My game is extremely dialogue-heavy and has very long scenes and conversations. To compensate, I've been breaking them up into multiple functions and when one finishes it just calls the next, but it has made any sort of choice trees or branching dialogue extremely unwieldy.

I know one way would be to do it as:
Conversation in Function 1 up to If 1 which either calls function 2 if no or A if yes,
A calls function 2 when finished
Function 2 runs up until If 2 which either calls function 3 if no or B if yes,
etc.
But if the conversation is going to have multiple choices I'm worried the one conversation is going to end up getting broken into 10 functions and I'm already sitting at around 90 functions, which I don't know if Quest is totally cool with or is going to start causing it problems eventually so if anyone knows if I'm cool to just have hundreds of functions or not I'd love to know and if it IS going to be an issue, what a better way is.

Thank you!


Is this with or without using Pixie's ConvLib? If you're not using Pixie's Conversation Library, I very Highly recommend it! It handles most of this pretty easily. It can be found here: https://github.com/ThePix/quest/wiki/Library:-Conversations

For adding conversations later based on leaving and doing things then coming back to the NPC, I find that (when using Pixie's Converstaion LIB) the easiest thing to do is create the conversation object as a "starting conversation" and have it a "waiting" room. Then have whatever trigger you like send it into the player's conversation holder to make it appear next time they talk to that NPC.


I'd second the suggestion for ConvLib.

Alternatively, you could try using a parameter and calling the same script again.
For your example, off the top of my head, your "look" script could be something like:

if (not IsDefined ("topic")) {
  // If we don't have a topic specified, use the starting one
  //   Of course, you could have an `if` here to start the conversation at a different point
  topic = "line1"
}
next = ""

// And then we have all the topics in a list here, so it does whichever one was chosen
switch (topic) {
  case ("line1") {
    msg ("1 I am an apple seller")
    next = "line2"
  }
  case ("line2") {
    msg ("2 I hear you like apples")
    next = "line3"
  }
  case ("line3") {
    // using a dictionary for ShowMenu lets you
    //    set the `result` to something different from the text the player sees
    options = NewStringDictionary()
    dictionary add (options, "4-yes", "Yes")
    dictionary add (options, "4-no", "No")
    ShowMenu ("3 Do you like red apples?", options, false) {
      do (Test, "look", QuickParams ("topic", result))
    }
  }
  case ("4-yes") {
    msg ("4 YesRed")
    SetObjectFlagOn (player, "Red")
    next = "line5"
  }
  case ("4-no") {
    msg ("NoRed")
    next = "line5"
  }
  case ("line5") {
    msg ("5 I have some apples")
    // We can use an `if` to choose what to set `next` to
    //    and the tree doesn't get too unwieldy, because the whole conversation isn't inside it
    if (GetBoolean(player, "Red")) {
      next = "line6"
    }
    else {
      next = "line8"
    }
  }
  case ("line6") {
    msg ("6 Since you like red apples here is a red apple")
    next = "line7"
  }
  case ("line7") {
    msg ("7 I hope you enjoy")
    next = "line8"
  }
  case ("line8") {
    msg ("8 Have a nice day")
  }
}

// And finally, if that topic set `next`, we do the wait
//    and then call this script again to show the next line
//    this is tail recursion, which is inefficient with memory,
//    but I think it's easier to read in this case
if (not next = "") {
  wait {
    do (this, "look", QuickParams ("topic", next))
  }
}

(If you're doing this for a verb other than "look", you'd need to change "look" both places it appears in that script, but I think everything else should work the same)


Oooo I've never heard of it before. I will give it a look, thank you so much for the suggestion, I'm very curious!


This topic is now closed. Topics are closed after 60 days of inactivity.

Support

Forums