1. The player Talks to an object or a person
2. A script routine calls the function talk_to(name,start)
When a conversation takes place, the game will load in the file containing the conversation and process it interactively like a web browser.
Conversations are based on pages. At the top of the page is an
image, normally a portrait of the person you're talking to.
Below this is the text of the conversation, and at the bottom are the
choices you get of what to say.
Each choice is a link to another page, or a link to "exit" which ends
the conversation.
Commands can also be embedded into the page, which can create objects,
remove objects, change flags, and call script functions.
You can also use commands to make different things happen depending
on whether a flag is true or false.
More commands will be added in the future as necessary.
Each page has it's own title. When the conversation starts it will look for the page called 'Start', although it may also look for other pages too in future.
The page starts with the command:
[page="start"]
..and continues until the command:
[endpage]
Everything between these two commands will be displayed on the screen, unless it is another command.
The commands you will need to know to make simple conversations are:
[nextpage=""]
[link=""]
[linkto=""]
[image=""]
[colour="#xxxxxx"]
Important tips!
5.2.1 Simple page linking
There are two ways to link pages. [nextpage=""] is the most simple, so I'll explain it first.
Here's an example:
[page="start"]
This is the first page.
Press a key for the second page...
[nextpage="page2"]
[endpage]
[page="page2"]
This is the second page!
Press a key to finish.
[nextpage="exit"]
[endpage]
This will display two lines:
This is the first page.
Press a key for the second page...
When you press a key, the page will change and read two more lines:
This is the second page!
Press a key to finish.
..and when you press a key the conversation will end.
The command [nextpage="page2"] makes the program wait for a key to be pressed, and then it looks for a page titled 'page2' and displays that.
The command [nextpage="exit"] makes the conversation finish when a key is pressed.
5.2.2 Interactive page linking
Now let's look at [link=""] and [linkto=""]
These two commands are used together to provide the choices at the bottom
of the page.
[link=""] displays the message at the bottom, and [linkto=""] is the
page that the link will take you to.
LINK must come first, and LINKTO just afterwards, otherwise it may
fail.
Here's an example:
[page="start"]
You see a shifty-looking man in a trenchcoat.
"Pssst! Wanna buy some stuff?"
[link="What 'stuff' have you got?"]
[linkto="whatstuff"]
[link="No! Get lost!"]
[linkto="getlost"]
[endpage]
[page="whatstuff"]
"The usual contrabands..Mars bars.. M&Ms... Terry's chocolate oranges.."
[link="Not today man, the feds are everywhere"]
[linkto="nottoday"]
[link="You're off your rocker!"]
[linkto="getlost"]
[endpage]
[page="getlost"]
"Suit yerself.."
He walks away in a huff.
[nextpage="exit"]
[endpage]
[page="nottoday"]
"Wo! Thanks for the tip, man."
He looks both ways and slips off into the night.
[nextpage="exit"]
[endpage]
You should be able to work out what that does. If not, put it into a file and try it out.
You can have a maximum of 10 links per page (this will take a lot of screen room!).
5.2.3 Images
The portrait at the top of the screen is set using the [image=""] command.
You must put this as the first command after the [page=""] line.
The word in quotes is the title of a Sprite found in the "Section:
sprites" part of the scriptfile, main.txt.
See chapter 3.2.1 of this document.
Here's an example:
[page="start"]
[image="greengrocer"]
You see a small greengrocer.
"Good day sir, how can I help you?"
:
:
:
[endpage]
You must specify a portait for each page. This allows you to change the character's expression from page to page.
You can also specify a background image if you don't like the blackness.
This is done with the following command:
[backing="filename.pcx"]
The game will not look in the Scriptfile for this image, it will be loaded directly from disk.
This is actually what happens if you press F1 for help in The Flat. It loads a conversation called "help.txt" which is in the FLAT/ directory, and this is what it does:
[page="start"]
[backing="backings/help1.pcx"]
[nextpage="exit"]
[endpage]
5.2.4 Setting the text colour
You may wish to change the colour of text in the body of the conversation.
This is done using the [colour=""] command. (You may also use
[color=""] if you prefer)
As of Release 0.65 it works in exactly the same way as HTML, so the
colour you choose will last for the entire document or until you change
it.
You can also set the colour of the links by using [link_colour=""] or
[links=""]
The colour is in quotes, and it is specified with a # followed by six
hex values, just like HTML.
The first two set the amount of red in the colour (00-ff), the second
two set the amount of green (00-ff) and the last two the amount of blue
in the colour (00-ff).
You can get little java applets and things to work out the colours,
just look for a good page about web design.
Here are some of the most commonly-used colours:
red: #ff0000
green: #00ff00
blue: #0000ff
pink: #ff00ff
yellow: #ffff00
cyan: #00ffff
orange: #ff8000
grey: #808080
Black would be #000000, but you can't change the background colour yet,
so this would be invisible.
White is #ffffff, but this is the default anyway.
Generally I use medium grey [colour="#808080"] for narration, and leave the rest of the text white.
Returning to the sweet-pusher as an example:
[page="start"]
[colour="#808080"]You see a shifty-looking man in a trenchcoat.
"Pssst! Wanna buy some stuff?"
[link="What 'stuff' have you got?"]
[linkto="whatstuff"]
[link="No! Get lost!"]
[linkto="getlost"]
[endpage]
This is done with flags. A flag is a message that can either be true or false, depending on what has happened previously.
5.3.1 Checking for an object
The simplest case is 'Am I carrying such-and-such an object?' The result will either be true(yes) or false (no).
Here's an example. It's not really a conversation, but anyhow. If you're carrying 'The Death', it says so, otherwise it says you're not carrying it.
[page="start"]
System test: are you carrying that nasty weapon, THE DEATH?
[am_carrying the_death]
[if true]Yes, you are carrying it.
[if_not true]No, you are not carrying it.
[endpage]
Now, how does it work?
[am_carrying the_death]
This looks in the player's pocket for an object named 'the_death'.
If it is in your pocket, it will set the flag 'True' to be true.
The next part is clever.
[if true]Yes, you are carrying it.
[if true] Examines the flag called 'true', and then decides what to do. If 'true' is set true, it prints the text. Otherwise it does nothing at all.
[if_not true]No, you are not carrying it.
This again looks at the flag called 'true'. But it does the opposite thing! If 'true' is NOT true, it prints the text, else it does nothing.
Because both of these are looking for one of the two possible states, ONE of them will be displayed and the other won't.
You can also use [if false] instead of [if_not true].
(For the advanced reader: TRUE and FALSE are separate flags, but they are always set to be opposite.)
5.3.2 Important tips!
[am_carrying mobile_phone]
[if true]"You have played this game for far too long, mortal!"
[if true]"It's time to go to bed..."
[am_carrying large_stereo]
[if true]"This is a library, sir. I'm afraid I must ask you to
leave."
[if true][nextpage="exit"]
[if false]"Welcome to the library. How can I help you?"
[if false][nextpage="howcanihelp"]
In this case, the librarian will ask you to leave and stop talking if you have the ghetto-blaster. If you don't, they will go onto a different page and continue the conversation.
If you want to do more complex actions conditionally, you can either use everal IF lines, or use the GOTO command to switch to another page. [goto=] is the same as [nextpage=], but it switches instantly, without waiting for a keypress.
Here's and example:
[page="something"]
[if murdered_king][goto="murderedking"]
[if murdered_queen][goto="murderedqueen"]
"Hello!"
:
:
:
[endpage]
[page="murderedking"]
"My God! You've murdered His Royal Highness! GUARDS!!!"
[nextpage="exit"]
[callvrm="callguards"]
[endpage]
[page="murderedqueen"]
"My God! You've murdered Her Majesty! GUARDS!!!"
[nextpage="exit"]
[callvrm="callguards"]
[endpage]
5.3.3 Checking for a party member
Similarly to looking for an object, you will also want to see if a particular person is in your party.
[is_in_party gordon_harris]
[if true]"Ah, any friend of Gordon's is a friend of mine."
[if true][nextpage="page2"]
[if false]"I don't know you, stranger!"
[if false][nextpage="exit"]
5.3.4 Using your own flags
You are not just lumbered with True and False, you can create any number of flags you like, up to 8192.
The commands you use to create flags are SET and CLEAR, which make the flag be true or false, depending on which one you used. (Set makes a flag true, clear makes it false).
The flags are automatically created as you try to use them. If you try to set or clear a flag which doesn't exist yet, it is created there and then. If you try to test a flag which doesn't exist , it is assumed to be false.
For example:
[if_not already_met]"Hello, I'm Gordon Harris."
"How can I help you?"
[set already_met]
The first time you have this conversation, he says "Hello, I'm Gordon
Harris", because the flag already_met is false.
Then it prints "How can I help you?" which always appears.
Finally it sets the flag 'already_met' to be True, so the introduction
will not be shown again, unless you do [clear already_met].
5.3.5 Personal Flags
The flags described above are fine for many circumstances, but they
are 'global', that is, all the characters see the flag the same.
Clearly this is not good for the above example, since by meeting Gordon
Harris, you would also have 'met' all the other characters in the game.
Once solution would be to have lots and lots of flags, for example 'met_gordon_harris' and 'met_kevin_parrot' etc, but this would be untidy.
Instead, there are 32 numbered flags, which are specific to the current
person you're talking to.
These are called 'Personal Flags', or p-flags for short.
As I mentioned, the p-flags do not have names, they are numbered from
0 to 31.
If you need to keep track of each p-flag number, you can write a memo
at the top of the file, before the first [page=""] line.
They have their own special [if] commands:
[if_pflag n] (or [if_personal_flag
n])
[if_not_pflag n] (or [if_not_personal_flag n])
[set_pflag n] (or [set_personal_flag
n])
[clear_pflag n] (or [clear_personal_flag n])
Here's an example:
[if_not_pflag 0]"Hello, I'm Gordon Harris."
"How can I help you?"
[set_pflag 0]
This time, it uses the personal flag specific to Gordon Harris.
In fact, if you had more than one copy of Gordon Harris in the game, you
would still be able to meet both of them individually.
This is the most neat part of the conversation system.
By manipulating the environment , you will be able to do really neat stuff, like buying and selling, creating and destroying objects, and by calling a VRM function, absolutely anything else.
5.4.1 Calling VRM functions
There are now three ways to call VRM functions from a conversation.
1. [callvrm="function"]
2. [on_exit_callvrm="function"]
3. [set_behaviour="function"]
[callvrm=]
This calls the VRM function immediately. You should not call redraw() in the VRM function you are using, or the display will become corrupted.
VRM functions can interact with the conversation too, by setting flags
(such as True and False) and p-flags.
This is a way to get information about the game state if there isn't
a command to do that in the conversation.
You can also use it to move objects around, or open doors by talking
to an intercom.
[on_exit_callvrm=]
This calls the VRM as soon as the conversation ends.
This should be used when the VRM will redraw the screen, or you are
doing something drastic such as killing the player.
When the VRM is called, current_object will be set to the character you're talking to.
For example:
[page="start"]
"Hello."
[link="You're a b*st*rd!"]
[linkto="bstard"]
[endpage]
[page="bstard"]
[if_not_pflag 0]"Never say that to me again!"
[if_not_pflag 0][nextpage="exit"]
[if_pflag 0]"Now you die!"
[if_pflag 0][on_exit_callvrm="killplayer"]
[if_pflag 0][nextpage="exit"]
[set_pflag 0]
[endpage]
If you insult this guy twice, he kills you, by calling the VRM function 'killplayer'.
[set_behaviour=]
This changes the behaviour of the current object so that it calls this VRM every turn.
For example:
[set_behaviour="enemy_flee"]
or:
"In the beginning there was Darkness, and the Darkness was without form
and void."
"And in addition to the Darkness there was also Me."
"And I moved upon the face of the Darkness and I saw that I was alone."
"Let there be light."
[set_behaviour="thermostellar_device_explode"]
[nextpage="exit"]
5.4.2 Creating and destroying objects
You can create objects directly in the player's pockets.
This has several uses, besides the obvious one in Ultima 6, where the
King gives you a key when you talk to him.
It can also be used for trading, by creating the money in the player's
backpack and destroying the object you sold, or vice-versa.
At present [create] does not check to see whether there is room in your
backpack to carry the object.
However [destroy] (or [remove]) does check to see whether the object
is
in your backpack, so that the angry trader can poke you in the eye if you
try to sell something you don't have.
This check is performed of course, by setting the global flags TRUE and FALSE to the appropriate value afterwards.
You also specify the amount of objects you want to create or destroy. In some cases this will be ignored, if the object is indivisible, but for other cases such as money, it will add or remove various quantities of that object from your backpack.
If you want to take away an amount of something, it will return FALSE if you don't have that much, to prevent you from being able to short-change the trader.
Here's an example, selling a TV set:
[destroy 1 tv]
[if false]"What are you trying to pull?"
[if true][create 1000 gold_coins]
[if true]"Done!"
[nextpage="start"]
Here's another, buying a TV set:
[destroy 2000 gold_coins]
[if false]"You can't afford it!"
[if true]"Thankyou, sir!"
[if true][create 1 tv]
[nextpage="start"]
5.4.3 The theory of the Conservation of Money
Now that example was very crude. The money was actually destroyed and the object was created on-demand.
This is what Ultima 6 and Ultima 7 do, but you might prefer it if the money and goods actually change hands.
This would mean that you could actually kill the trader after taking the money and get the TV back afterwards, but you would also have to make sure the trader is stuffed with cash, or he won't be able to afford the TV when you try to sell it!
If you prefer to work this way, instead of using CREATE and DESTROY,
use GIVE and TAKE.
But don't blame me if the King gives the player the only copy of the
key to the castle and the player loses it..
[take n objects]
This takes the specified object (or an amount of them)from the player's backpack and transfers it into the backpack of the character you're talking to. No loss!
Similarly,
[give n objects]
..will take the specified object(s) from the backpack of the character
you're talking to, and transfer them to the player's backpack.
As an example, here's the buying and selling the TV again, but with the money and the TV being moved around instead of created and destroyed.
[take 1 tv]
[if false]"What are you trying to pull?"
[if true][give 1000 gold_coins]
[if true]"Done!"
[nextpage="start"]
Here's another, buying a TV set:
[take 2000 gold_coins]
[if false]"You can't afford it!"
[if true]"Thankyou, sir!"
[if true][give 1 tv]
[nextpage="start"]
Neither of these examples take into account whether the trader has the
money or the TV.
This is more complex, since GIVE will change the state of TRUE and
FALSE, so we'll need to use a temporary flag.
Here's the finished version..
[clear temp]
[take 1 tv]
[if false]"What are you trying to pull?"
[if false][nextpage="exit"]
[if true][set temp]
[if temp][give 1000 gold_coins]
[if temp][if true]"Done!"
[if temp][if false]"I'm sorry sir, I seem to have exceeded my budget
for acquisitions."
[if temp][if false][give 1 tv]
[nextpage="start"]
[clear temp]
[take 2000 gold_coins]
[if false]"You can't afford it!"
[if true][set temp]
[if temp][give 1 tv]
[if temp][if true]"Thankyou, sir!"
[if temp][if false]"I'm sorry sir, we're out of stock."
[if temp][if false][give 2000 gold_coins]
[nextpage="start"]