How to Script

From Elanthipedia
Revision as of 23:00, 11 August 2013 by CARAAMON (talk | contribs) (→‎Labels)
Jump to navigation Jump to search
Caution.png
Read This First

Unless you are playing in The Fallen, scripting while unresponsive, regardless of your status at the keyboard, is against the rules. It is your responsibility to create scripts that will not continue endlessly, in case you fall asleep or have to leave the keyboard suddenly.
This is not a trivial matter and can result in experience penalties, character loss, or permanent lockout.
In game type "NEWS 5 17" to review DR scripting policy.

You have been warned.


This section will cover the most basic tools for scripting in the eScape and StormFront FEs.

Important Notes

  • Empty space before a command is ignored.
  • Empty lines are ignored.
  • If the end of the script is reached, the script exits.
  • All commands are case insensitive, though variables are not.
  • Only one command can be put on a line.

Simple Commands

  • # : Used for commenting, any line that begins with the number symbol is ignored by the script.
  • PUT <string>: This will cause the script to enter the string as if you typed it into the game and hit enter.
  • MOVE <string>: This will do the same thing as PUT, but will then pause the script until a new room is entered.
  • WAIT: This command will pause the script until a prompt is received. It is not affected by suppressing prompts in game.
  • WAITFOR <string>: This will pause the script until it sees the string.
  • WAITFORRE <string>: Same as WAITFOR but allows the use of Regular Expressions. See the advanced section for more details.
  • NEXTROOM: This will cause the script to wait until you enter a new room.
  • PAUSE <#>: This will pause the script for the indicated number of seconds.
  • SAVE: This is only useful in the Wizard, as it does not support standard global variables. See Variables section for the function that replaced it.
  • EXIT: This will end the script.

Labels

Labels are basically like signposts that you can cause the script to jump to. The most common way to cause a script to switch to a label is using "GOTO <label>" although MATCH/MATCHRE is another way.

A label is placed but putting a word on its own line, followed by a colon, such as

thisIsALabel:

Labels are not case sensitive, so "Label" is the same as "label" is the same as "lAbEl". Labels cannot have spaces in them, or anything after the colon.

Matches

The combined use of MATCH, MATCHRE and MATCHWAIT are essential tools for the majority of intermediate and advanced scripts.

The MATCH command is executed with two parts, the label and the match string, in the form of "MATCH <label> <string>". If the <string> is found, the script will immedately jump to the specified label.

Here's an example pulled from a real script (note: the numbers are the line numbers and are not part of the script):

1	putAway:
2	MATCH putAway ...wait
3	MATCH cycle Stow what?
4	MATCH cycle You are already wearing that.
5	MATCH cycle But that is already in your inventory.
6	MATCH cycle You
7	PUT stow my pickle
8	MATCHWAIT

The combination of lines one and two illustrate the most common use for for MATCH. If the game pops up "...wait x seconds" when you attempt a command, it will cycle back to the label on line one and attempt it again.

Lines 3-6 watch for the various outcomes of the command on 7, and will jump to the specified label upon detecting them. The fact that the label is the same regardless of the outcome is not important since any number of labels can be mixed.

Lastly, line 8 is a special command that tells the script "wait here until a match is found". This can either be desirable, such as if you're waiting for the barge and don't want to do anything till it shows up, or can be undesirable, such as when your action produces a result you didn't put in a MATCH for and will wait forever.

MATCHRE allows use of Regular Expressions in the search string. See the advanced section for details on regular expressions.

Match Order

An important thing to understand the order in which text is MATCHed. It can be thought of as being a first come first serve command. The first line with a MATCH result to come up triggers the MATCH. However, if a line contains two possible MATCHes, then it will go by the order in which the MATCHes are listed in the script itself. Therefor, it is a good idea to list them in order of importance.

MATCH Quirks

MATCH has some odd quirks that can be used for specialized purposes. A MATCH will keep looking for it's string until any MATCH is made. This is unimportant in the typical "MATCH table" such as the first example given above. But if no MATCHWAIT is used, the MATCHes will continue searching.

1	root:
2	MATCH root ...wait
3	MATCH run punches you
4	MATCH hide shoots you
5	PUT punch bob
6	PUT kick bob
7
8	retreat:
9	PUT retreat
10	.....

In the above example, since there is no MATCHWAIT it will punch, then kick, then head onto the retreat label. If somewhere down the line, "punches you" shows up, then it will suddenly divert to the run label, which can be good or bad.

Again, note that once any MATCH has been made, all previous MATCHes are removed.

In addition, MATCHes will not occur on text that shows up during a PAUSE or a WAIT, but will during a MATCHWAIT. This means including PAUSE or WAIT into a MATCH table will result in very odd behavior.

Variables

Variables are basically storage locations for words. They allow you to imput information in one place and retreive it at another. They are refered to using the syntax "%<variable name>" such as "%target" or "%person". Note: Unlike labels, variables are case sensitive; "%variable" is NOT the same as "%Variable" or "%vArIaBlE".

