Restrictions, Messages and Reactions - ThePix/QuestJS GitHub Wiki
Quest 6 gives authors all the common features of a text adventure built-in, but inevitably authors will want to tweak these to do somethng different, to make their game different. A broad approach to doing that is with restrictions, messages and reactions.
When the user types a command, the parser will try to identified what the user wants to do and get the appropriate command. The command will then establish if, in general, this is possible. Quest will go through this process:
- test any specific restrictions (and abort if necessary)
- perform the action
- print a message to let the player know
- determine any following reactions
So restrictions prevent the player doing something. A hat cannot be picked up because it is nailed to the floor, or a belt cannot be removed because it is cursed. These are function attributes, with a name in the form test[Verb]
, such as testOpen
or testDropIn
; they should return a Boolean - true
if the action is permitted, false
if not. In addition, they should say why the action is not permitted if that is the case. This is only for your custom restrictions; you can assume Quest has done all the usual checks for this type of object.
Messages let the user know the command was successful. They are string attributes, and take the form msg[Verb]
, for example msgSwitchOn
or msgWear
.
Reactions occur when the player does something - and the user has already been told it was successful. The alarm goes off as the player enters the room, the crowd gasp in astonishment when the sword is picked up or the item dropped whilst flying is lost forever. These are function attributes, and are named in the form after[Verb]
, such as afterClose
or afterRemove
.
When the Character Moves
To restrict how a specific character, including the player, moves, give her a "testMove" function with the exit as a parameter; this is checked as long as the exit does not have a custom "use" function - and if it does, you should include a check for this, to ensure it works the same!
To restrict a specific exit, give it a custom "simpleUse" function.
To react to moving, give the character an "afterMove" script, which again has the exit as a parameter.
Further reactions when the player moves
When the player leaves a location, the afterExit()
script on the location will trigger. Then, on entering a new location, various scripts on this location he enters can fire: beforeFirstEnter()
, beforeEnter()
, afterEnter()
, afterFirstEnter()
. None of these take parameters.
You could also use a custom "simpleUse" function to trigger when a specific exit is used.
The player's "afterMove" script will fire after all these.
When an Item is Manipulated
Most actions allow for a restriction attribute, a message attribute and a reactions attribute, though there are exceptions. For items, restriction attributes and reaction attributes both take one parameter; a dictionary of options. The message attribute, being a string, takes no parameters, but instead uses the text processor, and will have access to the same parameters.
Restrictions when an item is manipulated
There are a number of attributes you can set that will stop a character - usually the player - doing something with an item, depending on the verb. The table shows what is available, the "On" column indicates which item this should be an attribute of. The function will be sent a dictionary of options including "char", the character doing the action, and "multiple", a Boolean indicating if this is one of multiple items the command is handling. Other options are noted.
Function | On | Extra options |
---|---|---|
testTake | Item | count |
testDrop | Item | container, count |
testDropIn | Location or container | item |
testTakeOut | Location or container | item |
testWear | Item | |
testRemove | Item | |
testOpen | Item | |
testClose | Item | |
testSwitchOn | Item | |
testSwitchOff | Item | |
testCarry | Item | exit |
testPurchase | item | |
testSell | item | |
testFill | Item | fluid |
testEmpty | Item | fluid |
testPostureOn | Furniture | posture |
testGive | NPC | item |
Here is an example that will stop the player dropping anything in this location.
testDropIn:function() {
return falsemsg("It occurs to you that anything you drop here will be lost forever.")
},
Messages when an item is manipulated
These are used when the action is successful, as an alternative to the built-in message in the language file. These are all on the item itself, so note in particular that while testDropIn and afterTakeOut are attributes on the container, msgDropIn and msgTakeOut are attributes of the item going in the container.
Function | Extra options |
---|---|
msgDrop | |
msgTake | |
msgDropIn | container* |
msgTakeOut | container |
msgWear | |
msgRemove | |
msgOpen | |
msgClose | |
msgLock | |
msgCloseAndLock | |
msgUnlock | |
msgSwitchOff | |
msgSwitchOn | |
msgPurchase | |
msgSell | |
msgIngest | |
msgPress |
Here are three examples, the second uses the text processor directive to make it character-neutral. The third goes rather further. If this is not a special container called "bare_earth", the standard message is given, lang.drop_successful
. It is the "bare_earth", we get a custom message the uses the "count" of the item, and the "excess" (this is true
if the player tried to plant more seeds than she was holding).
msgClose:"You close the lid.",
msgClose:"{nv:char:close:true} the lid.",
msgDropIn:"{ifNot:container:name:bare_earth:" + lang.drop_successful + ":Mandy carefully plants {nm:item:count} in the bare earth{ifIs:params:excess:true:, wishing she had a few more}.}",
Note that the "msgDropIn" attribute can be a function that prints the message, taking the dictionary as a parameter. The reason for this is that the message can be dramatically different if you are putting the item on a shelf to inside a box - or even burying it in the ground.
Reactions when an item is manipulated
There are a similar set of function attributes that get called (if they exist) after the event. Note that a message saying this happened will already have been shown. The function will be sent the same dictionary of options.
Function | On | Extra options |
---|---|---|
afterExamine | Item | |
afterMove | Item | toLoc, fromLoc, end |
afterDropIn | Location or container | item |
afterTakeOut | Location or container | item |
afterWear | Item | |
afterRemove | Item | |
afterOpen | item | |
afterClose | item | |
afterLock | Item | |
afterUnlock | Item | |
afterSwitchOn | Item | |
afterSwitchOff | Item | |
afterCarry | Item | exit |
afterPurchase | item | |
afterSell | item | |
afterFill | Item | fluid, source |
afterEmpty | Item | fluid, sink |
afterPostureOn | Furniture | posture |
afterPress | Item | |
afterIngest | Item | |
afterAttach | Item | item |
afterDetach | Item | item |
Note that while TAKE and DROP are tested separately, there is a single "afterMove" that handles both, and possibly other scenarios too. There is no "afterGive" as it is assumed this will be handled on an individual basis anyway.
This example might be for a tree location. Anything dropped it will end up on the path below.
afterDropIn:function(item) { item.loc = 'woodland path' }