Some days ago i wrote an issue that i had trying to build conversation in my game, and the developer answered me with the official tutorials but didn't help beacause what i've understood is: dialogues needs libraries, but libraries need a script (where? Why?) so i searched on this site but it was a loop bringing me nowhere! I am using QUEST in the Desktop version..and i'm new to the program...so..how can i make conversations??? It is really important in my game.
If you had used the search function of the forum you would find a lot of posts about conversations e.g.
https://github.com/ThePix/quest/wiki/Conversations:-Library
TRANSCRIPT
You are in a room.
You can see Rondo.
> talk to rondo
You say something or other to Rondo.
He might respond bettter if you ASK RONDO ABOUT something...
> ask rondo about the game
"Well, I think you'll like what my creator has cooked up for you, after all is said and done," says Rondo.
> ask rondo about conversations
"They're not simple to set up," Rondo replies, "but conversations are a bit complicated in real life, as well, aren't they?"
http://docs.textadventures.co.uk/quest/conversations.html
http://docs.textadventures.co.uk/quest/ask_about.html
SPEAK TO
SCRIPTSPEAK TO
SCRIPTSet up an attribute for each NPC. Call it topics
.
Make it a String List:
Now, add a string to match each of your ASK topics:
Now, back to our SPEAK TO verb...
Change what's there to something like this:
OPTION A:
OPTION B:
EXAMPLE 1:
<!--Saved by Quest 5.7.6404.15496-->
<asl version="550">
<include ref="English.aslx" />
<include ref="Core.aslx" />
<game name="conversations">
<gameid>d8c62ce2-69e0-4776-897d-8dcce76cac97</gameid>
<version>1.0</version>
<firstpublished>2017</firstpublished>
<feature_asktell />
</game>
<object name="room">
<inherit name="editor_room" />
<object name="player">
<inherit name="editor_object" />
<inherit name="editor_player" />
</object>
<object name="Rondo">
<inherit name="editor_object" />
<inherit name="namedmale" />
<speak><![CDATA[You say something or other to Rondo.<br/><br/>He might respond bettter if you ASK RONDO ABOUT something...<br/>]]></speak>
<ask type="scriptdictionary">
<item key="game author story">
msg ("\"Well, I think you'll like what my creator has cooked up for you, after all is said and done,\" says Rondo.")
</item>
<item key="conversations conversation">
msg ("\"They're not simple to set up,\" Rondo replies, \"but conversations are a bit complicated in real life, as well, aren't they?\"")
</item>
</ask>
<askdefault type="script">
msg ("Rondo just shrugs.")
</askdefault>
<usedefaultprefix type="boolean">false</usedefaultprefix>
</object>
</object>
</asl>
EXAMPLE 2:
<!--Saved by Quest 5.7.6404.15496-->
<asl version="550">
<include ref="English.aslx" />
<include ref="Core.aslx" />
<game name="conversations">
<gameid>d8c62ce2-69e0-4776-897d-8dcce76cac97</gameid>
<version>1.0</version>
<firstpublished>2017</firstpublished>
<feature_asktell />
</game>
<object name="room">
<inherit name="editor_room" />
<object name="player">
<inherit name="editor_object" />
<inherit name="editor_player" />
</object>
<object name="Rondo">
<inherit name="editor_object" />
<inherit name="namedmale" />
<speak type="script">
ShowMenu ("What would you like to ask Rondo about?", Rondo.topics, true) {
if (not result = null) {
msg ("You ask Rondo about " + result + ".")
HandleSingleCommand ("ask Rondo about " + result + "")
}
}
</speak>
<ask type="scriptdictionary">
<item key="game author story">
msg ("\"Well, I think you'll like what my creator has cooked up for you, after all is said and done,\" says Rondo.")
</item>
<item key="conversations conversation">
msg ("\"They're not simple to set up,\" Rondo replies, \"but conversations are a bit complicated in real life, as well, aren't they?\"")
</item>
</ask>
<askdefault type="script">
msg ("Rondo just shrugs.")
</askdefault>
<usedefaultprefix type="boolean">false</usedefaultprefix>
<topics type="stringlist">
<value>game</value>
<value>conversations</value>
</topics>
</object>
</object>
</asl>
No, no. You download the game, and you download the library, and they should both be in the same folder/same place so Quest can use them. As long as they are in the same place, Quest will use them both when you open the game.
Or, you can look at the start of my game, here. http://textadventures.co.uk/games/view/0p9uxrxu2ueatixrnt1ixg/pokemon-type-harley-johto-and-sinnoh I just put a bunch of object in as "topics". Or I put a bunch of "topics" in as objects....
Right click this to download it: ConvLib
Just start up the game and check it out:
From here, use Pixie's guide-in-progress to set things up (sorry, I haven't played with this until just now, and it's a little complex):
https://github.com/ThePix/quest/wiki/Conversations:-Library
@ThePix
Informal pull request:
It would rock if the library added Speak to to the Character's verbs list. (Or does it, and I just messed something up? I notice it definitely sets up Consult on those objects...)
UPDATE:
Nevermind. It does set up Speak to on the object. (I don't know what I did! Ha-ha!)
Add a new topic to the NPC that you'd like to show up after it is brought up during play:
Remember to add the alias:
Now go to the Conversation tab, and make it a Conversation Topic
:
Now, go back to the dancer clear heels
object and add the newly created topic to Follow-on topics
:
TRANSCRIPT
You are in a room.
You can see Rondo and dancer.
> speak to dancer
"Oh, Rondo's one of my FAVORITE customers!" she replies.
Rondo hears his name and makes his way towards you and the dancer.
"Hey! Thanks, Darlin! You're my favorite, too!"
Darlin gives a little giggle at this. "Well, ain't you just so sweet you make sugar taste just like salt! That's why you're ONE of my favorites, Rondo!"
Rondo's face turns a little red at this. Darlin shoots you a quick nod in his direction and rolls her eyes when Rondo's not looking.
"Aw, shucks," Rondo kicks one foot at nothing in particular. "You're a sweetheart! And you serve the BEST beer around, too!
"Hey, you!" (This is directed towards you.) "Ask her about her favorite beer! It's called Two-Fisted Ale, or something like that..."
> speak to dancer
You ask the dancer about the beer.
"It's actually called Two-Hearted Ale. Here, have one! I snatched one out of XanMag's cooler while he was working on that Word document he's been working so hard on."
She produces a beer and hands it over.
> drink bottle of Two-Hearted Ale
You take a drink, and it IS pretty good stuff!
(I've been adding JS.scrollToEnd
to the end of all my scripts that utilize ShowMenu
(and, in turn, ClearMenu
), but not all of the time. Most of the time, it lines everything up the way I like it, but, if the menu is too long, it will scroll down past ALL of the outputted text.)
That thar be sum kinda splannin. Nice job KV. Check's in the mail!
I've used this for the last year.
if (ListCount(Orc Guard.thingstosay) = 0) {
msg ("\"Thats all I have for now.\"")
}
else {
n = GetRandomInt (0, ListCount(Orc Guard.thingstosay) - 1)
msg ("The Orc says, " + StringListItem(Orc Guard.thingstosay, n))
list remove (Orc Guard.thingstosay, StringListItem(Orc Guard.thingstosay, n))
}
It randomly pick from string list each time you "Speak to" the orc guard. It removes each response until the list is empty, then will only respond "That's all I have for now." then I can add new responses if the player discovers other things in the game.
Or I can give subtle hints about things to discover.
It has been awhile but one of the other members gave me this piece of code. (Don't remember who.) But thanks if they are reading this. ;)
TODO:
Make Pixie's Ask the room about script work with this.
Command pattern:
ask about #text#
Script
npcs = NewObjectList()
opts = NewStringDictionary()
foreach (o, GetDirectChildren(player.parent)) {
if ((HasTopics(o)) or HasAttribute(o, "ask")) {
list add (npcs, o)
dictionary add (opts, o.name, GetDisplayAlias(o))
}
}
if (ListCount(npcs) = 0) {
msg ("You can ask, but no one is here to tell you anything.")
}
else if (ListCount(npcs) = 1) {
if (HasAttribute(GetObject(ObjectListItem(npcs, 0))), "ask") {
DoAskTell (ObjectListItem(npcs, 0), text, "ask", "askdefault", "DefaultAsk")
}
else if (HasTopics(ObjectListItem(npcs, 0))) {
// TODO: Learn how to trigger the responses like Pixie does it.
msg ("This part of the command is not set up yet.")
}
}
else {
game.npcs = npcs
game.askabouttext = text
ShowMenu ("Ask who?", opts, true) {
if (not result = null) {
o = GetObject(result)
if (HasAttribute(o, "ask")) {
DoAskTell (o, game.askabouttext, "ask", "askdefault", "DefaultAsk")
}
else if (HasTopics(o)) {
// TODO Learn how to trigger the responses like Pixie does it.
msg ("This part of the command is not set up yet.")
}
}
}
}
It works for Rondo (who has the old setup, not ConvLib):
You can't directly ASK NPC ABOUT a topic you set up with ConvLib. You have to SPEAK TO THE NPC first and work from the menu.
This is to keep everything all tidy, you know. Pix has this set up to keep up with every topic that's been discussed and all sorts of other things.
So...
Ignore this post.
I'm abandoning adding the ConvLib NPCs to this script. It would most likely mess everything up if the player asked a question that wasn't supposed to be a topic yet.
@ Forgewright
Thank you, thank you.
I'm just copying and pasting, though. Everything was already documented in different places... The forum, the docs, Pixie's wiki page...
In related news: I'm "borrowing" your thingstosay
script, if you don't mind.
...and I've got a pretty sweet hints system cooked up, if you're interested in such things.
Each character can have a set of reactions. Each reaction will fire only once in a game, and will fire the first time the reaction's condition is true AND the character is in the same room as the player. A character will only ever have one reaction in any turn.
Each reaction is described by four or more lines, composed thus:
The first line must be a @
on a line on its own; this indicates the start of the reaction.
The second line is the name of the reaction. You can give a set of reactions the same name; only one will ever be used.
Third is the condition. The condition should be standard Quest code that will evaluate to true or false (you can use "this" as normal to refer to the character).
The four and all subsequent lines are "what will happen". You can use these to change the game world (to a limited extent) and to display text. These lines can be of various types, depending on the first character, however, most text (anything beginning with a letter or number) will be printed directly to screen.
Rondo will say 'Hi...' the first turn he's in the room with the player, and he'll say the next bit when the player is carrying the beer for the first time.
(Also notice I put the line reading
before his line of dialogue? A <br/>
didn't work. That did, though.)
Pixie will probably show us a better way, but I turned the ReactionsTurnScript
into a function (called ReactionsFunction
), then I call that function from the ReactionsTurnScript
(from which I cut and pasted the code into ReactionsFunction
; am I being hard to follow? sorry if so). I also call ReactionsFunction
AFTER entering the first room for the first time.
(NOTE: You may not want this to happen for numerous reasons, but I did in this instance, so I included it.)
If the line starts ~
then the rest of the line should be the name of another reaction for this character; that reaction will be removed along with this one.
If the line starts with &, then a script is run. The line should be in the format:
& mary myscript
You can use "this" to stand in for the character the reaction is attached to.
& this myscript
If the line starts with =, + or - then the given attribute is set to, incremented or decremented by the given amount. As before, "this" is supported. You can use strings with =
, but +
and -
are restricted to integers.
You should now find that characters have a Reactions tab, with a big text area.
Each character can have a set of reactions. Each reaction will fire only once in a game, and will fire the first time the reaction's condition is true AND the character is in the same room as the player. A character will only ever have one reaction in any turn.
Each reaction is described by four or more lines, composed thus:
The first line must be a @ on a line on its own; this indicates the start of the reaction.
The second line is the name of the reaction. You can give a set of reactions the same name; only one will ever be used.
Third is the condition. The condition should be standard Quest code that will evaluate to true or false (you can use "this" as normal to refer to the character).
The four and all subsequent lines are "what will happen". You can use these to change the game world (to a limited extent) and to display text. These lines can be of various types, depending on the first character, however, most text (anything beginning with a letter or number) will be printed directly to screen.
If the line starts ~ then the rest of the line should be the name of another reaction for this character; that reaction will be removed along with this one.
If the line starts with &, then a script is run. The line should be in the format:
& mary excitedscript
You can use "this" to stand in for the character the reaction is attached to.
& this excitedscript
If the line starts with =, + or - then the given attribute is set to, incremented or decremented by the given amount. As before, "this" is supported. You can use strings with =, but + and - are restricted to ints.
Here is an example, with five reactions. The first will fire immediately, and is just text. The second will fire when the player is wearing a plain hat, and the third when wearing a fancy hat. However, the third will delete the second, so if the plain puts on the fancy hat first, the second reaction will never be seen. The last two have the same name, so only one will ever fire.
@
greeting
true
'Hi!' says Mary
@
plain hat
# ghhjhj
plain_hat.worn
'Oh, you are wearing a hat,' says Mary.
& this testscript
@
fancy hat
fancy_hat.worn
'Wow, what a fancy hat,' says Mary.
~ plain hat
@
trophy
player.won_competition and trophy.parent = player
'Cool trophy,' says Mary.
@
trophy
player.won_competition
'Hey I heard you won the completion,' says Mary.
= this alias "Happy Mary"
+ Mary happiness 5
A new feature is the "consultable" type. Use this for encyclopedias and computers that the player can use to look stuff up on.
Topics are set up exactly as with conversations. In this case you probably want to untick the "Automatically hide" checkbox for each one.
At its simplest, that is all there is to it, however, you might want to change the "consult" script to fit your system, for example to check if the computer is turned on and connected to the internet.
Go to the object's Attributes tab, and find consult (it will be in grey). Click on Make editable copy, and then you can modify it as you wish.
The important bit is this line, which will handle the topics:
Converse(this, "Consult ")
However, you may want to test first that the computer is switched on for example (the keyword this refers to the object the script is attached to, by the way).
if (not this.switchedon) {
msg("You wonder if you should turn on the computer to use it.")
}
else {
Converse(this, "Consult ")
}
Behind the scenes, each topic has two flags controlling whether it will appear in the menu list or not, display and hidden. The topic will only get show if display is true and hidden is false. Any other combination and it will not appear.
What this means is that if you set a topic to be hidden, and later set it to be displayed, the hidden will take priority, and it will stay hidden.
To get a topic to display, use the ShowTopic function. To hide it, use HideTopic.
ShowTopic(topic)
HideTopic(topic)
Hiding topics is useful when a player's actions stops that being an option. For example, if the player has to choose between two option, each option should hide the other one in the script section.
Setting something to be a Character will automatically give it an integer attribute called state, set to zero. This is not used by the conversation system, but can be useful for you when you are tracking the state of a character.
Every topic has an integer attribute called count, set to zero. This will be increased by one each time the topic is seen, so gives a quick way to check if the player has seen it yet.
There is a function called TopicTest that will do some basic testing. You can add it to game.start to check your game; it will flag any obvious issues.
Topics that try to display new topics that do not exist
Delete it from game.start before publishing!
Rather than having the topics inside the character, you can create a new room, and put them all in there. The new room must be named exactly the same, but with "_topics" appended. You may find this more convenient, especially if the character is carrying several items anyway.
Note that you cannot have some topics in the character and some in the topics object. However, you can use one for one character and the other for another.
There is a time and place for everything, and what may be a witty retort on moment is a sad and bitter comment ten minutes later. To have topics expire, you must set up a turn script, and have it call IncConvTime (no parameters).
For topics, tick the checkbox to have it expire, and then put the number of turns it will be until it disappears.
Various functions and templates can be overriden (i.e., you create your own version of them in your game), to further customise the library.
These are the dynamic templates it uses:
<dynamictemplate name="NoSpeakTopics">"You wonder what you can talk to " + GetDisplayName(object) + " about..."</dynamictemplate>
<dynamictemplate name="NoConsultTopics">"You wonder what you can look up with " + GetDisplayName(object) + "."</dynamictemplate>
AddExtraTopics You can use this as a way to add extra topics, for example if you want all your characters to have some standard topics, add them this way.
<function name="AddExtraTopics" parameters="c, topics">
</function>
AfterTopicEvent Override this to have something happen after each exchange.
<function name="AfterTopicEvent">
</function>
P
Generally I recommend meaningful names for functions; in this instance I am copying the name of a print function in Ruby.
This gets called only when the action is successful; for text that is part of the narrative. You can override this in your own code to flag that a command was successful or to display narrative text differently to meta text.
<function name="P" parameters="s">
msg(s)
</function>
Footnote 1: Every single script in this thread was taken from either the Quest documents, Pixie's Wiki, or from this forum anyway. NONE OF THE SCRIPTS were written by me. I only filled in the "story's elements".
You are in a room.
You can see KV.
> how are you, kv?
I can't see that. (how are you)
> kv, how are you
Error running script: Error evaluating expression 'DynamicTemplate(defaulttemplate, object)': No template named 'DefaultTellTo'
> kv, how are you?
Error running script: Error evaluating expression 'DynamicTemplate(defaulttemplate, object)': No template named 'DefaultTellTo'
> how are you, kv
I can't see that. (how are you)
> how are you kv?
I can't see that. (kv?)
kv, how are you?
KV doesn't take orders from the likes of you.
> how are you, kv?
I can't see that. (how are you)
> how are you, kv
I can't see that. (how are you)
Okay...
So it wouldn't be easy to get around it that way...
How about we set up the verb with this pattern: how are you;how are you,
?
Hrmm... how are you, #object#
?
Okay, fine. Let's go see what that's all about...
Okay, so any time we say an object's name with some text after that, which follows a comma (example: kv, how are you), Quest will think it's an 'Order/Tell to' command.
So, let's press COPY (at the top right) and play around a little.
This is the default script:
DoAskTell (object, text, "tellto", "telltodefault", "DefaultTellTo")
I'm going to add this line before that one:
if (EndsWith(text, "?")) msg ("THIS WAS A QUESTION")
> kv, how are you?
THIS WAS A QUESTION
KV doesn't take orders from the likes of you.
> kv, how are you
KV doesn't take orders from the likes of you.
Okay, but a command could still have a question mark, right? Sort of?
I mean, you could be Asking NPC to do something...
>ITSLEO, will you give me a bite of that REAL pizza, please?
So, the question mark is ruled out.
BUT...
How about this:
text = LCase(text)
if (StartsWith(text, "how")) {
msg ("THIS WAS A QUESTION")
}
DoAskTell (object, text, "tellto", "telltodefault", "DefaultTellTo")
(Or does Quest already differentiate 'how, when, why, where'?)
> kv, how are you
THIS WAS A QUESTION
KV doesn't take orders from the likes of you.
So here's a dirty fix for this one:
text = LCase(text)
if (StartsWith(text, "how are you")) {
HandleSingleCommand(text + " " + GetDisplayName(object))
}
else {
DoAskTell (object, text, "tellto", "telltodefault", "DefaultTellTo")
}
> kv, how are you
"I'm fine," KV replies. "I hope you are, too!"
> kv, how are you?
I don't understand your command.
The question mark is a totally different problem.
I'm pretty sure it and the comma can be handled the same way, but I understand that kv
and kv?
are not the same word.
I'll find how it ignores the .
when you turn on multiple commands (or how it looks for a comma in a command with multiple objects), then I shall return.
<!--Saved by Quest 5.7.6404.15496-->
<asl version="550">
<include ref="English.aslx" />
<include ref="Core.aslx" />
<game name="for ITSLEO">
<gameid>898e90ef-b9c6-4bc6-9afa-da13651c5f27</gameid>
<version>1.0</version>
<firstpublished>2017</firstpublished>
<feature_asktell />
</game>
<command name="alttellto">
<pattern type="string"><![CDATA[^(?<object>.*), (?<text>.*)$]]></pattern>
<script>
text = LCase(text)
if (StartsWith(text, "how are you")) {
HandleSingleCommand (text + " " + GetDisplayName(object))
}
else {
DoAskTell (object, text, "tellto", "telltodefault", "DefaultTellTo")
}
</script>
</command>
<object name="room">
<inherit name="editor_room" />
<object name="player">
<inherit name="editor_object" />
<inherit name="editor_player" />
</object>
<object name="KV">
<inherit name="editor_object" />
<inherit name="namedmale" />
<speak>"Ciao!" says KV. "Try entering: ASK KV ABOUT something."</speak>
<howareyou>"I'm fine," KV replies. "I hope you are, too!"</howareyou>
<askdefault type="script">
msg ("\"I'm not programmed to know that,\" shrugs KV.")
</askdefault>
<telldefault type="script">
</telldefault>
<ask type="scriptdictionary">
<item key="game">
msg ("\"It's just an example game,\" says KV.")
</item>
</ask>
<usestandardverblist />
<telltodefault type="script">
msg ("KV doesn't take orders from the likes of you.")
</telltodefault>
</object>
</object>
<verb>
<property>howareyou</property>
<pattern>how are you</pattern>
<defaultexpression>"You can't how are you " + object.article + "."</defaultexpression>
</verb>
</asl>
a 'Verb' is just a Script Attribute on an Object, but with some extra coding fluff to make it function as a 'Verb', a sub/specific type of a Command
I think so, if this is how it works... (this area is beyond my knowledge)
I really haven't dug that much into the built-in stuff of quest, as I'm putting it off as it's not easy to figure out how quest works, lol. You know more about how quest works than I do. I'll get around to learning how quest works better at some point... along with all of the UI/GUI customization/js/css/html/xml/etc type of stuff... and a lot of other stuff.... I'm just really lazy... sighs.