Designing a dialog system for Chapter Two

Hi everybody! It’s again my turn to talk about the development of “The Last Door”. As you may remember from my last post (viewtopic.php?f=3&t=27) I am Daniel, one of the TLD programmers so guess what: Programming will be the subject throughout all my posts!!! 😉

Today I will talk about one of the new features displayed in chapter 2 and, from my point of view, one of the most important ones: the dialog system. Following my usual writing structure , I will explain first what is the dialog system, what was the problem we had to face, how we tackled it, what we have done, what we haven’t and finally, which outcome we got.

I am receptive to any doubt, critics or suggestions from you, so just raise your hand and you’ll be happily answered

What is the dialog system?

I think that almost everyone reading this post and who have played beforehand adventure games like “Monkey Island” will understand what I mean. The idea behind this system is give support to dialog trees (although dialogues are not really trees) implementation. That is, when you interact or talk with an NPC, the player can choose which subject he or she want to talk about till the conversation is over. These conversations can help us to obtain more information, go forward in the game and even, depending on our questions and answers, affect the final outcome (be careful with your responses during the game, we could use them in next chapters)

Image

The problem

The first problem and the easiest to notice from the point of view of a player who has played chapter 1, it’s that in the pilot chapter there wasn’t anybody to talk to. So, first thing we needed to do was to implement dialogues within the game but that’s not all, we also required a friendly tool to make the dialogues easy to design and test (chat simulations) for the game designers since the programmers we were too busy as to be loaded with an extra task. And everything was to be done in two or three week at the most. Quite enough, isn’t it?

The workflow we had in mind was the following:

Image

What have we implemented?

At engine level

Starting from the bottom up, we designed a graph data structure which in turn extended and used our actions system. So this way we had again something similar to a BehaviorTree (BT) but Attention! those with a minimal knowledge about graphs will know that a (as its name implies) BT is acyclic, while many of our conversations had cycles. Thus, we needed to push things a little bit more in our actions system. Basically, what we have now is a directed labeled graph consisting of nodes with a destination edge pointing to the next node. Each node has the following structure:

Image

This time, we have separated a bit more the structure (graph) from the data (actions).
Let’s explain a couple of things first:

  • Condition. This is a kind of Action which will check whether the necessary conditions are met to execute the node or not. There are two types of conditions; the “blocking” and the “passthrough”. In the first type, if the condition is not met the dialogue ends. In the second type, what happens is that the internal dialogue logic doesn’t execute, so it automatically goes to its neighbor node/destination.
  • Dialogue actions. Up to the present day, there are 3:
    • Say. An actor says something in the dialogueImage
    • Select Choice. Choose an answer, question or topic (​​destination edge) on which to continue the dialogueImage
    • Jump selector. Given a set of edges, take the destination nodes and check if they meet their condition or in the case they don’t, check if they are not blocking conditions. Choose the first node that meets the constraint. If none satisfies it, use the default destination which is normally the end of the conversation.Image

At tools level

Honestly, most part of our implementation was a Mauricio’s idea. Completely refusing to reinvent the wheel, he introduced me Chat Mapper (http://www.chat-mapper.com/), which with its standard commercial licence you can write your own exporters in C#. But not only that, it also allows to insert LUA code portions, providing some extra logic to dialogues.So we finally opted to use the great default power of this tool just to only focus in writing an exporter which could be able to generate us an ActionScript class coming from a finished dialogue in that tool. Well, not just an only class but something like this:

Image

Let’s overview the parts of this exporter:

  • Localization. It generates a localization file with the dialogue texts.
  • LUA Parser. One of my favorite parts, using ANTLR (http://www.antlr.org/), We have implemented a parser of the LUA subset supported by ChatMapper so we can “translate” that code to an Abstract Syntax Tree (AST), which by a TreeParser can be used to build our tree of ActionScript actions. Yes, we moved from LUA to ActionScript via C #.Image
  • Animations. In ChatMapper we can indicate just from a file which action tree must be used when a specific sentence it’s said, if that tree doesn’t exist, a new empty one is created by default. If the animations file does not exist either, again it is created by default. Hereunder you’ll find a simple example of an animations file :

    var show_postcard : Vector.<Action> = new <Action>
    [
    new PlayCharacterAnimationAction( "Player", "up_left_hand_ping", true )
    ];
    var mery_comes : Vector.<Action> = new <Action>
    [
    new MoveAction( 465, 475, null, NPC_MERY_VINGE, true, false, false ),
    new MoveAction( 650, 475, 1, NPC_MERY_VINGE, true, false, false, false),
    new WaitAction( 500 ),
    new PlayCharacterAnimationAction( “Player”, “up_left_hand_pong”, true ),
    new MoveAction( 465, 475, null, NPC_MERY_VINGE, true, false, false ),
    new MoveAction( 465, 460, null, NPC_MERY_VINGE, false, false, false, true ),
    new PlayCharacterAnimationAction( NPC_MERY_VINGE, “sitting” )
    ];

What have we not implemented?

At engine level

We decided not to implement a generic graph data structure mainly because we had a very specific problem, moreover, keeping this in mind, we had the perfect excuse to continue improving our BTs library (as for instance, splitting tree struture from the actions).

We haven’t any debugger/simulator beyond the one of the game itself, so if we already had that one of ChatMapper, we couldn’t afford to spend our scarce time in an unnecessary feature at that moment.

At tools level

First of all, my main idea was to make something like what our friend fellows from Autoloot Games made here: http://autoloot-games.com/?p=110. The idea was to try using again Brainiac as a design tool, but the fact of having to make a debugger and an exporter was a time wasting option. In addition, firstly we had to make brainiac support simple cycles easily.

Results

What went well

Again, I think that the most remarkable thing has been to achieve an easy to use tool, allowing us to add dialogues in future chapters.

What went wrong

One of the aspects that we could classify as negative, it’s been the poor optimization performed when saving data dialogues. Everyone who have played through chapter 2, you’ll have noticed that at the beginning of the game you were asked to allow more space storage (we fell short with only 100k ). Although we don’t need that huge requested space (is set by flash) I think that with little common sense we could reduce that space significantly.

Despite of all the simplicities provided by ChatMapper, there is something that it didn’t go as well as we expected. Taking into account the ability to add LUA logic (which for us was a must) to the dialogues, the person importing or translating dialogue texts to the tool needs a minimum of understanding in programming.

Closing comments

Again for reading the whole post here’s your prize. A video I’ve done this morning showing the basics of our exporter.

Leave a Reply

Your email address will not be published. Required fields are marked *