Welcome to Planewalker Games! We are the home of The Broken Hourglass, a new CRPG in development for Windows, Macintosh, and Linux computers.
Inside the Engine: Introduction to dialogue PDF Print

On the fourth Monday of the month, we discuss content development and modding topics in The Broken Hourglass. This month we build on our previous example and explore basic dialogue and store interaction.

Last month, we introduced Harika the shopkeeper as a CREATURE--she has basic stats, a sprite, some equipment, and an assigned area and X/Y position in the game. We also assigned her a dialogue and store resource, but we did not actually create those resources. We will do that now.

The important elements of Harika.CREATURE for our purposes in this installment are:

<xml>
.
.
<Dialogue    value="harika-dialogue"/>
<Store        value="harika-store"/>
.
.
</xml>

Dialogue in WeiNGINE is a state machine simulating a conversation between one or more gameworld characters. Participation from the player character is done through multiple-choice reply options.

We will create a file named harika.dlg/harika.d. (By convention, .d is the filename extension for files which contain dialogue code.)

A state of dialogue is identified by the dialogue resource it belongs to, and its state name. Each state in a single dialogue resource must have a unique name, which can be made up of almost any sequence of alphanumeric and some punctuation symbols.

One state label has a special, reserved meaning in the engine. When the player party clicks on a creature to initiate a conversation, the engine looks at the "talk" state in the dialogue (or dialogues) associated with that creature.

Therefore, this is how we get Harika talking: 

harika.dlg/harika.d

begin "harika-dialogue" // This is the name of the dialogue resource we ask for in her creature file
begin talk // We will now be creating a state named "talk" inside the "harika-dialogue" dialogue resource
say ~"Welcome to Harika's. We have a fine selection of scarves. May I interest you in a purchase today?"~ // Harika says this line.
reply ~"Yes, let us trade."~ do _start_store () exit // The player may choose this reply.
reply ~"No thank you.~ goto comeagain // Or the player may choose this reply.
end // This signifies the end of the "talk" state.

begin comeagain // We are now creating a state called "comeagain" inside harika-dialogue.DLG.
say ~"Perhaps some other time."~ // Harika speaks this line.
exit // We will not present any replies here, but simply exit dialogue.
end // We end the state "comeagain".

end // We end the "begin harika-dialogue" statement.

Every time the player clicks on Harika, she will welcome us to her store. As with XML resources, literal strings are enclosed in tildes--the quotation marks reflect a TBH game convention to enclose spoken text in quotation marks. If the player chooses reply 1, the action associated with that transition will be executed; in this case, do _start_store (), which turns the game over to the store interface and opens all of the valid stores associated with Harika. Dialogue mode will exit once we have finished with the store. If the player chooses the second reply option, we proceed (goto) to another state inside harika.DLG, "comeagain." Harika speaks another line in that case, then we exit dialogue mode.

Now we must create Harika's store. In WeiNGINE, a store is a specialized inventory possessed by a creature. It is distinguished from other inventories by having a discount factor for buying and selling items. Harika's store would look something like this:

Harika.store/harika-store.xml

<xml>
<Name           value=~Harika's Scarves~/>
<Portrait       value="scarf_portrait"/>
<Starting_Item  value="scarf_blue"/>
<Starting_Item  value="scarf_red"/>
<Starting_Item  value="scarf_sheer"/>
<Starting_Item  value="scarf_yellow"/>
<Store_Buys_Price_Multiplier    value="80"/>
<Store_Sells_Price_Multiplier   value="120"/>
</xml>

These attributes have the following meaning:

Name: The store interface looks much like the standard party inventory interface. This will be the displayed name of the store.

Portrait: This image will appear next to the store name. This can be a PNG or JPG available to the game in an .IMAGE directory.

Starting_Item: Each item described here will be granted to this store inventory when it is first created.

Store_Buys_Price_Multiplier: This discount factor will be applied to the internal Cost attribute of any item the store offers to buy from the player. In this case, the store will pay 80% of the "true" value of the item. Note that this cost is calculated before a haggling contest is conducted between the player party and the storekeeper. If both have equal haggling scores, then this multiplier will prevail.

Store_Sells_Price_Multiplier: This discount factor will be applied to the internal Cost attribute of any item the store offers to sell to the player. In this case, the store will charge 120% of the "true" value of the item. The same disclaimer about the haggling contest applies here.

That is all you need to create a rudimentary conversation with a scenery character. The next time we discuss dialogue, we will delve into more complex interactions, including NPC interjections and the concept of reply qualities--special tags which allow joinable NPCs to "score" the PC's behavior.


Some advanced dialogue concepts:

- A state may omit a say string. Such a state may not have any spoken reply transitions, however.

- Transitions in a state are evaluated in the following sequence:
*    Interjections are considered first. An interject is a special dialogue command which involves a character interrupting the dialogue in order to say a new line (interrupting, or interjecting, with his or her opinion.)
*    Silent transitions (those without reply lines) are considered next. Silent transitions may be ranked with priority ordering. If two or more transitions with the same priority could be followed (both conditions are true), the engine will pick one at random.
*    Reply transitions are considered next. Any reply with a valid predicate will be shown to the player, and then the game will proceed according to the reply (and its corresponding transition) selected by the player.
*    "Second" silent transitions are considered last. These are used in cases when a dialogue should present a player reply option only if certain condition are met, and if those conditions fail, we wish to silently proceed to a new state. Such as in this example:

begin example
say ~"If you have a bag of rubies, you can ask me a riddle. Otherwise, I will ignore you and keep talking."~
if _player_has_item "bagofrubies"::"ITEM" reply ~"What's black and white and red all over?"~ goto newspaper
then // "then" tells the dialogue parser that we are now defining second silent transitions
goto ignoreyou // the engine only considers this transition if we do not have the bag of rubies
end

- There is no "state weighting." You may use the _start_dialogue command to begin a conversation at any valid, named state.

- A transition may be given the tag of "once_trans" or "once_dest." Once_trans signifies that the given transition should only be considered valid once. Once_dest signifies that a transition should be considered invalid if the destination state has ever been visited. Such tags are useful for situations involving dialogue loops when a player returns to a set of reply lines (such as asking five questions of a quest character) more than once, but we wish to remove options which have already been selected without doing a lot of manual bookkeeping.

- If a state is prefaced by the keyword "banter", that state will be considered every time the engine's internal banter clock expires. Banter is generally used to represent dialogue between joinable NPCs, or a conversation started by the NPC with the player character. Consider this example:
  banter if (_ok_banter _sanelon && _ok_banter _carind) then begin carind_sanelon_1
    goto carind_sanelon_1_chain
   end

If both the Sanelon and Carind joinable NPCs are "okay to banter" (roughly speaking--they are near one another and we are not in combat) then we will goto a new state to begin this banter. The banter keyword implies a once_dest tag, meaning that this transition will only be considered valid once, which in turn means we will only see this particular conversation once.

Some advanced store concepts:

-    By default a store will offer to buy any item in the game, provided that the storekeeper has enough money to pay for it. Script hooks can be installed to inhibit the purchase of one or more items for each individual shopkeeper.

-    A storekeeper will not buy an item which has been stolen from it by the player party, although this list may be edited later via scripting in case the storekeeper has reason to offer the party amnesty (the player made restitution, performed some great service for the storekeeper, etc).

-    A store may be granted multiple instances of a single item through the Starting_Itemcount attribute. (An itemcount is a "stack" of one or more items.) This can save on copying and pasting if, say, a weaponsmith should have 24 spears.

Last Updated ( Monday, 22 January 2007 )
< Previous   Next >