There are two main types of variables, and two special ones.

Command Line Variables

The first type is called a command line variable. When you start your script using the ".<scriptname>" method, after the name you can input up to 9 other words for storage. Example:

	.kill him andHim andHimToo her monkey randomGuy

These are then able to be accessed by the script. They are accessed using "%0" through "%9", with "%1" being the first word after the script name, "%2" being the second, etc. Note that "%0" is the same as putting "%1 %2 %3 %4 %5" .... "%9", listing out all the command line variables.

%0 is a special variable that contains all command line variables, including those beond %9.

If you want to use multiple words as a single variable, there are two ways to do this.

  • word_word_word
  • "word word word"

Unfortunately, command line variables cannot be changed once the script is started, with a few exceptions, the major one being SHIFT. Upon encountering SHIFT, "%1" is deleted, and the rest is shifted down one, with "%2" now being "%1", "%3" being "%2", all the way to "%9" which is now empty.

How are these useful? Perhaps you wish to write a script that picks and disarms a box for you, however your box can be a crate, a strongbox, a box or even a coffer. Using "%1" in the proper place, you can run your script with ".pick coffer" and it will target your coffer for opening.

Note: These variables are deleted if the script ends for any reason.

It should be noted that if more than 9 variables are used, the program will store them, but they will be unavailable without use of the SHIFT command. For example, if you do include a tenth variable, the first SHIFT will cause it to become "%9".

Save

The SAVE command, while supported by later versions, is only useful in the Wizard FE. Using SAVE will store the following text into a special variable called %s.

For example,

 SAVE VariableContents

will store VariableContents in %s. This has been superceded by global variables in all later Simutronics Front Ends.

Global Variables

These variables are a different sort, because they can both be accessed from within the script and because they will remain after the script ends. However, unlike command line variables, they can only be altered by a script or through the Variables panel. Like all variables, they take the form of "%<variable name>".

There are two major script commands for interacting with standard variables. The first is SETVARIABLE, which uses the syntax "SETVARIABLE <variable name without the %> <variable contents>" such as "SETVARIABLE weapon sword". One thing to realize is that you can set a variable to nothing, by using "SETVARIABLE <variable name>", which can be useful in some advanced scripting.

The second way to interact with them is using DELETEVARIABLE, which does what you'd expect: it removes the variable and its contents.

It is important to distinguish between an empty variable and a deleted variable. An empty variable when you call it, simply adds a blank space, but a deleted variable will insert the variable name when called. Example:

Command:

PUT pick coffer %way

Empty:

Result: pick coffer
This will end up picking your coffer normally

Deleted:

Result: pick coffer %way
This will result in the game telling you it cannot find your "coffer %way".

Counter

The counter command provides the ability to do simple math and store the outcome to a variable. You are able to use the counter command in the following ways.

COUNTER ( SET | ADD | SUBTRACT | MULTIPLY | DIVIDE ).

The ability to do simple math and store the the value for use later opens up some great possibilities for your scripts.

The counter value itself is stored in the %c variable.

Counter Commands

SET:

The SET command allows you to set the %c variable to whatever number (or another variable holding a number)
1	COUNTER SET 52
2	ECHO the counter is %c

ADD:

The ADD command allows you to add a specified number (or variable containing a number) to the current counter value.
1	COUNTER SET 52
2	ECHO the counter is %c
3	COUNTER ADD 10
4	ECHO the counter is %c

SUBTRACT:

The SUBTRACT command allows you to subtract a specified number (or variable containing a number) from the current counter value.
1	COUNTER SET 52
2	ECHO the counter is %c
3	COUNTER SUBTRACT 10
4	ECHO the counter is %c

MULTIPLY:

The MULTIPLY command allows you to multiple the current counter value by a specified number (or variable containing a number).
1	COUNTER SET 52
2	ECHO the counter is %c
3	COUNTER MULTIPLY 10
4	ECHO the counter is %c

DIVIDE:

The DIVIDE command allows you to divide the current counter value by a specified number (or variable containing a number).
1	COUNTER SET 52
2	ECHO the counter is %c
3	COUNTER DIVIDE 10
4	ECHO the counter is %c

It should be noted that StormFront does not handle decimals at all, and they are simply truncated (rounded down to the nearest whole number).

Multiple Counters

The scripting engine itself does not allow you to have multiple counter variables going at once, there is however a way to get around this. Since the engine allows you to store one variable to another, and also allows you to set the current value of the counter you are able to preform a little coding magic, and give yourself multiple counters to work with.

The example below takes use of the fact you can set the counter to another variable(provided its a number), then do your math on it, and then store its value back to the original variable. Essentially this allows you to have as many counters going on as your heart desires.

