Some Tips and Tricks for Quest 5

The Pixie
18 Sept 2011, 18:37
As my first game nears completion, I thought I would share some tricks (or hacks) that I have used in case other people come across the same problems. Ideally, the system would make these

things trivial, but I think the great thing about Quest 5 is that you can hack it like this to bend it to your will.

WARNING: You need to have some idea about functions and things to understand these.

If you have any similar tips and tricks, feel free to add them to the thread.

The Pixie
18 Sept 2011, 18:38
Ubiquitous Items

I put this as a feature request, but I have devised a way of doing this in Quest 5.0. The point of a ubiquitous item is that it is there in the background all the time. An example to illustrate the problem:

You are in a big room.
>examine wall
You can't see that here.



It is a room, of course it has walls. But the author really cannot be bothered to add a wall object to every room. So... add the wall as a ubiquitous item. One way to code a ubiquitous item is to have one item that follows the player around, and to do that you you need to override the OnEnterRoom. Alex has made this very easy.

Click on "Filter" at the bottom left of the window, and select "Show Library Elements". In the left hand pane, you will see a whole load of functions appear, in gray. Look through for "OnEnterRoom" and click on it. Across the top, in the right pane, you will see a message that this is a library function, and to the right, a button "Copy". Click on that, and you get your own OnEnterRoom in you game file, and this one will be used rather than the library one.

Next create the items. You might want to put them in a room you create just for this purpose to keep them together. Each one needs "scenery" ticked, and a description.

The OnEnterRoom function fires each time the player enters a room, and handles displaying the room description. What we will make it do is move any ubiquitous items into the room. You can do this selectively, perhaps you only want walls in some rooms, and trees in another. We are goinmg to do this in the code view.

