Difference between revisions of "Getting started with LSL"

From Second Life Wiki
Jump to navigation Jump to search
m
m (Grammar: "let's", not "lets")
 
(38 intermediate revisions by 14 users not shown)
Line 8: Line 8:
'''FOR WHOM IS THIS TUTORIAL:'''
'''FOR WHOM IS THIS TUTORIAL:'''


This tutorial is intended for those who have never programmed before, Second Life or elsewhere. However, this tutorial will make little sense outside of Second Life. LSL is very specific to Second Life.
This tutorial is intended for those who have never programmed before, Second Life or elsewhere. However, this tutorial will make little sense outside of Second Life. LSL is very specific to Second Life.


You will begin by running the standard "hello world" script and eventually move towards making your own. You will need to be familiar with the basic principles of Second Life and have general building skills before you can make use of everything in this tutorial.
You will begin by running the standard "Hello, Avatar!" script and eventually move towards making your own. You will need to be familiar with the basic principles of Second Life and have general building skills '''before''' you can make use of everything in this tutorial.


== What is LSL? ==
== What is LSL? ==


LSL is the Linden Scripting Language. This is the language all scripts in Second Life are written in. Its structure is based on Java and C. A script in Second Life is a set of instructions that can be placed inside any primitive object in the world, but not inside an avatar. Avatars, however, can wear scripted objects. LSL scripts are written with a built-in editor/compiler which we will access in "Running Your First Script".
LSL is the Linden Scripting Language. This is the language all scripts in Second Life are written in. The structure of LSL is largely based on Java and C, both of which are widely used programming languages in the real world. A script in Second Life is a set of instructions that can be placed inside any primitive object in the world, but not inside an avatar. Avatars, however, can wear scripted objects. LSL scripts are written with a built-in editor/compiler which we will access in "Running Your First Script".


One thing that makes LSL special is its emphasis on "States" and "Events". A door can be "open" or "closed" and a light can be "on" or "off". A person can be "hyper", "calm", or "bored". Many real life behaviors can be modeled with "states" and the same can be true for LSL programs. Minimally a script will have one state, the default state.
'''NOTE:''' LSL is interpreted and executed on the Second Life servers (sims), not the client (Viewer). Although the script editor is part of the SL Viewer, the script itself runs on the server, which sends the results over the network to the Viewer, where you can see them.


An event can be thought of as a "Trigger". Events are not user defined in Second Life, but rather predefined. They are either caused by objects and avatars interacting in the world, or they are created in a script. Events trigger event handlers (sometimes just called "events" as well). For example, when an avatar touches an object, a ''touch_start'' message is sent to the object, which causes the [[touch_start]]() event handler to begin executing.  So the minimum LSL program must have one state with one event handler in it. Here is a look at a minimal program written in LSL that can loosely be translated as...."When I am in the default state, and I am touched, say "Hello World" on channel zero".
One thing that makes LSL unique is its emphasis on "[[state|States]]" and "[[:Category:LSL_Events|event]]". A door can be "open" or "closed" and a light can be "on" or "off". A person can be "awake" or "asleep". Many real life behaviors can be modeled with "states" and the same can be true for LSL programs. Minimally a script will have one [[state]], the default [[state]].


An event can be thought of as a "Trigger". Events are not user defined in Second Life, but rather predefined. They are either caused by objects and avatars interacting in the world, or they are created in a script. Events trigger event handlers (sometimes just called "events" as well). For example, when an avatar touches an object, a ''touch_start'' message is sent to the object, which causes the [[touch_start]]() event handler to begin executing. So the minimum LSL program must have one [[state]] with one event handler in it. Here is a look at a minimal program written in LSL that can loosely be translated as...."When I am in the default state, and I am touched, say "Hello, Avatar!" on channel zero".


<lsl>
<source lang="lsl2">
default
default
{
{
    touch_start(integer total_number)
    touch_start(integer num_detected)
    {
    {
          llSay(0,"Hello World");
        llSay(0, "Hello, Avatar!");
    }
    }
}
}
</lsl>
</source>


'''WHAT CAN I DO WITH SCRIPTS?'''
'''WHAT CAN I DO WITH SCRIPTS?'''
Line 35: Line 36:
Scripts can make an object move, listen, talk, operate as a vehicle or weapon, change color, size or shape. A script can make an object listen to your words as well as talk back to you, scripts even let objects talk to each other.
Scripts can make an object move, listen, talk, operate as a vehicle or weapon, change color, size or shape. A script can make an object listen to your words as well as talk back to you, scripts even let objects talk to each other.


The most basic object in Second Life is the "Prim" or primitive, the basic building block of all objects you can build in Second Life. When several prims are linked, they can each contain a script which speaks to the rest of the object via Link Messages. These are faster and more private than having objects "chat" or email each other. These are beyond the scope of this tutorial and we will instead focus on single scripts in a single prim.
The most basic object in Second Life is the "Prim" or primitive, the basic building block of all objects you can [[Good_Building_Practices|build in Second Life]]. When several prims are linked, they can each contain a script which speaks to the rest of the object via Link Messages. These are faster and more private than having objects "chat" or email each other. These are beyond the scope of this tutorial and we will instead focus on single scripts in a single prim.


