Tools:Dlgedit:Scripting
From the tutorial you might have seen that each dialogue gets compiled into a python class which then is fed into Adonthell’s Python interpreter to execute it step by step. Given the flexibility of Python, it is only sensible to use it to achieve more than simple static dialogues. In brief, Python makes it possible to reflect the gameworld’s current state in a dialogue, and also to change that state depending on the player’s behavior throughout the dialogue. As you have learned above, you can enter additional Python code at various places of the dialogue:
- into constructor and destructor of the dialogue class.
- directly into the text. This code has to be enclosed in braces ({}) and should return a string.
- as a condition that decides whether a chunk of dialogue is displayed or not
- and finally you can add code that is executed after a piece of dialogue has been displayed.
This section tries to give an overview of the possibilities additional Python code offers for the conversation with NPCs. For in-depth information about this topic, refer to the Adonthell Scripting Guide [1].
Embedded Code
The dialogue engine allows to embed a function call into a line of text and will insert whatever string this function returns in place of the function. This only works for methods defined in the custom function window (Dialogue → Functions or Ctrl+F). It mustn’t take any arguments and should return a string. For example, the method
def f_hello (self): return "Hello world!"
can be used in the text "This will print: {f_hello}" to produce "This will print: Hello world!". Of course for this to make sense, such a method should return one of several strings according to the current situation. Note that this code is always evaluated whenever the line of text is displayed, no matter whether it gets selected by the player or not.
Apart from that, there are the $name and $fm{text_a/text_b} macros. $name will be replaced with the player’s name at runtime, whereas $fm{/} will cause text_a to be displayed if the player is female or text_b in case the player is male.
Local Variables
For more advanced dialogues it might be necessary to define local variables. They belong to the dialogue class and are addressed as self.variable. Local variables are only accessible from within the dialogue itself and thus are only available as long as the dialogue is running. They are freed at the end of the dialogue.
What for are they then? Basically they can be used to track the player’s path through the dialogue. Information he may or may not have received could enable or disable additional choices at a later point in the same dialogue, but how does the dialogue engine learn about that. The solution is to use local variables. So when the player receives the special information you’d add the following variable code
self.special_info_gained = 1
and later on, you base the special choice on following condition:
if self.special_info_gained == 1:
Note that you need not define a variable before you use it. Undefined variables are assumed to have the value 0, so in above example you needn’t do anything about the case where the player doesn’t get that special information.
In many situations, it will be necessary that information survives an individual dialogue. That is where persistent variables come into play:
Persistent Variables
The state of the gameworld, of each NPC and the player are also accessible from a dialogue script. The full details should be discussed in a general scripting doc, but unless this has happened, here are the bits relevant for the dialogue engine.
The state of the gameworld is conserved in the various quests. All quests are stored in the global rpg.quest class. To retrieve the state of a certain quest you’d use either of these three methods:
is_started = rpg.quest.is_started ("quest.node") is_completed = rpg.quest.is_completed ("quest.node") in_progress = rpg.quest.in_progress ("quest.node")
The quest.node is the dot separated path to a certain node in the quest tree which can be created with the Quest Editor questedit. The state of a quest can be changed by setting a leaf in the quest tree to completed:
rpg.quest.set_completed ("quest.node.leaf")
To simplify things a bit, dlgedit recognizes the following shortcuts for retrieving and setting quest state:
# -- quest state queries to be used in conditionals quest.node ( == | != ) ( STARTED | COMPLETED | IN_PROGRESS ) # -- sets the given quest to complete quest.node.leaf = COMPLETED
Editors note: the following applies to Adonthell v0.3 only. It needs be revised once the appropriate engine parts of v0.4 are implemented.
Characters are treated in the same way. They are retrieved with gamedata_get_character and their attributes are also changed via the get_val/set_val methods. Even the shortcuts are the same. Instead of quest name you’ll have to give the character's name, e.g.
# character names containing blanks work too! Bjarn Fingolson.attribute_name = <expression>
As an addition, the member variable the_player always points to the player character and the_npc to the npc the dialogue is assigned to.
Of course you can do more than just read or change character and quest attributes. For example, you could change an NPC’s schedule, or assign a different dialogue:
# you can access any character you want ... bjarn = gamedata_get_character ("Bjarn Fingolson") # .. and completely change his behavior bjarn.set_schedule ("new_schedule") bjarn.set_dialogue ("new_dialogue")
In fact, you have access to almost the complete Adonthell API, so there is much more you can influence than just the characters. Take a look at the Architecture documentation for the numerous functions you have at your command.