The function definition starts like this:

 <function name="OnEnterRoom"><![CDATA[


For an item that is present in every room, just add a line just after the one avove to move the item to the room.

    MoveObject (wall, player.parent)


For other things, they might not always be present. I would guess it is unlikely the player will type "examine tree" in a cave, so you may feel it is easier to have all the objects there.

I feel it is better to just move the relevant ones. How you do this depends on how you set up the rooms, but let us suppose all rooms in the forest start "forest_" (so there might be "forest_east", "forest_inner" and so on). We can test for the name starting like that, and move the tree accordingly.

    if (StartsWith(player.parent.name, "forest_")) {
MoveObject(booth, player.parent)
}


Here is another example, for putting clothes into the room. If there is a male character, then the mans_clothes object is dragged in, for a woman, womans_clothes. Note that this is not going to work properly if there are two characters in the room (only one will get clothes).

    char = FindChar()
if (char <> null) {
if (DoesInherit(char, "female")) {
MoveObject(womans_clothes, player.parent)
}
else {
MoveObject(mans_clothes, player.parent)
}
}


To get this to work, you need to add this function which will return a character in the present room, or null if there is none.

  <function name="FindChar" type="object">
list = ScopeVisible()
return (null)
foreach (obj, list) {
if (DoesInherit(obj, "male") or DoesInherit(obj, "female")) {
return (obj)
}
}
</function>

The Pixie
18 Sept 2011, 18:40
Default Responses For Ask/Tell

So you have fifteen characters in your game, and there are ten topics that the player can ask about. A couple of characters have a useful answer to each topic, so you add those twenty responses and they will give some useful information. But what if the player asks a different character about a topic? Do you really want to add those 130 topics one-by-one?

Again we are going to override an existing methid, this time DoAskTell. Click on "Filter" left at the bottom right of the screen, and select "Show Library Elements". In the left hand pane, you will see a whole load of functions appear, in gray. Look through for "DoAskTell" and click on it. Across the top, in the right pane, you will see a message that this is a library function, and to the right, a button "Copy". Click on that, and you get your own DoAskTell in you game file, and this one will be used rather than the library one.

Now you need to edit the function. Thes first part is fine; that is handling responses on an individual basis sa normal - just as we want. The second part is what happens if the responses is not recognised, and should be modified like this:

  <function name="DoAskTell" parameters="object, text, property, defaultscript, defaulttemplate"><![CDATA[

...

if (not handled) {
if (HasScript(object, defaultscript)) {
do (object, defaultscript)
}
else {
DoDefaultAskTell (object, text, property)
}
}
]]></function>


Now, if the character has a default script defined, this will be invoked (as normal), but otherwise a new function, DoDefaultAskTell, is called. DoDefaultAskTell looks like this:

  <function name="DoDefaultAskTell" parameters="object, text, property"><![CDATA[
handled = false
maxstrength = 0
match = null
text = LCase(text)
dictionary = GetAttribute(default_asks, property)
foreach (keywords, dictionary) {
if (GetKeywordsMatchStrength(LCase(keywords), text) > maxstrength) {
match = ScriptDictionaryItem(dictionary, keywords)
}
}
if (match <> null) {
invoke (match)
handled = true
}
if (not handled) {
msg ("That is not a recognised topic.")
}
]]></function>


It is actually pretty similar to the DoAskTell function, the difference is that it looks at an object called default_asks, rather that the character spoken to, for responses.

So the final stage is to create an object called default_asks, and to add each of those ten topics exactly as you would for a character. I.e., you do it just once for the default_asks character, rather than going through each character in turn.

The Pixie
18 Sept 2011, 18:54
Lazy Listen And Smell

People are going to type "smell" and "listen" all the time in your game... Apparently. So what you should do is to have a response to both set up for each and every room.

If that sounds a bit liker hard work, you can fake it like this. This is still a fair bit of effort, but not so much. I am going to do "smell", but "listen" can be done just the same. There is already a smell command, so as before we are going to override it. For a command, you need to give it a new name however. The pattern part is the words the player might type. Then there is the script to handle the command.

  <command name="smell_subverted">
<pattern>smell; sniff</pattern>
<script>
if (HasString(player.parent, "smell")) {
msg (player.parent.smell)
}
else if (StartsWith(player.parent.name, "forest_")) {
msg ("You can smell the trees.")
}

...

else if (HasString(player.parent.parent, "smell")) {
msg (player.parent.parent.smell)
}
else {
msg ("You sniff the air, but can detect no unusal smells.")
}
</script>
</command>


You will need to modify this for your own use. The important thing to look at is the various "else if" components. The first one is for specific rooms. If there is an attribute called "smell" for the room, this takes precedence. The last is the default, if all the other checks fail. You will want both of those as is (though you may want to edit the message). In between come all the other smells. As an example, the second tests if the room starts "forest_" and if it does, then you gt a forest smell.

I set all my rooms up inside regions. Each region is also a room, but not accessible by the player. Every room has a region as a parent. There are various advantages to that, but in this instance, it means I can set the smell attribute of a region, and the last but one component will cause any room in that region (that is not picked up sooner in the functin) will use that.

By the way, I am guessing that people smell and listen more at the start of the game, so try to keep early rooms unique.

The Pixie
23 Sept 2011, 19:20
I do not know if this will be of interest to anyone, but I wrote a Ruby program to trawl a Quest 5 game and a library. It finds objects without aliases or look/description, lists items that are not scenery, has a go at evaluating message expressions and tries to extract all the text the player will read to a file that can be opened in a word processor, and spell checked (remember to correct the game file, not the extracted text).

You will to have Ruby (or JRuby) installed; the downloaded file will need to be renamed to a .rb extension; and you will need to change the file names so it points to your files. Experience in Ruby, so at least some coding, would be an advantage.

lelo14
23 Sept 2011, 19:58
I was going to ask about spell check. But I was saving it for later because I have so many other questions.
So I guess the answer is that Quest does not have any kind of spell check?
Are you saying that you created a something that lets you do spell check?

What is Ruby, where do you get it? Are you going to share your Ruby trawl program or are you just saying that we could do the same?

I was really worrying about the need for some kind of spell check.

The Pixie
23 Sept 2011, 21:50
Ruby is a programming language. You will need an interpretor to run it, available from here:
http://www.ruby-lang.org/en/downloads/

I have added the file to my previous post. This forum is fussy about the types of files uploaded, I thought giving it a .txt extension would fool it. Apparently not.

Alex has scheduled an integrated spell check for version 5.2.
http://quest.codeplex.com/workitem/836

I am submitting my game for a competition (IFcomp) next week, so I cannot wait that long! I would suggest that you wait until your game is nearing completion (at the beta-testing stage) before you use this program; it is really last checks rather than on-going, and it is possible 5.2 will be out by then (which will be much easier to use).

lelo14
24 Sept 2011, 00:34
The Pixie wrote:Alex has scheduled an integrated spell check for version 5.2.
http://quest.codeplex.com/workitem/836


oooooohhhh cool, looking forward to it. Alex must totaly rock.

The Pixie wrote:I am submitting my game for a competition (IFcomp) next week, so I cannot wait that long!


Good luck with the contest. When will we be able to play it ourselves?