Second Life: Scripting Recipes

Discuss scripting tips and techniques with other inworld developers. All scripting related discussions are encouraged here.

Second Life: Scripting Recipes

Postby Milen N Ester » March 9th, 2012, 17:09:45

    CHAPTER 1: INTRODUCTION TO LSL

    • Understanding State Machines
    • Implementing Basic Security
    • Changing the Appearance of an Object
    • Communicating
    • Using Dialogs

    This topic is designed for those who understand the basics of building and scripting in Second Life. For these people this topic will provide many useful Linden Scripting Language (LSL) examples. These examples are very useful in their own right, but also serve as starting points for more complex Linden Scripting Language projects.
    Chapter 1 begins with a quick review of the Linden Scripting Language. This chapter is not designed to teach the Linden Scripting Language to someone without programming experience.
    If you have already programmed a language, e.g.., C, C++, Java or C#, this chapter will provide suffi cient introduction to the Linden Scripting Language to get you started.
    If you have no programming experience, review one of the many tutorials for the Linden Scripting Language. A Google search on "LSL Tutorial" will reveal a few.
    This chapter will now introduce the Linden Scripting Language, beginning with state machines.

    State Machines
    The concept of a state machine is not unique to Second Life. State machines are a common programming paradigm. However, no language makes the concept of a state machine as integral as the Linden Scripting Language. Many of the recipes in this topic use state machines. As a result, it is very important to understand the concept of a state machine. To see state machines in action, consider the default script, which is automatically generated by Second Life, when a new script is created. This script is shown here.

    Code: Select all
    default
    {
    state_entry()
    {
    llSay(0, "Hello, Avatar!");
    }
    touch_start(integer total_number)
    {
    llSay(0, "Touched.");
    }
    }


    This script starts with the word default . The word default specifi es the name of the state that the enclosed code belongs to. For this script there is only one state. This state, which is named default , is the tarting state for any script in Second Life. Many scripts are constructed entirely within their default state. This is often bad design in Second Life. Consider the following script, which implements a simple switch that can be turned on or off.

    Code: Select all
    integer value;
    default
    {
    state_entry()
    {
    value = TRUE;
    }
    touch_start(integer total_number)
    {
    if( value==TRUE )
    {
    llSay(0,"On");
    value = FALSE;
    }
    else
    {
    llSay(0,"Off");
    value = TRUE;
    }
    }
    }


    As can be seen, a global variable, named value , is set to either TRUE or FALSE . As the user touches the object, the object will say either “On” or “Off”. As the object is touched these values alternate. Also, a ote on global variables. Global variables are normally considered bad programming practice. However in Second Life, there is really little choice as to whether to use them or not. Because the Linden Scripting Language does not support user defi ned classes, global variables are the primary way for a script to hold values long-term.

    This same functionality could be created using a state machine. The following lines of code do this.

    Code: Select all
    default
    {
    touch_start(integer total_number)
    {
    llSay(0,"On");
    state off;
    }
    }
    state off
    {
    touch_start(integer total_number)
    {
    llSay(0,"Off");
    state default;
    }
    }


    The above code creates a second state, named off . This gives the above script two states: default and off . Both states contain their own touch_start event handler. Both states use the state command to switch to the opposite state when the object is touched.

    The Linden Scripting Language is optimized for state engines. Because of this, state engines should be used when possible.

    Handling Events
    The last section showed how the touch_start function is called whenever an avatar touches an object. The touch_start function is an event handler. Second Life includes many different event handlers. The recipes in this topic make use of many of these event handlers.

    There are many different event handlers in the Linden Scripting Language. Appendix C, “Event Types” provides a listing of all of the event types in the Linden Scripting Language.
    Another very common event type is the timer event. Many of the recipes in this topic use timer events. The following script uses timer events.

    Code: Select all
    default
    {
    state_entry()
    {
    llSetTimerEvent(1);
    }
    touch_start(integer total_number)
    {
    llSetTimerEvent(0);
    }
    timer()
    {
    llSay(0,"Timer");
    }
    }


    The above script starts with a state_entry event handler. The state_entry event handler is called when the object enters the state associated with the event handler. In this case, the state_entry event handler is called when the default state is entered.

    The provided state_entry event handler begins by calling the llSetTimerEvent function to establish a timer. The parameter passed to the llSetTimerEvent function call specifi es the number of seconds between timer events. To disable the timer call the llSetTimerEvent function with a value of zero.

    Every time a timer event occurs, the timer event handler is called. The above script says “Timer” each time that the timer event occurs.

    Communicating
    Objects in Second Life can communicate in many of the same ways that avatars communicate. Objects listen to conversations going on around them. Objects can also speak and participate in those conversations. Additionally, objects can send instant messages to avatars. However, instant messages between an avatar and an object are one-way. An avatar cannot send an instant message back to an object.

    The following script demonstrates how an object can listen to conversations going on around it. The object will wait for someone to say either “hello” or “goodbye”. Once the object detects either of these words, the object makes an appropriate greeting to the avatar that spoke to the object.

    Code: Select all
    integer CHANNEL = 0;
    default
    {
    state_entry()
    {
    llListen(CHANNEL, "", NULL_KEY, "");
    }
    listen(integer channel, string name, key id,
    string message)
    {
    if( llToLower(message) == "hello" )
    {
    llSay(CHANNEL,"Hello " + name );
    }
    else if( llToLower(message) == "goodbye" )
    {
    llSay(CHANNEL,"Goodbye " + name );
    }
    }
    }


    For an object to begin listening, the object must call the llListen function. This function specifi es the channel the object would like to listen on. The above script calls the llListen function in the state_entry event handler. The script specifi es that it would like to listen to the channel specifi ed by the CHANNEL variable. The Linden Scripting Language does not have user defi ned constants. As a result, the above declaration of
    CHANNEL is as close as we can come to a constant.

    Channel zero is the normal conversation channel in Second Life. All communication between avatars is on channel zero. Therefore, by requesting to listen on channel zero, the object will be notifi ed anytime something is said near the object.

    The above script contains a listen event handler. This event handler is called each time something is said near the object. The object checks for either “hello” or “goodbye”. Because the strings are converted to lower case, the user could also enter “Hello” or any mixture of upper and lower case characters. The script responds with a greeting directed to the avatar's name. The avatar's name was passed in as a parameter named name .

    The llSay function is used when a script wants to say something. The above calls to llSay use channel zero. However, often objects want to communicate with each other, and not allow nearby avatars to listen. To do this, the script should specify a channel other than zero. Many recipes in this topic communicate on channels other than zero.

    In addition to llSay , there are three other functions allow a script to talk. The only difference between the four communication functions is the distance they cover. Table 1.1 summarizes the communication functions.

    Table 1.1: Communication Distances
    2012-03-09_165419.jpg


    There is a fi fth communication function, with unlimited range. The llInstantMessage function allows an instant message to be sent to the specifi ed avatar.

    Code: Select all
    default
    {
    touch_start(integer total_num)
    {
    // get the key of the objects owner.
    key owner=llGetOwner();
    llInstantMessage(owner,llKey2Name(owner)+", "
    + (string)total_num +" Avatar(s) touched me!");
    }
    }


    The above script sends a message to the object's owner every time the object is touched. It is also possible to send a message to the object's owner by using the llOwnerSay function. However, llOwnerSay does not have the unlimited distance of a llInstantMessage function call.

    Modifying Objects
    It is possible to modify objects using the Linden Scripting Language. Every aspect of an object can be modifi ed using script. A large number of functions in the Linden Scripting Language allow the script to change the numerous properties available.

    A number of these functions will be used by later recipes in this topic. A script that changes the color of an object is shown here. This script will change the object to red, blue or green, depending on what the user says.

    Code: Select all
    integer CHANNEL = 0;
    default
    {
    state_entry()
    {
    llListen(CHANNEL, "", NULL_KEY, "");
    }
    listen(integer channel, string name, key id,
    string message)
    {
    if( llToLower(message) == "red" )
    {
    llSetColor(<255,0,0>,ALL_SIDES);
    }
    else if( llToLower(message) == "green" )
    {
    llSetColor(<0,255,0>,ALL_SIDES);
    }
    else if( llToLower(message) == "blue" )
    {
    llSetColor(<0,0,255>,ALL_SIDES);
    }
    }
    }


    To change the color of an object, the above code uses the llSetColor function. This function must be passed two parameters. The fi rst is a vector specifying the desired color. The second parameter specifi es to which side this color should be applied. For this example, the ALL_SIDES constant is used, which specifi es that all of the sides should be set to the specifi ed color.

    The color value is specifi ed as a vector . For example, <255,0,0> specifi es the color red. The fi rst number is red, the second green, and the third blue. Using red, green and blue values of nearly any color can be specifi ed. The valid range for each color component is between zero and 255.

    Understanding Dialogs
    The Linden Scripting Language allows much more direct interaction with avatars than simple touch events. It is also possible to create a dialog. A Second Life dialog can be seen in Figure 1.1.

    Figure 1.1: Second Life Dialogs
    2012-03-09_170001.jpg
    2012-03-09_170001.jpg (2.62 KiB) Viewed 4715 times


    The following script makes use if a dialog to allow the user to select a color.
    Code: Select all
    integer CHANNEL = 10;
    default
    {
    state_entry()
    {
    llListen(CHANNEL, "", NULL_KEY, "");
    }
    touch_start(integer total_num)
    {
    list l = ["red","green","blue"];
    key who = llDetectedKey(0);
    llDialog(who, "Where to?", l, CHANNEL);
    }
    listen(integer channel, string name, key id,
    string message)
    {
    if( llToLower(message) == "red" )
    {
    llSetColor(<255,0,0>,ALL_SIDES);
    }
    else if( llToLower(message) == "green" )
    {
    llSetColor(<0,255,0>,ALL_SIDES);
    }
    else if( llToLower(message) == "blue" )
    {
    llSetColor(<0,0,255>,ALL_SIDES);
    }
    }
    }


    This script is very similar to the script presented in the previous section. There are two main differences. First, this script makes use of channel 10, rather than channel zero. The second difference is that this script uses a dialog.

    The dialog is used at the end of the touch_start event handler. Calling the llDialog function creates a dialog. The dialog displays buttons that correspond to the list that was passed into the llDialog function.

    Once the user selects one of the options from the dialog, the name of that button is “said” over the specifi ed channel. This causes the user's choice to be picked up by the listen event handler. In this way, implementing a dialog is very similar to implementing a script that listens to user conversation.

    Implementing Basic Security
    Some objects will only function when their owner is trying to use them. It is also possible to program an object to only function with group members. The following sections show how to implement basic security both for the owner and for groups.

    Implementing Owner Security
    Sometimes an object will only work with the owner of that object. This is particularly true of vehicles. The following script shows how to detect if someone, other than the owner, is trying to use the object.

    Code: Select all
    default
    {
    touch_start(integer total_number)
    {
    integer i;
    for(i=0;i<total_number;i++)
    {
    if( llDetectedKey(i)!=llGetOwner() )
    {
    llSay(0, llDetectedName(i)
    + " you are not my owner.");
    }
    else
    {
    llSay(0, llDetectedName(i)
    + " you are my owner.");
    }
    }
    }
    }


    When the above script is touched, the above script's touch_start event handler is called. The touch_start event handler is passed a value that indicates how many avatar's are touching it at once. It is very rare that more than one avatar will be touching the object at once. However, if the object is likely to have more than one avatar touching at once, the script should use the total_number parameter.

    This script makes use of the total_number parameter. A loop counts through all the avatars that have touched the object. The key to each touching avatar is obtained with llDetectedKey . This key is compared against the owner of the object. If the owner and touching avatar are not the same, the avatar is informed that they are not welcome. This is a quick method to determine whether an avatar is the owner or not.

    Implementing Group Security
    Sometimes a object will only work with the group of that object. The following script shows how to detect if someone, other than the group, is trying to use the object.

    The group that an object is in can be set from the object properties window. Figure 1.2 shows an object with a group set.

    Figure 1.2: Setting the Group of an Object
    2012-03-09_170520.jpg
    2012-03-09_170520.jpg (61.35 KiB) Viewed 4715 times


    The following script checks to see if the user that touched the object is in the same group as the object being touched.

    Code: Select all
    default
    {
    touch_start(integer total_number)
    {
    integer i;
    for(i=0;i<total_number;i++)
    {
    if( llDetectedGroup(i)==FALSE )
    {
    llSay(0, llDetectedName(i)
    + " you must be in correct group.");
    }
    else
    {
    llSay(0, llDetectedName(i)
    + " you are in my group.");
    }
    }
    }
    }


    To detect whether the touching avatar is in the same group as the object, the llDetectGroup function is called. If the avatar is in the same group, a value of TRUE is returned, otherwise FALSE is returned.

    Summary
    This chapter introduced some basic concepts that will be used by later chapters in this topic. Very short scripts that introduced key concepts were presented. None of the scripts presented in this chapter would be very useful by themselves. However, they illustrate techniques that recipes in future chapters will use.

    In this chapter object communication was demonstrated. Objects can both talk and listen to avatars. Additionally, an object can send an instant message. However, it is impossible for an object to receive an instant message. Objects can neither receive instant messages from other objects nor avatars. Dialogs can also be presented to communicate with avatars.

    Objects can modify their appearance. There are many functions available to modify the appearance of an object. This chapter showed how to change the color of an object. Many of the recipes presented later in this topic will change the appearance of an object in other ways.

    Sometimes an object should only function with the owner of that object or the group to which an object belongs. It is possible to compare the avatar that is trying to use the object to the owner of the object. If the avatar using the object does not match the owner, then the object will not allow itself to be used. The same check can be performed on groups.

    The Linden Scripting Language allows user functions to be created. The next chapter presents useful functions that may be useful in other scripts. Recipes presented later in this topic will use some of these functions.

    Scripting Recipes - CHAPTER 1.rar
    (10.62 KiB) Downloaded 275 times




[+/-] Copyright
User avatar
Milen N Ester
Administrator
Administrator
Posts: 3055
 




Return to Scripting



Who is online

Users browsing this forum: Baidu [Spider] and 1 guest

cron