What is the best way to implement a dialog tree system in my game? I want an NPC to give the player different sets of responses, some which may only appear when the Player has an item or a previous event has occurred.
Dialog Trees should be done using XML. You store the conditions for the responses and the response in nested trees with a reference to a script file if you need to do something more complex.
You should keep the scripts and dialog separate especially if you are putting together an RPG which has a metric ton worth of conversations. You can then use a library like simpleXML to read the XML file.
There's a similar question over on SO with an example: https://stackoverflow.com/questions/372915/game-logic-in-xml-files
I would look into a embedding a scripting language like lua or ruby and coding dialog interactions in that.
Thus a dialog script could look like:
switch showDialog "Why don't you just leave me along!", "Okay", "But I found your dog!" case 1: showDialog "And stay gone!" case 2: if playerHasObject "dog" showDialog "Thank you!" else showDialog "Liar!"
This also works well for coding AI and other simple things that are useful to tweak during run time. You can even add an editor built into your application that can be invoked when running in debug (or as an Easter Egg).
In the game Stendhal we use a finite state machine to implement NPCs.
The following diagram shows a little example from the how to write quests tutorial.
At the beginning, the NPC is in an IDLE state and may be walking around. A player can start a conversation by saying "hi" and the NPC will go to state ATTENDING. In this state it answers to questions about his "job" and offers some game "help". The player might ask for a quest and the NPC will go to state QUEST_OFFERED waiting for the player to accept ("yes") or decline ("no") it.
After a transition was executed the NPC may say some text and/or execute an action. Similar to the conditions we have defined a reusable set of actions like EquipItemAction which is used to give a quest reward to a player.
While the actual implementation in Stendhal suffers from not being translatable in other (human) languages easily, I think the general concept is good.
I think for adding in translations, you could still use XML for the logic as stated above. When you're getting into that type of complexity you should write your own dialogue tool. Your dialogue text would get stored as a key to a database that you could swap out depending on the language you'd want to display.
For example you could have:
<dialogue id="101" condition="!npc.carsFixed"> <message>Localize.FixMyCar</message> <choices> <choice condition="hero.carFixingSkill > 5" priority="7" id="Localize.Sure"> <command>hero.carFixingSkills += 1</command> <command>npc.carFixed = true</command> <command>hero.playSmokeAnimation()</command> <command>nextDialogue = 104</command> </choice> <choice condition="hero.carFixingSkill <= 5" id="Localize.CantFix"> <command>nextDialogue = 105</command> </choice> <choice id="Localize.FixYourself"> <command>npc.likesHero -= 1</command> </choice> </choices> </dialogue>
You would then have the quest text renderer replace "Localize.FixMyCar" with the appropriately translated text.
Your tool would display what the player would see in a selectable language alongside the editable raw XML.
Similarly you could use something like this from the example you referenced:
npc.add(ConversationStates.ATTENDING, ConversationPhrases.QUEST_MESSAGES, null, ConversationStates.QUEST_OFFERED, Localization[ "BringMeABeer" ], null);
If your keys are descriptive enough not having the complete text shouldn't be an issue.
Something like this could be useful as well:
Localization[ "<Location>.<NPC_name>.<Dialogue_text_key>" ];
Data drive your characters with LUA scripts or even XML files. When you interact with an NPC, grab the file that is attached to it, read it in, adjust for any game variables that may have been triggered, and product the valid response.
The biggest gain from doing it this way is you can easily go in and manipulate the dialog, add new characters, etc. You also avoid mucking up your code base with special logic in handling each and every case.
I think , that You use your own script language for directing these type of game(if not, You should).Then expand your script for dialogs handling too.
You can work with other game variables during creation of dialogs logic. Game engines are like Lego. You programmed only bricks and script uses them. It does not matter if You make some script interpreter or compiler. But script is always useful.
Simple automaton might do:
(dialogueline_id, condition) -> (next_id, response)
It might look something like this:
(1, troll is hungry?) -> (2, say "troll be hungry") (2, player has bananas?) -> (3, say "hey, you have bananas!") (3, ) -> (-1, (say "i like bananas, i take them and eat, you may pass, bye", remove bananas, feed the troll)) (2, player does not have bananas?) -> (-1, say "go away!!!")
In the game You find id and try to match id and the condition.
You need to model the conditions and actions. By objects, function pointers, XML ...
Good dialogue editor will be handy too.