Difference between revisions of "User:Fred Gandt/Scripts/Continued 4"

From Second Life Wiki
Jump to navigation Jump to search
m (cleaning up headings)
m (a little tidying)
 
(2 intermediate revisions by the same user not shown)
Line 7: Line 7:


==== Create The Object ====
==== Create The Object ====
*Create a fresh new prim and drop this script onto/into it. The prim will form the shape needed plus change the texturing etc. (you can do what you like to the texturing afterwards).
* Create a fresh new prim and drop this script onto/into it. The prim will form the shape needed plus change the texturing etc. (you can do what you like to the texturing afterwards).


<syntaxhighlight lang="lsl2">// V2 //
<syntaxhighlight lang="lsl2">// V2 //


default
default {
{
     state_entry() {
     state_entry()
         llSetPrimitiveParams( [
    {
            7, <0.5, 0.01, 0.25>, // Set the size
         llSetPrimitiveParams([7, <0.5, 0.01, 0.25>, // Set the size
            8, <0.0, 0.0, 0.0, 1.0>, // Set to ZERO_ROTATION
                              8, <0.0, 0.0, 0.0, 1.0>, // Set to ZERO_ROTATION
            9, 0, 0, <0.375, 0.875, 0.0>, 0.0, <0.0, 0.0, 0.0>, <1.0, 1.0, 0.0>, <0.0, 0.0, 0.0>, // Shape the prim
                              9, 0, 0, <0.375, 0.875, 0.0>, 0.0, <0.0, 0.0, 0.0>, <1.0, 1.0, 0.0>, <0.0, 0.0, 0.0>, // Shape the prim
            17, -1, "5748decc-f629-461c-9a36-a35a221fe21f", <1.0, 1.0, 0.0>, <0.0, 0.0, 0.0>, 0.0, // Apply the blank texture
                              17, -1, "5748decc-f629-461c-9a36-a35a221fe21f", <1.0, 1.0, 0.0>, <0.0, 0.0, 0.0>, 0.0, // Apply the blank texture
            18, -1, <1.0, 0.65, 0.1>, 1.0, // Color the prim (kinda orange)
                              18, -1, <1.0, 0.65, 0.1>, 1.0, // Color the prim (kinda orange)
            20, -1, 1, // Make fullbright
                              20, -1, 1, // Make fullbright
            25, -1, 0.05 // Slight glow
                              25, -1, 0.05]); // Slight glow
        ] );
         llRemoveInventory(llGetScriptName()); // Remove the script when done
         llRemoveInventory( llGetScriptName() ); // Remove the script when done
     }
     }
}</syntaxhighlight>
}</syntaxhighlight>


*When the script has worked its magic, '''[[How_to_use_the_building_grid_-_Video_Tutorial | Snap the prim to the grid]]''' with a grid size of .5 meters.
* When the script has worked its magic, '''[[How_to_use_the_building_grid_-_Video_Tutorial | Snap the prim to the grid]]''' with a grid size of .5 meters.
*Shift-Drag-Copy the prim, snapping each to the grid positively along the X axis until you have 10 prims in a continuous strip.
* Shift-Drag-Copy the prim, snapping each to the grid positively along the X axis until you have 10 prims in a continuous strip.
You can actually make the object as long or short as you like. 1 prim will work. 100 prims will work (although large linksets have been a problem for [[link_message]]s in the past). Just follow the same basic build plan.
You can actually make the object as long or short as you like. 1 prim will work. 100 prims will work (although large linksets have been a problem for [[link_message]]s in the past). Just follow the same basic build plan.
*Select each of the prims from the end that has the greatest X axis position, one at a time (negatively along the X axis) until ALL are selected.
* Select each of the prims from the end that has the greatest X axis position, one at a time (negatively along the X axis) until ALL are selected.


[[Image:Text Scroller How It Should Look jpg.jpg|800px]]
[[Image:Text Scroller How It Should Look jpg.jpg|800px]]


*Link the set.
* Link the set.


==== Display Script ====
==== Display Script ====
*Check "Edit Linked parts" and select one prim at a time, dropping this script in each.
* Check "Edit Linked parts" and select one prim at a time, dropping this script in each.
*'''DO NOT CREATE A FRESH SCRIPT IN EACH PRIM. DROP THE SAME SCRIPT FROM YOUR INVENTORY INTO EACH PRIM.'''
* '''DO NOT CREATE A FRESH SCRIPT IN EACH PRIM. DROP THE SAME SCRIPT FROM YOUR INVENTORY INTO EACH PRIM.'''


