Linden Scripting Language

LSL is Second Life's built-in programming language. It is use to develop applications that are then attached to objects in-world (i.e., things that you build). Programs written in LSL can range from the simple (i.e., displaying a name or changing a color) to the complex (an interactive game).

A couple of great resources for both beginning and experienced coders are:

- Second Life Wiki - Linden Lab's support wiki for all things SL. It's a great resource for looking up things such as functions, event handlers, etc., and there are lots of good code examples.
- LSL Wiki - another wiki resource for LSL developers.

In addition, when you download the Second Life viewer, it includes an LSL reference guide. It contains basic getting started info and a list of all functions.

---------

Basic Script Creation and Anatomy

To create a script in SL, locate the 'Scripts' folder in your Inventory. Right-click (ctrl-click on Mac) and choose 'New Script' from the pop-up menu. A fresh script will be created. Give it a name and double-click its icon in your Inventory. It will automatically open in the LSL editor (which compiles your code each time you click the 'Save' button). Whenever you create a new script, it is automatically populated with some default code:


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


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

This works well as an introduction to basic LSL anatomy. This little programs contains the following:

1 - a default state: default {}
2 - an entry event: state_entry() {}
3 - two instances of the function: llSay();
4 - a touch event: touch_start() {}

A function is a specific task. Events (or, event handler) contain instructions for what to do when a certain thing happens.

Let's break it down a little further. Each script in LSL consists of a default state. There may be others, but default {} is always a given. When a script begins, it will always be in the default state. Notice in the example that it occurs at the root level of the document -- that is, the entire content of the script is contained within the brackets of the default state.

