Thursday 2 June 2011

Second Life - The Linden Scripting

Introduction

While teleporting yourself from one land to another in second life, for sure you met people dressed with strange clothing and visited interesting places with strange buildings.
An interesting fact is that all buildings, all clothes and all strange objects that you encounter while travelling, are build by residents.
As a resident, Second Life enables you to build your own objects and store such objects in your inventory. To achieve this, the Second Life viewer provides the required tools to build your own objects, from simple static blocks to complex dynamic machines.
Static objects can be easily created; drag and drop, customize properties and that’s all you need to know. Dynamic objects are a bit more tricky because movement and logic can only be achieved by using scripting; Linden Scripting Language (LSL). Luckily for us, Second Live provides a script editor that enables you to create, debug and test your scripts.
This blog is all about scripting. I will try to explain some code blocks that I created while getting acquainted with the Linden Scripting language.
All scripting mentioned in this blog were created and tested on Fermi Sandbox; a land that enables residents to build their own objects for free.

Linden Scripting Language

The Linden Scripting Language (LSL) is used within Second Life to give behavior and animate avatars and primitives (prims).
The LSL is based on State Machines. Machines are objects that can change their state according to some Input. To better understand state machines, let’s assume that we have a light bulb. Unless the light bulb is not damaged or broken, the bulb can be in two different states; on or off. And an input to change the bulb state can be a switch.
Similar to other programming languages, LSL is made up of the following components:
  • Functions – These blocks of code, return results and modify objects based on parameters. Functions can be called and executed from other functions or Events to perform mathematical calculations and modify objects. In Second life a number of pre-defined functions are already built and for a full list of functions, refer to LSL Functions.
  • Events – These can be used as listeners. When an event is associated with an object, the event will stay idle until an event occur. When an event occurs, the code within the event is executed. For example, an event can be used to display a message when an avatar touches a specific prim. For a full list of pre-defined events, refer to LSL Events.
  • Types – LSL is strongly typed, variables have to be declared with their variable type. In LSL various types are supported, and amongst others you can create Integers, Floats and Strings. Similar to other programming languages, in LSL, type casting is supported. For example, you can change a String to an Integer and vice versa. For more information on Types refer to LSL Types.
  • Operators – These are used to perform mathematical functions and comparison. Amongst others, LSL supports, addition, subtraction, multiplication and many more. For a full list of supported operators, refer to LSL Operators.
  • Constants – Constant values can be used to refer to objects and object properties. Unlike variables, such values cannot be changed. For a full list of constants, refer to LSL Constants.
  • Libraries – LSL contains a list of pre-defined scripts that can be copied and used for free. Second Life residents can contribute to this list by creating their scripts and uploading them into the LSL library. For more information, refer to LSL Library
  • Flow Control – Similar to other languages, LSL supports, looping, function calling and conditional comparisons. Using loops and conditions you can iterate in a list of objects or call a function a number of times. For more information, refer to LSL Flow Control.

Create a basic script

The best way to describe how to create a basic script is by showing an example. Let us assume that we want to create a block that displays a message when is touched by an avatar.
1.    I teleported my avatar to Fermi Sandbox. This land enables you to build and test your prims for free.
2.    Right click an empty space and select Build. This will launch the Build toolbar.
3.    Select the Cube icon and the Create (Magic wand).
4.    Click an empty space to add the new block.
5.    In the Build toolbar, click Content and New Script. This will create a new script file containing the default syntax.
6.    Double click the new script file to launch the Script editor. The content should be similar to the following:
7.    Close the Build toolbar and test your prim.
When the prim is in the default state, the state_entry event will display some text using the llSay(<Channel>,<Text to display>).The event touch_start is executed when the prim is touched by an avatar.

Display messages

The following functions can be used by a prim to display a message:

Function
Description
Example
llSay(<Channel>,<Text to display>)
Text can be heard by everyone within 20 meters and can be 1023 bytes in length. To prevent recursion, a prim cannot llSay text to itself.
llSay(0,"Hello, Avatar!");

llOwnerSay(<Text to display>)
Test can be heard only by the prim owner. Messages longer that 1023 bytes are truncated.  The message will disappear after 45 seconds when the owner leaves the prim region.
llOwnerSay("Hello Owner!" );
llInstantMessage(<Key>,<Text>);
Message is send via chat to a specific avatar. The Key is used to identify the recipient of the message (Avatar UUID).
llInstantMessage(llDetectedKey(0),"You have been registered!");
NOTE: llDetectedKey(0) is used to get the avatar UUID.
llShout(<Channel>,<Text>);

Text can be heard by everyone within 100 meters and can be 1023 bytes in length. To prevent recursion, a prim cannot llShout text to itself.
llShout(0,"Hello All" );
llWhisper(<Channel>,<Text> );

