LSL-101 Beginner The School of Creation
Lead Instructor

Sorin Todys - Advanced expert with 20+ years of experience in virtual worlds


All classes take place in Alife Virtual World at our dedicated Alife Virtual School region

LSL Scripting Fundamentals - Your First Script

Explore the immersive 3D world of Alife Virtual - Your free virtual world alternative

Explore the immersive 3D world of Alife Virtual - Your free virtual world alternative
High-resolution image (1920×1080 pixels) from Alife Virtual World School

Course Code: LSL-101


Part of: The School of Creation
Difficulty: Beginner
Duration: 4 Weeks (Self-Paced)
Lead Instructor: Sorin Todys

1. Course Overview

Welcome to the World of LSL!

Welcome, future creator! You are about to take your first step into the incredible world of Linden Scripting Language (LSL). LSL is the magic that brings our virtual world to life. It's the "brain" inside every object that moves, speaks, listens, or interacts with you. If you've ever wondered how a door opens automatically or how a vehicle drives, the answer is LSL.

This course, LSL-101, is designed from the ground up for absolute beginners. We assume you know nothing about programming and will guide you step-by-step from the basic concepts to writing your very first functional, interactive script.

What You Will Master

By the end of this 4-week course, you will have a solid foundation in LSL and be able to:

  • Understand the fundamental structure of an LSL script, including states and events.
  • Read and write basic LSL syntax correctly.
  • Use variables to store information like numbers, text, and unique keys.
  • Work with common data types such as integer, string, and vector.
  • Implement core LSL functions to make objects speak (llSay), move (llSetPos), and listen (llListen).
  • Control your script's logic using if/else statements to make decisions.
  • Write, save, and debug a complete, working script in-world.

Why LSL is a Powerful Skill

Learning LSL opens up a universe of creative possibilities. It transforms you from a passive resident into an active creator. You can build anything you can imagine:

  • Interactive art installations that respond to visitors.
  • Automated homes with doors, lights, and security systems.
  • Tools and HUDs (Heads-Up Displays) to enhance your virtual life.
  • Games, puzzles, and role-playing systems.
  • Anything that requires logic, interaction, or automation!

Prerequisites

No programming experience is needed! All you need is:

  • Basic computer knowledge (using a mouse and keyboard).
  • Familiarity with the Alife Virtual world and the Firestorm Viewer (how to move your avatar, camera controls, and create a basic prim/object).
  • A curious mind and a desire to create!

About Your Instructor

Sorin TodysSorin T.
Sorin Todys is a veteran creator and LSL expert with over 20 years of continuous experience scripting in Second Life and OpenSim grids. Having taught thousands of students, Sorin specializes in breaking down complex topics into simple, understandable concepts. He believes that anyone can learn to script and is dedicated to helping you succeed on your creative journey.

2. Lesson 1: Your First Words - Anatomy of an LSL Script

Theory: The Core Structure

Every LSL script, no matter how complex, is built on a simple foundation. Think of it like a small, obedient robot waiting for instructions. It has two primary components:

  • States: A state is a "mode of being" for your script. A script is always in one, and only one, state at a time. The most basic state, which every script must have, is the default state. For now, think of it as the script's main operational mode.
  • Events: Events are things that happen in the virtual world that your script can react to. Examples include an avatar touching the object, a timer going off, or a chat message being heard. Your code inside an event block only runs when that specific event occurs.

The basic structure looks like this:


default
{
    // This is the default state. All scripts must have it.

    event_name()
    {
        // Code inside this event runs ONLY when the event happens.
    }
}
            

Your First Script: "Hello, World!"

Let's write a script that says a message when it's first run and a different message when you touch it. This is the "Hello, World!" of LSL.


// My First LSL Script - A simple greeter

default
{
    // The state_entry event runs once when the script is saved/reset,
    // or when the object is rezzed in-world.
    state_entry()
    {
        // llSay is a function that makes the object chat publicly.
        // Channel 0 is the public chat channel everyone can see.
        llSay(0, "My script is running! Touch me to get a greeting.");
    }

    // The touch_start event runs whenever an avatar clicks (touches) the object.
    // 'integer total_number' is a variable that holds how many fingers touched the prim.
    // We can ignore it for now, but it must be there.
    touch_start(integer total_number)
    {
        // This line will only execute when the object is touched.
        llSay(0, "Hello, Avatar!");
    }
}
            