Next, there is an entry event, state_entry() {}. This event is triggered the moment a script is saved or added to an object. Notice within the event's brackets, we have the llSay(); function. This function prints messages (can be public or private) to SL's text chat area. It takes two arguments: channel ('0' is public) and message (in quotations, in this case it's "Hello Avatar!").

Following is a touch event, which is triggered when an object is touched by an avatar. Notice there is a second instance of the llSay(); function within the touch event's brackets. Therefore, when the object containing this script is touched, the words 'Hello Avatar!' will be printed in the chat area.

Finally, the closing brackets complete the script. It is worth noting some syntax issues here:

The llSay(); function reflects the basic syntax for all functions:

The 'll' prefix stands for Linden Labs. Next is the function name, Say, followed by a parentheses set and semicolon terminator. In the case of the Say function, two arguments are passed: a channel on which to send a text message and the message itself. There are hundreds of channels available for private messaging, with '0' being the channel reserved for public chat messages. The message text is always enclosed in double-quotes.

The event touch_start(integer total_number) {} contains two arguments, 'integer' and 'total_number'. This essentially means that the event will detect each time the object containing this script is touched. If you are a newcomer to LSL, I would not think any deeper about that for the time being.

There are no comments in this default script, but I'll add some so you can see how they can be used in LSL:

// START SCRIPT'S DEFAULT STATE
default
{
   // WHEN THE SCRIPT STARTS, PRINT 'HELLO AVATAR' IN THE TEXT CHAT
    state_entry()
    {
        llSay(0, "Hello, Avatar!");
    }
   // WHEN THE OBJECT IS TOUCHED, PRINT 'TOUCHED' IN THE TEXT CHAT
    touch_start(integer total_number)
    {
        llSay(0, "Touched.");
    }
}
// END OF DEFAULT STATE, AND HENCE, THE SCRIPT


All text preceded by the double-slash characters ('//') are comments, and are ignored by the compiler. So, you can use them to provide brief descriptions of what is going on in a given area of a script. This is not only useful to others reading your code, but also useful to you because after awhile, believe me, when you write enough code you forget what you were thinking in a given line of programming.
As a start, you could use this script and try replacing the default functions and events with some of the others you'll find listed in the LSL scripting guide that you'll get when you download Second Life. As you get more comfortable, you can start to integrate multiple events and functions in your scripts.

---------

For the time being, let's start with some simple scripts. Copy and paste the italicized text in each example below into a new LSL script.

1. Invisibility - I am currently working on a meta-material outfit that effectively turns an avatar invisible. In the meantime, use this to turn objects invisible. The script responds to text commands, though it can be modified for other conditions. Notice there are several functions (llGetOwner, llListen, llSetAlpha ...), each of which feature a different number of arguments (or in the case of llGetOwner, no arguments at all). Notice also the 'listen' event, within which some conditional logic statements are contained (if/then). The llListen(); function makes the script 'listen' to what is typed in the text chat; the 'listen' event sets up what kind of action is taken if a certain message is typed.

//INVISIBILITY BY APIS MILENA, 2008

//Drop this on a prim or other object for instant invisibility. To turn the object visible, type 'reveal' in the //local chat. To hide it again, type 'hide.' To de-rez it, type 'finish.'

default
{
    state_entry()
    {
        llGetOwner();
        llListen(0,"","","");
        //llSetAlpha(0.0, ALL_SIDES); // make entire prim invisible.
    }
    listen(integer channel, string name, key id, string message)
    {
        if( message == "reveal" )
        {                                        
         llSetAlpha(1.0, ALL_SIDES); // make entire prim visible.
        }       
        if( message == "hide" )
        {                                        
         llSetAlpha(0.0, ALL_SIDES); // make entire prim invisible.
        }       
        if( message == "finish" )
        {                                        
         llDie(); // make entire prim disintegrate.
        }   
    }
}


2. Life Span- drop this on an object to establish a time limit on its existence. The script is easily modifiable to change the time limit before the object de-rezzes. I am thinking some great applications can be made with freely available outfits ...

//Life Span by Apis Milena, 2008.
//Drop this on an object to limit its existence. The default value is 8 seconds. Change the argument to the 'llSleep' function to adjust the time limit.

default
{
    state_entry()
    {
        llSleep(8.0);
        llDie();
    }
}  


3. Phantom Settings - this script alters an object's phantom settings via a text command. I've used it to grant access through force fields. Adjust the argument passed to llSleep() to change the time frame that the phantom settings are altered. Remove the llGetOwner that is passed to llListen() to make the script responsive to anyone.

//PHANTOM SETTINGS by Apis Milena, 2008.
// Use and Modify Freely

//use this script to turn phantom settings of a primitive off and on by typing a password


default
{
    state_entry()
    {
        llListen(0, "", llGetOwner(), "");
    }

   listen(integer channel, string name, key id, string message)
 {
  // if password is correct, turn phantom properties of door on
  if (message == "disable")
  {
   llSetPrimitiveParams([PRIM_PHANTOM, 1]);
  }
  //otherwise, you are denied
  else if (message != "disable")
  {
   llSay(0, "Access Denied");
  }
 
  //sleep 7 seconds, then turn phantom properties off. This should give you enough time
  //to get inside the field.
  llSleep (7);
  llSetPrimitiveParams([PRIM_PHANTOM, 0]);
 
    } 
}



4. Levitation - this little app makes it easy to cause objects to levitate. There is also a routine that will give an object a toss. Both actions are triggered by text commands. Adjust the llGetBuoyancy() argument to increase the levitation. This script was originally written for a Halloween gag involving flaming pumpkins.

//SWARM by Apis Milena, 2008

//Drop this script on an object, and when you type 'swarm' in the local chat, it will hurl itself around the area. Rez multiple objects holding this script, and they will //all swarm at once when you type. Uncomment the llSetBuoyancy function and adjust the float value for some added chaos!

 

default

    state_entry()
    {
        llListen(0, "", "", "");
        llSetStatus(STATUS_PHYSICS, TRUE);    
    }
   
listen(integer channel, string name, key id, string message)
 {
  // if password is correct, toss that pumpkin, MF!
  if (message == "swarm")
    {
  //This will launch it.
 
  //Each float variable below (x,y,z) results in a pseudo-random floating point number, generated by llFrand, between 0.0 and 10.0.

        float x = (float)llFrand(10.0);
        float y = (float)llFrand(10.0);
        float z = (float)llFrand(10.0);

  //The functions below perform a little math on the variable values generated above,
  //which send determine the directions in which the pumpkin is sent flying. This really
  //is at its best when there are several flaming pumpkins (or other objects) present and swarming in the area.
        
    llApplyImpulse(llGetMass()* <x, y, z>,FALSE);
}
   
    if (message == "levitate")
    {
    llSetStatus(STATUS_PHYSICS, TRUE);
    llSetBuoyancy(1.0);
    }


    if (message == "fall")
    {
    llSetBuoyancy(0.0);
    }
     if (message == "disappear")
    {
        llSleep(1.0);
        llDie();
    }     
}
}


5. Smoke - the llMakeSmoke(); function was deprecated awhile back, so now one should make use of the Particle System to create smoke in-world. Drop this script on an object, then touch it stop and start it smoking. Adjust particle system settings for larger or smaller objects.


