devxlogo

Writing Commerce Scripts in Second Life

Writing Commerce Scripts in Second Life

ommerce occurs in Second Life whenever money changes hands. Money, in Second Life, is the Linden Dollar. Although the Linden Dollar is not an actual currency, it can be freely exchanged for real-world currencies. Like many real-world currencies, the value of the Linden Dollar rises and falls against the US dollar. As of this writing, 1 US dollar buys approximately 186 Linden Dollars.

Second Life avatars exchange Linden Dollars in three different ways; by:

  • Directly transferring money to another avatar
  • Offering an item for sale
  • Using a script to process a “Pay” command

Transferring money directly to another avatar is the simplest of these three processes. To do that, you simply right-click on the other avatar and choose “Pay” from the popup menu. You can now transfer any amount of Linden Dollars you have available to that avatar.

From a commerce standpoint, direct transfer between avatars works fine for in-person service purchases, such as hiring another user to build something; however, for a store owner selling goods, direct money transfer is inefficient. Offering objects for sale is a major component of Second Life commerce—and direct transfer presents two obstacles. First, item purchases involve two direct transfers—the customer first transfers money to the owner, and the owner must then transfer the item to the avatar. More importantly, using direct transfer for item purchases requires the owner’s presence for each sale.

Fortunately, you can get around both problems by simply marking items “for sale” in Second Life. Any avatar that encounters an object for sale can purchase that object for the specified price. Many stores in Second Life operate exactly that way; they’re stocked with items marked for sale, and avatars purchase the items by selecting them and electing to buy. That functionality is built into Second Life objects, so such transactions need no custom scripting.

 
Figure 1. A Second Life Store: Here’s my avatar, Encog Dod, in a typical Second Life store.

For example, to create a store in Second Life, you simply construct a small region and place the objects for sale there, selecting each object and marking it for sale. You can sell either the marked objects themselves, or copies of the marked objects. If you select the “Sell Copy” option, the original item remains available even after an avatar has purchased a copy. As you can imagine, selling copies is popular in Second Life. Figure 1 shows my avatar, Encog Dod, at a typical Second Life store.

Unfortunately, even though you can sell copies, if you have a large number of items for sale it takes a proportionally large volume of space to display and sell them. Additionally, because building a stand-alone store isn’t always effective, many people sell items in malls in Second Life; just as in real life, that’s where the customers are. That presents a different problem. Mall stores typically make only a limited number of prims (shape primitives) available. To save on prim usage and take up less space, vendors often use scripts to manage the selling process.

Build a Vendor Script
You can think of a vendor script as being similar to a kiosk. The script displays a set of pictures of items for sale. Most scripts let avatars browse through the items using Forward and Back buttons. Figure 2 shows how such kiosks typically look.

 
Figure 2. Using a Vendor Script: The vendor script lets avatars scroll through images of items offered for sale in a kiosk-like manner, which saves space compared to building new stores or renting space in a mall to display the actual items.

A configuration notecard controls the vendor script. In Second Life notecards are similar to text files, and they’re often used to configure scripts. For example, here’s the content of the configuration notecard for the vendor script shown in Figure 2:

   buyredcar   Encog's Red Car   25   buyyellowcar   Super Car   30   buyboat   Encog's Boat   35

The lines in the configuration notecard occur in groups of three. The first group of three is:

   buyredcar   Encog's Red Car   25

The first line specifies the name of the texture (the image of the item) to display when that item becomes current. The second line specifies the name of the item, and the third line specifies the price of that item, in Linden Dollars. Each object being sold must be in the vendor’s object inventory.

Three scripts are required to run the vendor—the main script and two scripts to control each of the arrows.

Main Vendor Script
The main vendor script does most of the work. The Forward and Back buttons each contain a navigational script, but those simply tell the main script that it should navigate. Listing 1 shows the main vendor script in full; the rest of this section contains a detailed explanation of the code. You can download all the scripts for this article to experiment with them yourself.

The main vendor script begins by declaring some variables:

   integer index;   string notecardName;   key notecardQuery;   integer notecardIndex;   list notecardList;   integer price;   string itemName;

Table 1 shows the purpose of each variable:

Table 1: Main Script Variables: Here’s a list of the global variables used in the main vendor script.
Variable Name Purpose
index Holds the index of the item currently being viewed.
noteCardName Holds the name of the notecard being read.
notecardQuery Holds the query used to read the configuration notecard.
price Holds the price of the current item.
itemName Holds the current item’s name.

The displayItem function updates the vendor object to display a newly selected item. It begins by obtaining the texture from the list. The first three lines of the displayItem function read three items from the configuration notecard—the texture, name, and price:

   displayItem()   {       string textureName = llList2String(notecardList,index*3);       itemName = llList2String(notecardList,(index*3)+1);       string p = llList2String(notecardList,(index*3)+2);

Next, the script converts the price to an integer, stores it in the price variable, and then displays the price. It sends a message to all linked objects so the Buy button can display the text:

       price = (integer)p;       string display = itemName + "
L$" + p;       llMessageLinked(LINK_ALL_OTHERS , 0, ":"+display, NULL_KEY);

Finally, it displays the texture, and sets the purchase price. Second Life textures are used for many purposes; however, here the texture is simply an image of the item being sold:

       llSetLinkPrimitiveParams(5,[PRIM_TEXTURE, 1,          textureName, , , 0 ]);       llSetPayPrice(PAY_HIDE, [price, PAY_HIDE, PAY_HIDE,          PAY_HIDE]);   }