Step-by-Step Tutorial: Bringing Your Script to Life

  1. Create an Object: In the Alife Virtual world, right-click the ground and select "Build" (or "Create"). A magic wand icon will appear. Click the ground again to create a simple wooden cube (this is called a "prim" or "primitive").
  2. Open the Edit Window: Right-click your new cube and select "Edit". An editor window will appear.
  3. Navigate to the Content Tab: In the Edit window, click on the "Content" tab. This is where scripts and other items inside an object are stored.
  4. Create a New Script: Click the "New Script" button. A new script asset named "New Script" will appear in the Content tab. Double-click it to open the LSL editor.
  5. Write Your Code: The editor will open with some default code. Delete all of it and then copy and paste the "Hello, World!" script from above into the editor window.
  6. Save Your Script: Click the "Save" button. The script will compile. If there are no errors, you'll see "Save complete" in the editor's status bar. In your nearby chat, you should immediately see your object say: "My script is running! Touch me to get a greeting."
  7. Test It! Close the editor window. Now, left-click on your cube. It should say: "Hello, Avatar!"

Congratulations! You have just written and executed your first working LSL script. You've mastered the fundamental workflow of all LSL scripting.

3. Lesson 2: Giving Your Script a Memory - Variables & Functions

Theory: Variables and Data Types

In Lesson 1, our script could only react. To make scripts more intelligent, we need to give them a memory. In programming, this memory is called a variable. A variable is simply a named container that holds a piece of data. Each variable has a data type, which tells the script what kind of information it's storing.

Here are the most common data types you'll use:

  • integer: A whole number (e.g., 5, -20, 1000).
  • float: A number with a decimal point (e.g., 3.14, -0.5, 99.9).
  • string: A piece of text, always enclosed in double quotes (e.g., "Hello World", "Sorin Todys").
  • key: A unique identifier for an avatar or object (a UUID). It looks like "a1b2c3d4-...".
  • vector: A set of three float numbers, often used for position, scale, or color (e.g., <10.0, 20.0, 30.0>).

You declare a variable by stating its type, giving it a name, and optionally giving it an initial value. For example: integer touchCounter = 0;

More Powerful Functions

Functions are the action-words of LSL. We've already used llSay(). Let's introduce a few more that are incredibly useful:

  • llOwnerSay(string message): This is like llSay, but the message is only visible to the object's owner. It's the #1 tool for debugging your scripts!
  • llDetectedName(integer index): Used inside events like touch_start, this function gets the name of the avatar who triggered the event. The index is usually 0.
  • llGetOwner(): This function returns the unique key of the avatar who owns the object.
  • llListen(integer channel, string name, key id, string message): Tells the script to listen for chat messages on a specific channel. This is the foundation for command-based objects.

Example Script: A Personalized Greeter

Let's build on our last script. This time, instead of a generic greeting, it will greet the specific person who touches it by name.


// A personalized greeter script

// We declare a 'string' variable to hold our custom greeting message.
// This is a global variable, meaning it can be accessed from anywhere in the script.
string greetingMessage = "Welcome to my place, ";

default
{
    state_entry()
    {
        llOwnerSay("Personalized greeter script is ready.");
    }

    touch_start(integer total_number)
    {
        // Create a local variable 'name' of type string.
        // It will hold the name of the avatar who touched the object.
        string toucherName = llDetectedName(0);

        // Concatenate (join) our greeting message with the toucher's name.
        // The '+' operator joins strings together.
        string fullMessage = greetingMessage + toucherName + "!";

        // Say the complete, personalized message in public chat.
        llSay(0, fullMessage);
    }
}
            

How it works: When you touch the object, the touch_start event fires. The script immediately calls llDetectedName(0) to get your avatar's name and stores it in the toucherName variable. Then, it uses the + operator to combine the predefined greetingMessage with the detected name, creating a personalized sentence. Finally, it uses llSay to speak the result.

4. Lesson 3: Making Choices - Control Flow with if/else

Theory: Scripting with Logic

So far, our scripts react the same way every time. The true power of scripting comes from making decisions. LSL does this using control flow statements, the most important of which is the if statement.

An if statement checks if a condition is true. If it is, the code inside its curly braces is executed. If not, the code is skipped.


if (some_condition_is_true)
{
    // ...do this code.
}
            

You can create conditions using comparison operators:

  • == : Is equal to
  • != : Is NOT equal to
  • > : Is greater than
  • < : Is less than
  • >= : Is greater than or equal to
  • <= : Is less than or equal to

