This page serves as a basic tutorial for users new to
Linden Scripting Language and
SecondLife.
However,
LSL101 and the
Crash Course are far better options for both complete beginners, and people who have programmed before.
A
script is an item in the
inventory of an
object that contains instructions that make the object do stuff. Like other inventory items, scripts can be copied to the inventories of other objects, copied to
your inventory or given to other players (assuming the script has the appropriate
permissions set).
Scripts are written in LSL, a programming language created for Second Life. Its structure and syntax are similar to those of C and, to a lesser extent, Java. A script is organized into
states and
functions. States consist of a series of
events.
Any
object can have as many scripts on it as
memory allows. Scripts have a length limit, but it's not usually a problem. You create a new script by going to the "Content" tab of an object's "Edit" box and clicking the "New Script..." button. This will open the script editor with the example script (which makes the object say "Hello, Avatar!" on its
state_entry event and says "Touched" when
touched). The default
state is the state that the script first enters. The
state_entry event is the first event that is called in a state. So, the code you want executed when the script first starts goes where
llSay(0, "Hello Avatar"); is now. You end each
statement in LSL with a semicolon (;). So, to say a few things in our
state_entry, we would use:
llSay(0, "This is the first thing.");
llSay(0, "This is the second thing.");
The function
llSay has two
arguments: a
channel and a message. The channel can be any
integer. The message is a
string, which is a group of alphanumeric characters enclosed in quotation marks (
""). You must specify both or the script editor will give you an error and keep the script from running. For simple scripts that execute one segment of code on runtime, you only need to know about
state_entry. But if you want the object to react to other things, you'll need to use multiple events. See the
events page for a full list of them. The events are separate; you cannot put one event within another. Each event, state, and
FlowControl call are kept separate by using { }. For example:
default
{
// Now we are in the default state, but not in an event.
state_entry()
{
// Now we are in state_entry, in the default state.
if (1==1)
{
// Now we are in an if/then logic [[block]]. The code inside the { } is executed if the logical evaluation made in the ( ) is true.
}
// We are in state_entry. If the "if" statement was false, then execution would have skipped over the code inside the if's { } and resumed here.
}
// We have now left state_entry, and are in the default state.
}
// Now we are outside of the default state, and any events that are associated with it.
NOTE: The double slashes (
//) begin
comments, so any text following the
// on that line of code will be ignored by the LSL compiler. This is useful for placing notes about how your code works, or for adding notes to other scripters about what each block does, or for deactivating troublesome lines of code.
You define
variables in LSL by giving the
type of the variable (
string,
integer,
list, etc) and then the name, followed by a semicolon (
;). If you want them to be accessible in every event and every state, you define them before the "default" line. If you only want them avaliable to the function/event from which they were created, you put them in that function. For example:
string gStringName; // This is a global variable
default
{
state_entry
{
string gLocalString; // This is a local variable
}
}
If you want to use your own functions, define them at the top of the script, before the "default" state, using the standard
block notation, for example:
MyFunction(integer channel, string message) // If you want the function to take inputs, put their type/name here, separated with commas.
{
llSay(channel, message);
llSay((channel+1), message);
}
default
{
state_entry
{
MyFunction(0, "Hello, Avatar");
}
}
This script says "Hello, Avatar" on channel 0 and 1.
To learn more about the things you can do with LSL, look at the
function list. This is intended to be a guide to the basics of LSL scripting. If someone wants to add more basic information, feel free.
Quick Note: Typecasting
Many times, you are getting a
string that you want to serve as a
vector or
key for a particular function call. In this case, you use what programmers call typecasting. Typecasting is a method of using one variable of type X as one of type Y temporarily.
To typecast in LSL, you prefix a variable reference with the type you want to cast to in parentheses, like this:
integer gInt = 1;
llSetText((string)gInt, <0,0,0>, (float)gInt);
So, when
llSetText looks for a string of text, it changes the type of gInt from
integer to
string. Then, it is equal to "1", instead of 1. Also, the third argument of
llSetText is a
float, but you can supply an integer (in this case only 0 or 1) by simply typecasting it as a float. It's important to observe the distinctions between types, because
operators behave differently on different types; if you're not aware of this, you may be surprised when you add "1" and "1" and get "11".
Quick Note: Formatting
Proper indentation is the most important part of any code or script. There are a couple indentation styles for scripting and as long as you pick one and are consistant with it that is good. Random is not a style. Here are some simple rules:
- All { and } go on their own lines. There should never be text on the same line as a { or a }
- Never put more than one statement on a line.
- Each line should be indented the same amount as the line above it. Two exceptions:
- On the line after a { indent one additional tab (SL will do this for you if you hit enter immediately after typing {)
- On the line containing a } indent one less tab (SL will do this for immediately after typing } if there's a tab already in place)
The default script follows this pattern and SL will do most of this for you if you were to type your code straight from begining to end and hit enter at the right places (after a statement, a
{ and a
})
Why is this so important? For starters, although
Ama Omega likes to help new people with their scripts; he will not help you, and may scold you, if you give him a poorly formatted script. The main reason, though, is that if your script has the proper formatting you can see what code is inside each
loop, event, function, and state, including what variables are local to where. 99% of the scripts Ama Omega receives that won't compile do compile after the creator cleans up the code.