Prajna's LSL 101

From Second Life Wiki
Jump to navigation Jump to search

A Gentle Introduction to Scripting in Second Life

This section of LSL 101: The Wikibook is written for the SL user who wants to script the things they build or own but who, perhaps, has no experience of any kind with programming. If that's you, welcome! It will also be of use to people who have experience in other programming languages and would like a gentle introduction to LSL.

Since scripting is one aspect of building, we will assume that you, the reader, have rudimentary building skills. You should, at minimum, be able to create a prim, edit it, take it in and out of your inventory, be able to do the same with a notecard, and know how to put a notecard into a prim's inventory. That's about it. Everything else you'll need, we'll try to cover.

Whenever you want an object in SL to do something, to respond to a mouse click, to greet someone when they come close to it, to change its texture or colour - all the interesting things that objects do, other than just sit there - a script is needed. Scripts take note of things that happen and are able to carry out actions in response.

Scripts in SL are written in LSL (Linden Scripting Language), a simple but powerful programming language, tied closely to the SL environment. (Simple, in this case, is used to mean it is more limited than many other popular programming languages; not necessarily that it is simpler to learn, though it is not very difficult if you are really interested to do so.)

When you learned to speak you discovered that you needed to know not only some words (vocabulary) but also the order in which to use them (grammar). It is the same with computer languages: you have to learn the words and you have to learn the order in which to use them. When you learned to read and write you discovered that there is also punctuation - commas, full stops (periods, if you are American), brackets, etc. - which help to clarify how different words and phrases relate to each other. The difference between computer languages and human languages is that with human languages people can generally understand your meaning even if your pronunciation or spelling is not completely correct or your grammar is slightly wrong. Computer languages are not like that. If your spelling, punctuation or structure is even slightly wrong the computer will report an error or, at best, not do what you expected it to do. This can be very frustrating for beginners.

I'm sure, if you have ever attended a writing class, you were told that a story has a beginning, middle, and end. This we can call the structure of a story. In LSL the structure is very important and we will discuss that (and introduce you to some of the vocabulary, grammar and punctuation) in the next section



The Structure of a Script

Here is the simplest possible valid LSL script. It doesn't actually ask the computer to do anything but all scripts have, at minimum, this structure:

<lsl> default {

    state_entry() {
    }

} </lsl>

In order to explain even this short piece of code we need to introduce you to some terms that will probably be new to you.

LSL scripts use two concepts called states and events.

States

State is actually a very good name for what states do in LSL. If you think of a car, it can either be moving or stopped. We can say its state is moving (when it is moving) and its state is stopped (when it is stopped). Another example is your own state of being: you can be awake, asleep, active, sitting, standing, hungry, bored, confused, etc.

All LSL scripts have at least one state: the default state. This is the state when no other states are active. You can see in the code above the word default is used to tell the script about what happens in the default state.

Here is an example with two states:

<lsl> default {

    state_entry() {
        llOwnerSay("Switching to the hungry state...");
        state hungry;
    }

}

state hungry {

   state_entry() {
       llOwnerSay("I am very hungry! Does anyone have any spam?");
   }

} </lsl>

The first thing to notice is that the hungry state needs the word state, so that the script knows this describes a state rather than something else. The default state does not need to be proceeded by the word state.

Next, notice the curly braces '{' and '}'. These tell the script which lines are part of the default state, which are part of the hungry state, and which belong to the state_entry() event handler, which we describe next.

Events

When something happens we can say an event has happened. LSL knows about many kinds of events and can respond to them depending on what kind of event happened.

LSL scripts don't run on your PC, they run on the server where the sim you are in is running. The server takes care of seeing when something changes - an avatar moves, you click something, the clock ticks, someone types something in text chat, you create an object, save a notecard, give someone a landmark, etc. - and it passes on information about those changes to the viewer running on your PC, which then displays those changes or shows a dialog or whatever is needed. The server also passes those events on to any scripts that have asked to know about that particular kind of event.

Your script can tell the server to inform it of events by including an event handler. In the example above we have added event handlers called state_entry(), which requires the server to tell it when the script enters that particular state. When the script receives the state_entry() event it runs the instructions inside the curly braces belonging to the state_entry() event handler.