Text can be heard by everyone within 10 meters and can be 1023 bytes in length. To prevent recursion, a prim cannot llWhisper text to itself.
llWhisper(0,"whispering" );


Chat with a prim

An object can be instructed to listen to “chat messages” generated by another object. The following example shows a prim that will echo your message and display your name when you speak.
When the default state is initialized the code in line 6 will call the listen event. When the listen event is triggered, the messages are displayed using the llInstantMessage function.
The function llListen triggers the listen event and is constructed as follows:
llListen(<Channel>, <Object Name>,<Object UUID>,<Text Spoken>);
The above code will produce the following output when I say “Hello Prim”:

Moving an object

Using vectors you can instruct an object to move to a specific position in LSL. A vector is a data type made up of three float values. You can specify the X, Y and Z coordinates in a vector to represent a specific position in SL. A vector can be created by using the following syntax:
vector vec=<<X Value>, <Y Value>, <Z Value>>;
The following example shows a prim that when touched, the prim moves in 4 random positions. Once ready, the prim will return to its initial position.
To start with, I created a function that generates a random vector(random move) using the llFrand function as follows:
This function will create a vector with 2 random numbers. Since the block will not move vertically on the Z axis, only the X and Y axis are altered.
The next step is to create a global variable to store the prim initial position:
//Prim initial position
vector initialPosition;
The default state syntax is as follows:
When the prim is in the default state, the prim will whisper a welcome message to the avatar (line 17). When the prim is touched, the touch_start event stores the current prim position and change the prim state to move.
The move state syntax is as follows:
When the prim enters the move state, a loop that will iterate for 4 times is started. The loop will display a message in line 36.
In Line 37 the random vector from getRandomVector() function is added to the prim current position and the result is set as the prim current position. The algorithm is as follows:
Current Position = Current Position + Distance to move
Using the llSleep(<Time in Seconds>) at line 38, the event is halted for 1 second. In line 39 the repeat counter is incremented.
When the loop is finished, the event will display a message, will move the prim to its initial position and will change the prim to the default state.
One thing to note is, if you sit on this block and click on it, the avatar will move with the block.

Changing color

The llSetPrimitiveParams(<parameters and values>) function enables you to change any prim property. In the following example, I linked a ball shaped prim on s stand to simulate a “stand light”. By default the ball shaped prim is colored in black and transparent. When touched, the ball shaped prim is colored yellow with a bright effect. The following code will do the trick:
In the default state, the PRIM_COLOR parameter is used to set the color to <0,0,0> (RGB color code for black), while the PRIM_FULLBRIGHT parameter is used to remove the bright effect.
When the prim is touched, the state will change to on, the PRIM_COLOR is set to <1,1,0>(RGB Color code for yellow) and the PRIM_FULLBRIGHT parameter is set to true. The prim will return to default state if touched for the second time.

Using messages

Typically to build something in Second Life you’ll have to build and link various prims to form a single unit. When multiple prims are grouped, you can move the group and save the group in your inventory as a single unit.
A group of linked prims is made up of only one parent/root prim (the last prim selected when linking) and a number of children (child prims).
Message passing in LSL, enables you to send messages and instructions between prims through scripting. To explain this, let us assume that we have an object made up of multiple prims, and we want that all prims change color when the object is touched. This can only be achieved through message passing. When the parent prim is touched, the parent prim sends a message using llMessageLinked() to all child prims. All children must have the event link_message(), this is triggered when the script receives a link message sent by llMessageLinked().
The following script is added to the parent script and is used to send a message to all child prims:
When the default state is entered, line 6 will get the number of prims using llGetNumberOfPrims() and will store the value into a local variable. Using llMessageLinked(), the script sends the color vector to use <0,0,1> (blue) as a parameter to all child prims.
In line 17, the prim will change to StateOne when touched.
When the parent script is in StateOne, using llMessageLinked(), the script sends the color vector to use <0,1,0> (red) as a parameter to all child prims.
In line 44, the prim will change back to the default state when touched.
All child prims should implement the following code:
When a child prim receives a message, the link_message() event is triggered and the code in line 4 is executed.
In line 4, using llSetPrimitiveParams() function, the prim color is changed according to the variable str. The following screenshots show the prims changing colors using the code described in this section.

Conclusion

Objects, scripting and imagination, made Second Life as it is. Residents can create their own objects and customize their appearance using Second Life building tools.
Using LSL, you can add logic, animate and interact with building blocks (prims). LSL syntax is very similar to the commonly used web programming languages; the only difference is that is based on state machines.
While I tried to script my own objects, I learned how much effort was done to build places I’ve visited in the last few days. Creating a block with some basic scripting is one thing, creating a whole city is a lot of time, patience and persistence.
Happy scripting…

Resources

No comments:

Post a Comment