You can also provide an alternative action using else, for when the condition is false. For even more complex choices, you can chain conditions with else if.

Real-World Example: An Owner-Only Access Panel

Let's create a script that does one thing if the owner touches it, and something else if a stranger touches it. This is the basis for secure doors, control panels, and more.


// An owner-only security script

// Global variable to store the owner's key.
key ownerKey;

default
{
    state_entry()
    {
        // When the script starts, get the owner's key and store it.
        ownerKey = llGetOwner();
        llOwnerSay("Security system activated. Owner key is: " + (string)ownerKey);
    }

    touch_start(integer total_number)
    {
        // When touched, get the key of the avatar who touched it.
        key toucherKey = llDetectedKey(0);

        // This is our decision!
        // We compare the toucher's key with the stored owner's key.
        if (toucherKey == ownerKey)
        {
            // IF the keys match, run this code.
            llOwnerSay("Access Granted. Welcome, Owner!");
        }
        else
        {
            // ELSE (if the keys do NOT match), run this code instead.
            llSay(0, "Access Denied. This panel is for owner-use only.");
            llOwnerSay("Alert: Unauthorized access attempt by avatar key: " + (string)toucherKey);
        }
    }
}
            

How it works: In state_entry, the script figures out who the owner is and saves their key. This only happens once. Then, in touch_start, it gets the key of whoever touched it. The if statement is the crucial part: it compares the two keys. If they are identical (==), the "Access Granted" message is shown. If they are different, the else block is triggered, issuing a public denial and a private alert to the owner.

5. Lesson 4: Bringing It to Life - States and Practical Application

Theory: Managing Complexity with States

As scripts get more complex, it's useful to separate their behaviors into different modes. For example, a light can be "on" or "off". These modes are called states in LSL. A script can have many states, but it can only be in one at a time. We've been using the default state all along, but now we'll create our own.

You define a new state with the state keyword, followed by a name. You can then switch between states using the command: state new_state_name;

Each state can have its own set of events. For example, a touch_start event in the "off" state might do something different from a touch_start in the "on" state.

Putting It All Together: A Toggle Light Switch

This script combines everything we've learned: variables, functions, control flow, and multiple states. It will create a prim that acts as a light switch, toggling between an "on" and "off" state when touched.

We will use the powerful llSetPrimitiveParams function to change the object's color and enable its light.


// A multi-state toggle light switch

// This is the "off" state. Since it's the first state in the script,
// it's where the script will start. We've named it 'off' instead of 'default'
// for clarity, but you could use 'default' as the off state.
state_default
{
    state_entry()
    {
        // When entering the 'off' state:
        llOwnerSay("Light is now OFF.");
        // Set the prim color to dark grey and turn off the light feature.
        llSetPrimitiveParams([ PRIM_FULLBRIGHT, ALL_SIDES, FALSE,
                               PRIM_COLOR, ALL_SIDES, <0.2, 0.2, 0.2>, 1.0 ]);
    }

    touch_start(integer total_number)
    {
        // When touched in the 'off' state, switch to the 'on' state.
        state on;
    }
}

// This is our custom "on" state.
state on
{
    state_entry()
    {
        // When entering the 'on' state:
        llOwnerSay("Light is now ON.");
        // Set the prim to be full-bright (glow), set its color to yellow, and turn on the light.
        llSetPrimitiveParams([ PRIM_FULLBRIGHT, ALL_SIDES, TRUE,
                               PRIM_COLOR, ALL_SIDES, <1.0, 1.0, 0.0>, 1.0,
                               PRIM_POINT_LIGHT, TRUE, <1.0, 1.0, 0.0>, 1.0, 10.0, 0.75 ]);
    }

    touch_start(integer total_number)
    {
        // When touched in the 'on' state, switch back to the 'off' state.
        state state_default;
    }
}
            

How it works:

  1. The script starts in state_default. The state_entry event immediately runs, making the prim dark and ensuring the light is off. The script now waits.
  2. When you touch the prim, the touch_start event in state_default fires. Its only job is to issue the command state on;.
  3. The script immediately switches to the on state. This triggers the state_entry event inside the on state. This event's code runs, making the prim bright yellow and casting light. The script now waits in the on state.
  4. When you touch it again, the touch_start event in the on state fires, which sends it back to state_default, and the cycle repeats.

6. Hands-On LSL Exercises

The best way to learn is by doing! Try to complete these challenges. Create a new script for each one.

  1. 1. The Moody Greeter: Modify the "