// SMOKE STACK by Apis Milena, 2008,
// Drop this on an object, then touch it to turn the smoke off and on.
// modified from Keknehv Psaltery's Particle Script v1.1
// 1.0 -- 5/30/05
// 1.1 -- 6/17/05

MakeParticles()                //This is the function that actually starts the particle system.
{               
    llParticleSystem([                   //KPSv1.0 
        PSYS_PART_FLAGS , 0 //Comment out any of the following masks to deactivate them
    //| PSYS_PART_BOUNCE_MASK           //Bounce on object's z-axis
    | PSYS_PART_WIND_MASK             //Particles are moved by wind
    | PSYS_PART_INTERP_COLOR_MASK       //Colors fade from start to end
    | PSYS_PART_INTERP_SCALE_MASK       //Scale fades from beginning to end
    | PSYS_PART_FOLLOW_SRC_MASK         //Particles follow the emitter
    | PSYS_PART_FOLLOW_VELOCITY_MASK    //Particles are created at the velocity of the emitter
    //| PSYS_PART_TARGET_POS_MASK       //Particles follow the target
    //| PSYS_PART_EMISSIVE_MASK           //Particles are self-lit (glow)
    //| PSYS_PART_TARGET_LINEAR_MASK    //Undocumented--Sends particles in straight line?
    ,
   
    //PSYS_SRC_TARGET_KEY , NULL_KEY,   //Key of the target for the particles to head towards
                                                //This one is particularly finicky, so be careful.
    //Choose one of these as a pattern:
    //PSYS_SRC_PATTERN_DROP                 Particles start at emitter with no velocity
    //PSYS_SRC_PATTERN_EXPLODE              Particles explode from the emitter
    //PSYS_SRC_PATTERN_ANGLE                Particles are emitted in a 2-D angle
    //PSYS_SRC_PATTERN_ANGLE_CONE           Particles are emitted in a 3-D cone
    //PSYS_SRC_PATTERN_ANGLE_CONE_EMPTY     Particles are emitted everywhere except for a 3-D cone
   
    PSYS_SRC_PATTERN,           PSYS_SRC_PATTERN_ANGLE_CONE
   
    ,PSYS_SRC_TEXTURE,           "2ca57748-4944-de53-b301-8d0efbafb2c6"     //UUID of the desired particle texture 
    ,PSYS_PART_MAX_AGE,          5.0                //Lifetime, in seconds, that a particle lasts
    ,PSYS_SRC_BURST_RATE,        0.05               //How long, in seconds, between each emission
    ,PSYS_SRC_BURST_PART_COUNT,  1                  //Number of particles per emission
    ,PSYS_SRC_BURST_RADIUS,      5.0                //Radius of emission
    ,PSYS_SRC_BURST_SPEED_MIN,   1.5                //Minimum speed of an emitted particle
    ,PSYS_SRC_BURST_SPEED_MAX,   2.0                //Maximum speed of an emitted particle
    ,PSYS_SRC_ACCEL,             <0.0,0.0,0.8>      //Acceleration of particles each second
    ,PSYS_PART_START_COLOR,      <0.8,0.8,0.8>      //Starting RGB color
    ,PSYS_PART_END_COLOR,        <0.2,0.2,0.2>      //Ending RGB color, if INTERP_COLOR_MASK is on
    ,PSYS_PART_START_ALPHA,      0.9                //Starting transparency, 1 is opaque, 0 is transparent.
    ,PSYS_PART_END_ALPHA,        0.0                //Ending transparency
    ,PSYS_PART_START_SCALE,      <0.8,0.8,0.0>      //Starting particle size
    ,PSYS_PART_END_SCALE,        <4.3,4.3,0.0>      //Ending particle size, if INTERP_SCALE_MASK is on
    ,PSYS_SRC_ANGLE_BEGIN,       -.3                //Inner angle for ANGLE patterns
    ,PSYS_SRC_ANGLE_END,         .3                //Outer angle for ANGLE patterns
    ,PSYS_SRC_OMEGA,             <0.0,0.0,0.0>       //Rotation of ANGLE patterns, similar to llTargetOmega()
            ]);
}


default
{   
    state_entry()
    {
        MakeParticles();                //Start making particles
        llSetText("Uberto Power Plant", <1.0, 1.0, 1.0>, 0.0);
    }

    touch_start( integer num )            //Turn particles off when touched
    {
        state off;        //Switch to the off state
    }
}

state off
{
    state_entry()
    {
        llParticleSystem([]);        //Stop making particles
    }
   
    touch_start( integer num )        //Turn particles back on when touched
    {
        state default;
    }