Pages

Thursday, 16 June 2011

Further into Second Life

Introduction

This week's post will be about some more advanced objects with second life and about SL's ability to connect people all over the world.

In this post I will talk about:

  • Communicating with other SL users which are abroad
  • Building a Notecard  giver
  • Building a Post Box system
  • Building an object that interacts with a Web Page


Communicating on-line

 In the last lesson a student was in Costa Rica for a holiday and decided to take the opportunity to make a little experiment with us. The student joined the lesson using Skype to make a video chat with the class. It was interesting to see how today's technology allows visual chat from all over the world.

In a second part of the lesson, all students logged to Second Life including the student in Costa Rica. We tried to do a lesson for building objects. All students teleported to a sand box where the lecturer showed us different objects and SL scripts. Later on in the lesson, we travelled to different SL worlds to further explore the game. Seeing how easy people can communicate over from different places using SL shows the communicative power of this game.

Building a Note Card Giver

The note card giver is an object that dispatches note cards to SL Avatars. There are various types of Note Card  givers. Some give note cards to avatars on touch, while others do it when an avatar passes near by. In this case I chose to give a note card to every avatar passing by. The Code Below shows how the Note Card giver works.

string notecard = "Note1";
integer freq = 1;
integer maxList = 100;
list given;


default
{
    state_entry()
    {
        llSensorRepeat("", "",AGENT, 20, PI, freq);
        llSetText("", <1.0, 1.0, 1.0>, 1.0);
    }
 
    sensor(integer num_detected)
    {
        integer i;
        key detected;
     
        for(i=0;i<num_detected;i++)
        {
            detected = llDetectedKey(i);
         
            if( llListFindList(given, [detected]) < 0 )
            {
                given += llDetectedKey(i);
             
                llGiveInventory(detected, notecard);
                if (llGetListLength(given) >= maxList)
                {
                    given = llDeleteSubList(given,0,10);
                }                              
            }
        }              
    }
}


The string variable notecard holds the name of the note card that will be passed to the avatar. The integer frequency holds the number of seconds of intervals between each sensor checking. maxList is an integer that holds the number of avatars that will be stored in a list of already contacted avatars. The object starts by calling the function  llSensorRepeat() on state entry. This function causes a sensor to check for avatars every second.

In llSensorRepeat("", "",AGENT, 20, PI, freq) 

AGENT is a mask that allow the sensor to locate avatars through SL Legacy Names
The number 20 is the number of meters the sensor 
PI is the arc of the sensor. PI means that the sensor works 360 degrees.
freq is the number of seconds of each interval of the sensor.

 When the sensor detects something the function sensor(integer num_detected) is called. The function uses a for loop to go through all detections. When an avatar is detected, his name is checked in a list of previously detected avatars, to avoid giving the note card to the same avatar all over again. If the avatar is new, his name is added to the name list and the avatar is given a notecard. llGiveInventory() passes the notecard to the avatar. Finally the function checks the length of the list using the llGetListLength() function. if the function exceeds the maximum number of names, llDeleteSubList(given,0,10); delete the first 10 names in the list. This note card giver is not ideal in a crowded place as 100 names is not a lot, and you would risk the note card giver to keep trying to send note cards to the same avatar. The note card that will be handed to the avatar must be placed in the contents of the card giver.

For the note card giver object a used a thin square prim with a white texture. The image below shows the card giver passing a note card to an avatar.


Building a Post Box System

The post box system is a system designed to pass messages to its owner. In this case I decided to let avatars drag notecards into the postbox such that they can be received by my avatar. The post box object is made up of a cuboid base, a semi circular face. The post box can be seen in the image below.


The code below shows the script of the post box system.


default
{
    state_entry() {
        llAllowInventoryDrop(TRUE);
    }
    touch_start(integer total_number) {
        llSay(0,"Create a notecard and drop it into the mailbox");
    }
 
    changed(integer mask) {
        if (mask & (CHANGED_INVENTORY | CHANGED_ALLOWED_DROP)){

            integer i;
            for (i=0; i<llGetInventoryNumber(INVENTORY_ALL); i++) {
                string name = llGetInventoryName(INVENTORY_ALL, i);
                integer type = llGetInventoryType(name);
                if (type != INVENTORY_SCRIPT) {
                    integer perms = llGetInventoryPermMask(name, MASK_OWNER);
                    if ((perms & PERM_TRANSFER) == PERM_TRANSFER &&
                        (perms & PERM_COPY) == 0) {
         
                        // keep track so you don't thank someone for a
                        // notecard that someone else gave you!
                        llSay(0, "Thanks for the "+name);
                         llGiveInventory(llGetOwner(), name);
            llRemoveInventory(name);
                    } else {
                        llSay(0, "Sorry, "+name+" isn't nocopy, trans");
                        llRemoveInventory(name);
                    }
                }
            }
        }
    }

On state entry, the object calls  llAllowInventoryDrop(TRUE); to allow objects to be dragged in the post box system. On touch the avatars are instructed to create a note card and drop it into the post box using the llSay Method. Dragging something in an object calls the changed event. This event takes in a mask that when compared to other masks, the change can be identifies.

"if (mask & (CHANGED_INVENTORY | CHANGED_ALLOWED_DROP))" checks for changes in the inventory and the changed allowed drop state. The function then loops for items in the inventory of the object. If the object is not a script the inventory mask of the ovner of the object with respect to the item is obtained. If the object dragged is not a copy, it is given to the owner of the post box and then removed from the post box. If the item is a copy it is not copied to the owners inventory, but it is removed immediately.

Building an object that interacts with a Web Page

For interacting with a web page I created a flat square prim that returns the number of SL sign-ups. This value is obtained from a web page. The code below shows the script of the object.

string SL_STATS_URL = "http://secondlife.com/httprequest/homepage.php";
key gRequestid;

default
{
    touch_end(integer p) {
        gRequestid = llHTTPRequest(SL_STATS_URL, [HTTP_METHOD, "GET"], "");
    }
    http_response(key requestID, integer status, list metadata, string body) {
        if (requestID == gRequestid) {
            list lines = llParseString2List(body, ["\n"], []);
            integer i = llListFindList(lines, ["signups"]);
            llSay(0, "There are currently "+llList2String(lines, i+1)+
                     " signups");
        }
    }
}

On touch the function llHTTPRequest() sends an http request and returns a request ID that identifies the request. On the event http_response, if the request id of the response is that requested, the lines of the returned request are inserted in a list. Lines are obtained using the function  llParseString2List() that parses a sting into a list of strings given the split parameters, in this case, a space of a carriage return. Note that the web page http://secondlife.com/httprequest/homepage.php returns several values regarding SL statistics.  llListFindList() searches through a list to compare a particular string and returns the index of that list position if found. In this case we are looking for the string Sigups. Finally the object uses llSay to output the number of signups. This number is the next in the list so llList2String(lines, i+1) is used to recover it, where i is the position os the string "sigups" in the list.

Conclusion

Advanced scripting in SL can become quite complicated as the various pre-existing methods and events must be explored before creating an object. This involves a great deal of time, which in my opinion is too much to spend on a game. Fortunately most objects can be found pre-existing on the net, and with little modification, they can be manipulated to satisfy the users needs. 

No comments:

Post a Comment