Scripting is harder to learn than basic object manipulation, but is very rewarding once you make progress.
Scripting is harder to learn than basic object manipulation, but is very rewarding once you make progress. For creating scripts it can be helpful to have a local copy of them on your local harddrive as they're basically just text and edit them with one of the [[LSL_Alternate_Editors|alternate editors]].


If you have built in Second Life, everything you can define in the edit window can be defined in a script. All interaction you see between objects or between avatars and objects is via scripts.
If you have built in Second Life, everything you can define in the edit window can be defined in a script. All interaction you see between objects or between avatars and objects is via scripts.


Learning more about the world and building model is vital to some aspects of scripting, thus I would recommend a good foundation in building as you learn to script.
Learning more about the world and building model is '''vital to some aspects''' of scripting, thus I would recommend a good foundation in building as you learn to script.


== Running Your First Script ==
== Running Your First Script ==


Traditionally one starts by writing the smallest program possible to print "hello world". Since LSL only runs inside objects, you must know how to create an object and put a script inside it.
Traditionally one starts by writing the smallest program possible to print "Hello, Avatar!". Since LSL only runs inside objects, you must know how to create an object and put a script inside it.


You must be on land which allows building. Either your own land, or land where you have permission to build on such as a sandbox. Right click on the ground and choose '''create''' (for one button macs use command+click).
You must be on land which allows building. Either your own land, or land where you have permission to build, such as a sandbox. Right click on the ground and choose '''Build''' (for one button macs use command+click).


By default, you should see a '''wand''' icon with which you can click and create a cube on the ground.
By default, you should see a '''wand''' icon with which you can click and create a cube on the ground.