Some events also pass other information from the server; for instance the listen() event receives a channel number (to indicate which channel the chat was heard on), the name of the avatar or object that sent the chat, their (or its) UUID key, and the text of the message that was typed or sent. The listen() event handler is declared like this:

<lsl> listen(integer channel, string name, key id, string message) {

   // some actions to take when something is heard in text chat

} </lsl>

We will discuss more about events but before we do, and in order to explain the code above, we need to introduce another concept: variables.

Variables

We said that the server can pass information about events and in our example above you can see that we refer to the different pieces of information by giving them different names: channel, name, id, message. Not only are these separate pieces of information, they are different types of information: channel is a number, name is text, id is a special kind of number called a UUID key, message is text.

Variables, then, are declared by giving their type and their name. But variables would not be very useful if they did not also have a value. When we give a value to a variable it can be said we defined the variable.

Before you use a variable in LSL you must declare it and usually you will want to define it as well. These can both be done on separate lines or on the same line of code. Here are two examples:

<lsl> string myName; myName = "An Avatar";

// or

string myName = "An Avatar"; </lsl>

So what different types of variables does LSL know about?

integer

Integers are numbers, but only a limited set of numbers. Integers in LSL are any numbers between −2,147,483,648 and +2,147,483,647, so long as they are 'whole' numbers (that is, they don't have a decimal point, like 1.5).

integers are declared and defined like this

<lsl> integer myNumber = 42; </lsl>

You are used to using the decimal number system (called base 10), where numbers are counted using the digits 0 to 9, but you should also know there are other number systems that can be used with LSL, such as hexadecimal (base 16), which uses digits 0 to 9 and letters A to F. You don't need to know about the hexadecimal system to write scripts but you may well come across hexadecimal numbers if you are modifying scripts someone else has written and you may later find that there are some places where it makes sense to use hexadecimal numbers instead of decimals.

Hexadecimal numbers are written as in this example (which does exactly the same as the example above):

<lsl> integer myNumber = 0x2a; </lsl>

2a in hexidecimal = 42 [(2 * 16) + 10 is the same as (4 * 10) + 2]

A note to those who have used other programming languages before: LSL does not have a binary variable type. TRUE and FALSE are stored using integers with TRUE having a value of 1 and FALSE having a value of 0. We will discuss this in more detail later.

float

Floats store 'real' numbers; numbers that have a decimal point. That means they can be used to store fractions like 1.5 or 2.34567.

Floats are declared and defined like this: <lsl> float myFloat = 1.024; float myFraction = 1.762E-12; </lsl>

You may wonder, "Why use integers when floats can store whole numbers too?". The answer is that doing maths on integers is much quicker than doing maths on floating point numbers. It is also generally more accurate. Consider a number like one third (1/3). 1 divided by 3 is approximately 0.33333333333 (and a whole lot more 3s depending on how precise you want to be). If you multiply 0.3333333 by 3 you will get approximately 1, but not quite. For most purposes it doesn't matter that the values are not exact but with computers we can do things many times in quick succession and any inaccuracy quickly begins to make a difference. With integers it is easy to test if 1 = 1 but you need to be more careful with floats; you might think that 0.99999999999 is near enough to 1 but LSL doesn't consider them to be the same at all.

The second example above uses another way to express floating point numbers, called 'scientific notation'. Scientific notation (sometimes called standard form or exponential notation) is a way of conveniently writing very large and very small numbers. Our 0.3333333 above could be written 3.333333E-1. For more information on this (if you are interested) take a look at the [page on scientific notation].

When you set a value for a float always make sure you include the decimal point (for instance 17.) even if the value has no fraction after the decimal point (17.0 in that example). If you don't do that then the LSL compiler assumes the value you entered is an integer, which it must convert to a float. There won't be any error if you forget to do this but it does unnecessarily use and extra instruction to do the conversion, taking up space in the script and memory, and processor time when it is running.

string

String refers to a string of characters; all the letters, numbers and symbols you can type on your keyboard.

Strings are declared and defined like this: <lsl> string myName = "Some Avatar"; string newline = "\n"; </lsl>

The first thing to notice is that strings are surrounded by quote marks (") and the value of the string is all the characters between the starting quote and the end quote.