Table of Contents
Before you start…
…you should skim through the Adventure Script Player short manual. You probably should also try to play an example game, if you haven’t played any already.
The Basics
Learning Adventure Script isn’t hard and doesn’t require any knowledge whatsoever. In fact Adventure Script was designed to be easy. Believing is always the first step so repeat after me:
It’s easy.
I’m 100% capable of learning it.
I can do it.
Introducing Mary and Lucy
Let’s start from somewhere, look at the following line:
say "Mary looked at Lucy"
You can probably deduce that it will display the quoted text to the player. Now look at this line:
say mary "Lucy you monster! You seduced my mother's sister's fifth child which is also somehow my brother's ex-wife!"
This time we specified who will say the quoted text – Mary. As the first example had no speaker it was treated as narration. But who is Mary? We need to introduce her:
object mary "Mary the Wicked"
Let’s also introduce Lucy:
object lucy "Lucy the Spiteful"
And let’s put them into a room:
location room "Palace living room" object mary "Mary the Wicked" object lucy "Lucy the Spiteful"
That’s a lot of things to explain but they all should be quite intuitive.
Objects
Let take a look at Mary. object
informs that we are introducing a… well… object? Like a knife, unicorn anything else you can think off. Then comes the object’s identifier, in Mary’s case mary
. Think of it as of a computer file’s name. It will be used to refer to Mary – like we did by writing say mary
in one of the first examples. After the object’s identifier comes the object’s name written in quotes. This is how Mary will be displayed to the person playing the game.
Locations
That was easy, now what’s a location? A location is a well… you know… a location. In life locations usually consist of stuff (objects) in them. The same here! Easy right? Marvelous! Let’s move on. Locations just like objects have identifiers and names. How do we specify which objects are in a which locations? That’s where indentation comes in. There’s a tabulator before Mary and Lucy informing that they are in fact in the living room. You can make tabulators with the Tab key on your keyboard. Keep in mind that a tabulator is not the same thing as multiple Space! (but it looks the same)
Skipping stuff
Let’s take a quick look at the next example:
location cave object "angry dwarf"location "Quite magical Forest" object elfobject knife "rusty knife"
First of all the dwarf is in a cave, the elf is in a forest and the knife is in no specific location whatsoever. But look, the object
and location
declarations look different! The cave doesn’t have a name and the dwarf doesn’t have a identifier! How can that be! Well, we can skip one of these elements, but not both. When we skip the name it becomes the same as the identifier. When we skip the identifier we can not refer to this location (or object) later on.
Our first game
Let’s go back to Lucy and Mary and write something that actually does something. To do so we need do learn how to write events. First of all we need an on create
event that fires when the games starts. Let’s keep it simple:
on create goto roomlocation room "Palace living room" object mary "Mary the Wicked" object lucy "Lucy the Spiteful"
And look! It’s a actually working game! You can see it in action here! If you feel courageous enough you can also open it in the editor. We will get to how to use it in the next chapter.
Making stuff do things
Let’s learn about events. Without them the game can’t really do anything. Every event starts with an on
and then is followed by the event name. There’s lot of different events but for now let’s just introduce two:
on prompt
– executed each time an location or object is displayed to the playeron use
– executed when the player selects the “use” option in the opened object’s menu
See them in action in he following example:
on create goto roomlocation room "Palace living room" on prompt say "Two angry women are arguing here. It's awfully loud." object mary "Mary the Wicked" on prompt say mary "I'm busy shouting at Lucy, go away" on use say "You stab Mary in the heart. She dies. Lucy shuts up. She looks quite content." hide mary object lucy "Lucy the Spiteful" on prompt say lucy "Wanna taste ma fists? No? Then stop looking at me!" on use say "You try to stab Lucy. She grabs your hand in mid air." say lucy "Oh, I will enjoy this..." say "You get slowly punched to death." goto endlocation end "Game Over" on prompt say "You died. Welp, that's what you get for killing people."
You can (and should) play this game or open it in the editor.
So, as you can see, an event consists of actions in the same way that a location consists of objects. That means that actions need to be indented (with tabulators) to be included in an event. But what are these “actions”? For know let’s introduce some of them (listed below).
Basic actions
say "text"
– display narrationsay object "text"
– display a dialog lineequip object
– put an object into inventoryunequip object
– remove an object from inventoryshow object
– make an object visible in it’s locationhide object
– make an object invisible in it’s locationgoto location
– change current location
Actions are executed one-by-one, in the order they where written. goto
is a special action as it ends the event after being executed. What does that mean? Well, let’s consult an example:
on create goto room say "Don't mess with Lucy!!"location room "Palace living room" on prompt say "Two angry women are arguing here. It's awfully loud."
“Don’t mess with Lucy!!” will never be displayed as the goto room
action terminates the on create
event. I hope that’s clear.
Skipping stuff
We’ve done one more thing in the last example. Look at the living room’s on prompt
event. It looks different! If an event has only one action you can write it the same line without an indent! This makes the games much more compact and easier to read.
Commenting stuff
Comments are a useful thing – they are just portions of text that have no affect on the game. They are added to leave some information for the person reading the game’s code. Like side-notes on a draft of a book. Read the comments in the following example to understand how to write them:
# single line comments #= and mutliple line commentsaka "block comments" =# # comments can ignore # indentation rules # as they are ignored object dwarf # comments can also end a line...object #= ...and be inside a line =# dwarf
I will use comments to explain or highlight things directly inside the examples.
Conditioning stuff
You probably noticed that after Mary died the living’s room prompt still said “Two angry women are arguing here. It’s awfully loud.”. Let’s fix it:
on create goto room # a one-action event written in a single linelocation room "Palace living room" on prompt if mary.hidden # this is new! say "It got quiet. Mary is in a pool of blood on the floor. Lucy's looks at you cautiously" else say "Two angry women are arguing here. It's awfully loud." object mary "Mary the Wicked" on prompt say mary "I'm busy shouting at Lucy, go away" on use # this event has two actions so it can't be written in a single line say "You stab Mary in the heart. She dies. Lucy shuts up. She looks quite content." hide mary object lucy "Lucy the Spiteful" on prompt say lucy "Wanna taste ma fists? No? Then stop looking at me!" on use say "You try to stab Lucy. She grabs your hand in mid air." say lucy "Oh, I will enjoy this..." say "You get slowly punched to death." goto endlocation end "Game Over" on prompt say "You died. Welp, that's what you get for killing people."
You can play this game or open it in the editor.
Two things have changed. First, the one-action events where made compact. Second, the living’s room on prompt
event changed, and look! A condition! Conditions allow to selectively preform actions, choosing them with regard to some kind of information (in our example the visibility of Mary). So how does one write a condition?
Conditions
First comes an if
, then an expression (which can be quite complex – we will get to that later on). In our example the expression is equal to mary.hidden
. After the if
and the expression we write indented actions that are to be executed only if the expression is true. Actions belong to conditions, just like actions belong to events or objects belong to locations. After we finish adding actions to the condition we can (but not have to) write else
followed by another portion of indented actions. These actions will be executed only if the expression was false. In other words:
if expression # to be executed only when 'expression' is true action action ...# the condition can end here or we can add 'else' as shown belowelse # to be executed only when 'expression' is false action action ...
Skipping stuff
Again we can make things more compact. If a condition has only one action we can write it in a single line:
if mary.hidden say "It got quiet. Mary's in a pool of blood on the floor and Lucy's looks at you cautiously"else say "Two angry women are arguing here. It's awfully loud."
or even (but it’s ugly so don’t do it too much):
if mary.hidden say "It got quiet. Mary's in a pool of blood on the floor and Lucy's looks at you cautiously" else say "Two angry women are arguing here. It's awfully loud."
side-note: because of a bug shortened conditions get colored incorrectly. In the examples above the
say
actions are white when they should be yellow. Unfortunately no good solution was found to resolve this issue.
Referring to stuff
But there’s still one thing unexplained. What does mary.hidden
mean? We got to the hard part – mary.hidden
is a variable. Remember how I told you that object and location identifiers are like file names? Well, there’s more to that.
Containers
In fact objects, locations and even events are more like folders. We will call them containers as they contain things. Let’s continue the file and folder analogy:
hidden
is a file (with contents equal to true or false) inside of a folder calledmary
.mary
is a folder inside of a folder calledroom
(the living room)room
is a folder inside a folder calledroot
root
is the topmost folder (like theC:
drive of your computer).
Variables
So what is a variable? If folders were an analogy to containers and files were an analogy to values then by saying “a variable” we mean a folder or a file. It’s anything in the game that we can somehow reference (refer to). So how do we refer to things? The easiest (but highly unpractical) way is to use full paths – for example the hidden
value inside mary
has a full path equal to root.room.mary.hidden
(it’s just like a file path, but with dots instead of slashes). Paths can be shortened depending from the context they are used in. That may sound a bit cryptic but it’s really simple and intuitive. When inside the living room mary
refers to Mary The Wicked. There could be other variables named mary
somewhere else and to reference them we would need to use appropriate paths.
Contexts
To understand better what a context is take a look at the following example:
object knifelocation cave object knifelocation meadow object dwarf
Imagine that with each level of indentation you climb a tower. While on this tower you can look only directly below. When asked for an item you find the closest item matching the description in the range of your sight. In the example above while on the ground you see a knife
, and two towers – the meadow
and the cave
. As you can’t look up, you don’t know whats on top of them. Once you climb a tower, let’s say the meadow
tower, you find a dwarf
. You can also look directly below to see the knife
on the ground and the base of the cave
tower, but you can’t look sideways to see what’s on top of it. If you climb the cave
tower, you will see two knifes – one from the tower and one on the ground. But the knife
on the tower is closer, so you prefer it. Also, while on the cave
tower you can’t see the dwarf. He’s on the neighboring tower and you can’t look sideways.
To summarize let’s list all the different contexts in the example above and show how to refer to each variable from inside each of them:
The root
context:
Full path | Shortest path |
---|---|
root.knife |
knife |
root.cave |
cave |
root.cave.knife |
cave.knife |
root.meadow |
meadow |
root.meadow.dwarf |
meadow.dwarf |
The cave
context:
Full path | Shortest path |
---|---|
root.knife |
root.knife |
root.cave |
cave |
root.cave.knife |
knife |
root.meadow |
meadow |
root.meadow.dwarf |
meadow.dwarf |
The meadow
context:
Full path | Shortest path |
---|---|
root.knife |
knife |
root.cave |
cave |
root.cave.knife |
cave.knife |
root.meadow |
meadow |
root.meadow.dwarf |
dwarf |
Skipping stuff
Yes, it’s this paragraph once again. The thing is that full paths can skip the root
and start from a dot character. In other words .meadow.dwarf
is a abbreviation of root.meadow.dwarf
(but doesn’t have to be same thing as meadow.dwarf
– there could be a meadow
in the current context different from the meadow
in the root context).
Combining stuff
Let’s take a break from variables and do something fun. It’s time to put the inventory into use. As it has been already said, objects can be put in and out the inventory using the equip
and unequip
actions. It has also been said in the Adventure Script Player manual that objects inside the inventory can be combined with each other and with objects inside the current location. So how do define what should happen when the players decides to combine something? Take a look at the following example game:
on create goto room # 'equipped' is a object modifier. We will talk about them some time later.# Thanks to it the knife will be in the inventory when the game startsequipped object knife "Knife" on prompt say "A blunt knife. Still good for stabbing" on use say "You stab yourself. You die. What have you been thinking?" goto end on combine bow say "You stab a bow. It's stupid. The bow breaks." unequip bow on combine room.mary # notice that we can not simply write 'mary' -- we are not in the 'room' location say "You stab Mary in the heart. She dies. Lucy shuts up. She looks quite content." hide room.mary on combine room.lucy say "You try to stab Lucy. She grabs your hand in mid air." say room.lucy "Oh, I will enjoy this..." say "You get slowly punched to death." goto end # 'any' matches any object. on combine any say "Unfortunately you can't stab that" object bow "Toy bow" on prompt say "Looks dangerous. It even came with a toy arrow." location room "Palace living room" on prompt if mary.hidden say "It got quite. Mary is in a pool of blood on the floor. Lucy's looks at you cautiously" else say "Two angry women are arguing here. It's awfully loud." object "Weapon stand" on prompt say "There are some fine weapon here!" on combine bow say "It won't do much damage to it" on use # [object].equipped is true if an object is inside the inventory if bow.equipped say "Only toy swords left." else say "The bow looks useful." equip bow object mary "Mary the Wicked" on prompt say mary "I'm busy shouting at Lucy, go away" on use say mary "You want to USE me? Right." say "You get punched in the face." on combine bow say mary "Yes, I'm terrified. Show me that arrow, will you?" say "You find yourself with an arrow in your eye. You die" goto end object lucy "Lucy the Spiteful" on prompt say lucy "Wanna taste ma fists? No? Then stop looking at me!" on use say lucy "Of course you can use me!" say "You get punched in the face." say lucy "That was sarcasm." say "You get punched in the face." on combine bow say mary "Is that a toy bow? You want to HURT me with that?" say "You get disarmed and Mary breaks the bow in half." unequip bow location end "Game Over" on prompt say "You died. Welp, that's what you get for messing with insane women."
You can play this game or open it in the editor.
The on combine event
As you probably noticed the on combine
event is a bit different from the events we’ve been using so far. After the usual on
and the event’s name comes a third element – the target object. An on combine
event is executed when the player combines the target object with the object that the event is defined in. It is also executed when the reversed situation occurs – an on combine bow
event inside the knife
could be rewritten as an on combine knife
inside the bow
and would still do the same thing.
Wildcard targets
A wildcard target is a special target that matches any object. We used it in the example above in the knife
object. When two objects are combined and they don’t have an appropriate on combine
event, then a event with a wildcard target is executed instead (if one is defined). To create an on combine
event with a wildcard target we simply write any
instead of the target object.
What if both objects have an on combine
event with a wildcard target? When combining two objects the second one always have priority. Consider the player used the bow
on the knife
and they both have a event with a wildcard target. The knife’s on combine any
event will be executed (but only if there was no on combine knife
inside the bow
and no on combine bow
inside the knife
). If it’s still unclear try playing the following example and combine the bow
with the knife
and then the knife
with the bow
(in the inventory).
on create goto testequipped object knife on combine any say "Knife wildcard"equipped object bow on combine any say "Bow wildcard"location test
Like always, you can also open this example it the editor.
Talking with stuff
One more thing left in this chapter – writing dialogs. I won’t hide that creating complex dialog trees is quite tricky, as it requires understanding what trees are. That’s why for now I will only show you how to make really simple dialogs. Let’s start with a example:
on create goto meadow object axe "Dwarf's Axe" on prompt say "A beautiful example of dwarf craftsmanship." location meadow "Meadow" on prompt say "A boundless meadow, covered with a variety of spring flowers." object dwarf "Sad looking dwarf" on prompt say "A beardless, clean and cinnamon smelling dwarf." on use goto foo on combine axe say dwarf "Oh my..." say "You take a swing but the handle breaks and the blade falls on your head. You die." goto end dialog foo on prompt say dwarf "Yes, stranger?" option "Who are you?" say dwarf "I am a dwarf!" option "Why are you on a meadow?" say dwarf "I love grass, I hate caves. I'm quite an outcast." option axegive "Give me your axe" say dwarf "It sounds reasonable. Here take it." hide axegive equip axe option "I have to go" say dwarf "See you later!" goback location end "Game over" on prompt say "You died."
You can play this game or open it in the editor.
Two new elements appeared in this example: dialogs and contained in them options.
Dialogs
Dialogs are basically containers for options, but they can also contain events. When in a dialog, options are displayed to the player in a similar way that objects are displayed in a location.
To create a dialog write dialog
followed by an identifier. Then add appropriately indented events and options. For now let’s consider only the on prompt
event, executed each time the dialog is displayed to the player.
To enter a dialog use the goto
action the same way you would enter a location. To exit a dialog use the goback
action (described below) or enter a location with the goto
action.
In the example above the dialog was placed inside an object (the dwarf
). Notice that when the player is inside the dialog the header says “Dialog with Sad looking dwarf”. We can also place the dialog inside a location or in the root context but then the header will simply say “Dialog”.
Options
Options are something between events and objects. Just like objects they have identifiers and names but inside they contain actions like events. These actions are executed when the player clicks on a option inside a dialog.
Options can be hidden and shown using the hide
and show
actions just like objects. A hidden option will not be displayed to the player.
Inside options a special goback
action is available. Use it to exit the current dialog. Keep in mind that that just like goto
it terminates the current option after being executed.
To create an option write option
followed by an identifier and a name. Then add any amount of appropriately indented actions.
A short interlude…
…is recommended for reading the Adventure Script Editor manual. You already know enough to create and modify simple games. After reading it try playing with examples in this document. Add some objects, write some events – it will help you understand things a hundred times faster. If you make a mistake the editor will display an error, which for now will probably seem like cryptic gibberish. Don’t worry, we will get to them some time later. For now all I have for you is a small tip – if you see enigmatic baloney like this:
stack trace:
[5] /runtime/game.as:rret:57
[4] /game/main.as:bow:5
[3] /runtime/runtime.as:safecall:87
[2] /runtime/game.as:rrot:117
[1] /game/main.as:root:4
then it means that you made a mistake somewhere near line 5
of the /game/main.as
file it the bow
object. Always look at the topmost line of such messages that has a file from your project in it. The number on it’s end will be the number of the line that caused the error to occur.
One more thing before we move further: there is an useful print
command that can be used to print any variable / value / expression in the editor’s event log. Just like this.
Events
This chapter will focus on describing events in more detail. The last section contains a reference of all available events. Some sections of this chapter describe advanced features of Adventure Script. Beginners should skip them.
Object events
All object events have exactly the same functionality: when defined in an object they are displayed to the player in the object screen and executed when the player clicks on them. What’s more object events are user-defined, meaning you can create any object event you want, like stab or pickpocket.
There are three object events predefined inside the dafults.as
file that is included to each new project. Let’s took a look at them right now:
defineevent "use" "use" "fa-gears"defineevent "talk" "talk to" "fa-comments"defineevent "pickup" "pick up" "receive"
An object event is added by writing defineevent
followed by the event name in quotes. Then come three optional parameters also written in quotes: the display name, icon and background color. For example to define an on stab
event with red background and dagger icon we would write:
defineevent "stab" "Backstab" "curved-dagger" "tomato"on create goto Romelocation Rome object Cesar on stab say "Ouch!"
You can play this game or open it in the editor.
Object events need to be introduced before they are used for the first time. In the example above writing the defineevent
after the Cesar
object would result in the following error:
RUNTIME_ERROR: unknown event stab
System events
System events are executed on various occasions and unlike object events are hard-coded (no new system events can be added). Different types of these events can be defined inside different elements of the game. For example the on create
event can only be defined in the root namespace (context), while the on prompt
event can be defined in locations, objects and dialogs. A full list of different events with their desccirpion can be found in the event reference.
Template events
This section describes a feature that may prove to be harder to understand. Feel free to skip it and come back to it later.
A template event is an event defined outside of its normal context. For example an on equip
event defined inside a location. All elements inside a context with a template event will inherit this event unless they define their own event of the same type overriding the template event. The following example demonstrates an on use
template event:
on create goto meadowon use say "Hello from the root context!" # template event location meadow on prompt say "Trying using the dwarf and the elf." on use say "Hello from the meadow context!" # template event, # overrides the template event in the root context object dwarf on prompt say "Use me." on use say "Hello from the dwarf context!" # normal event, # overrides the template event in the meadow context object elf on prompt say "Use me." # no 'on use' event, the template event in the meadow context will be inherited object "passage to the cave" on trigger goto cave location cave on prompt say "Trying using the knife and the bow." object knife on prompt say "Use me." # normal event, # overrides the template event in the root context on use say "Hello from the knife context!" object bow on prompt say "Use me." # no 'on use' event, the template event in the root context will be inherited object "passage to the meadow" on trigger goto meadow
You can play this game or open it in the editor.
Predefined template events
The defaults.as
file comes with the following template events predefined:
on equip
on unequip
on combine any
on inventory
Feel free to change them to further customize your games.
Limitations
Not all events can have template events. Consult the event reference for further information on this matter.
Accessing the caller context
A template event’s context it equal to the context it has been defined in (just like normal events). This makes it impossible to determine in which context the event was called (executed) in – for example a template on equip
event has been called. But what object was equipped?
To solve this issue a special variable context
was made accessible inside all events. This variable points to the context that the event was called on. For example the on equip
template event inside defaults.as
has the following definition:
on equip say "Equipped \name{$context}."
Inside non-template events context
is equal to parent
.
Canceling events
All events can be canceled. Canceling an event causes it to immediately terminate and usually causes some special effect. These effects have been described in the event reference.
To cancel an event simply write return true
in it’s body. The following example demonstrates cancelling an on inventory
event:
on create goto testlocation test on prompt say "Try opening the inventory." on inventory say "This can not be done!" return true
You can play this game or open it in the editor.
To terminate an event without triggering the special effect use return false
or simply return
.
Disabling events
This section describes an advanced feature of Adventure Script.
Events can be disabled. Disabled events are ignored as if they were not defined. Following functions (actions) are used to disable an event:
disable container "event name"
disable container "combine" object
disable container "combine" .rt.game.wildcardobject
And similarly to enable an disabled event:
enable container "event name"
enable container "combine" object
enable container "combine" .rt.game.wildcardobject
Container should be a namespace / location / object / dialog containing the event to be disabled. The event name needs to be written in quotes. Writing disable container "combine"
will disable all combine events inside the chosen container. To disable a specific combine event the target object has to be specified. To disable the wildcard combine event .rt.game.wildcardobject
has to be used as the target object. An event can be also disabled by adding the disabled
modifier to it’s declaration.
An example demonstrating how disabling and enabling events works is shown below.
on create goto teston trigger say "Hello from root!"location test "disable demo" on prompt say " .ontrigger.disabled = $.ontrigger.disabled\br .test.ontrigger.disabled = $.test.ontrigger.disabled\br .test.run.ontrigger.disabled = $.test.run.ontrigger.disabled\br " on trigger say "Hello from test!" object run on trigger say "Hello from run!" on prompt say "All trigger events disabled" goto test object 'disable root "trigger"' on trigger disable root "trigger" object 'disable test "trigger"' on trigger disable test "trigger" object 'disable run "trigger"' on trigger disable run "trigger" object 'enable root "trigger"' on trigger enable root "trigger" object 'enable test "trigger"' on trigger enable test "trigger" object 'enable run "trigger"' on trigger enable run "trigger"
You can play this game or open it in the editor.
Manually calling events
This section describes an advanced feature of Adventure Script.
Events can be called (executed) manually using the do
function with a syntax similar to the enable
/ disable
functions:
do container "event name"
do container "combine" object
Container should be a namespace / location / object / dialog containing the event to be called. The event name needs to written in quotes. If the container does not have the specified event, then a appropriate template event is executed (if present).
If no event or template event is found the function returns none. In other cases it returns the value returned by the event it executed.
Event reference
This section may make use of concepts not yet explained, like namespaces or string interpolation. For now ignore fragments you don’t understand and come back to them later.
Complete Adventure Script event reference:
- on create
- on prompt
- on enter
- on leave
- on inventory
- on trigger
- on equip
- on unequip
- on show
- on hide
- on combine
- object events
on create
This event is executed once the game start. Is should set the initial location of the game. Can not be canceled.
Can be defined in:
- root namespace
on prompt
Executed upon displaying a location / object / dialog screen. Used primary to set the prompt. Canceling this event has no special effect.
Can be defined in:
- locations
- objects
- dialogs
on enter
In locations this event is executed when the player enters the location this event is defined in. The player’s location needs to change for this event to be executed – using goto
to the current location will not execute this event. Canceling this event prevents the location change – the players stays in the location he was trying to leave.
In dialogs this event is executed when the player changes or moves down in a dialog sub-tree. This is explained in more detail in the dialogs chapter. Canceling this event prevents the dialog change.
Can be defined in:
- locations
- dialogs
on leave
In locations this event is executed when the player leaves the location this event is defined in. The player’s location needs to change for this event to be executed – using goto
to the current location will not execute this event. Canceling this event prevents the location change – the players stays in the location he was trying to leave.
In dialogs this event is executed when the player changes or moves up in a dialog sub-tree. This is explained in more detail in the dialogs chapter. Canceling this event prevents the dialog change.
Can be defined in:
- locations
- dialogs
on inventory
Executed before the inventory opens. Used primary to set the inventory prompt. Canceling this event will prevent the inventory from opening. This allows restricting the player access to the inventory when needed. The following on inventory
event is predefined in the defaults.as
file:
on inventory say "Inventory contents"
Can be defined in:
- locations
- namespaces (as template)
on trigger
Executed when the player selects an object from the location screen, just before the execution of the on prompt
event. This event causes an automatic return to the location screen upon finish – the object screen doesn’t get displayed and the on prompt
event doesn’t get executed. Canceling this event resumes the normal flow – the object screen gets displayed normally after executing the on prompt
event.
Simple example:
on create goto Meadowlocation Meadow on prompt say "Dwarfs on a meadow!" object "Normal dwarf" on prompt say "This is the normal dwarf" object "Trigger dwarf" on trigger say "This is the trigger dwarf"
You can play this game or open it in the editor.
Can be defined in:
- objects
- locations (as template)
- namespaces (as template)
on equip
This event is executed when an object is added to the inventory. Canceling this event causes the object to not be added to the inventory. The following on equip
event is predefined in the defaults.as
file:
on equip say "Equipped \name{$context}."
Can be defined in:
- objects
- locations (as template)
- namespaces (as template)
on unequip
This event is executed when an object is removed from the inventory. Canceling this event causes the object to not be removed from the inventory. The following on unequip
event is predefined in the defaults.as
file:
on unequip say "Unequipped \name{$context}."
Can be defined in:
- objects
- locations (as template)
- namespaces (as template)
on show
This event is executed when an object is set visible via the show
action. This event will not be executed if the object was already visible. Canceling this event causes the object’s visibility state to stay unchanged.
- objects
- locations (as template)
- namespaces (as template)
on hide
This event is executed when an object is hidden via the hide
action. This event will not be executed if the object was already hidden. Canceling this event causes the object’s visibility state to stay unchanged.
- objects
- locations (as template)
- namespaces (as template)
on combine
Combine events are executed when two objects are combined by the player. They’ve been described in more detail in the previous chapter. Canceling these event has no special effect. The following wildcard on combine
event is predefined in the defaults.as
file:
on combine any say "This can not be done."
Combine events also expose a special target
variable in their body allowing referring to the target object when the wildcard target is used. Short demonstration of this feature:
on create goto testlocation test on prompt say "Try combining objects in your inventory" on combine any say "context: $context" say "target: $target" hidden equipped object knife hidden equipped object bow hidden equipped object arrow
You can play this game or open it in the editor.
object events
Events displayed to the player in the object screen. Executed upon selection by the player. Canceling these events has no special effect. Read more about object events here.
Can be defined in:
- objects
- locations (as template)
- namespaces (as template)
Variables
The first chapter introduced variables, but did not specify how to modify their values or how to create new ones. This chapter will return to this subject and explain it in much more detail.
Why do I need variables?
Let’s start by answering the question from this section’s header. I’ll do it with a short example:
defineevent 'ignite'on create goto cave location cave on prompt if torch.lit say "IT'S THE SPANISH INQUISITION!" else say "It's too dark to see anything." object torch on prompt if torch.lit say "It's ignited." else say "It's not ignited." on ignite if torch.lit say "It's already ignited" else set torch.lit say "You ignite the torch."
You can play this game or open it in the editor.
Of course similar functionality could be achieved by defining an ignited torch and an unignited torch then hiding the first one and showing the second one. Variables are there to make things simpler. If you don’t want to use them you don’t have to. But do use them.
Special variables
They are four special variables that are available in every context:
root
referring to the root contextself
referring to the current contextparent
referring to the parent contextsuper
referring to the super element (used in inheritance)
It is very important to understand what self
refers to. Take a short look a the following code:
object example on use hide self # error!
The on use
event will fail with an error saying that we can’t hide an event. That shouldn’t be a surprise as self
in the on use
refers to the event itself, not to the object example
. To hide this object we should write hide parent
or hide example
. Notice that thanks to parent
we can write events that manipulate objects without identifiers:
object "I'm an object without an identifier" on use hide parent # it works!
The set command
To modify and create variables use the set
command. Writing set path
will set the variable referred by path
to true. Writing unset path
will set it to false. Other values, like numbers or strings can be set by writing set path expression
where expression
is any valid expression.
The set command can be used anywhere in the game’s code – not only in events. Commands outside events will be executed before the game starts.
Setting a variables value to none deletes it.
Some variables may be locked meaning that only the game itself can modify their value.
Invalid paths
Consider that you want to save a file on your computer. You are asked for a file path. If you provide a path to an existing file, this file will be overwritten. If you provide a path to an nonexistent file but all the folders on the way to it exist, this file will be created. If you provide a path with a nonexistent folder an error will be reported.
The same rule applies to variable paths in Adventure Script. A path is valid as long as all path elements excluding the last exist. Otherwise a NULL_REFERENCE
error is reported.
A valid path to a nonexistent variable will always be resolved as a special none value. In conditions none is treated them same way as false.
Creating variables
To create a variable simply use the set
command with a valid path to a nonexistent variable. There is but one limitation – the path needs to explicitly specify in which container to create the variable (in layman’s terms it has to have at least one dot in it). This is shown on the example below:
set foo # invalidset root.foo # validobject cave set boo # invalid set self.boo # valid set cave.boo # also valid
System variable reference
Many elements of the game have variables automatically created in them by the game itself. Like hidden
inside objects or disable
inside events. These variables can be accessed and modified like any other variable in the game. This section will show what system variables are available and what is their meaning.
text (string)
The text
variable is present in location, objects and options and is equal to their name. Changing it will alter the way they are displayed. Example:
on create goto cavelocation cave on prompt say "Is this realy a cave?" object dwarf on trigger say dwarf "The cave is a LIE!" set cave.text "The Great Meadow" # change the cave name
You can play this game or open it in the editor.
hidden (boolean)
The hidden
variable is present in objects and options. It is set by the show
and hide
functions (actions). Manually changing it’s value will change the object’s visibility state but will not trigger the on hide
and on show
events.
equipped (boolean)
The equipped
variable is present in objects. It is set by the equip
and unequip
functions (actions). This variable is locked and can not be changed manually.
disabled (boolean)
The disabled
variable is present in events. It is set by the disable
and enable
functions (actions). Manually changing it’s value has the exact same event as using the disable
and enable
functions.
icon (string)
The icon
variable is present in objects and options. Changing it’s value will change the the displayed icon. Example:
on create goto meadowlocation meadow on prompt say "Look at the paw!" object dwarf set self.icon "fa-paw"
You can play this game or open it in the editor.
bgcolor (string)
The bgcolor
variable is present in objects and options. Changing it’s value will change the the displayed background color. Example:
on create goto meadowlocation meadow on prompt say "It's not pink, it's salmon!" object dwarf set self.bgcolor "pink"
You can play this game or open it in the editor.
.data.location (location)
This variable holds the current location. It is locked and can not be changed manually.
.data.inventory (array)
This variable holds the inventory in form of an array of objects. It is locked and can not be changed manually.
Modifiers
Modifiers can be added to definitions of game elements. There are three basic modifiers:
hidden
– works with objects and options, causes them to be hidden when the game startsequipped
– works with objects, causes them to be equipped when the game startsdisabled
– works with events, causes them to be disabled when the game starts
Modifiers need to be specified as the first element of a definition. A single definitions can have more then one modifier, for example to define a hidden and equipped object knife
one can simply write:
hidden equipped object knife
The order of modifiers doesn’t matter.
Defining new modifiers
Understanding how to add new types of modifiers requires basic knowledge about functions and namespaces.
A new type of modifier can be added to the game by defining a one argument function in the .data.modifiers
namespace. The function’s name will become the name of the new modifier. Upon creating a game element preceded by this modifier the function will be called with the element passed in the argument. An example custom doorway
modifier is defined in the defaults.as
file:
function data.modifiers.doorway o::object set o.icon 'entrance'
This modifier sets the icons of the objects preceded by it to the ‘entrance’ icon. Note that the argument’s type has been set to object
, allowing this modifiers to be used only on objects.
Strings
Text values written in quotes are called strings. This chapter will describe them in detail. The probably most interesting part of this chapter will be about patterns which are used to format the text displayed to the player.
String syntax
Don’t read this section if you don’t know squat about programing.
There are two types of strings – single quoted ('
) and double quoted ("
) strings. There is a slight difference between them.
Double quoted strings are interpolated and can use patterns. They also ignore white spaces used inside them (just like paragraphs in HTML). The $
, ~
, "
and /
symbols inside them need to be escaped with the /
escape character.
Single quoted strings are literal strings, only the '
and /
need to be escaped inside them (also by the /
escape character).
Both type of strings can be multi-line, what has already been shown for example in this section’s example on prompt
event.
HTML entitles inside strings are automatically escaped during compilation. This feature can be disabled by writing #!unescaped_strings
in the begin of a source file. Doing so allows usage of raw HTML inside such file. Be warned that every tag that’s not a span
or br
gets stripped by the Adventure Script Player.
String interpolation
Don’t read this section if you don’t know squat about programing.
Double quoted strings support string interpolation with the use of the $
character:
- variables can be inserted into strings by writing
$variable
- expressions can be inserted into strings by writing
$(expression)
${function a b c}
is a syntax sugar for$({function a b c})
Short example:
print "variables inside strings: $.data.location"print "expressions inside strings: $(16+32)"print "function calls inside strings: ${math.pow 2 5}"
Patterns
Patterns are a useful feature of Adventure Script that among other things allow formatting the text displayed to the user. Using predefined patterns i very easy but creating new ones can be tricky and requires much more knowledge.
Formatting of headers and prompts in the Adventure Script Player’s screens is realized by patterns defined in the defaults.as
. Feel free to modify them to further customize your games.
Each pattern has a name. For example the pattern bold
can be used to make a portion of text bold. To use this pattern inside a string write a \
followed by the pattern name (bold
) and the text to be made bold surrounded in curly brackets ({
and }
). Just like this:
say "The word \bold{meadow} is made bold."
bold
is a one-argument pattern, as you only specify the text to be made bold. Some patterns can have more arguments, for example to use the color
pattern you have to specify the color and the text. To make a portion of text red one would write:
say "The word \color{red}{meadow} is made red."
In this example the first argument is ‘red’ (the color) and the second is ‘meadow’ (the text). Arguments are written one after another, each one surrounded in curly brackets.
Patterns can be mixed together, for example:
say "\bold{This text is in bold. \color{red}{This text is bold and red}}"
All available patterns are listed in the pattern reference.
Creating patterns
This section describes an advanced feature of Adventure Script.
Patterns can be defined in two different ways: as template strings or pattern functions.
Template string patterns
A pattern can be defined by writing pattern
followed by a name and template string. A template string is a string with placeholder variables. Placeholder variables are numbered from zero, each number corresponding to subsequent arguments of a pattern. For example the color
pattern is defined in the following way:
pattern color "<span style=\"color:$0\">$1</span>"
Function patterns
A pattern can be defined by writing pattern
followed by a name and a function body. Arguments of the pattern are created automatically and are called _n
where n
is the argument number (starting from zero). The function body should return the result string. For example the nbsp
pattern is defined in the following way:
pattern nbsp if {istype _0 'string'} set _0 {atof _0} local out '' while _0 > 0 set out out+' ' set _0 _0-1 return out
Pattern reference
Adventure Script predefined pattern reference:
Example usage of all of these patterns has been shown in the code below:
on create goto testlocation test "Patterns demo" on prompt say "\span{font-style:normal}{ \bold{bold text}\br \emph{italic text}\br \color{red}{colored text}\br \bgcolor{red}{coloted background}\br multiple\nbsp{4}spaces\br ~~multiple~~~~spaces~~\br \span{font-family:'Comic Sans MS'}{styled span}\br \name{$test} }"
You can play this game or open it in the editor.
\bold{text}
Makes text bold.
Arguments:
- text fragment
\emph{text}
Makes text italic.
Arguments:
- text fragment
\color{color}{text}
Set text’s color.
Arguments:
- color
- text fragment
\bgcolor{color}{text}
Set text’s background color.
Arguments:
- color
- text fragment
\nbsp{number}
Inserts multiple non-breaking spaces. Writing a ~
inside a string is a shortcut for \nbsp{1}
.
Arguments:
- number of non-breaking spaces to be inserted
\br
Inserts a line break.
No arguments.
\span{style}{text}
Inserts a styled HTML span element. Only the following CSS properties are allowed:
- color
- background-color
- font-style
- font-weight
- font-family
- text-decoration
Arguments:
- list of CSS properties (the content of the
style
HTML attribute). - text fragment
\name{variable}
Inserts the name of a game element.
Arguments:
- path to the element
\ignore{argument}
Does nothing with a pattern argument.
Arguments:
- pattern argument
Dialogs
This chapter is sh*t. I’ll write a better one someday.
A dialog tree is created by defining dialogs inside dialogs. The position of a dialog in a dialog tree effects the way on enter
and on leave
events are executed. There are two special actions that can be used inside dialog options:
goback
– moves one level up in the dialog treequit
– exits the whole dialog tree
Play the following example and observe how the on enter
and on on leave
are executed:
on create goto demo dialog main on enter say "I entered the main dialog" on leave say "I left the main dialog" on prompt say "Hello from the main dialog" option "enter first child" goto firstchild option "enter second child" goto secondchild option "enter inner child" goto firstchild.innerchild option "exit" quit option "goback" goback dialog firstchild on enter say "I entered the first child dialog" on leave say "I left the first child dialog" on prompt say "Hello from the first child dialog" option "enter main" goto main option "enter second child" goto secondchild option "enter inner child" goto innerchild option "exit" quit option "goback" goback dialog innerchild on enter say "I entered the inner child dialog" on leave say "I left the inner child dialog" on prompt say "Hello from the inner child dialog" option "enter main" goto main option "enter first child" goto firstchild option "enter second child" goto secondchild option "exit" quit option "goback" goback dialog secondchild on enter say "I entered the second child dialog" on leave say "I left the second child dialog" on prompt say "Hello from the second child dialog" option "enter main" goto main option "enter first child" goto firstchild option "enter inner child" goto firstchild.innerchild option "exit" quit option "goback" goback location demo on prompt say "Open the dialog and observe how events are executed." object "start dialog" on trigger goto main
You can play this game or open it in the editor.
The on enter
event is executed when the player moves up in the dialog tree (for example from firstchild
to innerchild
). The on leave
event is executed when the player moves down in the dialog tree (for example from innerchild
to firstchild
). When the player moves sideways both events are executed (for example from firstchild
to secondchild
).
Expressions
Ugh, this chapter came out to be unreadable for people without basic programing skills.
A expressions is a mix of values, variables and operators.
Values
Adventure Script has the following scalar types:
- string (
"text"
or'text'
) - undefined (
none
) - numeric
- number (
12
or12.12
or1.12e10
or0x12
or0b10010
) - boolean (
true
andfalse
)
- number (
Operators
Operators in Adventure Script in the order of their precedence:
Operator | Description | Argument types | Example | Result |
---|---|---|---|---|
|| , or |
logical or | any | false or 2 |
2 |
&& , and |
logical and | any | false and 2 |
false |
| |
bitwise or | numeric | 1 | 3 |
3 |
^ |
bitwise xor | numeric | 1 ^ 3 |
2 |
& |
bitwise and | numeric | 1 & 3 |
1 |
== |
equal to | any | 1 == 1 |
true |
=== |
typed equal to | any | 0 === false |
false |
!= |
not equal to | any | 1 != 1 |
false |
!== |
typed not equal to | any | 0 !== false |
true |
< |
greater then | numeric | 2 < 1 |
true |
<= |
greater equal | numeric | 2 <= 2 |
true |
> |
greater then | numeric | 2 > 1 |
false |
>= |
greater equal | numeric | 2 >= 2 |
true |
<< |
left shift | numeric | 1 << 3 |
8 |
>> |
right shift | numeric | 8 >> 3 |
1 |
- |
minus | numeric | 2 - 1 |
1 |
+ |
add | string, numeric | 2 + 1 |
3 |
* |
multiplication | numeric | 2 * 1 |
3 |
/ |
division | numeric | 2 / 1 |
2 |
% |
modulus | numeric | 2 % 1 |
0 |
! ,not |
logical negation | any | !true |
false |
~ |
bitwise negation | numeric | ~1 |
-2 |
@ |
reference extraction | @variable |
reference | |
( … ) |
grouping operator | (1+2)*3 |
9 | |
[ … ] |
array literal | [1 2 3] |
array | |
{ … } |
function call | {math.pow 2 3} |
8 | |
c?a:b |
ternary operator | true?'a':'b' |
‘a’ |
Notes:
- logical operators are short circuited
- addition operator (
+
) can be used on strings to preform string concatenation - unary minus is weird:
2 - 1
is not the same thing as2 -1
but the same thing as(2 -1)
- content of each type off brackets can be spread over multiple lines
Type system
Complete type hierarchy in Adventure Script:
- any
- undefined
- reference
- unbounded
- defined
- array
- scalar
- string
- numeric
- number
- boolean
- container
- callable
- function
- dispatcher
- pattern
- event
- option
- namespace
- dialog
- inheritable
- location
- object
- callable
Notes:
- the only valid value of type
undefined
is none reference
can not be serialized (breaks save-games)- every sub-type of
container
can own member variables - every sub-type of
callable
can be called - every sub-type of
namespace
has it’s body executed during the build process - every sub-type of
inheritable
can inherit from elements of the same type
Namespaces
A namespace is the base type of dialogs, locations and objects. Namespaces have two main functionalities:
- they can have other namespaces and functions defined inside them
- any code written directly inside them will be executed during the build process
The special root
variable points to a predefined topmost namespace called root
with the parent
variable equal to none.
Creating namespaces
Namespaces can be created to scope your code, for example to define a group of locations in a chapter1
namespace for convince. To create a namespace write namespace
followed by a identifier. For example this is how the data.modifiers
namespace is defined inside Adventure Script run-time:
namespace data.modifiers function equipped obj::object equip obj false function hidden obj::container hide obj false function disabled obj::event disable obj
Extending namespaces
Remember that dialogs, locations and objects are namespaces. Everything that can be done with namespaces can also be done with them.
A already created namespace can be extended with additional elements outside of it’s block. This can be done in the following two ways.
Extend keyword
Write the extend
keyword followed by a namespace you want to extend, then open a block. Everything in this block will be executed it that namespace’s context.
Every Adventure Script source file extends the root
namespace this way. This is done automatically but could be written as:
extend root # source file contents
Path as identifier
Another way to extend a namespace is to use a path instead of an identifier in a element defection. For example this is done in the defaults
file to define a custom modifier:
function data.modifiers.doorway o::object set o.icon 'entrance'
This feature is quite useful when writing dialog trees. It can keep the indention level reasonably low by defining all inner dialogs on the same indention level.
Functions
This chapter assumes you have basic programing skills.
To call a function in Adventure Script one simply writes the function name (or a expression that resolves to a function) followed by a white-space separated list of arguments if form of expressions. So for example say lucy "hello"
calls the function say
with lucy
and "hello"
as the arguments. In fact every “action” presented in this manual (say
, goto
, equip
, …) was a function. But not set
and unset
, they are keywords.
Function calls can also be part of expressions. The syntax is exactly the same, but the call needs be surrounded by curly brackets ({ ... }
).
Here is a example of a complex function call taken from the Adventure Script run-time:
{index {index {index stack -2} 'options'} input}
It is equivalent to the following line written in a C-like language:
(index(index(index(stack,-2),'options'),input))()
Fun fact: functions, as well as everything else in the game can be named like a keyword as long as the name is enclosed in back-quotes (so you can define a
function `function`
).
Arguments
Function arguments are specified after the function name in form of a white-space separated list of names. Arguments can be typed and untyped and can be passed by value or reference. A argument type is specified by writing ::type
after it’s name (for example x::number
). By default every argument is untyped and passed by value. To pass an argument by reference add the reference extraction operator (@
) before the argument name. The argument may still specify a type. A good example of a function using untyped arguments passed by reference is the swap
function:
function swap @a @b local c a set a b set b c
More about references and the reference extraction operator in the references section below.
When a value of an invalid type is passed to a function with a typed argument a TYPE_ERROR
error is raised. All sub-types of the specified type are considered valid (for example specifying ::any
is equivalent to an untyped argument).
When a function is called with a different amount of arguments then specified in the definition a INVALID_ARRITY
error is raised.
Variadic functions
Variadic functions can be defined by adding the variadic
modifier to a function definition. The arguments can be accessed by calling the arguments
function, which will return them in form of an array. Named arguments may still be specified. The amount of named arguments determines the minimal arrity – calling the function with less arguments then the amount of the named arguments will result in a INVALID_ARRITY
error. The concat
function is a example of a variadic function without named arguments:
variadic function concat local arr {arguments} local i 0 local str '' while i < {length arr} local e {index arr i} set str str+{istype e 'string'}?e:{tostring e} set i i+1 return str
Locals
Adventure Script supports classical block-scoped locals. To define a local use the local
keyword followed by a name and a optional initial value. If the initial value is not specified none will be used. Look at the the concat
function in the section above for a example.
While and elseif
The only loop supported in Adventure Script is the while
loop with the following syntax:
while expression commands
Inside the while loop break
and continue
can be used.
Adventure Script also supports any number of elseif
blocks inside conditions:
if expression commandselseif expression commandselse commands
References
Adventure Script supports PHP style references. References are created by the reference extraction operator (@
). A newly created reference is unbounded and after it gets assigned to any variable it becomes bounded. Accessing a bounded references accesses the value of the referenced variable. Ugh, you know what? Just look at the example:
local a 5local b @alocal c blocal d @bset a a+1print a # 6print b # 6print c # 5print d # 6
Using the reference extraction operator on a reference makes an unbounded copy of it.
Warning: references don’t get serialized – they can’t be a part of save-games. Leaving a reference hanging somewhere in a global variable will crash the save process. So don’t do that.
Multiple dispatch
Multiple dispatch is implemented via dispatchers. The syntax is sadly pure crap. Here is the definition of the tostring
dispatcher and some of it’s member functions:
dispatcher tostringfunction tostring_container value::container extends tostring return "${path value}::${typeof value}"function tostring_numeric value::numeric extends tostring return value+''function tostring_string value::string extends tostring return '"'+value+'"'function tostring_any value::any extends tostring return '::'+{typeof value}function tostring_none value::undefined extends tostring return 'none'
A dispatcher is created by writing the dispatcher
keyword followed by a name. Any function can be added to the dispatcher by writing extends
after it’s argument list, followed by a path to the target dispatcher. Alternatively the push
function can be used with the first argument equal to the target dispatcher and the second to the function to be added.
Inheritance
OOP means something to you? No? Then you probably won’t understand a thing.
Locations and objects support inheritance in form of something similar to a prototype chain. The problem is that Adventure Script does not have prototypes or classes, only instances. Personally I think the resulting instance-to-instance inheritance chain is weird and confusing. And I wrote it!
To make A
inherit from B
write extends B
at the end of the A
definition (for example object A extend B
). The identifier can be skipped – is such case it will be taken form to element we inherit from (in other words we can write object extend B
to create a object B
in the current context that inherits from the original B
object… that didn’t help, didn’t it)?
Assume we write A.something
:
- if
something
is inA
we will access it - if
something
is insideB
and not inA
we will access it - if
something
is neither inA
andB
it will be created inB
To create / access a variable something
inside A
regardless if it’s in B
:
- Write
self.something
from insideA
- Use the
index
function
To create / access a variable something
inside B
regardless if it’s in A
:
- Write
super.something
from insideA
- Write
B.something
Of course events get inherited just like everything else.
Inheritance has been used in the example game. Open it and take a look at the object steve
and how it’s added to the home
location.
Understanding errors
There are three types of errors:
- parse errors
- VM errors
- runtime errors
Parse errors
The thing is nobody taught me how to write a compiler with nice error routines so I didn’t write them at all. Yup, that means that parse errors suck and they do it big time. Don’t even bother reading them. Just check the line number.
This code (missing say
before "Hello!"
)
on prompt "Hello!"
will result in something like this: Expecting 'NL', 'VARNAME', 'IF', 'WHILE', 'INDT', '{', 'CONTINUE', 'YIELD', 'BREAK', 'RETURN', 'THROW', 'LOCAL', 'SET', 'UNSET', got 'STRING_START'
. Beautiful isn’t it?
VM errors
There are four VM errors you are likely to see:
NULL_REFERENCE
– you tried to resolve an invalid pathVALUE_IS_CONSTANT
– you tried to set a locked variableINVALID_ARRITY
– you called a function with an incorrect number of argumentsTYPE_ERROR
– you called a function with an incorrect argument type
Each VM error includes a stack trace that allows localizing the error in the code.
Runtime errors
Here are some common runtime errors:
target destination for <type> <name> is not empty
– two elements have the same identifier in the same context (namespace)got NaN in math
– you f*** up some calculationsrestricted
– you tried to call a function that you aren’t allowed to callcould not find compatible function in dispatcher
– you called a dispatcher function with an invalid set of argumentsambiguity in dispatcher
– their are conflicting functions in a dispatcheruse of unknown modifier
– you probable misspelled a modifierevent <name> can not be defined in <type>
– you defined an event in a context it can’t be defined in (see here)unknown event
– you probably misspelled an event nameduplicated target <object> in 'on combine' event
– there are two events for the same target object in aon combine
eventobject <name> not found in event 'on combine <object>' of <namespace>
– an object specified as the target of aon combine
event was not found. The stack trace won’t be helpful for this error<name> in event 'on combine <object>' of <namespace> has wrong type
– the target of aon combine
event is not an object. The stack trace won’t be helpful for this errorunknown goto destination <name>
– you usedgoto
on something that’s not a location / object / dialog
Each VM error includes a stack trace that allows localizing the error in the code.
Stack traces
A stack trace shows what the virtual machine was doing in the moment the error occurred. Let’s take a look at an example stack trace and explain what information if holds:
stack trace:
[5] /runtime/game.as:rret:57
[4] /game/main.as:bow:5
[3] /runtime/runtime.as:safecall:87
[2] /runtime/game.as:rrot:117
[1] /game/main.as:root:4
The error occurred on line 57 of the file /runtime/game.as
during executing the rret
function. This is unhelpful as this file is part of the Adventure Script standard library and not your code. Let’s look at the line below to see where the rret
function was executed – on line 5 of the /game/main.as
file. This is the last line of your code executed before the error happened and most likely the localization of the error.
Runtime function reference
This chapter lists all functions available to the user.
All run-time functions are defined in the
rt
namespace and exported to the global context (root namespace). You can freely overwrite these exports.
General functions
index ::array ::number
returns an array array element with the given index in form of a bounded reference (see example below). Negative numbers can be used to index from the end.
local T [1 2 3 4 5]print {index T 2} # 3print {index T -2} # 4set {index T 2} 8 # sets T[2] to 8local v {index T 2} # v holds the VALUE 8local r @{index T 2} # r holds a reference to T[2]set v 9 # T[2] is still 8set r 9 # T[2] is now 9
index ::string ::number
returns a character with the given position. Negative numbers can be used to index from the end.
index ::container ::string
returns a container’s member in form of a bounded reference. index a b
is equivalent to resolve 'self.'+b a
.
length ::array
returns the length of a array
length ::string
returns the length of a string
push ::array [::any…]
adds elements to the end of an array
push ::dispatcher ::function
adds a function to a dispatcher
slice ::array ::number [::number]
see https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/slice
slice ::string ::number [::number]
see https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/String/slice
tostring ::any
returns the passed value converted to a string
find ::array ::any [::number]
see https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf
find ::string ::any [::number]
see https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/String/indexOf
export ::container
copies all elements from a container to the root namespace
export ::container ::string [::string…]
copies specified elements from a container to the root namespace
resolve ::string ::container
evaluates a path in a given context without searching through the given context’s parents. The result is returned in form of a bounded reference.
fullresolve ::string ::container
evaluates a path in a given context. The result is returned in form of a bounded reference.
exists::string ::container
checks if a path is valid in a given context. Returns a boolean value.
lock @::any
locks a variable
islocked @::any
checks if a variable is locked. Returns a boolean value.
istype @::any ::string
checks if a variable is of a given type (or it’s sub-type). Returns a boolean value.
typeof @::any
returns variable’s type as string
nameof ::container
returns container’s identifier as string
print [::any…]
prints values on the console / IDE event log
apply ::function ::array
calls a function with the argument list equal to the given array
arguments
returns current function’s argument list in form of an array
members ::container
returns all member names of a container in form of an array of strings
path ::container
returns a containers full-path in form of a string
atof ::string
converts a string to a number and returns it
concat [::any…]
converts all arguments to strings and returns a single joined string
swap @::any @::any
swaps two variables in-place
Math functions
see https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Math
- math.random
- math.abs ::numeric
- math.ceil ::numeric
- math.floor ::numeric
- math.round ::numeric
- math.sin ::numeric
- math.cos ::numeric
- math.acos ::numeric
- math.asin ::numeric
- math.atan ::numeric
- math.sqrt ::numeric
- math.tan ::numeric
- math.exp ::numeric
- math.log ::numeric
- math.pow ::numeric ::numeric
- math.atan2 ::numeric ::numeric
- math.min [::number…]
- math.max [::number…]
Note that Adventure Script functions raise errors on Infinity and NaN.
Array functions
array.create
returns an empty array
array.wrap [::any…]
returns an array created from the passed arguments (does the same thing as the [ ... ]
operator)
array.pop ::array
removes and returns an element from the top
array.shift ::array
removes and returns an element from the beginning
array.unshift ::array ::any
adds element to the beginning
array.clear ::array
clears an array
Game functions
say ::string
displays narration
say ::object ::string
displays dialog line said by an object
show ::object [::boolean=true]
shows an object. If second argument is false doesn’t execute on show
.
show ::option
shows an option
hide ::object [::boolean=true]
hides an object. If second argument is false doesn execute on hide
.
hide ::option
hides an option
equip ::object [::boolean=true]
equips an object. If second argument is false doesn’t execute on equip
.
unequip ::object [::boolean=true]
unequips an object. If second argument is false doesn’t execute on unequip
.
enable ::event
enables an event
enable ::namespace ::string [::object]
enables an event in the specified namespace. Third argument is the target object for combine events.
disable ::event
disables an event
disable ::namespace ::string [::object]
disables an event in the specified namespace. Third argument is the target object for combine events.
defineevent ::string [::string [::string [::string] ] ]
defines an object event with the specified name, text, icon and background color
do ::namespace ::string
executes an event in the specified namespace
dialogowner ::dialog
returns the object owning the specified dialog
goto ::any
goes to location / dialog / object screen. This function preforms a long jump.
goback
goes one level up in the dialog tree. This function preforms a long jump.
quit
quits the dialog tree. This function preforms a long jump.