You will automatically enter '''edit''' mode and an edit window will pop up. To place a script in an existing object, right click it and hit edit to open the edit window.
You will automatically enter '''Edit''' mode and an [[Edit_window#Edit_Tool|edit window]] will pop up. To place a script in an existing object, right click the object and click '''Edit''' to open the edit window.


In the edit window you may see a button marked '''more>>>''' click it to reveal five tabs marked '''general''', '''object''', '''features''', '''content''', and '''texture'''. Click '''content'''.
In the edit window you may see a button marked '''More>>''' click it to reveal five tabs marked '''General''', '''Object''', '''Features''', '''Texture''', and '''Content'''. Choose the '''Content''' tab.


This window shows the contents of an object which can hold scripts, notecards, even other objects. Press '''new script''' to add a new script.
This tab shows the contents of an object which can hold scripts, notecards, textures, sounds, even other objects. Press '''New Script''' to add a new script.


This will open the LSL editor with a default script. This editor will color code your syntax and provide some info about keywords when you hold your mouse over them. It will also do basic syntax checking.
This will open the LSL editor with a default script. This editor will color code your syntax and provide some info about keywords when you hold your mouse over them. It will also do basic syntax checking. Alternatively you can use one of the [[LSL_Alternate_Editors|alternate editors]] to write your scripts on your local harddrive and copy them to Second Life whenever you feel like it.


Before explaining the code, lets run it. Hit '''save''' and close your edit window (not the LSL editor window).
Before explaining the code, let's run it. Hit '''Save''' and close your [[Edit_window#Edit_Tool|edit window]] (not the LSL editor window).


You should see the words "Hello Avatar" from "object"
You should see the words <code>Hello, Avatar!</code> from your object named "Object".


If you touch the object, it will say "Touched." The "edit" building window must be closed for touching to work.
If you touch the object, it will say <code>Touched.</code> The [[Edit_window#Edit_Tool|edit window]] must be closed for touching to work.


Congratulations! You have compiled and run your first LSL script!
Congratulations! You have compiled and run your first LSL script!
Line 71: Line 72:
(aka Wash / Rinse / Repeat)
(aka Wash / Rinse / Repeat)


We now have a running script, however most scripts you make will not run the first time you run them. It will take many tries as you correct errors and make improvements. When you hit "save" on a script, the LSL editor "compiles" the code to something LSL can understand. It will stop however if it finds an error.
We now have a running script, however most scripts you make will not run the first time you run them. It will take many tries as you correct errors and make improvements. When you hit "Save" on a script, the LSL editor "compiles" the code to something LSL can understand. It will stop however if it finds an error.


Brackets, parenthesis, and semicolons must all be perfectly in place before a script will run. If you are new to programing this can be one of the most infuriating steps and lead you to screaming DWIM (Do what I mean!) Part of becoming a programmer in ANY language is learning how to precisely define steps and correctly type them into the language you are working in. Thus you will find yourself writing, running, then RE-writing your code several times.
Brackets (or Braces, if you prefer), parentheses, and semicolons must all be perfectly in place before a script will run. If you are new to programing this can be one of the most infuriating steps and lead you to screaming DWIM (Do what I mean!). Part of becoming a programmer in ANY language is learning how to precisely define steps and correctly type them into the language you are working in. Thus you will find yourself writing, running, then '''RE-writing''' your code several times.


The script you made runs the instant you hit save. If you take it into inventory, it will "suspend" what it was doing but go right back to it when rezzed (resurrected) again. (If you are not familiar with "taking" and "rezzing" an object you may need to revisit your building skills).
<br>


Each time you re-write your code you will want to reset the script.
{{LSL Tip|The [http://en.wikipedia.org/wiki/Pareto_principle pareto principle] applies. '''At least (if not more than)''' 80% of the time you're spending on writing scripts you're actually not writing them but fixing stuff you messed up during the first 20% of the time. Having a look at the [[LSL_Style_Guide|Style Guide]] certainly helps with being more productive cause you can read your own code.}}


Try resetting the script in the following ways.
<br>


1. Press Reset in the script window.
[[File:Pareto_principle_scripting.gif|thumb|700px|center|Writing and fixing scripts takes time and effort. '''Readability is key to being more productive!''' [[LSL_Alternate_Editors|Alternate Editors do help, too.]] ]]
2. Select the object and go to TOOLS>RESET SCRIPTS IN SELECTION


Also try stopping and starting the script from running via checking and unchecking the "running" button, or the TOOLS>SET SCRIPTS TO NOT RUNNING IN SELECTION and then TOOLS>SET SCRIPTS TO RUNNING IN SELECTION.
The script you made runs the instant you hit save. If you take it into inventory, it will "suspend" what it was doing but will continue from that exact point when rezzed (resurrected) again. (If you are not familiar with "taking" and "rezzing" an object you may need to revisit your building skills).


Once you get comfortable with stopping, starting, and resetting a script, try changing the words "Hello Avatar" and see what else you can make it say.... for goodness sakes keep it PG.
Each time you amend your code and save it, it is reset.  You can also reset a script inside a prim in the following ways:
 
# Press Reset in the script window.
# Select the object and choose BUILD > SCRIPTS > RESET SCRIPTS (for older viewers TOOLS>RESET SCRIPTS IN SELECTION)
# By checking and unchecking the "Running" check-box
# Choose BUILD > SCRIPTS > SET SCRIPTS TO NOT RUNNING (for older viewers TOOLS>SET SCRIPTS TO NOT RUNNING IN SELECTION) and then BUILD > SCRIPTS > SET SCRIPTS TO RUNNING (for older viewers TOOLS>SET SCRIPTS TO RUNNING IN SELECTION).
 
Once you get comfortable with stopping, starting, and resetting a script, try changing the words "Hello, Avatar!" and see what else you can make it say.... for goodness sakes keep it PG.


===WHY STOP AND START?===
===WHY STOP AND START?===
Line 96: Line 103:
For simplicity's sake, the following examples will all be used individually so be sure not to put two or more into the same object.
For simplicity's sake, the following examples will all be used individually so be sure not to put two or more into the same object.


== Dissecting "Hello World" ==
== Dissecting "Hello, Avatar!" ==


Lets take a look at the default code.
Let's take a look at the default code.
 
<source lang="lsl2">


<lsl>
default
default
{
{
    state_entry()
    state_entry()
    {
    {
        llSay(0, "Hello, Avatar!");
        llSay(0, "Hello, Avatar!");
    }
    }


    touch_start(integer total_number)
    touch_start(integer total_number)
    {
    {
        llSay(0, "Touched.");
        llSay(0, "Touched.");
    }
    }
}
}
</lsl>
</source>
 
The code above contains 1 [[state]], 2 [[:Category:LSL_Events|event]] and 2 [[:Category:LSL_Functions|functions]]. Let's look at them individually.
 
Any line starting with two forward slashes <code>//</code> is a comment. It will not run and is used to help you document your code.


The code above contains 1 state, 2 events and 2 functions. Lets look at them individually.
<source lang="lsl2">
// This is a comment
</source>


Any line starting with two forward slashes is a comment. It will not run and is used to help you document your code.
You can also use block comments, although it's not recommended for sake of better readability. Block comments start with <code>/*</code> and end with <code>*/</code>.


// This is a comment
<source lang="lsl2">
/* this  *
* is     *
* a       *
* block  *
* comment */
</source>


===STATES===
===STATES===


A "State" in LSL is a section that is running, and waiting for events. Only one state can be active at any one time per script. Every script must have a default state with at least one event in it. Except for the default state, each state is defined by the word STATE followed by the name of the state. The contents of the state are enclosed in two curly brackets.
A [[state]] in LSL is a section that is running, and waiting for events. Only one [[state]] can be active at any one time per script. Every script must have a default [[state]] with at least one event in it. Except for the default [[state]], each [[state]] is defined by the word ''state'' followed by the name of the [[state]]. The contents of the [[state]] are enclosed in two curly brackets.


<lsl>
<source lang="lsl2">
default
default
{
{
// contents of state go here
    // contents of state go here
}
}
 
state playing
state playing
{
{
// this is a state called "playing"
    // this is a state called "playing"
}
}
</lsl>
</source>


===EVENTS===
===EVENTS===


Events are inside of states. By "inside" I mean it is between the open and closed curly brackets that represent the body of the state. When that state is active, those events wait to be triggered and run the code inside them. We have seen "[[state_entry]]" which is triggered by the state being entered, and "[[touch_start]]" which is triggered when you, or anyone, touches an object.
[[:Category:LSL_Events|event]] are inside of [[state|states]]. By "inside" I mean it is between the open and closed curly brackets that represent the body of the [[state]]. When that [[state]] is active, those events wait to be triggered and run the code inside them. We have seen "[[state_entry]]" which is triggered by the [[state]] being entered, and "[[touch_start]]" which is triggered when you, or anyone, touches an object.


Lets take a look at the default code.
Let's take a look at the default code.


<lsl>
<source lang="lsl2">
// Code start
// state begins
default
default
{
{
    touch_start(integer total_number) // this is an event
    // event begins
    {
    touch_start(integer num_detected)
    // this is the content of the event (between curly braces)
    {
    }
        // this is the content of the event (between curly brackets)
 
    }
    // event ends
}
}
// end of default state
// state ends
</lsl>
</source>


===FUNCTIONS===
===FUNCTIONS===


Functions lay inside of events and are either defined by you or built-in. Those built in to LSL all start with two lowercase Ls. We have seen [[llSay]]() so far. Functions take "arguments" or values in the parentheses that follow it. If you hover over the function in the editor, a pop-up will show that tell you what the function is expecting. In the case of llSay it expects a number and a string. We send it the number zero and the string "Hello, Avatar!" separated by commas. The function is "expecting" a number and strings and will not take anything else.
[[:Category:LSL_Functions|Functions]] lay inside of events and are either defined by you or built-in. Those built in to LSL all start with two lowercase L's. We have seen [[llSay]]() so far. [[:Category:LSL_Functions|Functions]] take "arguments" or values in the parentheses that follow it. If you hover over the function in the editor, a pop-up will show that tells you what the function is expecting. In the case of [[llSay]] it expects a number and a string. We send it the number zero and the string "Hello, Avatar!" separated by a comma. The function is "expecting" a number and strings and will not take anything else.


=== Putting it all together ===
=== Putting it all together ===


Line by line, here is the hello avatar script.  
Line by line, here is the hello avatar script.


<lsl>
<source lang="lsl2">default // All Scripts need a Default State
 
default   // All Scripts need a Default State


{ // this open curly bracket denotes the start of the state
{ // this open curly bracket denotes the start of the state
     state_entry() // an event
     state_entry() // an event
     {
     {
         llSay(0, "Hello, Avatar!"); // a function inside the event's curly braces
         llSay(0, "Hello, Avatar!"); // a function inside the event's curly brackets
     }
     } // closed curly bracket closes the state_entry event
    // closed curly bracket closes the state_entry event


     touch_start(integer total_number)  // another event inside default state
     touch_start(integer total_number)  // another event inside default state
     {
     {
         llSay(0, "Touched."); // a function between the brackets of the touch_start body
         llSay(0, "Touched."); // a function between the brackets of the touch_start body
     }
     } // end of touch start
    // end of touch start
} // Code end</source>
}
// Code end
</lsl>


The instant you save your script, it enters default state, which in turn runs the "[[state_entry]]" event which in turn runs the function [[llSay]]() which makes the object talk.
The instant you save your script, it enters default state, which in turn runs the "[[state_entry]]" event which in turn runs the function [[llSay]]() which makes the object talk.
Line 192: Line 207:
== Introducing States and Events ==
== Introducing States and Events ==


LSL scripts will not run beginning to end. Instead, they will look for a default state and wait for an event. Within those events, there can be a call to go to a new state.
LSL scripts will not run beginning to end. Instead, they will look for a default state and wait for an event. Within those [[:Category:LSL_Events|event]], there can be a call to go to a new state.


All programs must contain the default state, inside of which must be one event.  Events are triggered either by actions happening to or around the object the script resides in, or are triggered from the script itself.  
All programs must contain the default state, inside of which must be at least one event.  [[:Category:LSL_Events|event]] are triggered either by actions happening to or around the object the script resides in, or are triggered from the script itself.


=== On/Off Example Using States ===
=== On/Off Example Using States ===


Let us look at a script with two states with two events in each.
Let us look at a script with two states with two [[:Category:LSL_Events|event]] in each.


<lsl>
<source lang="lsl2">default //default state is mandatory
default //default state is mandatory
{
{
     state_entry() // runs each time the state is entered
     state_entry() // runs each time the state is entered
     {
     {
         llSay(0, "turning on!"); //object speaks!
         llSay(0, "turning on!"); //object speaks!
         llSetColor(<1.0, 1.0, 1.0>, ALL_SIDES); // sets all sides to most bright
         llSetColor(<1.0, 1.0, 1.0>, ALL_SIDES); // sets no tint (white)
         // note the semicolons at the end of each instruction (do not put them at the end of if statements)
         // note the semicolons at the end of each instruction
        // (do not put them at the end of "if" statements)
     }
     }
 
 
     touch_start(integer total_number) // another event with only one function inside
     // Note: for technical reasons discussed elsewhere, we use a touch_end event rather than touch_start when state changes are involved
    touch_end(integer total_number) // another event with only one function inside
     {
     {
         state off; // sets the script to a new "state" and starts running "state off"
         state off; // sets the script to a new "state" and starts running "state off"
     }
     }
} // this curly bracket ends the body of the default state.
} // this curly bracket ends the body of the default state.
 
state off // a second state besides "default"
state off // a second state besides "default"
{
{
Line 221: Line 237:
     {
     {
         llSay(0, "turning off!");
         llSay(0, "turning off!");
         llSetColor(<0.0, 0.0, 0.0>, ALL_SIDES); // sets all sides as dark as possible
         llSetColor(<0.0, 0.0, 0.0>, ALL_SIDES); // sets black tint
     }
     }
 
     touch_start(integer total_number)
     touch_end(integer total_number)
     {
     {
         state default;
         state default;
     }
     }
}
}</source>
</lsl>
A simplification of this would be
A simplification of this would be


 
<source lang="lsl2"> default
<lsl>
default
  {
  {
  //set color to light and, if touched, enter the "off" state.
  //set color to light and, if touched, enter the "off" state.
  }
  }
 
  state off
  state off
  {
  {
  //set color to dark and, if touched, enter the "default" state.
  //set color to dark and, if touched, enter the "default" state.
  }
  }</source>
</lsl>


Note that after "[[default]]" all new states begin with the word "[[state]]". Also, while the object has a texture, the color will affect the "tint" more than the true color.
Note that after "[[default]]" all new states begin with the word "[[state]]". Also, while the object has a texture, the color will affect the "tint" more than the true color.
Line 251: Line 263:
Let us examine the default state.
Let us examine the default state.


First we see the "[[state_entry]]" event, which gets triggered each time the default state is entered. Which is this case in entered the first time the script is run.
First we see the "[[state_entry]]" event, which gets triggered each time the default state is entered. Which in this case is entered the first time the script is run.


'''SPEAK TO ME!'''
'''SPEAK TO ME!'''
Line 257: Line 269:
The first line in the event state_entry is...
The first line in the event state_entry is...


<lsl>llSay(0, "turning on!");</lsl>
<source lang="lsl2">llSay(0, "turning on!");</source>


This makes the object speak "turning on!" on channel zero. What is channel zero? It is the same channel you see all public chat on.
This makes the object speak "turning on!" on channel zero. What is channel zero? It is the same channel you see all public chat on.
Line 263: Line 275:
A semicolon ends the line and yet another instruction follows.
A semicolon ends the line and yet another instruction follows.


<lsl>llSetColor(<1.0, 1.0, 1.0>, ALL_SIDES);</lsl>
<source lang="lsl2">llSetColor(<1.0, 1.0, 1.0>, ALL_SIDES);</source>


This turns the prim to its brightest tint. If you take the texture off the prim, you would see it as bright white but with a texture, it looks "normal." The three ones stand for the Red, Green, and Blue values of the tint.
This turns the prim to its brightest tint. If you take the texture off the prim, you would see it as bright white but with a texture, it looks "normal." The three ones stand for the Red, Green, and Blue values of the tint.
Line 271: Line 283:
'''TOUCHED BY AN AVATAR'''
'''TOUCHED BY AN AVATAR'''


While idle in the default state a touch will trigger the "[[touch_start]]" event.
While idle in the default state a touch will trigger the "[[touch_end]]" event.


Inside of the "touch_start" event is only one command:
Inside of the "touch_end" event is only one command:


<lsl>state off;</lsl>
<source lang="lsl2">state off;</source>


This is a command to move immediately to a new state named "off".
This is a command to move immediately to a new state named "off".
Line 292: Line 304:
Then the whole thing starts over.
Then the whole thing starts over.


== A final word on words ==
== A Final Word on Words ==


Making your object speak is a great way to know what a script is doing, but everyone can hear it for 30m all around you. As you get into more complex scripts this can get pretty noisy! Three alternative ways to see what is going on exist.
Making your object speak is a great way to know what a script is doing, but everyone can hear it for 20m all around you. As you get into more complex scripts this can get pretty noisy! Three alternative ways to see what is going on exist.


'''SHHHH WHISPER'''
'''SHHHH WHISPER'''


[[llWhisper]]( ) is just like [[llSay]]( ) but only broadcasts at half the distance. You still must state what channel. So...
[[llWhisper]]( ) is just like [[llSay]]( ) but only broadcasts at half the distance (10m). You still must state what channel. So...


<lsl>llWhisper(0,"turning on!");</lsl>
<source lang="lsl2">llWhisper(0, "turning on!");</source>


...might work a bit to save the sanity of your neighbors.
...might work a bit to save the sanity of your neighbors.


Using [[llShout]]( ) doubles the distance heard, but can cut the amount of friends you have in half.  
Using [[llShout]]( ) increases the distance heard to a radius of 100m, but can cut the amount of friends you have in half.
 
[[llOwnerSay]]( ) uses no channel and is heard only by you. Very useful and can triple the amount of friends you have!
 
<lsl>llOwnerSay("turning on!");</lsl>


[[llOwnerSay]]( ) uses no channel, and is seen in chat only by the object's owner. Very useful and can triple the amount of friends you have!


<source lang="lsl2">llOwnerSay("turning on!");</source>


'''THE SOUND OF SILENCE'''
'''THE SOUND OF SILENCE'''
Line 316: Line 326:
You can make a totally silent message via [[llSetText]]( ) like this.
You can make a totally silent message via [[llSetText]]( ) like this.


<lsl>llSetText("I am on", <1.0, 1.0, 1.0>,1.0);</lsl>
<source lang="lsl2">llSetText("I am on", <1.0, 1.0, 1.0>, 1.0);</source>
 
What do the numbers mean? The <1.0, 1.0, 1.0> we have seen before. It represents the values for red, green, and blue. For now just know that <1.0, 1.0, 1.0> means "white" and <0.0, 0.0, 0.0> means "black".


What do the numbers mean? The <1.0, 1.0, 1.0> we have seen before. It represents the values for red, green, and blue. For now just know that <1.0, 1.0, 1.0> means "white" and <0.0, 0.0, 0.0> means "black". Replace the [[llSay]](0,"turning off!"); with...
Replace the


<lsl>llSetText("I am off", <0.0, 0.0, 0.0>,1.0);</lsl>
<source lang="lsl2">llSay(0, "turning off!");</source>


The 1.0 is the alpha setting. 1.0 means fully opaque, and 0.0 would be completely transparent (invisible).
with...


<source lang="lsl2">llSetText("I am off", <0.0, 0.0, 0.0>, 1.0);</source>


The 1.0 is the alpha setting. 1.0 means fully opaque, and 0.0 would be completely transparent (invisible).


== Next steps ==
== Next steps ==


Now than you can edit and run LSL code, move on to one of the more advanced [[LSL_Tutorial|LSL Tutorial]]s.
Now that you can edit and run LSL code, move on to one of the more advanced [[LSL_Tutorial|LSL Tutorial]]s.


{{LSLC|Tutorials}}
{{LSLC|Tutorials}}

Latest revision as of 18:50, 15 December 2022


Getting started in LSL scripting in Second Life

LSL stands for "Linden Scripting Language" and is used to script the objects you will encounter and make in Second Life.

FOR WHOM IS THIS TUTORIAL:

This tutorial is intended for those who have never programmed before, Second Life or elsewhere. However, this tutorial will make little sense outside of Second Life. LSL is very specific to Second Life.

You will begin by running the standard "Hello, Avatar!" script and eventually move towards making your own. You will need to be familiar with the basic principles of Second Life and have general building skills before you can make use of everything in this tutorial.

What is LSL?

LSL is the Linden Scripting Language. This is the language all scripts in Second Life are written in. The structure of LSL is largely based on Java and C, both of which are widely used programming languages in the real world. A script in Second Life is a set of instructions that can be placed inside any primitive object in the world, but not inside an avatar. Avatars, however, can wear scripted objects. LSL scripts are written with a built-in editor/compiler which we will access in "Running Your First Script".

NOTE: LSL is interpreted and executed on the Second Life servers (sims), not the client (Viewer). Although the script editor is part of the SL Viewer, the script itself runs on the server, which sends the results over the network to the Viewer, where you can see them.

One thing that makes LSL unique is its emphasis on "States" and "event". A door can be "open" or "closed" and a light can be "on" or "off". A person can be "awake" or "asleep". Many real life behaviors can be modeled with "states" and the same can be true for LSL programs. Minimally a script will have one state, the default state.

An event can be thought of as a "Trigger". Events are not user defined in Second Life, but rather predefined. They are either caused by objects and avatars interacting in the world, or they are created in a script. Events trigger event handlers (sometimes just called "events" as well). For example, when an avatar touches an object, a touch_start message is sent to the object, which causes the touch_start() event handler to begin executing. So the minimum LSL program must have one state with one event handler in it. Here is a look at a minimal program written in LSL that can loosely be translated as...."When I am in the default state, and I am touched, say "Hello, Avatar!" on channel zero".

default
{
    touch_start(integer num_detected)
    {
        llSay(0, "Hello, Avatar!");
    }
}

WHAT CAN I DO WITH SCRIPTS?

Scripts can make an object move, listen, talk, operate as a vehicle or weapon, change color, size or shape. A script can make an object listen to your words as well as talk back to you, scripts even let objects talk to each other.

The most basic object in Second Life is the "Prim" or primitive, the basic building block of all objects you can build in Second Life. When several prims are linked, they can each contain a script which speaks to the rest of the object via Link Messages. These are faster and more private than having objects "chat" or email each other. These are beyond the scope of this tutorial and we will instead focus on single scripts in a single prim.

Scripting is harder to learn than basic object manipulation, but is very rewarding once you make progress. For creating scripts it can be helpful to have a local copy of them on your local harddrive as they're basically just text and edit them with one of the alternate editors.

If you have built in Second Life, everything you can define in the edit window can be defined in a script. All interaction you see between objects or between avatars and objects is via scripts.

Learning more about the world and building model is vital to some aspects of scripting, thus I would recommend a good foundation in building as you learn to script.

Running Your First Script

Traditionally one starts by writing the smallest program possible to print "Hello, Avatar!". Since LSL only runs inside objects, you must know how to create an object and put a script inside it.

You must be on land which allows building. Either your own land, or land where you have permission to build, such as a sandbox. Right click on the ground and choose Build (for one button macs use command+click).

By default, you should see a wand icon with which you can click and create a cube on the ground.

You will automatically enter Edit mode and an edit window will pop up. To place a script in an existing object, right click the object and click Edit to open the edit window.

In the edit window you may see a button marked More>> click it to reveal five tabs marked General, Object, Features, Texture, and Content. Choose the Content tab.

This tab shows the contents of an object which can hold scripts, notecards, textures, sounds, even other objects. Press New Script to add a new script.

This will open the LSL editor with a default script. This editor will color code your syntax and provide some info about keywords when you hold your mouse over them. It will also do basic syntax checking. Alternatively you can use one of the alternate editors to write your scripts on your local harddrive and copy them to Second Life whenever you feel like it.

Before explaining the code, let's run it. Hit Save and close your edit window (not the LSL editor window).

You should see the words Hello, Avatar! from your object named "Object".

If you touch the object, it will say Touched. The edit window must be closed for touching to work.

Congratulations! You have compiled and run your first LSL script!

Development Cycle

(aka Wash / Rinse / Repeat)

We now have a running script, however most scripts you make will not run the first time you run them. It will take many tries as you correct errors and make improvements. When you hit "Save" on a script, the LSL editor "compiles" the code to something LSL can understand. It will stop however if it finds an error.

Brackets (or Braces, if you prefer), parentheses, and semicolons must all be perfectly in place before a script will run. If you are new to programing this can be one of the most infuriating steps and lead you to screaming DWIM (Do what I mean!). Part of becoming a programmer in ANY language is learning how to precisely define steps and correctly type them into the language you are working in. Thus you will find yourself writing, running, then RE-writing your code several times.


KBcaution.png Important: The pareto principle applies. At least (if not more than) 80% of the time you're spending on writing scripts you're actually not writing them but fixing stuff you messed up during the first 20% of the time. Having a look at the Style Guide certainly helps with being more productive cause you can read your own code.


Writing and fixing scripts takes time and effort. Readability is key to being more productive! Alternate Editors do help, too.

The script you made runs the instant you hit save. If you take it into inventory, it will "suspend" what it was doing but will continue from that exact point when rezzed (resurrected) again. (If you are not familiar with "taking" and "rezzing" an object you may need to revisit your building skills).

Each time you amend your code and save it, it is reset. You can also reset a script inside a prim in the following ways:

  1. Press Reset in the script window.
  2. Select the object and choose BUILD > SCRIPTS > RESET SCRIPTS (for older viewers TOOLS>RESET SCRIPTS IN SELECTION)
  3. By checking and unchecking the "Running" check-box
  4. Choose BUILD > SCRIPTS > SET SCRIPTS TO NOT RUNNING (for older viewers TOOLS>SET SCRIPTS TO NOT RUNNING IN SELECTION) and then BUILD > SCRIPTS > SET SCRIPTS TO RUNNING (for older viewers TOOLS>SET SCRIPTS TO RUNNING IN SELECTION).

Once you get comfortable with stopping, starting, and resetting a script, try changing the words "Hello, Avatar!" and see what else you can make it say.... for goodness sakes keep it PG.

WHY STOP AND START?

Scripting in Second Life can be a little bit like fixing your car...while going 60mph down the freeway. Thus you need ways to stop the programs for they may affect others.

Objects can hold more than one script and they will all run at once. This can be used in the following manner. Say you write a script that makes a prim change color every few seconds. You also write one to make it follow you. Put them both in one object and it will follow you while changing colors!

For simplicity's sake, the following examples will all be used individually so be sure not to put two or more into the same object.

Dissecting "Hello, Avatar!"

Let's take a look at the default code.

default
{
    state_entry()
    {
        llSay(0, "Hello, Avatar!");
    }

    touch_start(integer total_number)
    {
        llSay(0, "Touched.");
    }
}

The code above contains 1 state, 2 event and 2 functions. Let's look at them individually.

Any line starting with two forward slashes // is a comment. It will not run and is used to help you document your code.

// This is a comment

You can also use block comments, although it's not recommended for sake of better readability. Block comments start with /* and end with */.

/* this   *
* is      *
* a       *
* block   *
* comment */

STATES

A state in LSL is a section that is running, and waiting for events. Only one state can be active at any one time per script. Every script must have a default state with at least one event in it. Except for the default state, each state is defined by the word state followed by the name of the state. The contents of the state are enclosed in two curly brackets.

default
{
    // contents of state go here
}

state playing
{
    // this is a state called "playing"
}

EVENTS

event are inside of states. By "inside" I mean it is between the open and closed curly brackets that represent the body of the state. When that state is active, those events wait to be triggered and run the code inside them. We have seen "state_entry" which is triggered by the state being entered, and "touch_start" which is triggered when you, or anyone, touches an object.

Let's take a look at the default code.

// state begins
default
{
    // event begins
    touch_start(integer num_detected)
    {
        // this is the content of the event (between curly brackets)
    }
    // event ends
}
// state ends

FUNCTIONS

Functions lay inside of events and are either defined by you or built-in. Those built in to LSL all start with two lowercase L's. We have seen llSay() so far. Functions take "arguments" or values in the parentheses that follow it. If you hover over the function in the editor, a pop-up will show that tells you what the function is expecting. In the case of llSay it expects a number and a string. We send it the number zero and the string "Hello, Avatar!" separated by a comma. The function is "expecting" a number and strings and will not take anything else.

Putting it all together

Line by line, here is the hello avatar script.

default // All Scripts need a Default State

{ // this open curly bracket denotes the start of the state
    state_entry() // an event
    {
        llSay(0, "Hello, Avatar!"); // a function inside the event's curly brackets
    } // closed curly bracket closes the state_entry event

    touch_start(integer total_number)  // another event inside default state
    {
        llSay(0, "Touched."); // a function between the brackets of the touch_start body
    } // end of touch start
} // Code end

The instant you save your script, it enters default state, which in turn runs the "state_entry" event which in turn runs the function llSay() which makes the object talk.

After this, the program waits idle in the default state until a new event is called.

Touching the box triggers the event "touch_start" which also makes the object speak.

Introducing States and Events

LSL scripts will not run beginning to end. Instead, they will look for a default state and wait for an event. Within those event, there can be a call to go to a new state.

All programs must contain the default state, inside of which must be at least one event. event are triggered either by actions happening to or around the object the script resides in, or are triggered from the script itself.

On/Off Example Using States

Let us look at a script with two states with two event in each.

default //default state is mandatory
{
    state_entry() // runs each time the state is entered
    {
        llSay(0, "turning on!"); //object speaks!
        llSetColor(<1.0, 1.0, 1.0>, ALL_SIDES); // sets no tint (white)
        // note the semicolons at the end of each instruction
        // (do not put them at the end of "if" statements)
    }

    // Note: for technical reasons discussed elsewhere, we use a touch_end event rather than touch_start when state changes are involved
    touch_end(integer total_number) // another event with only one function inside
    {
        state off; // sets the script to a new "state" and starts running "state off"
    }
} // this curly bracket ends the body of the default state.

state off // a second state besides "default"
{
    state_entry() // this is run as soon as the state is entered
    {
        llSay(0, "turning off!");
        llSetColor(<0.0, 0.0, 0.0>, ALL_SIDES); // sets black tint
    }

    touch_end(integer total_number)
    {
        state default;
    }
}

A simplification of this would be

 default
 {
 //set color to light and, if touched, enter the "off" state.
 }

 state off
 {
 //set color to dark and, if touched, enter the "default" state.
 }

Note that after "default" all new states begin with the word "state". Also, while the object has a texture, the color will affect the "tint" more than the true color.

Default State

Let us examine the default state.

First we see the "state_entry" event, which gets triggered each time the default state is entered. Which in this case is entered the first time the script is run.

SPEAK TO ME!

The first line in the event state_entry is...

llSay(0, "turning on!");

This makes the object speak "turning on!" on channel zero. What is channel zero? It is the same channel you see all public chat on.

A semicolon ends the line and yet another instruction follows.

llSetColor(<1.0, 1.0, 1.0>, ALL_SIDES);

This turns the prim to its brightest tint. If you take the texture off the prim, you would see it as bright white but with a texture, it looks "normal." The three ones stand for the Red, Green, and Blue values of the tint.

At this point the event is finished with the two lines of commands. Then the script waits idle in the default state for more events to happen.

TOUCHED BY AN AVATAR

While idle in the default state a touch will trigger the "touch_end" event.

Inside of the "touch_end" event is only one command:

state off;

This is a command to move immediately to a new state named "off".

This state is defined after the default state and nearly mirrors the default state, except that it turns the prim dark and, when touched, will put the script back into default mode, thus creating a loop.

  1. Enters default state
  2. Runs code in "state entry"
  3. Waits to be touched
  4. When touched enters "state off"
  5. Enters "state off"
  6. Runs code in "state entry" (note in the "off" state's body)
  7. Waits to be touched
  8. When touched enters "default" state

Then the whole thing starts over.

A Final Word on Words

Making your object speak is a great way to know what a script is doing, but everyone can hear it for 20m all around you. As you get into more complex scripts this can get pretty noisy! Three alternative ways to see what is going on exist.

SHHHH WHISPER

llWhisper( ) is just like llSay( ) but only broadcasts at half the distance (10m). You still must state what channel. So...

llWhisper(0, "turning on!");

...might work a bit to save the sanity of your neighbors.

Using llShout( ) increases the distance heard to a radius of 100m, but can cut the amount of friends you have in half.

llOwnerSay( ) uses no channel, and is seen in chat only by the object's owner. Very useful and can triple the amount of friends you have!

llOwnerSay("turning on!");

THE SOUND OF SILENCE

You can make a totally silent message via llSetText( ) like this.

llSetText("I am on", <1.0, 1.0, 1.0>, 1.0);

What do the numbers mean? The <1.0, 1.0, 1.0> we have seen before. It represents the values for red, green, and blue. For now just know that <1.0, 1.0, 1.0> means "white" and <0.0, 0.0, 0.0> means "black".

Replace the

llSay(0, "turning off!");

with...

llSetText("I am off", <0.0, 0.0, 0.0>, 1.0);

The 1.0 is the alpha setting. 1.0 means fully opaque, and 0.0 would be completely transparent (invisible).

Next steps

Now that you can edit and run LSL code, move on to one of the more advanced LSL Tutorials.