1	SETVARIABLE MyCounter1 10
2	SETVARIABLE MyCounter2 20
3     
4	ECHO MyCounter1 is %MyCounter1
5	ECHO MyCounter2 is %MyCounter2
6     
7	COUNTER SET %MyCounter1
8	ECHO the counter is currently %c
9	COUNTER ADD 5
10	ECHO the counter is currently %c
11	SETVARIABLE MyCounter1 %c
12     
13	COUNTER SET %MyCounter2
14	ECHO the counter is currently %c
15	COUNTER ADD 5
16	ECHO the counter is currently %c
17	SETVARIABLE MyCounter2 %c
18     
19	ECHO MyCounter1 is %MyCounter1
20	ECHO MyCounter2 is %MyCounter2

Logic

Many people look at the list of commands and falsely believe that there is no way to control a script beyond the initial command line variables and primative MATCHes and that there are no ways to compare values. The following is a list of ways to give greater responsiveness to these scripts.

IF

The most basic logic statements is the IF_<#1-9>. When this is added to the line before a command, it will check whether or not the variable is present and, if so, execute the command normally.

1	IF_1 GOTO %1
2	GOTO exit

This set of lines would check to see if there was anything in command line variable 1 and if so, go to the label that matches it. If not, it would exit the program.

MATCH/Variable Pairs

One of the issues often encountered that MATCH can't do alone is finding a way to match a string and alter it's behavior later, beyond the next step. This can be done by using a MATCH to go to a label that will then set a variable.

1	MATCH scorpion A scorpion walks in
2	MATCH spider A spider walks in
3	MATCHWAIT
4
5	scorpion:
6	SETVARIABLE someVariable scorpion
7	GOTO nextstep

As you can see, this enables a variable that can be used much later in the script. In theory, you can set it to react to as many conditions as you want to build MATCH and SETVARIABLE pairs for.

However, the is no way to directly load text from the game into a variable. All possible settings have to be built into the script prior to the event.

Label/Variable Pairs

One of the other important functions needed to a way to vary a script's behavior based on variables. While IF can do a primitive version of this, and using variables with in game commands can cover many situations, there is a way to do completely internal changes.

An important fact is that both GOTO and MATCH will allow the use of variables in their names. We saw this earlier with GOTO %1, but it's possible to build compound labels, such as GOTO weapon%WeaponVariable.

If we continue the previous example:

1	nextstep:
2	GOTO creature%someVariable
3
4	creatureScorpion:
5	GOTO fight
6
7	creatureSpider:
8	GOTO runAway

This would allow you to set your script to fight scorpions, but run away if spiders arrive.

Labelerror

There is a special use for the special errorlabel label. Recall that errorlabel will catch any GOTO or MATCH that attempts to go to a label that doesn't exist.

This label can be used with Label/Variable pairs to handle all cases which do not have a section for them. This doesn't happen with variable labels that are set inside the script as you can be sure to set all options, but can be useful in the case of a label that uses a command line. Since it is impossible to be account for all possible things that might be entered by the user, this is a good catchall for "everything else."

1	GOTO punch%1
2
3	punchBob:
4	blah blah blah blah

If you were to use this, and the user enters anything other than "bob" then the script aborts with an error about the label not existing.

Not that this can be a problematic process to use, as this label will catch ALL nonexistent labels, including all labels that are typoed or otherwise bugged, and this can make troubleshooting difficult.

Partial Matching

While there is no built in way to partially match an incomplete command line variable, there is brute force trick to save yourself some typing,

1	GOTO %1
2
3	swo:
4	swor:
5	sword:
6	swords:
7	blah blah blah blah

As you can see by that, it will match even a partial piece of "swords." This often best used when a command line variable is used to activate a small piece of a program, for example, to activate the pounding section of a forging script.

Regular Expressions

Both the MATCHRE and WAITFORRE functions support regular expressions, a way of setting conditions that can match several options. They are incredibly useful for keeping the amount of lines your code is down to a minimum.

It functions exactly the same as a MATCH/WAITFOR, except that a pipe ( | ) separates each of the regular expressions, and that it must start and end with forward slashes ( / ).

1	putAway:
2	MATCH putAway ...wait
3	MATCHRE cycle / (Stow what?|You are already wearing that.|But that is already in your inventory.|You) /
4	PUT stow my pickle
5	MATCHWAIT

This will goto cycle if "Stow what?" "You are already wearing that." "But that is already in your inventory." or even just plain "You" occurs.

The /s are used to set the area, the ( and ) sets the area that will vary, and the | will separate the possibilities. For example:

1	PUT pull lever
2	MATCH ball /(blue|green) ball bounces by/
3	PUT get ball

This will match either "blue ball bounces by" or "green ball bounces by".

If the line is ended in /i rather then /, then it will ignore the case of the letters, otherwise it is case sensitive. For example:

1	PUT pull lever
2	MATCH ball /(blue|green) ball bounces by/i
3	PUT get ball

This will match "blue ball bounces by", "green ball bounces by", or even "BlUE baLL bounces by".