The script is normally executed line by line, starting at the first line and ending at the End statement or at the last line.
The script flow can be re-directed to certain parts of the script: the Labels and the Subs. See the section on Events for handeling unpredictable happenings such as chat, detection of movement, clicks etc... that temporarily interrupt the main script execution.
Labels and Subs are structural elements of a script
Label $label a label is just that: a label, it has no other function than to mark a place in the script, and can be used to jump to it, the script will resume execution at the line following the label. Labels may be found:
|
Sub $sub a Sub is quite different: it has an entry point, the line starting with Sub, and a point of exit, at the Return or EndSub statement. Within a Sub, statements will be executed until the Return or EndSub statement is met, then execution will continue at the line following the one where the Sub was called with the Gosub statement. Subs and Event handlers may only be placed after the End statement of the main part of the script |
In all the examples here, $label and $sub are strings which may only contain letters, numbers and underscores, and must start with a letter. They can be packed in variables, or more often just string literals (no "" needed here). They must exist as Labels or Subs. If a Label is not found, or a Sub does not exist, the script produces an error message on screen (X1.exe) and triggers a LabelNotFound event: the script may trap that event and decide what to do. This can happen if the script uses variables in Goto and Gosub statements to point to labels or subs. See Errors and debugging
Jumps in the execution of the program flow are triggered by five statements: GoSub, Goto, ResetTo, EscapeTo and Escape.
Gosub $sub is used to call a Sub. The label $sub is the name of the sub, for example, Sub ThisOne can be called with Gosub ThisOne. |
Goto $label is used to jump to a label in the same section of the script. If Goto $label is in the main section, the Label $label must also be in this section; if Goto $label is in the body of an event handler, Label $label must be in there too; and if Goto $label is in a Sub, Label $label must be in the same Sub. If the Label is out of scope, the script produces an error message on screen (X1.exe) and triggers a LabelNotFound event, see Errors and debugging. For example, if in the main body there is a label called Label donkey, you can use Got donkey in the main body. Two frequent applications of this:
|
ResetTo $label exits all subs, clears the sub stack, clears the Wait command and resets the script pointer to the line following the specified label. The label must be in the main part of the script. If the Label is out of scope, the script produces an error message on screen (X1.exe) and triggers a LabelNotFound event, see Errors and debugging.
|
EscapeTo $label is new (X1.exe 2.9999950, Av99Bot/SrvcXlgBot 1.66). It is very similar to ResetTo, but it always exits inmediately (there is no difference in behaviour when it is in the main section and in the event handlers): it exits all subs, clears the sub stack, clears the Wait command and resets the script pointer to the line following the specified label. The label must be in the main part of the script. If the Label is out of scope, the script produces an error message on screen (X1.exe) and triggers a LabelNotFound event, see Errors and debugging. |
Escape is new (X1.exe 2.9999950, Av99Bot/SrvcXlgBot 1.66), and must be used with care. It will terminate and exit any Sub or Event handler, and reset the pointer at the line in the main body of the script following the one where the main script was interrupted. An interruption, in this context, is a Gosub statement in the main script, or an Event. It is only really useful when used to exit an Event handler, because it will exit it inmediately, even from within a Sub, without resetting the script's main pointer, that is: if the main execution of the script (before it was interrupted by the Event) is still somewhere in a Sub called by the main portion, it will resume execution where it was interrupted (in that Sub, it does not clear the main stack if used in Events). On the other hand, if used outside an Event handler, it clears the main stack and resumes execution at the line following the one where it entered the first Sub on the stack. If not used within an Event or a Sub (if it appears in the main body of the script) it does nothing. |
For example, the statement using a literal
Goto MyLabel |
Label MyLabel |
and the statement using a string variable
$Start_param = "StartParameters" Gosub $Start_param |
End # none or more subs here, then Sub StartParameters #some code here EndSub |
The following is also possible and legal, the last EndSub closes the Sub. Therefore, the Goto's are also OK here, they 'stay' within the Sub:
End # none or more subs here, then Sub StartParameters #some code here IfInt %r > 3 Goto StartParameters1 Else IfInt %r > 2 Goto StartParameters2 Else IfInt %r < 0 EndSub #some more code here EndSub Label StartParameters1 # some code here EndSub Label StartParameters2 # some code here EndSub |
This statement has two functions, depending on whether it is followed by arguments or not.
Do on its own, the "empty" Do, forces the script processor to pass control to the main bot program, if issued in the main part of the script or in a sub called from the main part. In an event handler it does nothing. Notice that some other statements have an implicit empty Do, so this statement is rarely needed except after a Suspend statement.
Do $a allows executing a statement stored in a string variable, as if it were part of the script. If $a is an empty string or is not a valid statement, it does nothing.
Example. Supposing you have a list /s_listA of name-value pairs,
which contains the following pair:
tea=Gosub ServeTea
If somewhere in your code, you have a string equal to the keyword "Tea", for instance if $a = "Tea", you can use this keyword to go to subroutine ServeTea:
IfSListGetValue /s_listA $a $b Do $b |
IfString "Tea" = $a Gosub ServeTea |
Suspend
This is a most dangerous statement. If unwisely used, it can cause the script to take control of the bot and never return to the main program, resulting in an endless loop.
What does it do? If used in the main body or in a Sub called from the main body, Suspend prevents the bot from automatically regaining control at each heartbeat until an empty Do statement or a ResetTo statement is encountered. Many statements force the script to pass control back to the bot. This is necessary: the bot needs to communicate with the universe and world servers, and can only do so by regaining control at each bot heartbeat. Moreover, the other bots in the program must have their turn as well.
On some occasions, you will want to suspend for a short time this behaviour, to speed up script parsing and processing. This might be the case, for instance, if you wish to issue a series of ObjectChange statements, and do not wish the script to pass control back to the bot after each statement (this causes a delay of approximately 0.5 seconds after each of these statements) but prefer to process all these statements first and then return control to the bot so that it sends all these changes to the server in one go. You may then protect your statements in a Suspend .... Do block. Keep in mind that all the code between Suspend and Do will be parsed without giving control back to the bot.
Suspend # your code here Do |
Using Suspend ... Do wisely can speed up the execution of the script, but you must test your code thoroughly to see that it is really doing what you want it to do: some statements might not work properly after a Suspend statement. Suspend does not work in Event handlers.