<syntaxhighlight lang="lsl2">// V1 //
<syntaxhighlight lang="lsl2">// V1 //
Line 44: Line 44:
// A accurate representation of the characters featured on the texture used to display the text.
// A accurate representation of the characters featured on the texture used to display the text.
   
   
vector GetOffset(string s)
vector GetOffset(string s) {
{
     if ( s == "" ) { // If there is no text
     if(s == "") // If there is no text
         s = " "; // Use a space
         s = " "; // Use a space
     integer i = llSubStringIndex(font, s); // Find the character
    }
     if(i == -1) // If we can't find it
     integer i = llSubStringIndex( font, s ); // Find the character
     if ( i == -1 ) { // If we can't find it
         i = 94; // Use a space
         i = 94; // Use a space
     return <(-0.45 + ((i % 10) * 0.1)), (0.45 - (llRound(i / 10) * 0.1)), 0.0>;
    }
     return <( -0.45 + ( ( i % 10 ) * 0.1 ) ), ( 0.45 - ( llRound( i / 10 ) * 0.1 ) ), 0.0>;
} // Return the offset needed to display the correct section of the texture by doing the mathematics *coughs*
} // Return the offset needed to display the correct section of the texture by doing the mathematics *coughs*
   
   
Line 60: Line 61:
integer my_ss_6; // Used to store the index of the feed text we display on face 6
integer my_ss_6; // Used to store the index of the feed text we display on face 6
   
   
default
default {
{
     state_entry() {
     state_entry()
    {
         me = llGetLinkNumber();
         me = llGetLinkNumber();
         my_ss_6 = ((me - 1) * 2); // Whatever link we are (in a correctly built object) establish the index to grab
         my_ss_6 = ( ( me - 1 ) * 2 ); // Whatever link we are (in a correctly built object) establish the index to grab
         my_ss_5 = (my_ss_6 + 1); // And also grab the next
         my_ss_5 = ( my_ss_6 + 1 ); // And also grab the next
     }
     }
     link_message(integer sender, integer num, string msg, key id)
     link_message( integer sender, integer num, string msg, key id ) {
    {
         llSetLinkPrimitiveParamsFast( me, [
         llSetLinkPrimitiveParamsFast(me, [17, 5, id, <0.1, 0.1, 0.0>, GetOffset(llGetSubString(msg, my_ss_5, my_ss_5)), 0.0,
            17, 5, id, <0.1, 0.1, 0.0>, GetOffset( llGetSubString( msg, my_ss_5, my_ss_5 ) ), 0.0,
                                          17, 6, id, <0.1, 0.1, 0.0>, GetOffset(llGetSubString(msg, my_ss_6, my_ss_6)), 0.0]);
            17, 6, id, <0.1, 0.1, 0.0>, GetOffset( llGetSubString( msg, my_ss_6, my_ss_6 ) ), 0.0
        ] );
     } // Set the texture to the correct offset to display the correct characters
     } // Set the texture to the correct offset to display the correct characters
}</syntaxhighlight>
}</syntaxhighlight>
Line 77: Line 77:
==== Control Script ====
==== Control Script ====
One possible way amongst many to feed the text to the script is by notecard. That is the way I set this script. As such, you need a notecard in the root containing the text you wish to display. One notecard will be read. If you add more notecards (without altering the script) it will read the first it finds alphabetically.
One possible way amongst many to feed the text to the script is by notecard. That is the way I set this script. As such, you need a notecard in the root containing the text you wish to display. One notecard will be read. If you add more notecards (without altering the script) it will read the first it finds alphabetically.
*There is a [[LlGetNotecardLine#Caveats|caveat]] regarding the length of the lines of text in the notecard. If the line is longer then 255 bytes the [[dataserver]] will return the first 255 bytes of the line.
* There is a [[LlGetNotecardLine#Caveats|caveat]] regarding the length of the lines of text in the notecard. If the line is longer then 255 bytes the [[dataserver]] will return the first 255 bytes of the line.
*This example - taken from one of Shakespeare's Hamlet's soliloquy (To be, or not to be...) is too long by the red lettering -
* This example - taken from one of Shakespeare's Hamlet's soliloquy (To be, or not to be...) is too long by the red lettering -
:*"For who would bear the whips and scorns of time, th'oppressor's wrong, the proud man's contumely, the pangs of despised love, the law's delay, the insolence of office, and the spurns that patient merit of th'unworthy takes, when he himself might his quiet<font style="color:red;">us make with a bare bodkin?</font>"
** "For who would bear the whips and scorns of time, th'oppressor's wrong, the proud man's contumely, the pangs of despised love, the law's delay, the insolence of office, and the spurns that patient merit of th'unworthy takes, when he himself might his quiet<font style="color:red;">us make with a bare bodkin?</font>"
*Add your text notecard to the root.
* Add your text notecard to the root.
*Drop this script into the root.
* Drop this script into the root.


<syntaxhighlight lang="lsl2">// V1 //
<syntaxhighlight lang="lsl2">// V1 //
Line 97: Line 97:
integer on; // Are we on or off?
integer on; // Are we on or off?
   
   
default
default {
{
     state_entry() {
     state_entry()
         NC = llGetInventoryName( INVENTORY_NOTECARD, 0 ); // Establish the name of our NC
    {
         llGetNotecardLine( NC, NCC ); // Ask for the first line
         NC = llGetInventoryName(INVENTORY_NOTECARD, 0); // Establish the name of our NC
         llGetNotecardLine(NC, NCC); // Ask for the first line
     }
     }
     dataserver(key q, string data)
     dataserver( key q, string data ) {
    {
         if ( data != EOF ) { // If the data is useful
         if(data != EOF) // If the data is useful
             text += ( data + " " ); // Store it
        {
             llGetNotecardLine( NC, ( ++NCC ) ); // And get the next line
             text += (data + " "); // Store it
         } else { // If not useful we are at the end of the NC
             llGetNotecardLine(NC, (++NCC)); // And get the next line
             length = llStringLength( text ); // Establish the length of our text
         }
        else // If not useful we are at the end of the NC
        {
             length = llStringLength(text); // Establish the length of our text
             // The number 19 is 1 less than the number of faces (2 per prim) that display text. Change that number accordingly if...
             // The number 19 is 1 less than the number of faces (2 per prim) that display text. Change that number accordingly if...
             // ...you have a larger or smaller number of prims in your object.
             // ...you have a larger or smaller number of prims in your object.
             llMessageLinked(-1, 0, llGetSubString("Touch start scroll.", count, (count + 19)), "b6349d2d-56bf-4c18-4859-7db0771990a5");
             llMessageLinked( -1, 0, llGetSubString( "Touch start scroll.", count, ( count + 19 ) ), "b6349d2d-56bf-4c18-4859-7db0771990a5" );
         } // Message the display scripts that we are ready to function
         } // Message the display scripts that we are ready to function
     }
     }
     timer()
     timer() {
    {
         if ( count == length ) { // If we have gone full circle
         if(count == length) // If we have gone full circle
            count = 0; // Start again
        count = 0; // Start again
        }
         llMessageLinked(-1, 0, llGetSubString(text, count, (count + 19)), "b6349d2d-56bf-4c18-4859-7db0771990a5");
         llMessageLinked( -1, 0, llGetSubString( text, count, ( count + 19 ) ), "b6349d2d-56bf-4c18-4859-7db0771990a5" );
         ++count; // Message the display scripts with a chunk of text
         ++count; // Message the display scripts with a chunk of text
     }
     }
     touch_end(integer nd)
     touch_end( integer nd ) {
    {
         if ( on ) { // Are we running?
         if(on) // Are we running?
            llSetTimerEvent( 0.0 ); // Stop the timer
        llSetTimerEvent(0.0); // Stop the timer
         } else { // No?
         else // No?
            llSetTimerEvent( 0.15 ); // Start the timer
        llSetTimerEvent(0.15); // Start the timer
        }
         on = (!on); // Remember what we did
         on = ( !on ); // Remember what we did
     }
     }
     changed(integer change)
     changed( integer change ) {
    {
         if ( change & CHANGED_INVENTORY ) { // If the inventory has changed the NC may have
         if(change & CHANGED_INVENTORY) // If the inventory has changed the NC may have
            llResetScript(); // So reset the script to read the new card
        llResetScript(); // So reset the script to read the new card
        }
     }
     }
}</syntaxhighlight>
}</syntaxhighlight>
Line 145: Line 139:
==== The Charsheet Texture ====
==== The Charsheet Texture ====
I am a scriptor, not a texturizerer. I created a very simple Charsheet (Character Sheet) to get you going but, it isn't very good *grins*. You will probably want to replace it.
I am a scriptor, not a texturizerer. I created a very simple Charsheet (Character Sheet) to get you going but, it isn't very good *grins*. You will probably want to replace it.
 
* The texture MUST be 10 characters by 10 characters (you may have empty spaces so, 56 chars is fine so long as the grid is the full 100 spaces).
*The texture MUST be 10 characters by 10 characters (you may have empty spaces so, 56 chars is fine so long as the grid is the full 100 spaces).
* Unlike the texture I have supplied...ALL the chars should be perfectly evenly spaced and not spreading into the neighboring spaces.
*Unlike the texture I have supplied...ALL the chars should be perfectly evenly spaced and not spreading into the neighboring spaces.
This is the texture supplied. You don't need to copy this. The script already has the [[UUID]] in it.
This is the texture supplied. You don't need to copy this. The script already has the [[UUID]] in it.


Line 153: Line 146:


The display scripts contain a string that is in the exact same order the chars are read from top left to bottom right (row by row, not column by column).
The display scripts contain a string that is in the exact same order the chars are read from top left to bottom right (row by row, not column by column).
*'''HAVING THE SAME ORDER OF CHARS IN THE TEXTURE AND STRING IS VITAL'''
* '''HAVING THE SAME ORDER OF CHARS IN THE TEXTURE AND STRING IS VITAL'''
The order you choose is entirely up to you as long as the strings in ALL the display scripts match the order of chars in the texture.
The order you choose is entirely up to you as long as the strings in ALL the display scripts match the order of chars in the texture.
*Don't forget to include a blank grid space on your 10 x 10 texture for a space "character". There also needs to be an empty space (in the correct place) in the scripts.
* Don't forget to include a blank grid space on your 10 x 10 texture for a space "character". There also needs to be an empty space (in the correct place) in the scripts.
*In the display script strings there are two characters that must be treated unusually. The \ and the " must have a \ placed before them.
* In the display script strings there are two characters that must be treated unusually. The \ and the " must have a \ placed before them.
:*Example "ABCabc123.,:\"\\/{{!}} " Note the included space and the way the \ and " have a \ before them.
** Example "ABCabc123.,:\"\\/{{!}} " Note the included space and the way the \ and " have a \ before them.


=== Sell To Group Only ===
=== Sell To Group Only ===
This is a simple GROUP ONLY vendor script. It can be used to GIVE FREE items to group only too.
This is a simple GROUP ONLY vendor script. It can be used to GIVE FREE items to group only too.
*'''THIS SCRIPT WILL ASK FOR DEBIT PERMISSIONS. THEY MUST BE GRANTED FOR THE SCRIPT TO FUNCTION. L$ WILL BE TAKEN FROM THE OBJECT OWNERS ACCOUNT.'''
*'''THIS SCRIPT WILL ASK FOR DEBIT PERMISSIONS. THEY MUST BE GRANTED FOR THE SCRIPT TO FUNCTION. L$ WILL BE TAKEN FROM THE OBJECT OWNERS ACCOUNT.'''
**The debit permissions are required for making refunds in the event of an over or under payment or a payment being made by a non group member.
**The debit permissions are required for making refunds in the event of an over or under payment or a payment being made by a non group member.
Line 187: Line 179:
key owner;
key owner;
   
   
default
default {
{
     on_rez( integer param ) {
     on_rez(integer param)
    {
         llResetScript();
         llResetScript();
     }
     }
     changed(integer change)
     changed( integer change ) {
    {
         if ( change & ( CHANGED_OWNER | CHANGED_INVENTORY ) ) {
         if(change & (CHANGED_OWNER | CHANGED_INVENTORY))
            llResetScript();
        llResetScript();
        }
     }
     }
     state_entry()
     state_entry() {
    {
         llSetClickAction( CLICK_ACTION_TOUCH );
         llSetClickAction(CLICK_ACTION_TOUCH);
         llRequestPermissions( ( owner = llGetOwner() ), PERMISSION_DEBIT );
         llRequestPermissions((owner = llGetOwner()), PERMISSION_DEBIT);
     }
     }
     run_time_permissions(integer perm)
     run_time_permissions( integer perm ) {
    {
         if ( perm & PERMISSION_DEBIT ) {
         if(perm & PERMISSION_DEBIT)
             integer in = llGetInventoryNumber( INVENTORY_ALL );
        {
             integer in = llGetInventoryNumber(INVENTORY_ALL);
             integer count;
             integer count;
             string name;
             string name;
             do
             do {
            {
                 if ( ( name = llGetInventoryName( INVENTORY_ALL, count ) ) != llGetScriptName() ) {
                 if((name = llGetInventoryName(INVENTORY_ALL, count)) != llGetScriptName())
                    contents_list += [ name ];
                contents_list += [name];
                }
            }
             } while ( ( ++count ) < in );
             while((++count) < in);
             if ( llGetListLength( contents_list ) ) {
             if(llGetListLength(contents_list))
                 if ( ( group_key = llList2Key( llGetObjectDetails( llGetKey(), [ OBJECT_GROUP ] ), 0 ) ) == NULL_KEY ) {
            {
                     llOwnerSay( "You NEED to set this object to a group in order to have it sell contents ONLY to that group." +
                 if((group_key = llList2Key(llGetObjectDetails(llGetKey(), [OBJECT_GROUP]), 0)) == NULL_KEY)
                                "\nThis script is resetting. You will need to grant debit permissions again." +
                {
                                "\n!! ONLY DO THAT AFTER SETTING THIS OBJECT TO THE DESIRED GROUP !!" );
                     llOwnerSay("You NEED to set this object to a group in order to have it sell contents ONLY to that group." +
                              "\nThis script is resetting. You will need to grant debit permissions again." +
                              "\n!! ONLY DO THAT AFTER SETTING THIS OBJECT TO THE DESIRED GROUP !!");
                     llResetScript();
                     llResetScript();
                } else {
                    llHTTPRequest( "http://world.secondlife.com/group/" + ( ( string )group_key ), [], "" );
                 }
                 }
                else
             } else {
                llHTTPRequest("http://world.secondlife.com/group/" + ((string)group_key), [], "");
                 llOwnerSay( "There are no contents. This object cannot sell thin air. There is no air in SL." +
             }
                            "\nPlease add the contents to sell." +
            else
                            "\n!! ONLY RE-GRANT PERMISSIONS WHEN ALL CONTENTS ARE ADDED !!" );
            {
                 llOwnerSay("There are no contents. This object cannot sell thin air. There is no air in SL." +
                          "\nPlease add the contents to sell." +
                          "\n!! ONLY RE-GRANT PERMISSIONS WHEN ALL CONTENTS ARE ADDED !!");
             }
             }
         }
         } else {
        else
             llOwnerSay( "You MUST grant permissions for this script to function." );
        {
             llRequestPermissions( owner, PERMISSION_DEBIT );
             llOwnerSay("You MUST grant permissions for this script to function.");
             llRequestPermissions(owner, PERMISSION_DEBIT);
         }
         }
     }
     }
     http_response(key q, integer status, list metadata, string body)
     http_response( key q, integer status, list metadata, string body ) {
    {
         if ( status == 200 ) {
         if(status == 200)
             llOwnerSay( "This object is set to the group - " +
        {
                        ( group_name = llGetSubString( body, ( llSubStringIndex( body, "<title>" ) + 7 ),
             llOwnerSay("This object is set to the group - " +
                                                            ( llSubStringIndex( body, "</title>" ) - 1 ) ) ) +
                      (group_name = llGetSubString(body, (llSubStringIndex(body, "<title>") + 7),
                        "\nOnly members of that group will be able to buy this objects contents." +
                                                          (llSubStringIndex(body, "</title>") - 1))) +
                        "\nContents for sale - \n" + llDumpList2String( contents_list, "\n" ) +
                      "\nOnly members of that group will be able to buy this objects contents." +
                        "\nPrice is " + ( ( string )cost ) + "L$" );
                      "\nContents for sale - \n" + llDumpList2String(contents_list, "\n") +
             if ( cost ) {
                      "\nPrice is " + ((string)cost) + "L$");
                 llSetClickAction( CLICK_ACTION_PAY );
             if(cost)
                 llSetPayPrice( PAY_HIDE, [ cost, PAY_HIDE, PAY_HIDE, PAY_HIDE ] );
            {
                 llSetClickAction(CLICK_ACTION_PAY);
                 llSetPayPrice(PAY_HIDE, [cost, PAY_HIDE, PAY_HIDE, PAY_HIDE]);
                 state shoptastic;
                 state shoptastic;
            } else {
                state freebietastic;
             }
             }
            else
         } else {
            state freebietastic;
             llOwnerSay( "HTTP Request failed. Trying again in 45 seconds. Please wait." );
         }
             llSleep( 45.0 );
        else
             llHTTPRequest( "http://world.secondlife.com/group/" + ( ( string )group_key ), [], "" );
        {
             llOwnerSay("HTTP Request failed. Trying again in 45 seconds. Please wait.");
             llSleep(45.0);
             llHTTPRequest("http://world.secondlife.com/group/" + ((string)group_key), [], "");
         }
         }
     }
     }
}
}
state freebietastic
state freebietastic {
{
     on_rez( integer param ) {
     on_rez(integer param)
    {
         llResetScript();
         llResetScript();
     }
     }
     changed(integer change)
     changed( integer change ) {
    {
         if ( change & ( CHANGED_OWNER | CHANGED_INVENTORY ) ) {
         if(change & (CHANGED_OWNER | CHANGED_INVENTORY))
            llResetScript();
        llResetScript();
        }
     }
     }
     touch_start(integer nd)
     touch_start( integer nd ) {
    {
         while( nd ) {
         while(nd)
             key id = llDetectedKey( --nd );
        {
             if ( llSameGroup( id ) ) {
             key id = llDetectedKey(--nd);
                llGiveInventoryList( id, folder_name, contents_list );
             if(llSameGroup(id))
             } else {
            llGiveInventoryList(id, folder_name, contents_list);
             else
            {
                 string msg = "";
                 string msg = "";
                 if(offer_group_join)
                 if ( offer_group_join ) {
                msg = "\nYou can join this group by clicking this - \nsecondlife:///app/group/" + ((string)group_key) + "/about";
                    msg = "\nYou can join this group by clicking this - \nsecondlife:///app/group/" + ( ( string )group_key ) + "/about";
                 llRegionSayTo(id, 0, "Sorry, this vendor is set to give only to " + group_name + " group members." + msg);
                }
                 llRegionSayTo( id, 0, "Sorry, this vendor is set to give only to " + group_name + " group members." + msg );
             }
             }
         }
         }
     }
     }
}
}
state shoptastic
state shoptastic {
{
     on_rez( integer param ) {
     on_rez(integer param)
    {
         llResetScript();
         llResetScript();
     }
     }
     changed(integer change)
     changed( integer change ) {
    {
         if ( change & ( CHANGED_OWNER | CHANGED_INVENTORY ) ) {
         if(change & (CHANGED_OWNER | CHANGED_INVENTORY))
            llResetScript();
        llResetScript();
        }
     }
     }
     money(key id, integer amount)
     money( key id, integer amount ) {
    {
         if ( llSameGroup( id ) ) {
         if(llSameGroup(id))
             if ( amount >= cost ) {
        {
                 if ( amount > cost ) {
             if(amount >= cost)
                    llGiveMoney( id, ( amount - cost ) );
            {
                }
                 if(amount > cost)
                 llGiveInventoryList( id, folder_name, contents_list );
                llGiveMoney(id, (amount - cost));
            } else if ( amount < cost ) {
                 llGiveInventoryList(id, folder_name, contents_list);
                llGiveMoney( id, amount );
                llRegionSayTo( id, 0, "Sorry, you paid to little.\nThe cost is " + ( ( string )cost ) + "L$" );
             }
             }
            else if(amount < cost)
        } else {
             {
             llGiveMoney( id, amount );
                llGiveMoney(id, amount);
            string msg = "";
                 llRegionSayTo(id, 0, "Sorry, you paid to little.\nThe cost is " + ((string)cost) + "L$");
            if ( offer_group_join ) {
                 msg = "\nYou can join this group by clicking this - \nsecondlife:///app/group/" + ( ( string )group_key ) + "/about";
             }
             }
        }
             llRegionSayTo( id, 0, "Sorry, this vendor is set to sell only to " + group_name + " group members." + msg );
        else
        {
            llGiveMoney(id, amount);
            string msg = "";
            if(offer_group_join)
            msg = "\nYou can join this group by clicking this - \nsecondlife:///app/group/" + ((string)group_key) + "/about";
             llRegionSayTo(id, 0, "Sorry, this vendor is set to sell only to " + group_name + " group members." + msg);
         }
         }
     }
     }
Line 337: Line 301:


Sliding door that glides smoothly from closed to open and back with an auto timer.
Sliding door that glides smoothly from closed to open and back with an auto timer.
*'''DO NOT LINK TO HOUSE''' (even though it is quite funny).
*'''DO NOT LINK TO HOUSE''' (even though it is quite funny).


Line 355: Line 318:
vector pos;
vector pos;


Door()
Door() {
{
     vector targ;
     vector targ;
     if(!open)
     if ( !open ) {
    {
         targ = ( pos + target );
         targ = (pos + target);
         llSetTimerEvent( time );
         llSetTimerEvent(time);
    } else {
        llSetTimerEvent( 0.0 );
        targ = ( pos );
     }
     }
    else
     open = ( !open );
    {
     t = llTarget( targ, 0.04 );
        llSetTimerEvent(0.0);
     llMoveToTarget( targ, 0.75 );
        targ = (pos);
     llSetStatus( STATUS_PHYSICS | STATUS_PHANTOM, TRUE);
    }
     open = (!open);
     t = llTarget(targ, 0.04);
     llMoveToTarget(targ, 0.75);
     llSetStatus(STATUS_PHYSICS |
                STATUS_PHANTOM, TRUE);
}
}


default
default {
{
     on_rez( integer param ) {
     on_rez(integer param)
    {
         llResetScript();
         llResetScript();
     }
     }
     state_entry()
     state_entry() {
    {
         llSetStatus( STATUS_BLOCK_GRAB, TRUE );
         llSetStatus(STATUS_BLOCK_GRAB, TRUE);
         llSetStatus( STATUS_PHYSICS |
         llSetStatus(STATUS_PHYSICS |
                    STATUS_ROTATE_X |
                    STATUS_ROTATE_X |
                    STATUS_ROTATE_Y |
                    STATUS_ROTATE_Y |
                    STATUS_ROTATE_Z |
                    STATUS_ROTATE_Z |
                    STATUS_PHANTOM, FALSE );
                    STATUS_PHANTOM, FALSE);
         pos = llGetPos();
         pos = llGetPos();
     }
     }
     touch_start(integer nd)
     touch_start( integer nd ) {
    {
         Door();
         Door();
     }
     }
     at_target(integer num, vector tpos, vector opos)
     at_target( integer num, vector tpos, vector opos ) {
    {
         llTargetRemove( t );
         llTargetRemove(t);
         llSetStatus( STATUS_PHYSICS | STATUS_PHANTOM, FALSE );
         llSetStatus(STATUS_PHYSICS |
         llSetPos( tpos );
                    STATUS_PHANTOM, FALSE);
         llSetPos(tpos);
     }
     }
     timer()
     timer() {
    {
         llSetTimerEvent( 0.0 );
         llSetTimerEvent(0.0);
         Door();
         Door();
     }
     }
Line 411: Line 362:
=== Link-Set Texture Configuration ===
=== Link-Set Texture Configuration ===
For example - We have a piece of furniture with 5 frame prims and 4 cushion prims.
For example - We have a piece of furniture with 5 frame prims and 4 cushion prims.
*You want the frame to have 4 texture options -
* You want the frame to have 4 texture options -
**Dark Wood
** Dark Wood
**Light Wood
** Light Wood
**Aluminium
** Aluminium
**Shiny Black
** Shiny Black
*And the cushions have 4 texture options -
* And the cushions have 4 texture options -
**Pink Damasque
** Pink Damasque
**Green Twill
** Green Twill
**Black Fur
** Black Fur
**Crimson Velour
** Crimson Velour
You want these options to be available to choose from -
You want these options to be available to choose from -
*Dark Wood frame with Crimson Velour cushions.
* Dark Wood frame with Crimson Velour cushions.
*Light Wood frame with Pink Damasque cushions.
* Light Wood frame with Pink Damasque cushions.
*Aluminium frame with Green Twill cushions.
* Aluminium frame with Green Twill cushions.
*Shiny Black frame with Black Fur cushions.
* Shiny Black frame with Black Fur cushions.
*Dark Wood frame with Pink Damasque cushions.
* Dark Wood frame with Pink Damasque cushions.
*Light Wood frame with Green Twill cushions.
* Light Wood frame with Green Twill cushions.
*Aluminium frame with Black Fur cushions.
* Aluminium frame with Black Fur cushions.
*Shiny Black frame with Crimson Velour cushions.
* Shiny Black frame with Crimson Velour cushions.
*Dark Wood frame with Green Twill cushions.
* Dark Wood frame with Green Twill cushions.
*Light Wood frame with Black Fur cushions.
* Light Wood frame with Black Fur cushions.
*Aluminium frame with Crimson Velour cushions.
* Aluminium frame with Crimson Velour cushions.
*Shiny Black frame with Pink Damasque cushions.
* Shiny Black frame with Pink Damasque cushions.
Put this script in any prim in the set. If you put it in the root prim, the whole object will become touchable. This may be undesirable. If the script is in any other prim in the set, only that prim will be touchable (unless you have other touch active scripts in the object). The script responds to its owner only. It will reset if the owner changes so that the new owner can control it.
Put this script in any prim in the set. If you put it in the root prim, the whole object will become touchable. This may be undesirable. If the script is in any other prim in the set, only that prim will be touchable (unless you have other touch active scripts in the object). The script responds to its owner only. It will reset if the owner changes so that the new owner can control it.
#Set the object manually to one of the texturing configurations.
# Set the object manually to one of the texturing configurations.
#Set your Viewer Preferences > Text Chat > Chat Options > Show Timestamp in Local Chat to '''OFF''' (uncheck that option).
# Set your Viewer Preferences > Text Chat > Chat Options > Show Timestamp in Local Chat to '''OFF''' (uncheck that option).
#Click the prim with this script in it.
# Click the prim with this script in it.
#A dialog will appear, click the "Config" button.
# A dialog will appear, click the "Config" button.
#A load of data will be chatted to you.
# A load of data will be chatted to you.
#Copy from your local chat history '''all''' the text '''between''' "!!!!!!!!!!----CONFIGURATION START----!!!!!!!!!!" & "!!!!!!!!!!----CONFIGURATION END----!!!!!!!!!!". Don't include those two lines. Since this is local chat (and the script is cleaner without automatic removal) you'll need to check there is no ''unwanted'' chat mixed up in the object data chat.
# Copy from your local chat history '''all''' the text '''between''' "!!!!!!!!!!----CONFIGURATION START----!!!!!!!!!!" & "!!!!!!!!!!----CONFIGURATION END----!!!!!!!!!!". Don't include those two lines. Since this is local chat (and the script is cleaner without automatic removal) you'll need to check there is no ''unwanted'' chat mixed up in the object data chat.
#Paste that text into an otherwise clean Notecard (no other text in the card).
# Paste that text into an otherwise clean Notecard (no other text in the card).
#Name it. The Notecard name needs to be short enough to be the name of that configuration option when offered on a dialog button.
# Name it. The Notecard name needs to be short enough to be the name of that configuration option when offered on a dialog button.
#Set the object manually to another of the texturing configurations.
# Set the object manually to another of the texturing configurations.
#Repeat these steps until all the configurations (Maximum of 12) are stored to Notecards.
# Repeat these steps until all the configurations (Maximum of 12) are stored to Notecards.
Once all the Notecards are saved and named, drop them all into the same prim contents as the script. That's it.
Once all the Notecards are saved and named, drop them all into the same prim contents as the script. That's it.
Now when the prim is clicked a dialog will appear offering the options, taking the names for each option from the Notecards the script finds.
Now when the prim is clicked a dialog will appear offering the options, taking the names for each option from the Notecards the script finds.
*To add new configurations after adding Notecards to the prim, you'll need to remove the Notecards already in the contents and add them again after creating the new Notecards. In other words, If the prim has any Notecards in it, it will offer the options. If the prim has no Notecards in it, it will offer the "Config" button.
* To add new configurations after adding Notecards to the prim, you'll need to remove the Notecards already in the contents and add them again after creating the new Notecards. In other words, If the prim has any Notecards in it, it will offer the options. If the prim has no Notecards in it, it will offer the "Config" button.
*The change from one configuration to another can be very slow (depending on the number of prims and the number of faces of each prim etc).
* The change from one configuration to another can be very slow (depending on the number of prims and the number of faces of each prim etc).
**This slowness is a trade off. The main advantages are -
** This slowness is a trade off. The main advantages are -
***The script doesn't use a vast amount of memory ("Memory use is bad, M'kay?").
*** The script doesn't use a vast amount of memory ("Memory use is bad, M'kay?").
***There are not loads of scripts. Just one script for the whole object.
*** There are not loads of scripts. Just one script for the whole object.
***Dramatically different texturing is as simple to apply as slight changes.
*** Dramatically different texturing is as simple to apply as slight changes.
**This isn't designed for dynamic effect. It is for simply changing decoration. Speed is hardly important when changing the color of an arm chair after all.
** This isn't designed for dynamic effect. It is for simply changing decoration. Speed is hardly important when changing the color of an arm chair after all.
All texture parameters are catered for. Every individual face separately.
All texture parameters are catered for. Every individual face separately.
*Texture
* Texture
**UUID
** UUID
**Repeats
** Repeats
**Offsets
** Offsets
**Rotations
** Rotations
*Color
* Color
*Alpha
* Alpha
*Mapping
* Mapping
**Default or Planar
** Default or Planar
*Shiny
* Shiny
**High, Medium, Low or None
** High, Medium, Low or None
*Bump Mapping
* Bump Mapping
**All the bumpy options are recorded
** All the bumpy options are recorded
*Fullbright
* Fullbright
*Glow
* Glow
'''This is early days for this idea (I may possibly rework it sometime) and there are limits. The amount of data that can be stored to a Notecard being one of them. Very large prim-count objects with complex prims (hollowed and path cut boxes having up to 9 faces for example) may create too much data to be stored to one Notecard. Sorry bout that.'''
'''This is early days for this idea (I may possibly rework it sometime) and there are limits. The amount of data that can be stored to a Notecard being one of them. Very large prim-count objects with complex prims (hollowed and path cut boxes having up to 9 faces for example) may create too much data to be stored to one Notecard. Sorry bout that.'''


<syntaxhighlight lang="lsl2">// V2 //
<syntaxhighlight lang="lsl2">// V2 //


SpewConfig(integer nol)
SpewConfig( integer nol ) {
{
     llSetObjectName( "" );
     llSetObjectName("");
     llOwnerSay( "/me /n!!!!!!!!!!----CONFIGURATION START----!!!!!!!!!!" );
     llOwnerSay("/me /n!!!!!!!!!!----CONFIGURATION START----!!!!!!!!!!");
     integer ln = 1;
     integer ln = 1;
     do
     do {
    {
         list s = [];
         list s = [];
         list p = [];
         list p = [];
         integer c = 0;
         integer c = 0;
         integer f = 0;
         integer f = 0;
         integer l = llGetListLength((s = llGetLinkPrimitiveParams(ln, [17, -1])));
         integer l = llGetListLength( ( s = llGetLinkPrimitiveParams( ln, [ 17, -1 ] ) ) );
         do
         do {
        {
             llOwnerSay( "/me " + llDumpList2String( [17, ( f++ ) ] + llList2List( s, c, ( c + 3 ) ), "," ) );
             llOwnerSay("/me " + llDumpList2String([17, (f++)] + llList2List(s, c, (c + 3)), ","));
             c += 4;
             c += 4;
         }
         } while ( c < l );
        while(c < l);
       
         c = 0;
         c = 0;
         f = 0;
         f = 0;
         l = llGetListLength((s = llGetLinkPrimitiveParams(ln, [18, -1])));
         l = llGetListLength( ( s = llGetLinkPrimitiveParams( ln, [ 18, -1 ] ) ) );
         do
         do {
        {
             llOwnerSay( "/me " + llDumpList2String( [ 18, ( f++ ) ] + llList2List( s, c, ( c + 1 ) ), "," ) );
             llOwnerSay("/me " + llDumpList2String([18, (f++)] + llList2List(s, c, (c + 1)), ","));
             c += 2;
             c += 2;
         }
         } while ( c < l );
        while(c < l);
       
         c = 0;
         c = 0;
         f = 0;
         f = 0;
         l = llGetListLength((s = llGetLinkPrimitiveParams(ln, [19, -1])));
         l = llGetListLength( ( s = llGetLinkPrimitiveParams( ln, [ 19, -1 ] ) ) );
         do
         do {
        {
             p += [ 19, ( f++ ) ] + llList2List( s, c, ( c + 1 ) );
             p += [19, (f++)] + llList2List(s, c, (c + 1));
             c += 2;
             c += 2;
         }
         } while ( c < l );
        while(c < l);
         llOwnerSay( "/me " + llDumpList2String( p, "," ) );
         llOwnerSay("/me " + llDumpList2String(p, ","));
       
         p = [];
         p = [];
         c = 0;
         c = 0;
         f = 0;
         f = 0;
         l = llGetListLength((s = llGetLinkPrimitiveParams(ln, [20, -1])));
         l = llGetListLength( ( s = llGetLinkPrimitiveParams( ln, [ 20, -1 ] ) ) );
         do
         do {
        p += [20, (f++)] + llList2List(s, c, c);
            p += [ 20, ( f++ ) ] + llList2List( s, c, c );
         while((++c) < l);
         } while ( ( ++c ) < l );
         llOwnerSay("/me " + llDumpList2String(p, ","));
         llOwnerSay( "/me " + llDumpList2String( p, "," ) );
       
         p = [];
         p = [];
         c = 0;
         c = 0;
         f = 0;
         f = 0;
         l = llGetListLength((s = llGetLinkPrimitiveParams(ln, [22, -1])));
         l = llGetListLength( ( s = llGetLinkPrimitiveParams( ln, [ 22, -1 ] ) ) );
         do
         do {
        p += [22, (f++)] + llList2List(s, c, c);
            p += [ 22, ( f++ ) ] + llList2List( s, c, c );
         while((++c) < l);
         } while ( ( ++c ) < l );
         llOwnerSay("/me " + llDumpList2String(p, ","));
         llOwnerSay( "/me " + llDumpList2String( p, "," ) );
       
         p = [];
         p = [];
         c = 0;
         c = 0;
         f = 0;
         f = 0;
         l = llGetListLength((s = llGetLinkPrimitiveParams(ln, [25, -1])));
         l = llGetListLength( ( s = llGetLinkPrimitiveParams( ln, [ 25, -1 ] ) ) );
         do
         do {
        p += [25, (f++)] + llList2List(s, c, c);
            p += [ 25, ( f++ ) ] + llList2List( s, c, c );
         while((++c) < l);
         } while ( ( ++c ) < l );
         llOwnerSay("/me " + llDumpList2String(p, ","));
         llOwnerSay( "/me " + llDumpList2String( p, "," ) );
         llOwnerSay("/me LINK");
       
     }
         llOwnerSay( "/me LINK" );
    while((++ln) <= nol);
     } while ( ( ++ln ) <= nol );
     llOwnerSay("/me !!!!!!!!!!----CONFIGURATION END----!!!!!!!!!!\n");
   
     llSetObjectName(my_name);
     llOwnerSay( "/me !!!!!!!!!!----CONFIGURATION END----!!!!!!!!!!\n" );
     llSetObjectName( my_name );
}
}


list TypeCast(list p)
list TypeCast( list p ) {
{
     list P = [];
     list P = [];
     list c = [];
     list c = [];
     integer int = 0;
     integer int = 0;
     integer count = 0;
     integer count = 0;
     integer length = llGetListLength(p);
     integer length = llGetListLength( p );
     do
     do {
    {
         if ( ( int = ( ( integer )llList2String( ( c = llCSV2List( llList2String( p, count ) ) ), 0 ) ) ) == 17 ) {
         if((int = ((integer)llList2String((c = llCSV2List(llList2String(p, count))), 0))) == 17)
             P += [ int, ( ( integer )llList2String( c, 1 ) ),
        {
                        ( ( key )llList2String( c, 2 ) ),
             P += [int, ((integer)llList2String(c, 1)),
                        ( ( vector )llList2String( c, 3 ) ),
                      ((key)llList2String(c, 2)),
                        ( ( vector )llList2String( c, 4 ) ),
                      ((vector)llList2String(c, 3)),
                        ( ( float )llList2String( c, 5 ) )
                      ((vector)llList2String(c, 4)),
                ];
                      ((float)llList2String(c, 5))];
         } else if ( int == 18 ) {
         }
             P += [ int, ( ( integer )llList2String( c, 1 ) ),
        else if(int == 18)
                        ( ( vector )llList2String( c, 2 ) ),
        {
                        ( ( float )llList2String( c, 3 ) )
             P += [int, ((integer)llList2String(c, 1)),
                ];
                      ((vector)llList2String(c, 2)),
         } else {
                      ((float)llList2String(c, 3))];
             integer l = ( llGetListLength( c ) - 1 );
         }
        else
        {
             integer l = (llGetListLength(c) - 1);
             integer i = -1;
             integer i = -1;
             if(int == 19)
             if ( int == 19 ) {
            {
                 do {
                 do
                {
                     ++i;
                     ++i;
                     P += [int, ((integer)llList2String(c, (++i))),
                     P += [ int, ( ( integer )llList2String( c, ( ++i ) ) ),
                              ((integer)llList2String(c, (++i))),
                                ( ( integer )llList2String( c, ( ++i ) ) ),
                              ((integer)llList2String(c, (++i)))];
                                ( ( integer )llList2String( c, ( ++i ) ) )
                 }
                        ];
                while(i < l);
                 } while ( i < l );
             }
             } else if ( ( int == 20 ) | ( int == 22 ) ) {
            else if((int == 20) | (int == 22))
                 do {
            {
                 do
                {
                     ++i;
                     ++i;
                     P += [int, ((integer)llList2String(c, (++i))),
                     P += [ int, ( ( integer )llList2String( c, ( ++i ) ) ),
                              ((integer)llList2String(c, (++i)))];
                                ( ( integer )llList2String( c, ( ++i ) ) )
                 }
                        ];
                while(i < l);
                 } while ( i < l );
             }
             } else if ( int == 25 ) {
            else if(int == 25)
                 do {
            {
                 do
                {
                     ++i;
                     ++i;
                     P += [int, ((integer)llList2String(c, (++i))),
                     P += [ int, ( ( integer )llList2String( c, ( ++i ) ) ),
                              ((float)llList2String(c, (++i)))];
                                ( ( float )llList2String( c, ( ++i ) ) )
                 }
                        ];
                while(i < l);
                 } while ( i < l );
             }
             }
         }
         }
     }
     } while ( ( ++count ) < length );
    while((++count) < length);
     return P;
     return P;
}
}
Line 624: Line 559:
string present = "Default"; // The name of your default configuration NC
string present = "Default"; // The name of your default configuration NC


default
default {
{
     state_entry() {
     state_entry()
    {
         owner = llGetOwner();
         owner = llGetOwner();
         my_name = llGetObjectName();
         my_name = llGetObjectName();
     }
     }
     touch_start(integer nd)
     touch_start( integer nd ) {
    {
         if ( llDetectedKey( 0 ) == owner ) {
         if(llDetectedKey(0) == owner)
             integer inn = llGetInventoryNumber( INVENTORY_NOTECARD );
        {
             if ( inn ) {
             integer inn = llGetInventoryNumber(INVENTORY_NOTECARD);
             if(inn)
            {
                 list ncn = [];
                 list ncn = [];
                 while(inn)
                 while ( inn ) {
                ncn += [llGetInventoryName(INVENTORY_NOTECARD, (--inn))];
                    ncn += [ llGetInventoryName( INVENTORY_NOTECARD, ( --inn ) ) ];
                 llListenRemove(lis);
                }
                 lis = llListen(channel, llKey2Name(owner), owner, "");
                 llListenRemove( lis );
                 llDialog(owner, ("\n\nChoose your texture configuration.\nThe present configuration is - \"" + present + "\""), ncn, channel);
                 lis = llListen( channel, llKey2Name( owner ), owner, "" );
                 llSetTimerEvent(60.0);
                 llDialog( owner, ( "\n\nChoose your texture configuration.\nThe present configuration is - \"" + present + "\"" ), ncn, channel );
             }
                 llSetTimerEvent( 60.0 );
            else
             } else { // Could just jump right to it but, this stops accidental activation.
            {   // Could just jump right to it but, this stops accidental activation.
                 llListenRemove( lis );
                 llListenRemove(lis);
                 lis = llListen( channel, llKey2Name( owner ), owner, "Config" );
                 lis = llListen(channel, llKey2Name(owner), owner, "Config");
                 llDialog( owner, "\n\nClick \"Config\" when the objects texturing is set.", [ "Config" ], channel );
                 llDialog(owner, "\n\nClick \"Config\" when the objects texturing is set.", ["Config"], channel);
                 llSetTimerEvent( 10.0 );
                 llSetTimerEvent(10.0);
             }
             }
         }
         }
     }
     }
     timer()
     timer() {
    {
         llSetTimerEvent( 0.0 );
         llSetTimerEvent(0.0);
         llListenRemove( lis );
         llListenRemove(lis);
         llOwnerSay( "The listen has been removed by timer." );
         llOwnerSay("The listen has been removed by timer.");
     }
     }
     dataserver(key q, string data)
     dataserver( key q, string data ) {
    {
         if ( ( q == iq ) && ( data != EOF ) ) {
         if((q == iq) && (data != EOF))
             if ( ( data = llStringTrim( data, STRING_TRIM ) ) != "LINK" ) {
        {
                params += [ data ];
             if((data = llStringTrim(data, STRING_TRIM)) != "LINK")
             } else {
            params += [data];
                 llSetLinkPrimitiveParamsFast( ( ++link ), TypeCast( params ) );
             else
            {
                 llSetLinkPrimitiveParamsFast((++link), TypeCast(params));
                 params = [];
                 params = [];
             }
             }
             iq = llGetNotecardLine(present, (++nclc));
             iq = llGetNotecardLine( present, ( ++nclc ) );
         }
         }
     }
     }
     listen(integer chan, string name, key id, string msg)
     listen( integer chan, string name, key id, string msg ) {
    {
         llSetTimerEvent( 0.0 );
         llSetTimerEvent(0.0);
         llListenRemove( lis );
         llListenRemove(lis);
         if ( msg == "Config" ) {
         if(msg == "Config")
            SpewConfig( llGetObjectPrimCount( llGetKey() ) );
        SpewConfig(llGetObjectPrimCount(llGetKey()));
         } else {
         else
        {
             params = [];
             params = [];
             link = 0;
             link = 0;
             iq = llGetNotecardLine((present = msg), (nclc = 0));
             iq = llGetNotecardLine( ( present = msg ), ( nclc = 0 ) );
         }
         }
     }
     }
     changed(integer change)
     changed( integer change ) {
    {
         if ( change & ( CHANGED_OWNER | CHANGED_INVENTORY ) ) {
         if(change & (CHANGED_OWNER | CHANGED_INVENTORY))
            llResetScript();
        llResetScript();
        }
     }
     }
}</syntaxhighlight>
}</syntaxhighlight>
Line 697: Line 620:
=== Zippadeedoodah (Teleporter) ===
=== Zippadeedoodah (Teleporter) ===
These are those "sit & go" type prim based ''teleporters'' that you might use to get from the ground to a skybox (or similar).
These are those "sit & go" type prim based ''teleporters'' that you might use to get from the ground to a skybox (or similar).
: Add the destination as a comma separated string of three numbers to the description of the prim the script is in (ideally the root).
: When you sit on the object the operation happens automatically.
:* ''e.g.'' '''<tt>36, 128, 4000.5</tt>'''
* Reaching the destination target is not guaranteed. See [[llSetRegionPos]] for details.
: The numbers represent the X, Y and Z coordinates of the destination on the region the scripted object is on.
When you sit on the object the operation happens automatically.
* Reaching the destination target is not garenteed. See [[llSetRegionPos]] for details.


==== Temp Rez Version ====
==== Temp Rez Version ====
This version is a one way, self deleting type ''e.g.'' an object containing this script could be rezzed by a sign when touched allowing visitors to use the rezzed teleporter to be taken directly to areas of a region/parcel. Since the sign could be just 1 prim providing multiple destinations and each rezzed teleporter is both temporary and phantom the savings on both prim count and server stress are obvious.
This version is a one way, self deleting type ''e.g.'' a sign, when touched, rezzes a teleporter seat which takes them directly to areas of a region/parcel. Since the sign could be just 1 prim providing multiple destinations and each rezzed teleporter is both temporary and phantom the savings on both prim count and server stress are obvious.
 
===== Sign Board =====
* Add textures to the faces (multiple faces is fine and each may show a different selection of destinations) of the prim you want to use as the sign, that shows all of the ''buttons'' to click in order to rez a seat to that destination.
* The script will chat instructions to you about how to set it up. It's easy :-)
* If you add or remove destination seats after the set up, you'll need to set it up again, but once done, the script remembers everything, even if you take a re-rez it.
* Since the seats have all the information they need about their job, the sign can be moved without affecting the results.
Annotations will come later.
 
<syntaxhighlight lang="lsl2">// V1 //
 
vector seat_rez_position = <0.0, 0.0, 0.0>; // You may want to play with these.
 
//////////////////////////////////////////////////////////////////////////////
 
list making_boxes;
list destinations;
list destination_buttons;
 
integer destindex;
integer number_of_dests;
 
integer mapDestinations() {
    integer noo = llGetInventoryNumber( INVENTORY_OBJECT );
    string dest;
    while ( noo ) {
        dest = llGetInventoryName( INVENTORY_OBJECT, --noo );
        if ( ( vector )( "<" + dest + ">" ) ) {
            if ( !~llListFindList( destinations, [ dest ] ) ) {
                destinations += [ dest ];
            }
        }
    }
    return ( number_of_dests = llGetListLength( destinations ) );
}
 
integer instruct2DefineButton() {
    if ( destindex < number_of_dests ) {
        llOwnerSay( "Define the button for destination: " + llList2String( destinations, destindex++ ) );
        return FALSE;
    }
    return TRUE;
}
 
resetIfInventoryChanges( integer c ) {
    if ( c & CHANGED_INVENTORY ) {
        llResetScript();
    }
}


<syntaxhighlight lang="lsl2">// V8 //
default {
default {
     on_rez( integer param ) {
     state_entry() {
         llSetClickAction( CLICK_ACTION_SIT ); // Makes the prim "Click to sit".
         if ( mapDestinations() ) {
        llSetLinkPrimitiveParamsFast( LINK_SET, [ PRIM_TEMP_ON_REZ, TRUE, // Make the object temporary,
            llOwnerSay( "For each destination, touch the sign at 2 diagonally opposing corners of an imagined box around the area of the sign that shows the \"button\" to click to go there." );
                                                  PRIM_PHANTOM, TRUE ] ); // and phantom.
            instruct2DefineButton();
         // Makes the object less intensive for the region. Also makes a smoother llUnSit.
         }
     }
     }
     changed( integer change ) {
     changed( integer change ) {
         if ( change & CHANGED_LINK ) { // If an avatar sits on the object they become one of the links.
         resetIfInventoryChanges( change );
            integer links = llGetNumberOfPrims();
    }
             if ( llGetObjectPrimCount( llGetKey() ) < links ) { // Check if there are more links than prims.
    touch_start( integer nd ) {
                vector dest = ( vector )( "<" + llGetObjectDesc() + ">" ); // Create a vector from the object description.
        while ( nd ) {
                llSetRegionPos( dest ); // Transport us as close as possible.
             if ( llDetectedKey( --nd ) == llGetOwner() ) {
                llSetLinkPrimitiveParamsFast( !!llGetLinkNumber(), [ PRIM_POSITION, dest ] ); // Make sure we're exactly on target.
                if ( llGetListLength( destination_buttons ) < llGetListLength( destinations ) ) {
                llUnSit( llGetLinkKey( links ) ); // When we arrive, Un-Sit the key that is not a prim.
                    vector UV = llDetectedTouchUV( nd );
                    if ( llGetListLength( making_boxes ) ) {
                        making_boxes += [ UV.x, UV.y ];
                        making_boxes = llListSort( [ llList2Float( making_boxes, 0 ), llList2Float( making_boxes, 2 ) ], 1, TRUE ) +
                                      llListSort( [ llList2Float( making_boxes, 1 ), llList2Float( making_boxes, 3 ) ], 1, TRUE );
                        destination_buttons += [ llList2CSV( [ llDetectedTouchFace( nd ) ] + making_boxes ) ];
                        making_boxes = [];
                        if ( instruct2DefineButton() ) {
                            llOwnerSay( "Setup complete." );
                            state ready;
                        }
                    } else {
                        making_boxes = [ UV.x, UV.y ];
                    }
                }
             }
             }
            llDie(); // Delete the object.
         }
         }
    }
}
state ready {
    touch_start( integer nd ) {
        while ( nd ) {
            vector UV = llDetectedTouchUV( --nd );
            integer count = number_of_dests;
            string destseat = "";
            list button = [];
            while ( destseat == "" && count ) {
                button = llCSV2List( llList2String( destination_buttons, --count ) );
                if ( llList2Integer( button, 0 ) == llDetectedTouchFace( nd ) ) {
                    if ( UV.x >= llList2Float( button, 1 ) && UV.x <= llList2Float( button, 2 ) ) {
                        if ( UV.y >= llList2Float( button, 3 ) && UV.y <= llList2Float( button, 4 ) ) {
                            destseat = llList2String( destinations, count );
                            llRezObject( destseat, llDetectedTouchPos( nd ), seat_rez_position, llGetLocalRot(), 0 );
                        }
                    }
                }
            }
        }
    }
    changed( integer change ) {
        resetIfInventoryChanges( change );
    }
}</syntaxhighlight>
===== Teleporter Seats =====
* Add the destination as a comma separated string of three numbers to the '''name''' of the prim the script is in (ideally the root).
:* ''e.g.'' '''<tt>36.025, 128, 4000.5</tt>'''
* The numbers represent the X, Y and Z coordinates of the destination on the region the scripted object is on.
<syntaxhighlight lang="lsl2">// V9 //
// These two variables can be used to set the position and rotation of the seat's sit target.
// Although the avatar won't be seated for long enough for this to matter much,
// how the avatar is dismounted may be affected.
vector sit_position = <0.0, 0.0, 0.1>; // Must not be zero
rotation sit_rotation = ZERO_ROTATION;
/////////////////////////////////////////////////////////////////////////////////////////////
integer zippadeeDoodah( vector dest ) {
    if ( llSetRegionPos( dest ) ) { // Transport us as close as possible and, if that worked
        llSetLinkPrimitiveParamsFast( !!llGetLinkNumber(), [ PRIM_POSITION, dest ] ); // make sure we're exactly on target.
        return TRUE; // Return true if everything worked and
    }
    return FALSE; // return false if it didn't.
}
vector string2Vector( string str ) {
    return ( vector )( "<" + str + ">" ); // create a vector from the string and return it.
}
default { // Set up the seat for use.
    on_rez( integer param ) { // On being rezzed:
        llSitTarget( sit_position, sit_rotation ); // Make space to sit on even an uncomfortable object.
        llSetClickAction( CLICK_ACTION_SIT ); // Make the prim click-to-sit-able.
        llSetLinkPrimitiveParamsFast( !!llGetLinkNumber(), [ PRIM_PHANTOM, TRUE,
                                                            PRIM_TEMP_ON_REZ, TRUE ] ); // Make the object less intensive for the region.
    }
    changed( integer change ) { // If something about the object has changed, such as the number of links,
        if ( change & CHANGED_LINK && llAvatarOnSitTarget() != NULL_KEY ) { // there may be aseated avatar.
            vector dest = string2Vector( llGetObjectName() ); // Establish the destination from the object name,
            if ( dest ) { // and if the destination makes sense:
                if ( zippadeeDoodah( dest ) ) { // Move the seat and the rider to the destination from the object description.
                    state rest_in_peace; // And if that worked, go to a quite place to die.
                }
            } // If we get to this point, we haven't functioned correctly, so message the owner about the problem and
            llInstantMessage( llGetOwner(), "Hi boss. So I was supposed to be doing my job but, something went wrong." +
                                            "\nYou might need to fix something in my clones so they don't fail the same way." +
                                            "\nGoodbye cruel world!" );
            llDie(); // delete the object.
        }
    }
    state_exit() { // On the way out of this state
        key rider = llAvatarOnSitTarget(); // Establish that the rider didn't fall off,
        if ( rider ) { // and if they didn't,
            llUnSit( rider ); // give 'em a push! ;-)
        }
    }
}
state rest_in_peace {
    state_entry() { // On entering the state:
        llDie(); // Delete the object.
     }
     }
}</syntaxhighlight>
}</syntaxhighlight>


==== Permanent Version ====
==== Permanent Version ====
This version drops the user off at the destination then either waits for the set time or goes straight back home to be reused.
This version drops the user off at the destination then goes straight back home to be reused.
* Add the '''home''' position as a comma separated string of three numbers to the '''name''' of the prim the script is in (ideally the root).
* Add the '''destination''' as a comma separated string of three numbers to the '''description'''.
:* ''e.g.'' '''<tt>36.025, 128, 4000.5</tt>'''
* The numbers represent the X, Y and Z coordinates of the destinations on the region the scripted object is on.


<syntaxhighlight lang="lsl2">// V10 //
<syntaxhighlight lang="lsl2">// V13 //
 
float time = 3600.0; // The time in seconds to wait before returning to home position.
// These two variables can be used to set the position and rotation of the seat's sit target.
                    // If set to zero, the return home for the object will be immediate.
// Although the avatar won't be seated for long enough for this to matter much,
// how the avatar is dismounted may be affected.
/////////////////////////////////////////////////////////////////////////////////////////
vector sit_position = <0.0, 0.0, 0.1>; // Must not be zero
rotation sit_rotation = ZERO_ROTATION;
vector home; // Used to store the home position.
 
//////////////////////////////////////////////////////////
 
integer zippadeeDoodah( vector dest ) {
    if ( llSetRegionPos( dest ) ) { // Transport us as close as possible and, if that worked
        llSetLinkPrimitiveParamsFast( !!llGetLinkNumber(), [ PRIM_POSITION, dest ] ); // make sure we're exactly on target.
        return TRUE; // Return true if everything worked and
    }
    return FALSE; // return false if it didn't.
}
 
vector string2Vector( string str ) {
    return ( vector )( "<" + str + ">" ); // create a vector from the string and return it.
}


zippadeeDoodah( vector dest ) {
default { // Set up the seat for use.
    llSetRegionPos( dest ); // Transport us as close as possible.
    state_entry() { // On entering the state:
    llSetLinkPrimitiveParamsFast( !!llGetLinkNumber(), [ PRIM_POSITION, dest ] ); // Make sure we're exactly on target.
        llSitTarget( sit_position, sit_rotation ); // Make space to sit on even an uncomfortable object.
        llSetClickAction( CLICK_ACTION_SIT ); // Make the prim click-to-sit-able.
        llSetLinkPrimitiveParamsFast( !!llGetLinkNumber(), [ PRIM_PHANTOM, TRUE ] ); // Make the object less intensive for the region.
        state coiled_spring; // With the seat set up, go to a state with a changed event.
    }
}
}
 
default {
state coiled_spring { // Be prepared for riders.
    state_entry() {
     changed( integer change ) { // If something about the object has changed, such as the number of links,
        home = llGetRootPosition(); // Establish where our home pos is.
        if ( change & CHANGED_LINK && llAvatarOnSitTarget() != NULL_KEY ) { // there may be aseated avatar.
        // For this reason, reset the script when the home position of the object is chosen.
            vector dest = string2Vector( llGetObjectDesc() ); // Establish the destination from the object description,
        llSetClickAction( CLICK_ACTION_SIT ); // Makes the prim "Click to sit".
            if ( dest ) { // and if the destination makes sense:
        llSetLinkPrimitiveParamsFast( LINK_SET, [ PRIM_PHANTOM, TRUE ] ); // Makes the object less intensive for the region.
                if ( zippadeeDoodah( dest ) ) { // Move the seat and the rider to the destination from the object description.
    }                                                                    // Also makes a smoother llUnSit.
                     state recoil; // And if that worked, go to a state with no changed event.
     changed( integer change ) {
        if ( change & CHANGED_LINK ) { // If an avatar sits on the object they become one of the links.
            integer links = llGetNumberOfPrims();
            key rider = llGetLinkKey( links ); // The key of the link that is not a prim.
            if ( llGetObjectPrimCount( llGetKey() ) < links ) { // Check if there are more links than prims.
                vector dest = ( vector )( "<" + llGetObjectDesc() + ">" ); // Create a vector from the object description.
                if ( llVecDist( llGetRootPosition(), dest ) > 0.0015 ) { // Check if the object is near destination. If not, go there.
                    zippadeeDoodah( dest ); // Hang onto your hat!
                    llUnSit( rider ); // When we arrive, Un-Sit the rider.
                     if ( ( integer )time ) {
                        llSetTimerEvent( time ); // Start a timer.
                    } else {
                        zippadeeDoodah( home ); // Go back home.
                    }
                } else {
                    llUnSit( rider ); // Un-Sit the rider.
                 }
                 }
            } // If we get to this point, we haven't functioned correctly, so
            state cannot_function; // deactivate and call for help.
        }
    }
    state_exit() { // On the way out of this state
        key rider = llAvatarOnSitTarget(); // Establish that the rider didn't fall off,
        if ( rider ) { // and if they didn't,
            llUnSit( rider ); // give 'em a push! ;-)
        }
    }
}
state recoil {
    state_entry() { // On entering the state:
        vector home = string2Vector( llGetObjectName() ); // Establish the way home from the object name,
        if ( home ) { // and if it makes sense:
            if ( zippadeeDoodah( home ) ) { // Send the seat back to it's home and
                state coiled_spring; // if that worked, go back to being prepared for riders.
            }
        } // If we get to this point, we haven't functioned correctly, so
        state cannot_function; // deactivate and call for help.
    }
}
state cannot_function {
    state_entry() { // On entering the state:
        llSetClickAction( CLICK_ACTION_TOUCH ); // Make the prim click-able and message the owner.
        llInstantMessage( llGetOwner(), "Hi boss. So I was supposed to be doing my job but, something went wrong." +
                                        "\nYou'll probably need to reset my script after fixing whatever was wrong with me." +
                                        "\nWhen you've fixed the problem, just click me to reset my script." );
    }
    touch_end( integer nd ) {
        while ( nd ) { // For each detected touch
            if ( llDetectedKey( --nd ) == llGetOwner() ) { // check if the toucher is the owner
                llResetScript(); // and if it is, reset the script.
             }
             }
         }
         }
    }
    timer() {
        llSetTimerEvent( 0.0 ); // Cancel the timer.
        zippadeeDoodah( home ); // Go back home.
     }
     }
}</syntaxhighlight>}}
}</syntaxhighlight>}}

Latest revision as of 07:36, 5 April 2020

I get in-world very rarely these days. The knock-on effect of this, is that I am not in the best position to keep these scripts updated. Please message me in-world (forwarded to email) if you discover any bugs (that can't be simply fixed), and I'll do my best to find a solution.

My Contributions

If unsure about how to use these scripts

I have implemented a version number system to make it more obvious if a script is updated. The V# is a comment at the top of each script.

If you have any comments about the content of this page please post them HERE

All my scripts are written for compilation as MONO

More Scripts

Legal Stuff

The legal stuff about contributing to this wiki. (worth reading)

PJIRA Issue Tracker

The issues I have filed on the PJIRA

Tuition

Tuition scripts, notes, videos and screenshots etc. (hardly any content yet)

Free Scripts

Text Scroller

A simple text display unit that scrolls text from right to left (like those LED signs) in a continuous loop. Touch to start and stop the scrolling. It is not very sophisticated.

Create The Object

  • Create a fresh new prim and drop this script onto/into it. The prim will form the shape needed plus change the texturing etc. (you can do what you like to the texturing afterwards).
// V2 //

default {
    state_entry() {
        llSetPrimitiveParams( [
            7, <0.5, 0.01, 0.25>, // Set the size
            8, <0.0, 0.0, 0.0, 1.0>, // Set to ZERO_ROTATION
            9, 0, 0, <0.375, 0.875, 0.0>, 0.0, <0.0, 0.0, 0.0>, <1.0, 1.0, 0.0>, <0.0, 0.0, 0.0>, // Shape the prim
            17, -1, "5748decc-f629-461c-9a36-a35a221fe21f", <1.0, 1.0, 0.0>, <0.0, 0.0, 0.0>, 0.0, // Apply the blank texture
            18, -1, <1.0, 0.65, 0.1>, 1.0, // Color the prim (kinda orange)
            20, -1, 1, // Make fullbright
            25, -1, 0.05 // Slight glow
        ] );
        llRemoveInventory( llGetScriptName() ); // Remove the script when done
    }
}
  • When the script has worked its magic, Snap the prim to the grid with a grid size of .5 meters.
  • Shift-Drag-Copy the prim, snapping each to the grid positively along the X axis until you have 10 prims in a continuous strip.

You can actually make the object as long or short as you like. 1 prim will work. 100 prims will work (although large linksets have been a problem for link_messages in the past). Just follow the same basic build plan.

  • Select each of the prims from the end that has the greatest X axis position, one at a time (negatively along the X axis) until ALL are selected.

Text Scroller How It Should Look jpg.jpg

  • Link the set.

Display Script

  • Check "Edit Linked parts" and select one prim at a time, dropping this script in each.
  • DO NOT CREATE A FRESH SCRIPT IN EACH PRIM. DROP THE SAME SCRIPT FROM YOUR INVENTORY INTO EACH PRIM.
// V1 //

string font = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890(){}[]<>|\\/.,;:'!?\"£$%^&*_+-=~#@ ";
// A accurate representation of the characters featured on the texture used to display the text.
 
vector GetOffset(string s) {
    if ( s == "" ) { // If there is no text
        s = " "; // Use a space
    }
    integer i = llSubStringIndex( font, s ); // Find the character
    if ( i == -1 ) { // If we can't find it
        i = 94; // Use a space
    }
    return <( -0.45 + ( ( i % 10 ) * 0.1 ) ), ( 0.45 - ( llRound( i / 10 ) * 0.1 ) ), 0.0>;
} // Return the offset needed to display the correct section of the texture by doing the mathematics *coughs*
 
integer me; // Used to store the Link number
 
integer my_ss_5; // Used to store the index of the feed text we display on face 5
 
integer my_ss_6; // Used to store the index of the feed text we display on face 6
 
default {
    state_entry() {
        me = llGetLinkNumber();
        my_ss_6 = ( ( me - 1 ) * 2 ); // Whatever link we are (in a correctly built object) establish the index to grab
        my_ss_5 = ( my_ss_6 + 1 ); // And also grab the next
    }
    link_message( integer sender, integer num, string msg, key id ) {
        llSetLinkPrimitiveParamsFast( me, [
            17, 5, id, <0.1, 0.1, 0.0>, GetOffset( llGetSubString( msg, my_ss_5, my_ss_5 ) ), 0.0,
            17, 6, id, <0.1, 0.1, 0.0>, GetOffset( llGetSubString( msg, my_ss_6, my_ss_6 ) ), 0.0
        ] );
    } // Set the texture to the correct offset to display the correct characters
}

Control Script

One possible way amongst many to feed the text to the script is by notecard. That is the way I set this script. As such, you need a notecard in the root containing the text you wish to display. One notecard will be read. If you add more notecards (without altering the script) it will read the first it finds alphabetically.

  • There is a caveat regarding the length of the lines of text in the notecard. If the line is longer then 255 bytes the dataserver will return the first 255 bytes of the line.
  • This example - taken from one of Shakespeare's Hamlet's soliloquy (To be, or not to be...) is too long by the red lettering -
    • "For who would bear the whips and scorns of time, th'oppressor's wrong, the proud man's contumely, the pangs of despised love, the law's delay, the insolence of office, and the spurns that patient merit of th'unworthy takes, when he himself might his quietus make with a bare bodkin?"
  • Add your text notecard to the root.
  • Drop this script into the root.
// V1 //

integer count; // Used to keep track of iterations
 
integer length; // A measure of string length
 
string text = "                   "; // Adding this creates a gap between beginning and end of text
 
integer NCC; // NoteCardCount for tracking which line to read
 
string NC; // NoteCard name
 
integer on; // Are we on or off?
 
default {
    state_entry() {
        NC = llGetInventoryName( INVENTORY_NOTECARD, 0 ); // Establish the name of our NC
        llGetNotecardLine( NC, NCC ); // Ask for the first line
    }
    dataserver( key q, string data ) {
        if ( data != EOF ) { // If the data is useful
            text += ( data + " " ); // Store it
            llGetNotecardLine( NC, ( ++NCC ) ); // And get the next line
        } else { // If not useful we are at the end of the NC
            length = llStringLength( text ); // Establish the length of our text
            // The number 19 is 1 less than the number of faces (2 per prim) that display text. Change that number accordingly if...
            // ...you have a larger or smaller number of prims in your object.
            llMessageLinked( -1, 0, llGetSubString( "Touch start scroll.", count, ( count + 19 ) ), "b6349d2d-56bf-4c18-4859-7db0771990a5" );
        } // Message the display scripts that we are ready to function
    }
    timer() {
        if ( count == length ) { // If we have gone full circle
            count = 0; // Start again
        }
        llMessageLinked( -1, 0, llGetSubString( text, count, ( count + 19 ) ), "b6349d2d-56bf-4c18-4859-7db0771990a5" );
        ++count; // Message the display scripts with a chunk of text
    }
    touch_end( integer nd ) {
        if ( on ) { // Are we running?
            llSetTimerEvent( 0.0 ); // Stop the timer
        } else { // No?
            llSetTimerEvent( 0.15 ); // Start the timer
        }
        on = ( !on ); // Remember what we did
    }
    changed( integer change ) {
        if ( change & CHANGED_INVENTORY ) { // If the inventory has changed the NC may have
            llResetScript(); // So reset the script to read the new card
        }
    }
}

It should set the text to read "Touch Start Scroll.". If you get something else, you haven't followed these instructions.

The Charsheet Texture

I am a scriptor, not a texturizerer. I created a very simple Charsheet (Character Sheet) to get you going but, it isn't very good *grins*. You will probably want to replace it.

  • The texture MUST be 10 characters by 10 characters (you may have empty spaces so, 56 chars is fine so long as the grid is the full 100 spaces).
  • Unlike the texture I have supplied...ALL the chars should be perfectly evenly spaced and not spreading into the neighboring spaces.

This is the texture supplied. You don't need to copy this. The script already has the UUID in it.

Charsheet Mono Black on White jpg.jpg

The display scripts contain a string that is in the exact same order the chars are read from top left to bottom right (row by row, not column by column).

  • HAVING THE SAME ORDER OF CHARS IN THE TEXTURE AND STRING IS VITAL

The order you choose is entirely up to you as long as the strings in ALL the display scripts match the order of chars in the texture.

  • Don't forget to include a blank grid space on your 10 x 10 texture for a space "character". There also needs to be an empty space (in the correct place) in the scripts.
  • In the display script strings there are two characters that must be treated unusually. The \ and the " must have a \ placed before them.
    • Example "ABCabc123.,:\"\\/| " Note the included space and the way the \ and " have a \ before them.

Sell To Group Only

This is a simple GROUP ONLY vendor script. It can be used to GIVE FREE items to group only too.

  • THIS SCRIPT WILL ASK FOR DEBIT PERMISSIONS. THEY MUST BE GRANTED FOR THE SCRIPT TO FUNCTION. L$ WILL BE TAKEN FROM THE OBJECT OWNERS ACCOUNT.
    • The debit permissions are required for making refunds in the event of an over or under payment or a payment being made by a non group member.
// V2 //
 
integer cost = 0; // The cost of the contents of this object (A whole round number (No decimal places)).
                  // If this is set to zero, the object will act as a group only freebie giver, however...
                  // ...it will still ask for permissions to debit.
 
string folder_name = "Folder"; // The Name of the folder in which to give the contents.
 
integer offer_group_join = TRUE; // Set TRUE or FALSE to offer group membership link on failed purchase attempt.
 
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////// YOU NEED NOT CHANGE ANYTHING BELOW THIS POINT /////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
list contents_list = [];
 
string group_name;
 
key group_key;
 
key owner;
 
default {
    on_rez( integer param ) {
        llResetScript();
    }
    changed( integer change ) {
        if ( change & ( CHANGED_OWNER | CHANGED_INVENTORY ) ) {
            llResetScript();
        }
    }
    state_entry() {
        llSetClickAction( CLICK_ACTION_TOUCH );
        llRequestPermissions( ( owner = llGetOwner() ), PERMISSION_DEBIT );
    }
    run_time_permissions( integer perm ) {
        if ( perm & PERMISSION_DEBIT ) {
            integer in = llGetInventoryNumber( INVENTORY_ALL );
            integer count;
            string name;
            do {
                if ( ( name = llGetInventoryName( INVENTORY_ALL, count ) ) != llGetScriptName() ) {
                    contents_list += [ name ];
                }
            } while ( ( ++count ) < in );
            if ( llGetListLength( contents_list ) ) {
                if ( ( group_key = llList2Key( llGetObjectDetails( llGetKey(), [ OBJECT_GROUP ] ), 0 ) ) == NULL_KEY ) {
                    llOwnerSay( "You NEED to set this object to a group in order to have it sell contents ONLY to that group." +
                                "\nThis script is resetting. You will need to grant debit permissions again." +
                                "\n!! ONLY DO THAT AFTER SETTING THIS OBJECT TO THE DESIRED GROUP !!" );
                    llResetScript();
                } else {
                    llHTTPRequest( "http://world.secondlife.com/group/" + ( ( string )group_key ), [], "" );
                }
            } else {
                llOwnerSay( "There are no contents. This object cannot sell thin air. There is no air in SL." +
                            "\nPlease add the contents to sell." +
                            "\n!! ONLY RE-GRANT PERMISSIONS WHEN ALL CONTENTS ARE ADDED !!" );
            }
        } else {
            llOwnerSay( "You MUST grant permissions for this script to function." );
            llRequestPermissions( owner, PERMISSION_DEBIT );
        }
    }
    http_response( key q, integer status, list metadata, string body ) {
        if ( status == 200 ) {
            llOwnerSay( "This object is set to the group - " +
                        ( group_name = llGetSubString( body, ( llSubStringIndex( body, "<title>" ) + 7 ),
                                                             ( llSubStringIndex( body, "</title>" ) - 1 ) ) ) +
                        "\nOnly members of that group will be able to buy this objects contents." +
                        "\nContents for sale - \n" + llDumpList2String( contents_list, "\n" ) +
                        "\nPrice is " + ( ( string )cost ) + "L$" );
            if ( cost ) {
                llSetClickAction( CLICK_ACTION_PAY );
                llSetPayPrice( PAY_HIDE, [ cost, PAY_HIDE, PAY_HIDE, PAY_HIDE ] );
                state shoptastic;
            } else {
                state freebietastic;
            }
        } else {
            llOwnerSay( "HTTP Request failed. Trying again in 45 seconds. Please wait." );
            llSleep( 45.0 );
            llHTTPRequest( "http://world.secondlife.com/group/" + ( ( string )group_key ), [], "" );
        }
    }
}
state freebietastic {
    on_rez( integer param ) {
        llResetScript();
    }
    changed( integer change ) {
        if ( change & ( CHANGED_OWNER | CHANGED_INVENTORY ) ) {
            llResetScript();
        }
    }
    touch_start( integer nd ) {
        while( nd ) {
            key id = llDetectedKey( --nd );
            if ( llSameGroup( id ) ) {
                llGiveInventoryList( id, folder_name, contents_list );
            } else {
                string msg = "";
                if ( offer_group_join ) {
                    msg = "\nYou can join this group by clicking this - \nsecondlife:///app/group/" + ( ( string )group_key ) + "/about";
                }
                llRegionSayTo( id, 0, "Sorry, this vendor is set to give only to " + group_name + " group members." + msg );
            }
        }
    }
}
state shoptastic {
    on_rez( integer param ) {
        llResetScript();
    }
    changed( integer change ) {
        if ( change & ( CHANGED_OWNER | CHANGED_INVENTORY ) ) {
            llResetScript();
        }
    }
    money( key id, integer amount ) {
        if ( llSameGroup( id ) ) {
            if ( amount >= cost ) {
                if ( amount > cost ) {
                    llGiveMoney( id, ( amount - cost ) );
                }
                llGiveInventoryList( id, folder_name, contents_list );
            } else if ( amount < cost ) {
                llGiveMoney( id, amount );
                llRegionSayTo( id, 0, "Sorry, you paid to little.\nThe cost is " + ( ( string )cost ) + "L$" );
            }
        } else {
            llGiveMoney( id, amount );
            string msg = "";
            if ( offer_group_join ) {
                msg = "\nYou can join this group by clicking this - \nsecondlife:///app/group/" + ( ( string )group_key ) + "/about";
            }
            llRegionSayTo( id, 0, "Sorry, this vendor is set to sell only to " + group_name + " group members." + msg );
        }
    }
}

Basic Smooth Sliding Door

Sliding door that glides smoothly from closed to open and back with an auto timer.

  • DO NOT LINK TO HOUSE (even though it is quite funny).
// V1 //

vector target = <1.5, 0.1, 0.0>; // Play about to get the result you want.
// Each of the 3 floats represents X, Y, Z region axis in meters.

float time = 10.0; // Time for auto close. Set to zero to disable.

//////////////////////////////////////////////////////////////////

integer t;

integer open;

vector pos;

Door() {
    vector targ;
    if ( !open ) {
        targ = ( pos + target );
        llSetTimerEvent( time );
    } else {
        llSetTimerEvent( 0.0 );
        targ = ( pos );
    }
    open = ( !open );
    t = llTarget( targ, 0.04 );
    llMoveToTarget( targ, 0.75 );
    llSetStatus( STATUS_PHYSICS | STATUS_PHANTOM, TRUE);
}

default {
    on_rez( integer param ) {
        llResetScript();
    }
    state_entry() {
        llSetStatus( STATUS_BLOCK_GRAB, TRUE );
        llSetStatus( STATUS_PHYSICS |
                     STATUS_ROTATE_X |
                     STATUS_ROTATE_Y |
                     STATUS_ROTATE_Z |
                     STATUS_PHANTOM, FALSE );
        pos = llGetPos();
    }
    touch_start( integer nd ) {
        Door();
    }
    at_target( integer num, vector tpos, vector opos ) {
        llTargetRemove( t );
        llSetStatus( STATUS_PHYSICS | STATUS_PHANTOM, FALSE );
        llSetPos( tpos );
    }
    timer() {
        llSetTimerEvent( 0.0 );
        Door();
    }
}

Link-Set Texture Configuration

For example - We have a piece of furniture with 5 frame prims and 4 cushion prims.

  • You want the frame to have 4 texture options -
    • Dark Wood
    • Light Wood
    • Aluminium
    • Shiny Black
  • And the cushions have 4 texture options -
    • Pink Damasque
    • Green Twill
    • Black Fur
    • Crimson Velour

You want these options to be available to choose from -

  • Dark Wood frame with Crimson Velour cushions.
  • Light Wood frame with Pink Damasque cushions.
  • Aluminium frame with Green Twill cushions.
  • Shiny Black frame with Black Fur cushions.
  • Dark Wood frame with Pink Damasque cushions.
  • Light Wood frame with Green Twill cushions.
  • Aluminium frame with Black Fur cushions.
  • Shiny Black frame with Crimson Velour cushions.
  • Dark Wood frame with Green Twill cushions.
  • Light Wood frame with Black Fur cushions.
  • Aluminium frame with Crimson Velour cushions.
  • Shiny Black frame with Pink Damasque cushions.

Put this script in any prim in the set. If you put it in the root prim, the whole object will become touchable. This may be undesirable. If the script is in any other prim in the set, only that prim will be touchable (unless you have other touch active scripts in the object). The script responds to its owner only. It will reset if the owner changes so that the new owner can control it.

  1. Set the object manually to one of the texturing configurations.
  2. Set your Viewer Preferences > Text Chat > Chat Options > Show Timestamp in Local Chat to OFF (uncheck that option).
  3. Click the prim with this script in it.
  4. A dialog will appear, click the "Config" button.
  5. A load of data will be chatted to you.
  6. Copy from your local chat history all the text between "!!!!!!!!!!----CONFIGURATION START----!!!!!!!!!!" & "!!!!!!!!!!----CONFIGURATION END----!!!!!!!!!!". Don't include those two lines. Since this is local chat (and the script is cleaner without automatic removal) you'll need to check there is no unwanted chat mixed up in the object data chat.
  7. Paste that text into an otherwise clean Notecard (no other text in the card).
  8. Name it. The Notecard name needs to be short enough to be the name of that configuration option when offered on a dialog button.
  9. Set the object manually to another of the texturing configurations.
  10. Repeat these steps until all the configurations (Maximum of 12) are stored to Notecards.

Once all the Notecards are saved and named, drop them all into the same prim contents as the script. That's it. Now when the prim is clicked a dialog will appear offering the options, taking the names for each option from the Notecards the script finds.

  • To add new configurations after adding Notecards to the prim, you'll need to remove the Notecards already in the contents and add them again after creating the new Notecards. In other words, If the prim has any Notecards in it, it will offer the options. If the prim has no Notecards in it, it will offer the "Config" button.
  • The change from one configuration to another can be very slow (depending on the number of prims and the number of faces of each prim etc).
    • This slowness is a trade off. The main advantages are -
      • The script doesn't use a vast amount of memory ("Memory use is bad, M'kay?").
      • There are not loads of scripts. Just one script for the whole object.
      • Dramatically different texturing is as simple to apply as slight changes.
    • This isn't designed for dynamic effect. It is for simply changing decoration. Speed is hardly important when changing the color of an arm chair after all.

All texture parameters are catered for. Every individual face separately.

  • Texture
    • UUID
    • Repeats
    • Offsets
    • Rotations
  • Color
  • Alpha
  • Mapping
    • Default or Planar
  • Shiny
    • High, Medium, Low or None
  • Bump Mapping
    • All the bumpy options are recorded
  • Fullbright
  • Glow

This is early days for this idea (I may possibly rework it sometime) and there are limits. The amount of data that can be stored to a Notecard being one of them. Very large prim-count objects with complex prims (hollowed and path cut boxes having up to 9 faces for example) may create too much data to be stored to one Notecard. Sorry bout that.

// V2 //

SpewConfig( integer nol ) {
    llSetObjectName( "" );
    llOwnerSay( "/me /n!!!!!!!!!!----CONFIGURATION START----!!!!!!!!!!" );
    integer ln = 1;
    do {
        list s = [];
        list p = [];
        integer c = 0;
        integer f = 0;
        integer l = llGetListLength( ( s = llGetLinkPrimitiveParams( ln, [ 17, -1 ] ) ) );
        do {
            llOwnerSay( "/me " + llDumpList2String( [17, ( f++ ) ] + llList2List( s, c, ( c + 3 ) ), "," ) );
            c += 4;
        } while ( c < l );
        
        c = 0;
        f = 0;
        l = llGetListLength( ( s = llGetLinkPrimitiveParams( ln, [ 18, -1 ] ) ) );
        do {
            llOwnerSay( "/me " + llDumpList2String( [ 18, ( f++ ) ] + llList2List( s, c, ( c + 1 ) ), "," ) );
            c += 2;
        } while ( c < l );
        
        c = 0;
        f = 0;
        l = llGetListLength( ( s = llGetLinkPrimitiveParams( ln, [ 19, -1 ] ) ) );
        do {
            p += [ 19, ( f++ ) ] + llList2List( s, c, ( c + 1 ) );
            c += 2;
        } while ( c < l );
        llOwnerSay( "/me " + llDumpList2String( p, "," ) );
        
        p = [];
        c = 0;
        f = 0;
        l = llGetListLength( ( s = llGetLinkPrimitiveParams( ln, [ 20, -1 ] ) ) );
        do {
            p += [ 20, ( f++ ) ] + llList2List( s, c, c );
        } while ( ( ++c ) < l );
        llOwnerSay( "/me " + llDumpList2String( p, "," ) );
        
        p = [];
        c = 0;
        f = 0;
        l = llGetListLength( ( s = llGetLinkPrimitiveParams( ln, [ 22, -1 ] ) ) );
        do {
            p += [ 22, ( f++ ) ] + llList2List( s, c, c );
        } while ( ( ++c ) < l );
        llOwnerSay( "/me " + llDumpList2String( p, "," ) );
        
        p = [];
        c = 0;
        f = 0;
        l = llGetListLength( ( s = llGetLinkPrimitiveParams( ln, [ 25, -1 ] ) ) );
        do {
            p += [ 25, ( f++ ) ] + llList2List( s, c, c );
        } while ( ( ++c ) < l );
        llOwnerSay( "/me " + llDumpList2String( p, "," ) );
        
        llOwnerSay( "/me LINK" );
    } while ( ( ++ln ) <= nol );
    
    llOwnerSay( "/me !!!!!!!!!!----CONFIGURATION END----!!!!!!!!!!\n" );
    llSetObjectName( my_name );
}

list TypeCast( list p ) {
    list P = [];
    list c = [];
    integer int = 0;
    integer count = 0;
    integer length = llGetListLength( p );
    do {
        if ( ( int = ( ( integer )llList2String( ( c = llCSV2List( llList2String( p, count ) ) ), 0 ) ) ) == 17 ) {
            P += [ int, ( ( integer )llList2String( c, 1 ) ),
                        ( ( key )llList2String( c, 2 ) ),
                        ( ( vector )llList2String( c, 3 ) ),
                        ( ( vector )llList2String( c, 4 ) ),
                        ( ( float )llList2String( c, 5 ) )
                 ];
        } else if ( int == 18 ) {
            P += [ int, ( ( integer )llList2String( c, 1 ) ),
                        ( ( vector )llList2String( c, 2 ) ),
                        ( ( float )llList2String( c, 3 ) )
                 ];
        } else {
            integer l = ( llGetListLength( c ) - 1 );
            integer i = -1;
            if ( int == 19 ) {
                do {
                    ++i;
                    P += [ int, ( ( integer )llList2String( c, ( ++i ) ) ),
                                ( ( integer )llList2String( c, ( ++i ) ) ),
                                ( ( integer )llList2String( c, ( ++i ) ) )
                         ];
                } while ( i < l );
            } else if ( ( int == 20 ) | ( int == 22 ) ) {
                do {
                    ++i;
                    P += [ int, ( ( integer )llList2String( c, ( ++i ) ) ),
                                ( ( integer )llList2String( c, ( ++i ) ) )
                         ];
                } while ( i < l );
            } else if ( int == 25 ) {
                do {
                    ++i;
                    P += [ int, ( ( integer )llList2String( c, ( ++i ) ) ),
                                ( ( float )llList2String( c, ( ++i ) ) )
                         ];
                } while ( i < l );
            }
        }
    } while ( ( ++count ) < length );
    return P;
}

key iq;

key owner;

integer lis;

integer link;

integer nclc;

list params = [];

string my_name = "";

integer channel = -4756297; // The channel for dialog coms. Keep it negative and in the millions.

string present = "Default"; // The name of your default configuration NC

default {
    state_entry() {
        owner = llGetOwner();
        my_name = llGetObjectName();
    }
    touch_start( integer nd ) {
        if ( llDetectedKey( 0 ) == owner ) {
            integer inn = llGetInventoryNumber( INVENTORY_NOTECARD );
            if ( inn ) {
                list ncn = [];
                while ( inn ) {
                    ncn += [ llGetInventoryName( INVENTORY_NOTECARD, ( --inn ) ) ];
                }
                llListenRemove( lis );
                lis = llListen( channel, llKey2Name( owner ), owner, "" );
                llDialog( owner, ( "\n\nChoose your texture configuration.\nThe present configuration is - \"" + present + "\"" ), ncn, channel );
                llSetTimerEvent( 60.0 );
            } else { // Could just jump right to it but, this stops accidental activation.
                llListenRemove( lis );
                lis = llListen( channel, llKey2Name( owner ), owner, "Config" );
                llDialog( owner, "\n\nClick \"Config\" when the objects texturing is set.", [ "Config" ], channel );
                llSetTimerEvent( 10.0 );
            }
        }
    }
    timer() {
        llSetTimerEvent( 0.0 );
        llListenRemove( lis );
        llOwnerSay( "The listen has been removed by timer." );
    }
    dataserver( key q, string data ) {
        if ( ( q == iq ) && ( data != EOF ) ) {
            if ( ( data = llStringTrim( data, STRING_TRIM ) ) != "LINK" ) {
                params += [ data ];
            } else {
                llSetLinkPrimitiveParamsFast( ( ++link ), TypeCast( params ) );
                params = [];
            }
            iq = llGetNotecardLine( present, ( ++nclc ) );
        }
    }
    listen( integer chan, string name, key id, string msg ) {
        llSetTimerEvent( 0.0 );
        llListenRemove( lis );
        if ( msg == "Config" ) {
            SpewConfig( llGetObjectPrimCount( llGetKey() ) );
        } else {
            params = [];
            link = 0;
            iq = llGetNotecardLine( ( present = msg ), ( nclc = 0 ) );
        }
    }
    changed( integer change ) {
        if ( change & ( CHANGED_OWNER | CHANGED_INVENTORY ) ) {
            llResetScript();
        }
    }
}

Zippadeedoodah (Teleporter)

These are those "sit & go" type prim based teleporters that you might use to get from the ground to a skybox (or similar).

When you sit on the object the operation happens automatically.
  • Reaching the destination target is not guaranteed. See llSetRegionPos for details.

Temp Rez Version

This version is a one way, self deleting type e.g. a sign, when touched, rezzes a teleporter seat which takes them directly to areas of a region/parcel. Since the sign could be just 1 prim providing multiple destinations and each rezzed teleporter is both temporary and phantom the savings on both prim count and server stress are obvious.

Sign Board
  • Add textures to the faces (multiple faces is fine and each may show a different selection of destinations) of the prim you want to use as the sign, that shows all of the buttons to click in order to rez a seat to that destination.
  • The script will chat instructions to you about how to set it up. It's easy :-)
  • If you add or remove destination seats after the set up, you'll need to set it up again, but once done, the script remembers everything, even if you take a re-rez it.
  • Since the seats have all the information they need about their job, the sign can be moved without affecting the results.

Annotations will come later.

// V1 //

vector seat_rez_position = <0.0, 0.0, 0.0>; // You may want to play with these.

//////////////////////////////////////////////////////////////////////////////

list making_boxes;
list destinations;
list destination_buttons;

integer destindex;
integer number_of_dests;

integer mapDestinations() {
    integer noo = llGetInventoryNumber( INVENTORY_OBJECT );
    string dest;
    while ( noo ) {
        dest = llGetInventoryName( INVENTORY_OBJECT, --noo );
        if ( ( vector )( "<" + dest + ">" ) ) {
            if ( !~llListFindList( destinations, [ dest ] ) ) {
                destinations += [ dest ];
            }
        }
    }
    return ( number_of_dests = llGetListLength( destinations ) );
}

integer instruct2DefineButton() {
    if ( destindex < number_of_dests ) {
        llOwnerSay( "Define the button for destination: " + llList2String( destinations, destindex++ ) );
        return FALSE;
    }
    return TRUE;
}

resetIfInventoryChanges( integer c ) {
    if ( c & CHANGED_INVENTORY ) {
        llResetScript();
    }
}

default {
    state_entry() {
        if ( mapDestinations() ) {
            llOwnerSay( "For each destination, touch the sign at 2 diagonally opposing corners of an imagined box around the area of the sign that shows the \"button\" to click to go there." );
            instruct2DefineButton();
        }
    }
    changed( integer change ) {
        resetIfInventoryChanges( change );
    }
    touch_start( integer nd ) {
        while ( nd ) {
            if ( llDetectedKey( --nd ) == llGetOwner() ) {
                if ( llGetListLength( destination_buttons ) < llGetListLength( destinations ) ) {
                    vector UV = llDetectedTouchUV( nd );
                    if ( llGetListLength( making_boxes ) ) {
                        making_boxes += [ UV.x, UV.y ];
                        making_boxes = llListSort( [ llList2Float( making_boxes, 0 ), llList2Float( making_boxes, 2 ) ], 1, TRUE ) +
                                       llListSort( [ llList2Float( making_boxes, 1 ), llList2Float( making_boxes, 3 ) ], 1, TRUE );
                        destination_buttons += [ llList2CSV( [ llDetectedTouchFace( nd ) ] + making_boxes ) ];
                        making_boxes = [];
                        if ( instruct2DefineButton() ) {
                            llOwnerSay( "Setup complete." );
                            state ready;
                        }
                    } else {
                        making_boxes = [ UV.x, UV.y ];
                    }
                }
            }
        }
    }
}

state ready {
    touch_start( integer nd ) {
        while ( nd ) {
            vector UV = llDetectedTouchUV( --nd );
            integer count = number_of_dests;
            string destseat = "";
            list button = [];
            while ( destseat == "" && count ) {
                button = llCSV2List( llList2String( destination_buttons, --count ) );
                if ( llList2Integer( button, 0 ) == llDetectedTouchFace( nd ) ) {
                    if ( UV.x >= llList2Float( button, 1 ) && UV.x <= llList2Float( button, 2 ) ) {
                        if ( UV.y >= llList2Float( button, 3 ) && UV.y <= llList2Float( button, 4 ) ) {
                            destseat = llList2String( destinations, count );
                            llRezObject( destseat, llDetectedTouchPos( nd ), seat_rez_position, llGetLocalRot(), 0 );
                        }
                    }
                }
            }
        }
    }
    changed( integer change ) {
        resetIfInventoryChanges( change );
    }
}
Teleporter Seats
  • Add the destination as a comma separated string of three numbers to the name of the prim the script is in (ideally the root).
  • e.g. 36.025, 128, 4000.5
  • The numbers represent the X, Y and Z coordinates of the destination on the region the scripted object is on.
// V9 //

// These two variables can be used to set the position and rotation of the seat's sit target.
// Although the avatar won't be seated for long enough for this to matter much,
// how the avatar is dismounted may be affected.
vector sit_position = <0.0, 0.0, 0.1>; // Must not be zero
rotation sit_rotation = ZERO_ROTATION;

/////////////////////////////////////////////////////////////////////////////////////////////

integer zippadeeDoodah( vector dest ) {
    if ( llSetRegionPos( dest ) ) { // Transport us as close as possible and, if that worked
        llSetLinkPrimitiveParamsFast( !!llGetLinkNumber(), [ PRIM_POSITION, dest ] ); // make sure we're exactly on target.
        return TRUE; // Return true if everything worked and
    }
    return FALSE; // return false if it didn't.
}

vector string2Vector( string str ) {
    return ( vector )( "<" + str + ">" ); // create a vector from the string and return it.
}

default { // Set up the seat for use.
    on_rez( integer param ) { // On being rezzed:
        llSitTarget( sit_position, sit_rotation ); // Make space to sit on even an uncomfortable object.
        llSetClickAction( CLICK_ACTION_SIT ); // Make the prim click-to-sit-able.
        llSetLinkPrimitiveParamsFast( !!llGetLinkNumber(), [ PRIM_PHANTOM, TRUE,
                                                             PRIM_TEMP_ON_REZ, TRUE ] ); // Make the object less intensive for the region.
    }
    changed( integer change ) { // If something about the object has changed, such as the number of links,
        if ( change & CHANGED_LINK && llAvatarOnSitTarget() != NULL_KEY ) { // there may be aseated avatar.
            vector dest = string2Vector( llGetObjectName() ); // Establish the destination from the object name,
            if ( dest ) { // and if the destination makes sense:
                if ( zippadeeDoodah( dest ) ) { // Move the seat and the rider to the destination from the object description.
                    state rest_in_peace; // And if that worked, go to a quite place to die.
                }
            } // If we get to this point, we haven't functioned correctly, so message the owner about the problem and
            llInstantMessage( llGetOwner(), "Hi boss. So I was supposed to be doing my job but, something went wrong." +
                                            "\nYou might need to fix something in my clones so they don't fail the same way." +
                                            "\nGoodbye cruel world!" );
            llDie(); // delete the object.
        }
    }
    state_exit() { // On the way out of this state
        key rider = llAvatarOnSitTarget(); // Establish that the rider didn't fall off,
        if ( rider ) { // and if they didn't,
            llUnSit( rider ); // give 'em a push! ;-)
        }
    }
}

state rest_in_peace {
    state_entry() { // On entering the state:
        llDie(); // Delete the object.
    }
}

Permanent Version

This version drops the user off at the destination then goes straight back home to be reused.

  • Add the home position as a comma separated string of three numbers to the name of the prim the script is in (ideally the root).
  • Add the destination as a comma separated string of three numbers to the description.
  • e.g. 36.025, 128, 4000.5
  • The numbers represent the X, Y and Z coordinates of the destinations on the region the scripted object is on.
// V13 //

// These two variables can be used to set the position and rotation of the seat's sit target.
// Although the avatar won't be seated for long enough for this to matter much,
// how the avatar is dismounted may be affected.
vector sit_position = <0.0, 0.0, 0.1>; // Must not be zero
rotation sit_rotation = ZERO_ROTATION;

//////////////////////////////////////////////////////////

integer zippadeeDoodah( vector dest ) {
    if ( llSetRegionPos( dest ) ) { // Transport us as close as possible and, if that worked
        llSetLinkPrimitiveParamsFast( !!llGetLinkNumber(), [ PRIM_POSITION, dest ] ); // make sure we're exactly on target.
        return TRUE; // Return true if everything worked and
    }
    return FALSE; // return false if it didn't.
}

vector string2Vector( string str ) {
    return ( vector )( "<" + str + ">" ); // create a vector from the string and return it.
}

default { // Set up the seat for use.
    state_entry() { // On entering the state:
        llSitTarget( sit_position, sit_rotation ); // Make space to sit on even an uncomfortable object.
        llSetClickAction( CLICK_ACTION_SIT ); // Make the prim click-to-sit-able.
        llSetLinkPrimitiveParamsFast( !!llGetLinkNumber(), [ PRIM_PHANTOM, TRUE ] ); // Make the object less intensive for the region.
        state coiled_spring; // With the seat set up, go to a state with a changed event.
    }
}

state coiled_spring { // Be prepared for riders.
    changed( integer change ) { // If something about the object has changed, such as the number of links,
        if ( change & CHANGED_LINK && llAvatarOnSitTarget() != NULL_KEY ) { // there may be aseated avatar.
            vector dest = string2Vector( llGetObjectDesc() ); // Establish the destination from the object description,
            if ( dest ) { // and if the destination makes sense:
                if ( zippadeeDoodah( dest ) ) { // Move the seat and the rider to the destination from the object description.
                    state recoil; // And if that worked, go to a state with no changed event.
                }
            } // If we get to this point, we haven't functioned correctly, so
            state cannot_function; // deactivate and call for help.
        }
    }
    state_exit() { // On the way out of this state
        key rider = llAvatarOnSitTarget(); // Establish that the rider didn't fall off,
        if ( rider ) { // and if they didn't,
            llUnSit( rider ); // give 'em a push! ;-)
        }
    }
}

state recoil {
    state_entry() { // On entering the state:
        vector home = string2Vector( llGetObjectName() ); // Establish the way home from the object name,
        if ( home ) { // and if it makes sense:
            if ( zippadeeDoodah( home ) ) { // Send the seat back to it's home and
                state coiled_spring; // if that worked, go back to being prepared for riders.
            }
        } // If we get to this point, we haven't functioned correctly, so
        state cannot_function; // deactivate and call for help.
    }
}

state cannot_function {
    state_entry() { // On entering the state:
        llSetClickAction( CLICK_ACTION_TOUCH ); // Make the prim click-able and message the owner.
        llInstantMessage( llGetOwner(), "Hi boss. So I was supposed to be doing my job but, something went wrong." +
                                        "\nYou'll probably need to reset my script after fixing whatever was wrong with me." +
                                        "\nWhen you've fixed the problem, just click me to reset my script." );
    }
    touch_end( integer nd ) {
        while ( nd ) { // For each detected touch
            if ( llDetectedKey( --nd ) == llGetOwner() ) { // check if the toucher is the owner
                llResetScript(); // and if it is, reset the script.
            }
        }
    }
}

More Scripts...

If you have any comments about the content of this page please post them HERE