Second Life objects are state driven, and all begin in the default state. Second Life fires a state_entry event whenever the state changes. Whenever the default state fires, the script checks to see if any items are loaded. If not, the script enters the loading state, which you’ll see in the next section:

   default   {       state_entry()       {           if( llGetListLength(notecardList)==0 )           {               notecardName = "Config";               state loading;           }

Otherwise, (if items are loaded) the script displays the first item:

           else           {               index = 0;               displayItem();           }       }

The navigation buttons send messages when an avatar pushes them. The link_message event handler processes these messages:

       link_message(integer sender_num, integer num,           string str, key id)       {

Just as you would expect, the Back button moves to the previous item, while the Forward button moves to the next item:

           if( str=="back" )           {               index--;           }           if( str=="forward" )           {               index++;           }

The script displays the items in a circular fashion; if the last item has been passed, then it wraps around to the first item:

           if(index>=(llGetListLength(notecardList)/3) )               index = 0;

Similarly, if a user backs up past the first item, the script wraps around to the last item:

           if(index

Finally, it displays the current item:

           displayItem();       }

When a user buys an item the script calls the money event handler, and—if the user paid enough—gives the item to the purchaser:

       money(key id, integer amount)       {           if( amount>=price )           {               llGiveInventory(id,itemName);               llSay(0,"Thanks for your purchase!");           }       }       }

Now you're ready to see how to load items.Loading Items
When the default state fires, and there are no items loaded, the script sets the loading state, which begins by submitting a query to read the notecard:

   state loading   {       state_entry()       {           llSay(0,"Loading product data...");           notecardIndex = 0;           notecardQuery = llGetNotecardLine(              notecardName,notecardIndex++);           }

The script reads lines one at a time from the notecard. After reading each line, the script calls the dataserver event handler:

       dataserver(key query_id, string data)        {           if ( notecardQuery == query_id)            {

The script stops reading when it reaches the end of the notecard, and returns to the default state:

               if (data == EOF)                {                       llSay(0,"Products loaded...");                   state default;

Until it reaches the end of the notecard data, it adds the data read to the notecardList variable:

               } else                {                   notecardList += [data];                   notecardQuery = llGetNotecardLine(                       notecardName,notecardIndex++);                }           }       }   }

There are three other scripts in the vendor object that handle navigation and display of the textual information about the item.

Vendor Navigation Scripts
The vendor object has two buttons that allow navigation. Clicking the Forward and Back buttons switches the display of the current object for sale. Here's the Forward button's script:

   default   {       touch_start(integer total_number)       {           llMessageLinked(LINK_ALL_OTHERS , 0,               "forward", NULL_KEY);       }   }

Touching the Forward button simply sends a "forward" message that will be picked up by the main vendor script. The vendor object can also go backward. The Back button's script is identical, except that it sends a "back" message:

   default   {       touch_start(integer total_number)       {           llMessageLinked(LINK_ALL_OTHERS , 0,               "back", NULL_KEY);       }   }

The Buy button just displays instructions on buying—to buy an item you just pay the object, which purchases the item. However, the Buy button is useful because it is right under the texture, so adding text to the Buy button puts the text display right under the picture of the item. Here's the Buy button's script:

   default   {              link_message(integer sender_num,           integer num, string str, key id)       {           string prefix = llGetSubString(str,0,0);           if( prefix==":" )           {               string rest = llGetSubString(str,1,-1);               llSetText(rest,,1);                          }              }   }

The buy button simply waits for messages, and then displays them.

You've seen the fundamentals required to automate commerce in Second Life. Although the idea of selling virtual items in a virtual world may seem like play, real people earn their livings selling objects in Second Life. Vendor kiosks, such as the one you've seen here, are at the center of many Second Life stores because they let you sell items without having to display a physical copy of every item, thus reducing the amount of space required.

You can get a copy of the vending device (the kiosk) discussed in this chapter directly from Second Life by visiting the Second Live URL (SLURL) http://slurl.com/secondlife/Encogia/211/181/63 (you must be a member of Second Life to reach this SLURL). There you'll find the complete vendor script with full modify permissions. You can also download the scripts for this article, and build your own kiosk.

devxblackblue

About Our Editorial Process

At DevX, we’re dedicated to tech entrepreneurship. Our team closely follows industry shifts, new products, AI breakthroughs, technology trends, and funding announcements. Articles undergo thorough editing to ensure accuracy and clarity, reflecting DevX’s style and supporting entrepreneurs in the tech sphere.

See our full editorial policy.

About Our Journalist