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

From Second Life Wiki
Jump to: navigation, search
(Grid Status Updater ( V15 ): Even better. I must say, I'm enjoying this.)
(update enzeroizer)
 
(44 intermediate revisions by 2 users not shown)
Line 1: Line 1:
{{LSL Header}}
+
{{User:Fred Gandt/Template|content=
 
+
[[Image:FG_jpg.jpg|thumb|right]]
+
 
+
{{RightToc|right;}}
+
 
+
== My Contributions ==
+
 
+
'''[[User:Fred_Gandt#How_to_Collect_These_Scripts | If unsure about how to use these scripts]]'''
+
 
+
'''I have implemented a V# system to make it more obvious if a script is updated. The V# forms part of the title of each script.'''
+
 
+
'''If you have any comments about the content of this page please post them [[User_talk:Fred_Gandt/Scripts/Continued_1 | HERE]]'''
+
 
+
'''All my scripts are written for compilation as [[Mono|MONO]]'''
+
 
+
=== More Pages ===
+
 
+
'''[[User:Fred_Gandt/Scripts| Free Scripts]]''' (content constantly updating)
+
 
+
'''More Free Scripts''' (this page)
+
 
+
'''[[User:Fred_Gandt/Scripts/Continued_2| Even More Free Scripts]]''' (content constantly updating)
+
 
+
'''[[User:Fred_Gandt/Scripts/Continued_3| Even More More Free Scripts]]''' (content constantly updating)
+
 
+
'''[[User:Fred_Gandt/Scripts/Continued_4| Even More More More Free Scripts]]''' (content constantly updating)
+
 
+
=== Legal Stuff ===
+
 
+
'''[[Project:Contribution Agreement| The legal stuff about contributing to this wiki (worth reading).]]'''
+
 
+
=== PJIRA Issue Tracker ===
+
 
+
'''[http://jira.secondlife.com/secure/IssueNavigator.jspa?reset=true&&reporterSelect=specificuser&reporter=Fred+Gandt&sorter/field=issuekey&sorter/order=DESC The issues I have filed on the PJIRA]'''
+
 
+
== Tuition ==
+
 
+
'''[[User:Fred_Gandt/Tuition| Tuition scripts, notes, videos and screenshots etc.]]''' (hardly any content yet)
+
  
 
== Free Scripts ==
 
== Free Scripts ==
 +
=== L$ Gift Giver ===
 +
'''TAKE CARE WITH THIS ONE. IT WILL DEDUCT L$ FROM YOUR ACCOUNT ONCE YOU GRANT PERMISSIONS.'''
  
=== Limited Use L$ Gift Giver ( V1 ) ===
+
The script will give a gift of the stated amount of L$ to whoever touches the object it is in. The money will be deducted from the object owner's account. Only one gift will be given to each agent and only if the total amount given since the last time permissions were granted has not been maxed. Once the amount given is equal to the total stated, the script will enter a quiet state and wait to be reset.
  
'''TAKE CARE WITH THIS ONE. IT WILL DEDUCT L$ FROM YOUR ACCOUNT ONCE YOU GRANT PERMISSIONS'''
+
<syntaxhighlight lang="lsl2">// V2 //
  
'''I WAS ASKED TO MAKE IT THIS WAY. IT WAS DESIGNED TO BE REZZED FOR SHORT PERIODS OF TIME'''
+
integer total = 100; // Total amount the script is allowed to give away.
  
'''IF TOO MANY AGENTS USE IT THE MEMORY WILL RUN OUT AND IT WILL FAIL'''
+
integer gift = 1; // Amount to give per gift.
  
<lsl>// V1 //
+
/////////////////////////////////////////////
  
key owner; // Global variable to store the owner UUID (key)
+
key owner; // Used to store the owners UUID.
  
integer perms; // Global to store the condition of the request for permissions.
+
integer perms; // Used to store if permissions were granted.
  
integer count; // Global counter.
+
integer given; // Used to count the total amount given.
  
list visitors; // This stores the keys of all the agents who take the gift. They will be allowed only one gift.
+
list agents = []; // Used to store the UUIDs of the agents who have had a gift.
 
+
integer ammount = 1; // Change this figure to the required ammount to give away (e.g. 5). Then drop in your object.
+
  
 
default
 
default
Line 84: Line 46:
 
         llRequestPermissions(owner, PERMISSION_DEBIT); // If not we ask for them again.
 
         llRequestPermissions(owner, PERMISSION_DEBIT); // If not we ask for them again.
 
     }
 
     }
     touch_end(integer nd)
+
     touch_start(integer nd)
 
     {
 
     {
         do // Loop through the detected touchers to cover the rare cases when
+
         while(nd && (given < total) && perms) // Have we got permissions? Have we given less than the total allowed?
         { // more than one agent touches the object at the same time.
+
         {
             key toucher = llDetectedKey(count);
+
             key agent = llDetectedKey(--nd); // grab the UUID of the touching agent.
             if(llListFindList(visitors, [toucher]) == -1) // Check if the agent has touched us before by searching the list for a match.
+
             if(llListFindList(agents, [agent]) == -1) // Have we already given a gift to this agent?
 
             {
 
             {
                 if(perms) // Check if we have permissions.
+
                 agents += [agent]; // Add the agent to the list.
                 {
+
                 llGiveMoney(agent, gift); // Give the gift to the agent who touched us.
                    llGiveMoney(toucher, ammount); // Ker-ching!!
+
                if((given += gift) == total) // Increment the amount given by the amount just given and check if we have maxxed out yet.
                    visitors += [toucher]; // That's all buster! NEXT!!
+
                 state maxxed_out; // If maxxed out, go to a state with no touch_ event so we are not repeatedly messaged.
                 }
+
 
             }
 
             }
 
         }
 
         }
        while((++count) < nd); // Increment the counter and loop while it is less than the number of touchers detected.
 
        count = 0; // Reset the counter.
 
 
     }
 
     }
}</lsl>
+
}
 +
state maxxed_out
 +
{
 +
    state_entry()
 +
    {
 +
        llInstantMessage(owner, "The total amount this object can give away has been given." + // Contact the owner.
 +
                                "\nTo allow more to be given the script must be reset.");
 +
    }
 +
}</syntaxhighlight>
  
=== Linked Multi-Prim Drawers (2 scripts) ( V4 ) ===
+
=== Linked Multi-Prim Drawers ===
 
+
Could also be used for doors etc.
'''NOW RECORDS ROTATIONS AS WELL.'''
+
 
+
'''Could also be used for doors etc.'''
+
  
 
==== Instructions (Copy to NC or Script) ====
 
==== Instructions (Copy to NC or Script) ====
 
+
<pre>// V4 //
<lsl>// V4 //
+
  
 
// INSTRUCTIONS FOR USE (there are two scripts that make up the set)
 
// INSTRUCTIONS FOR USE (there are two scripts that make up the set)
Line 131: Line 94:
 
// Drop both the scripts (at the same time or "Linkypooz" first) into the root of the object.
 
// Drop both the scripts (at the same time or "Linkypooz" first) into the root of the object.
  
// You will get further instructions in local chat. Follow them.</lsl>
+
// You will get further instructions in local chat. Follow them.</pre>
  
 
==== Drawer Script ====
 
==== Drawer Script ====
 
+
<syntaxhighlight lang="lsl2">// V4 //
<lsl>// V4 //
+
  
 
// This script needs to be named "Linkypooz".
 
// This script needs to be named "Linkypooz".
Line 206: Line 168:
 
         Drawer();
 
         Drawer();
 
     }
 
     }
}</lsl>
+
}</syntaxhighlight>
  
 
==== Script Delivery Script ====
 
==== Script Delivery Script ====
 
+
<syntaxhighlight lang="lsl2">// V4 //
<lsl>// V4 //
+
  
 
default
 
default
Line 240: Line 201:
 
         llRemoveInventory(llGetScriptName());
 
         llRemoveInventory(llGetScriptName());
 
     }
 
     }
}</lsl>
+
}</syntaxhighlight>
 
+
=== Auto Set Group Joiner ( V1 ) ===
+
  
<lsl>// V1 //
+
=== Auto Set Group Joiner ===
 +
<syntaxhighlight lang="lsl2">// V2 //
  
 
key group_key;
 
key group_key;
Line 255: Line 215:
 
     else
 
     else
 
     {
 
     {
         llSay(0, "Since you are not wearing a group tag I am not set to any group.
+
         llSay(0, "\nSince you are not wearing a group tag I am not set to any group." +
        \nWear a group tag and try again.
+
                "\nWear a group tag and try again." +
        \nThis script will self delete.");
+
                "\nThis script will self delete.");
 
         llRemoveInventory(llGetScriptName());
 
         llRemoveInventory(llGetScriptName());
 
     }
 
     }
Line 290: Line 250:
 
         else
 
         else
 
         {
 
         {
 +
            llOwnerSay("HTTP Request failed. Trying again in 60 seconds. Please wait.");
 +
            llSleep(60.0);
 
             llHTTPRequest("http://world.secondlife.com/group/" + ((string)group_key), [], "");
 
             llHTTPRequest("http://world.secondlife.com/group/" + ((string)group_key), [], "");
 
         }
 
         }
Line 297: Line 259:
 
         llSay(0, "/me by clicking this link\nsecondlife:///app/group/" + ((string)group_key) + "/about");
 
         llSay(0, "/me by clicking this link\nsecondlife:///app/group/" + ((string)group_key) + "/about");
 
     }
 
     }
}</lsl>
+
}</syntaxhighlight>
  
=== Percentage Paying (optional) Tip Jar ( V1 ) ===
+
=== Percentage Paying (optional) Tip Jar ===
 +
Pays the percentage (if chosen) to the founder of the group you set the object to.
  
'''Pays the percentage (if chosen) to the founder of the group you set the object to.'''
+
'''UNDER CERTAIN CONDITIONS (That you set and agree to) THIS SCRIPT WILL TAKE MONEY FROM YOUR ACCOUNT.'''
 
+
'''UNDER CERTAIN CONDITIONS (That you set and agree to) THIS SCRIPT WILL TAKE MONEY FROM YOUR ACCOUNT'''
+
 
+
<lsl>// V1 //
+
  
 +
<syntaxhighlight lang="lsl2">// V2 //
 +
 
key owner;
 
key owner;
 
+
 
integer debit_perms = FALSE;
 
integer debit_perms = FALSE;
 
+
 
integer pay_price = 0;
 
integer pay_price = 0;
 
+
 
list pay_buttons = [20, 50, 100, 250];
 
list pay_buttons = [20, 50, 100, 250];
 
+
 
integer percentage = 50; // Percentage to pay to the founder of the group the object is set to.
 
integer percentage = 50; // Percentage to pay to the founder of the group the object is set to.
 
+
 
key beneficiary;
 
key beneficiary;
 
+
 
string default_message = "/me is very grateful for the generous contribution from ";
 
string default_message = "/me is very grateful for the generous contribution from ";
 
+
 
string beneficiary_message = "% of which has been paid to the founder of ";
 
string beneficiary_message = "% of which has been paid to the founder of ";
 
+
 
key group_key;
 
key group_key;
 
+
 
string group_name;
 
string group_name;
 
+
Function()
+
{
+
    owner = llGetOwner();
+
    string owner_name = llKey2Name(owner);
+
    string object_name = (owner_name + "'s Money Box");
+
    llSetObjectName(object_name);
+
    llSetPayPrice(pay_price, pay_buttons);
+
    if(percentage)
+
    llRequestPermissions(owner, PERMISSION_DEBIT);
+
}
+
 
+
 
default
 
default
 
{
 
{
     on_rez(integer param)
+
     on_rez(integer param) {
    {
+
         llResetScript();
         Function();
+
 
     }
 
     }
     state_entry()
+
     state_entry() {
    {
+
         owner = llGetOwner();
         Function();
+
        llSetObjectName(llKey2Name(owner) + "'s Money Box");
 +
        llSetPayPrice(pay_price, pay_buttons);
 +
        if (percentage) {
 +
            llRequestPermissions(owner, PERMISSION_DEBIT);
 +
        }
 
     }
 
     }
     run_time_permissions(integer perms)
+
     run_time_permissions(integer perms) {
    {
+
         if (perms & PERMISSION_DEBIT) {
         if(perms & PERMISSION_DEBIT)
+
        {
+
 
             debit_perms = TRUE;
 
             debit_perms = TRUE;
 
             group_key = llList2Key(llGetObjectDetails(llGetKey(), [OBJECT_GROUP]), 0);
 
             group_key = llList2Key(llGetObjectDetails(llGetKey(), [OBJECT_GROUP]), 0);
             if(group_key != NULL_KEY)
+
             if (group_key != NULL_KEY) {
            llHTTPRequest("http://world.secondlife.com/group/" + ((string)group_key), [], "");
+
                llHTTPRequest("http://world.secondlife.com/group/" + ((string)group_key), [], "");
 +
            }
 +
        } else {
 +
            llOwnerSay("Permissions must be granted for this script to function.");
 +
            llRequestPermissions(owner, PERMISSION_DEBIT);
 
         }
 
         }
        else
 
        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)
+
        {
+
 
             integer name_start = (llSubStringIndex(body, "<title>") + 7);
 
             integer name_start = (llSubStringIndex(body, "<title>") + 7);
 
             integer name_end = (llSubStringIndex(body, "</title>") - 1);
 
             integer name_end = (llSubStringIndex(body, "</title>") - 1);
Line 370: Line 321:
 
             beneficiary = llGetSubString(body, founder_key_start, founder_key_end);
 
             beneficiary = llGetSubString(body, founder_key_start, founder_key_end);
 
             group_name = llGetSubString(body, name_start, name_end);
 
             group_name = llGetSubString(body, name_start, name_end);
         }
+
         } else if (status != 404) {
        else
+
            llOwnerSay("There is a problem O.o");
        {
+
            llSleep(10.0);
 
             llHTTPRequest("http://world.secondlife.com/group/" + ((string)group_key), [], "");
 
             llHTTPRequest("http://world.secondlife.com/group/" + ((string)group_key), [], "");
 +
        } else {
 +
            llOwnerSay("Catastrophic failure! Run for you life!!");
 
         }
 
         }
 
     }
 
     }
Line 381: Line 334:
 
         integer dividend;
 
         integer dividend;
 
         string payer = llKey2Name(id);
 
         string payer = llKey2Name(id);
         if(!percentage)
+
         if (!percentage) {
        {
+
 
             message = (default_message + payer);
 
             message = (default_message + payer);
         }
+
         } else {
        else
+
             dividend = llFloor((((float)amount)/100.0) * ((float)percentage));
        {
+
             if (dividend) {
             dividend = llFloor((((float)amount)/100.0) * ((float)percentage)); // I'm very tired and my eyes are sticky!
+
                 if (debit_perms) {
             if(dividend)
+
            {
+
                 if(debit_perms)
+
                {
+
 
                     message = (default_message + payer + ".\n" + ((string)percentage) + beneficiary_message + group_name);
 
                     message = (default_message + payer + ".\n" + ((string)percentage) + beneficiary_message + group_name);
 
                     llGiveMoney(beneficiary, dividend);
 
                     llGiveMoney(beneficiary, dividend);
                 }
+
                 } else {
                else
+
                {
+
 
                     message = (default_message + payer);
 
                     message = (default_message + payer);
 
                 }
 
                 }
Line 402: Line 348:
 
         }
 
         }
 
         llSay(PUBLIC_CHANNEL, message);
 
         llSay(PUBLIC_CHANNEL, message);
 +
        // OR llInstantMessage(id, message);
 
     }
 
     }
}</lsl>
+
}</syntaxhighlight>
  
=== Grid Status Updater ( V16 ) ===
+
=== Grid Status Updater ===
 +
{{note|Since [[Release_Notes/Second_Life_Release/5.0.4.324646|LL Viewer v5.0.4.324646]] ''"you can now add a Grid Status button to your screen from the Toolbox (Me -> Toolbar)"'' which utilizes and connects you to [http://secondlife-status.statuspage.io/ secondlife-status.statuspage.io].
 +
* If the button is added:
 +
** The button will turn orange when a status update is added, alerting you to current and/or pending issues.
 +
** If clicked, your browser will open to show various details about the grid status in chronologically descending order (newest at the top).
 +
This built in viewer functionality is long overdue, welcome and far better for you and everyone around you than the use of this script.}}
 +
{{note|The format of the source of the Grid Status has changed many times since the creation of this script, and there's therefore every reason to assume it may change again. Should this happen, the output of this script may be malformed. I endeavour to keep up to date with the changes, but should really rebuild this script to parse whatever is thrown at it; don't hold your breath!
 +
* However, due to the changes mentioned in the note above, this script may no longer be of any practical use (except example).}}
 +
Checks the Second Life Grid Status every five minutes to see if there are any new issues. If there are it will IM you.
  
'''Checks the Second Life Grid Status every ten minutes to see if there are any new issues. If there are it will IM you.'''
+
Drop this script onto any prim that is currently not expected to do something else (e.g. a wall or floor etc) and let it run. If it is in an attachment it will work fine but, only while you are logged in. The script will maintain the name of the prim (or object if in a root) but when sending an update will use a special name set by you. This is simply more aesthetically pleasing. Getting an update from "Ceiling Fan" can seem a little odd.
  
'''Drop this script onto any prim that is currently not expected to do something else (e.g. a wall or floor etc) and let it run. If it is in an attachment it will work fine but, only while you are logged in. The script will maintain the name of the prim (or object if in a root) but when sending an update will use a special name set by you. This is simply more aesthetically pleasing. Getting an update from "Ceiling Fan" can seem a little odd.'''
+
<syntaxhighlight lang="lsl2">// V25 //
 
+
<lsl>// V16 //
+
 
+
string feed_url = "http://status.secondlifegrid.net/feed/"; // From where we draw our updates.
+
  
 +
float update_rate = 300.0; // How many second between checking for updates.
 +
 
string alert_name = "Grid Status Update"; // What we call the object while it messages us.
 
string alert_name = "Grid Status Update"; // What we call the object while it messages us.
  
string my_proper_name; // Used to store the memory of the name of the object when dormant.
+
////////////////////////////////////////////////////////////////////////////////////////////////////
 
+
key owner; // Used to store the owners UUID.
+
 
   
 
   
 
string last; // Used to store the last update so we can tell if the latest is new.
 
string last; // Used to store the last update so we can tell if the latest is new.
Line 425: Line 376:
 
key iq; // Used to verify the source of the HTTPRequest.
 
key iq; // Used to verify the source of the HTTPRequest.
  
string MultiReplace(string src, list thisnthats)
+
list timezones = [ 7, "PDT", 8, "PST" ];
{
+
 
 +
list lookup_months = [ "January ",
 +
                      "February ",
 +
                      "March ",
 +
                      "April ",
 +
                      "May ",
 +
                      "June ",
 +
                      "July ",
 +
                      "August ",
 +
                      "September ",
 +
                      "October ",
 +
                      "November ",
 +
                      "December " ];
 +
 
 +
string prettyTimestamp( string ts ) {
 +
    list stamp_parts = llParseString2List( ts, [ "T", "-", ":" ], [] );
 +
    string date =  llList2String( lookup_months, llList2Integer( stamp_parts, 1 ) - 1 ) + llList2String( stamp_parts, 2 ) + ", " + llList2String( stamp_parts, 0 );
 +
    string time = llDumpList2String( llList2List( stamp_parts, 3, 4 ), ":" );
 +
    string tz = llList2String( timezones, llListFindList( timezones, [ llList2Integer( stamp_parts, 6 ) ] ) + 1 );
 +
    return date + " at " + time + " " + tz;
 +
}
 +
 +
list exchange = [
 +
    "&amp;", "&",
 +
    "&nbsp;", " ",
 +
    "&lt;p&gt;", "",
 +
    "&lt;/p&gt;", "",
 +
    "&lt;br&gt;", "",
 +
    "&lt;br /&gt;", "",
 +
    "&lt;small&gt;", "",
 +
    "&lt;/small&gt;", "",
 +
    "&lt;strong&gt;", ": ",
 +
    "&lt;/strong&gt;", "" ]; // Various strings we find in the HTTP response that we may wish to bulk exchange.
 +
 +
string multiStringReplace( string src ) {
 
     integer index = 0;
 
     integer index = 0;
 
     integer lc = 0;
 
     integer lc = 0;
     integer ll = llGetListLength(thisnthats);
+
     integer ll = llGetListLength( exchange );
     do
+
     string this;
     {
+
     do {
         string this = llList2String(thisnthats, lc);
+
         this = llList2String( exchange, lc );
         string that = llList2String(thisnthats, (++lc));
+
         ++lc;
        integer sl = (llStringLength(this) - 1);
+
         while ( ( index = llSubStringIndex( src, this ) ) != -1 ) {
         while((index = llSubStringIndex(src, this)) != -1)
+
            src = llInsertString( llDeleteSubString( src, index, index + ( llStringLength( this ) - 1 ) ), index, llList2String( exchange, lc ) );
        src = llInsertString(llDeleteSubString(src, index, (index + sl)), index, that);
+
        }
    }
+
     } while ( ++lc < ll );
     while((++lc) < ll);
+
 
     return src;
 
     return src;
 
}
 
}
 +
 +
messageOwner( string msg ) {
 +
    string my_proper_name = llGetObjectName();
 +
    llSetObjectName( alert_name );
 +
    llInstantMessage( llGetOwner(), msg );
 +
    llSetObjectName( my_proper_name );
 +
}
 +
 +
checkForUpdates() {
 +
    iq = llHTTPRequest( "http://status.secondlifegrid.net/history.atom", [], "" );
 +
}
 +
 +
default {
 +
    on_rez( integer param ) {
 +
        llResetScript();
 +
    }
 +
    state_entry() {
 +
        llSetTimerEvent( update_rate );
 +
        checkForUpdates();
 +
    }
 +
    timer() {
 +
        checkForUpdates();
 +
    }
 +
    http_response( key q, integer status, list meta, string body ) {
 +
        if ( q == iq ) {
 +
            if ( status == 200 ) {
 +
                body = multiStringReplace( llGetSubString( body, llSubStringIndex( body, "<entry>" ) + 6, -1 ) );
 +
                string latest = llGetSubString( body, llSubStringIndex( body, "<content type=\"html\">" ) + 21,
 +
                                                      llSubStringIndex( body, "</content>" ) - 1 );
 +
                if ( latest != last ) {
 +
                    last = latest;
 +
                    string issue = "ISSUE --> " + llGetSubString( body, llSubStringIndex( body, "<title>" ) + 7,
 +
                                                                        llSubStringIndex( body, "</title>" ) - 1 );
 +
                    string time = "\n\nTIME --> " + prettyTimestamp( llGetSubString( body, llSubStringIndex( body, "<updated>" ) + 9,
 +
                                                                                          llSubStringIndex( body, "</updated>" ) - 1 ) );
 +
                    string more = "\n\nMORE --> " + llGetSubString( body, llSubStringIndex( body, "href=\"" ) + 6,
 +
                                                                          llSubStringIndex( body, "\"/>" ) - 1 );
 +
                    string update = "\n\nLATEST --> " + latest;
 +
                    string all = issue + time + update + more;
 +
                    integer total = llStringLength( all );
 +
                    if ( total > 1000 ) {
 +
                        all = issue + time + llDeleteSubString( update, total - 1000, -1 ) + " ... (cont.)" + more;
 +
                    }
 +
                    messageOwner( all );
 +
                }
 +
            } else {
 +
                messageOwner( "Feed not responding with anything useful.\n" +
 +
                              "Trying again in " + ( string )llRound( update_rate / 60 ) + " minutes." );
 +
            }
 +
        }
 +
    }
 +
}</syntaxhighlight>
 +
 +
=== Simple Texturing Helpers ===
 +
==== Touch Texture Getter ====
 +
Put this script in the root prim of an object and touch whichever face of whichever prim you want the texture UUID of. It will be chatted to you. If you do not have permission to get the UUID you will not get it! A long held touch will delete the script.
 +
 +
<syntaxhighlight lang="lsl2">// V2 //
 +
 +
integer tc;
 +
 +
key owner;
 
   
 
   
 
default
 
default
Line 446: Line 492:
 
     state_entry()
 
     state_entry()
 
     {
 
     {
        my_proper_name = llGetObjectName();
 
 
         owner = llGetOwner();
 
         owner = llGetOwner();
        llSetTimerEvent(600.0);
 
        iq = llHTTPRequest(feed_url, [], "");
 
 
     }
 
     }
     timer()
+
     touch_end(integer nd)
 
     {
 
     {
         iq = llHTTPRequest(feed_url, [], "");
+
         while(nd)
 +
        {
 +
            if(llDetectedKey(--nd) == owner)
 +
            {
 +
                tc = 0;
 +
                llOwnerSay(llList2String(llGetLinkPrimitiveParams(llDetectedLinkNumber(nd), [PRIM_TEXTURE, llDetectedTouchFace(nd)]), 0));
 +
            }
 +
        }
 
     }
 
     }
     http_response(key q, integer status, list meta, string body)
+
     touch(integer nd)
 
     {
 
     {
         if(q == iq)
+
         while(nd)
 
         {
 
         {
             if(status == 200)
+
             if(llDetectedKey(--nd) == owner)
 
             {
 
             {
                 body = llGetSubString(body, (llSubStringIndex(body, "<item>") + 6), -1);
+
                 if((++tc) == 20)
                string latest = llStringTrim(llGetSubString(body, (llSubStringIndex(body, "<description><![CDATA[") + 22),
+
                 llRemoveInventory(llGetScriptName());
                                                                  (llSubStringIndex(body, "]]></description>") - 1)), STRING_TRIM);
+
                if(latest != last)
+
                 {
+
                    last = latest;
+
                    string dnt = llGetSubString(body, (llSubStringIndex(body, "<pubDate>") + 9), (llSubStringIndex(body, "</pubDate>") - 10));
+
                    llSetObjectName(alert_name);
+
                    llInstantMessage(owner, "/me \n\nISSUE --> " + llGetSubString(body, (llSubStringIndex(body, "<title>") + 7),
+
                                                                                        (llSubStringIndex(body, "</title>") - 1)) +
+
                                            "\n\nTIME --> " + llGetSubString(dnt, -5, -1) + ", " + (llGetSubString(dnt, 0, -7) + " (UTC)") +
+
                                            "\n\nLATEST --> " + MultiReplace(latest, [" [...]",    "...",
+
                                                                                      "&#8221;",  "\"",
+
                                                                                      "&#8220;",  "\"",
+
                                                                                      "&#8217;",  "'",
+
                                                                                      "&#62;",    ">",
+
                                                                                      "&#38;",    "&"]) +
+
                                            "\n\nVISIT --> " + llGetSubString(feed_url, 0, -6));
+
                    llSetObjectName(my_proper_name);
+
                }
+
            }
+
            else
+
            {
+
                llSleep(60.0);
+
                iq = llHTTPRequest(feed_url, [], "");
+
 
             }
 
             }
 
         }
 
         }
 
     }
 
     }
}</lsl>
+
}</syntaxhighlight>
 
+
=== Touch Texture Setter ( V2 ) ===
+
  
'''Fill out the UUID for the texture to set. Drop the script in the prim to texture. The texture then sets on each face touched. A long held touch will delete the script.'''
+
==== Touch Texture Setter ====
 
+
Fill out the UUID for the texture to set. Drop the script in the root prim of the object to texture. The texture then sets on each face touched. A long held touch will delete the script.
<lsl>// V2 //
+
 
+
key texture_uuid = "f05755e7-d31c-116d-9cf2-a4840bdfc56b";
+
  
 +
<syntaxhighlight lang="lsl2">// V3 //
 +
 +
key texture_uuid = "f05755e7-d31c-116d-9cf2-a4840bdfc56b"; // Fence texture
 +
 
integer tc;
 
integer tc;
 
+
 
key owner;
 
key owner;
 
+
 
default
 
default
 
{
 
{
Line 516: Line 542:
 
             {
 
             {
 
                 tc = 0;
 
                 tc = 0;
                 llSetTexture(texture_uuid, llDetectedTouchFace(nd));
+
                 llSetLinkTexture(llDetectedLinkNumber(nd), texture_uuid, llDetectedTouchFace(nd));
 
             }
 
             }
 
         }
 
         }
Line 531: Line 557:
 
         }
 
         }
 
     }
 
     }
}</lsl>
+
}</syntaxhighlight>
  
=== Enzeroizer (Rotation Fixer) ( V3 ) ===
+
=== Enzeroizer (Rotation Fixer) ===
 +
Drop this into a single prim or the root of your linked object. It will set the rotations to whatever they were but with the smallest 3 decimal places made {{HoverText|000|ZERO}}.
 +
*E.g. <75.458392, 128,038754, 298.836580> will become <75.458000, 128,038000, 298.836000>.
 +
This will make minor rotational drifts that occur due to one of our favorite bugs less of an issue.
  
'''Drop this into the root of your linked object and it will self seed to all links in a set (object). After re-rezzing the object and setting the scripts running it will set the rotations to whatever they were but with the smallest 3 decimal places made {{HoverText|000|ZERO}}.'''
+
<syntaxhighlight lang="lsl2">// V4 //
*'''E.g. <75.458392, 128,038754, 298.836580> will become <75.458000, 128,038000, 298.836000>.'''
+
'''This will make minor rotational drifts that occur due to one of our favorite bugs less of an issue.'''
+
'''I have done light testing and think it's fine. Make a copy of your object before using this script just in case it goes wrong.'''
+
'''I will post an updated version using [[llGetLinkPrimitiveParams]] & [[llSetLinkPrimitiveParamsFast]] when server 1.38 is rolled out and actually working.'''
+
  
<lsl>// V3 //
+
string enzeroizer( float f ) {
+
     return llGetSubString( ( string )f, 0, -5 ) + ( string )llRound( ( float )llGetSubString( ( string )f, -4, -1 ) / 1000 ) + "000";
SelfSeed() // The function name.
+
}
{
+
     string name = llGetScriptName(); // Store the name of this script to save calling for it over and over.
+
    integer links_in_set = llGetObjectPrimCount(llGetKey()); // Store how many links there are.
+
    integer count = 2; // Establish a counter that will start at the next link in the set.
+
    do // This is the point from which we loop if the while condition is met.
+
    llGiveInventory(llGetLinkKey(count), name); // Deliver a copy of this script to the link number "count".
+
    while((++count) <= links_in_set); // Increment "count" and check if it is still less than or equal to the number of links.
+
} // If "count" is not more than the number of links loop back to "do".
+
  
float Float(float f) // The function name and the float data it carries.
+
rotation enzeroized( rotation rot ) {
{
+
    vector euler = llRot2Euler( rot ) * RAD_TO_DEG;
     return ((float)(llDeleteSubString(((string)f), -3, -1) + "000")); // Typecast the delivered float to a string.
+
     return llEuler2Rot( ( vector )( "<" + llList2CSV( [ enzeroizer( euler.x ),
                                                                      // Chop the last 3 characters off the string and add 3 zeros.
+
                                                        enzeroizer( euler.y ),
                                                                      // Then typecast the result to a float and return it.
+
                                                        enzeroizer( euler.z ) ] ) + ">" ) * DEG_TO_RAD );
 
}
 
}
+
 
Enzeroize() // The function name.
+
resetRotations( integer ln ) {
{
+
     llSetLinkPrimitiveParamsFast( ln, [ PRIM_ROT_LOCAL, enzeroized( llList2Rot( llGetLinkPrimitiveParams( ln, [ PRIM_ROT_LOCAL ] ), 0 ) ) ] );
     vector rot = (llRot2Euler(llGetLocalRot())*RAD_TO_DEG); // Store the local rotation of the prim as a vector.
+
    // Below : Take each of the axes (X, Y & Z) and feed to the "Float()" function then convert the vector to a rotation and set it.
+
    llSetLocalRot(llEuler2Rot(<Float(rot.x), Float(rot.y), Float(rot.z)>*DEG_TO_RAD));
+
 
}
 
}
+
 
default // Create a state.
+
default {
{
+
     state_entry() {
     state_entry() // On entering the state...
+
         integer links = llGetObjectPrimCount( llGetKey() );
    {
+
        if ( links == 1 ) {
         if(llGetLinkNumber() == 1) // ...Check if we are the root of a LINK_SET.
+
             resetRotations( 0 );
        {
+
        } else {
             SelfSeed(); // Call the "SelfSeed()" function.
+
             while ( links ) {
             Enzeroize(); // Call the "Enzeroize()" function.
+
                resetRotations( --links );
            // Below : Issue instructions in chat to the owner of the object.
+
            }
            llOwnerSay("\nTake me to your inventory and re-rez me." +
+
                      "\nThen open an edit on me and goto your \"Tools\" menu." +
+
                      "\nNear the bottom of the menu click \"Set Scripts Running In Selection\"." +
+
                      "\nAll the scripts will self delete after Enzeroizing.");
+
 
         }
 
         }
        else // If not in the root or if not in a LINK_SET...
 
        Enzeroize(); // ...Call the "Enzeroize()" function.
 
        llRemoveInventory(llGetScriptName()); // Whether in the root or not, this script removes itself from the prim.
 
 
     }
 
     }
}</lsl>
+
}</syntaxhighlight>
 
+
=== Pose Stand ( V3 ) ===
+
  
'''Multi type, multi sex, multi story car park? Nope it just does poses.'''
+
=== Pose Stand ===
 +
Multi type, multi sex, multi story car park? Nope it just does poses.
  
'''Create a fresh prim and drop this script on it. You have an instant pose stand. Then fill it with various poses and animations and copy the names of the animations into the lists at the top of the script. As you can see there are categories for 3 sex types and 3 body types. You could change these to suit (e.g. 3 styles (action, silly, erotic)) and 3 other things if you liked.'''
+
Create a fresh prim and drop this script on it. You have an instant pose stand. Then fill it with various poses and animations and copy the names of the animations into the lists at the top of the script. As you can see there are categories for 3 sex types and 3 body types. You could change these to suit (e.g. 3 styles (action, silly, erotic)) and 3 other things if you liked.
  
'''Just put the names in the list that it makes most sense to put it in. As you sit on the stand (maybe these things should be called pose seats) you will be posted a dialog menu asking for "What type" then "What sex" then the list of anims appropriate for those choices. After making the animation choice, to recall the dialog menu click the pose stand.'''
+
Just put the names in the list that it makes most sense to put it in. As you sit on the stand (maybe these things should be called pose seats) you will be posted a dialog menu asking for "What type" then "What sex" then the list of anims appropriate for those choices. After making the animation choice, to recall the dialog menu click the pose stand.
  
'''I kinda rushed to the finish with this one because something else came up. I will probably get back to it sometime but for now it seems to work ok.'''
+
I kinda rushed to the finish with this one because something else came up. I will probably get back to it sometime but for now it seems to work ok.
  
'''ANIMATIONS WITH A BUILT IN OFFSET MAY BE POSITIONED BADLY. THAT'S SOMETHING I NEED TO ADD LATER'''
+
'''ANIMATIONS WITH A BUILT IN OFFSET MAY BE POSITIONED BADLY.'''
  
<lsl>// V3 //
+
<syntaxhighlight lang="lsl2">// V4 //
  
 
///////////////////////////////////////////////////////////////////
 
///////////////////////////////////////////////////////////////////
Line 920: Line 926:
 
                 else
 
                 else
 
                 {
 
                 {
                     string name = llList2String(agent_anim_set, (((integer)msg) - 1));
+
                     string inv_name = llList2String(agent_anim_set, (((integer)msg) - 1));
                     if(llGetInventoryType(name) == INVENTORY_ANIMATION)
+
                     if(llGetInventoryType(inv_name) == INVENTORY_ANIMATION)
 
                     {
 
                     {
 
                         if(playing != "")
 
                         if(playing != "")
 
                         llStopAnimation(playing);
 
                         llStopAnimation(playing);
                         playing = name;
+
                         playing = inv_name;
 
                         if(agent != NULL_KEY)
 
                         if(agent != NULL_KEY)
                         llStartAnimation(name);
+
                         llStartAnimation(inv_name);
 
                     }
 
                     }
 
                     else
 
                     else
 
                     {
 
                     {
 
                         if(agent != NULL_KEY)
 
                         if(agent != NULL_KEY)
                         llInstantMessage(agent, "\"" + name + "\" is missing from the pose stand inventory.");
+
                         llInstantMessage(agent, "\"" + inv_name + "\" is missing from the pose stand inventory.");
 
                     }
 
                     }
 
                 }
 
                 }
Line 947: Line 953:
 
         TypeCast();
 
         TypeCast();
 
     }
 
     }
}</lsl>
+
}</syntaxhighlight>}}
 
+
== More Scripts... ==
+
 
+
'''[[User:Fred_Gandt/Scripts| Free Scripts]]''' (content constantly updating)
+
 
+
'''More Free Scripts''' (this page)
+
 
+
'''[[User:Fred_Gandt/Scripts/Continued_2| Even More Free Scripts]]''' (content constantly updating)
+
 
+
'''[[User:Fred_Gandt/Scripts/Continued_3| Even More More Free Scripts]]''' (content constantly updating)
+
 
+
'''[[User:Fred_Gandt/Scripts/Continued_4| Even More More More Free Scripts]]''' (content constantly updating)
+
 
+
'''If you have any comments about the content of this page please post them [[User_talk:Fred_Gandt/Scripts/Continued_1 | HERE]]'''
+

Latest revision as of 11:23, 28 March 2017

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

L$ Gift Giver

TAKE CARE WITH THIS ONE. IT WILL DEDUCT L$ FROM YOUR ACCOUNT ONCE YOU GRANT PERMISSIONS.

The script will give a gift of the stated amount of L$ to whoever touches the object it is in. The money will be deducted from the object owner's account. Only one gift will be given to each agent and only if the total amount given since the last time permissions were granted has not been maxed. Once the amount given is equal to the total stated, the script will enter a quiet state and wait to be reset.

// V2 //
 
integer total = 100; // Total amount the script is allowed to give away.
 
integer gift = 1; // Amount to give per gift.
 
/////////////////////////////////////////////
 
key owner; // Used to store the owners UUID.
 
integer perms; // Used to store if permissions were granted.
 
integer given; // Used to count the total amount given.
 
list agents = []; // Used to store the UUIDs of the agents who have had a gift.
 
default
{
    on_rez(integer param)
    {
        llResetScript(); // Clear all lists and reset all variables. This action will also clear the permissions.
    }
    changed(integer change)
    {
        if(change & CHANGED_OWNER) // If the script or object changes ownership the script will not be able
        llResetScript();           // to deduct cash from the previous owners account.
    }
    state_entry()
    {
        owner = llGetOwner(); // Store the owners key.
        llRequestPermissions(owner, PERMISSION_DEBIT); // !! THIS MEANS IT WILL TAKE YOUR MONEY !!
    }
    run_time_permissions(integer perm)
    {
        if(perm & PERMISSION_DEBIT) // Have we got the permissions we requested?
        perms = TRUE; // Store the result of success.
        else
        llRequestPermissions(owner, PERMISSION_DEBIT); // If not we ask for them again.
    }
    touch_start(integer nd)
    {
        while(nd && (given < total) && perms) // Have we got permissions? Have we given less than the total allowed?
        {
            key agent = llDetectedKey(--nd); // grab the UUID of the touching agent.
            if(llListFindList(agents, [agent]) == -1) // Have we already given a gift to this agent?
            {
                agents += [agent]; // Add the agent to the list.
                llGiveMoney(agent, gift); // Give the gift to the agent who touched us.
                if((given += gift) == total) // Increment the amount given by the amount just given and check if we have maxxed out yet.
                state maxxed_out; // If maxxed out, go to a state with no touch_ event so we are not repeatedly messaged.
            }
        }
    }
}
state maxxed_out
{
    state_entry()
    {
        llInstantMessage(owner, "The total amount this object can give away has been given." + // Contact the owner.
                                "\nTo allow more to be given the script must be reset.");
    }
}

Linked Multi-Prim Drawers

Could also be used for doors etc.

Instructions (Copy to NC or Script)

// V4 //

// INSTRUCTIONS FOR USE (there are two scripts that make up the set)

// Make your chest of drawers and link the whole set together with the body (any prim that doesn't move) of the chest as the root.

// Name every prim used as a part of a drawer (include handles, drawer fronts, bases etc.) "drawer " plus a number.

// All the prims of one drawer should now all be named the same. e.g. "drawer 1".

// Name every drawer a different number. e.g. "drawer 1", "drawer 2" etc.

// With all the parts named correctly, edit the object so that all the drawers are closed.

// At this point you might want to take a copy.

// Be sure that no prims are named "drawer (something)" unless they are supposed to be (according to the above).

// Drop both the scripts (at the same time or "Linkypooz" first) into the root of the object.

// You will get further instructions in local chat. Follow them.

Drawer Script

// V4 //
 
// This script needs to be named "Linkypooz".
 
vector open_pos;
 
vector closed_pos;
 
rotation open_rot;
 
rotation closed_rot;
 
integer OPEN;
 
key owner;
 
integer my_response_num;
 
integer my_link_num;
 
Drawer()
{
    if(OPEN)
    llSetPrimitiveParams([PRIM_POSITION, closed_pos, PRIM_ROTATION, (closed_rot / llGetRootRotation())]);
    else
    llSetPrimitiveParams([PRIM_POSITION, open_pos, PRIM_ROTATION, (open_rot / llGetRootRotation())]);
    OPEN = (!OPEN);
}
 
default
{
    state_entry()
    {
        owner = llGetOwner();
        closed_pos = llGetLocalPos();
        closed_rot = llGetLocalRot();
        my_link_num = llGetLinkNumber();
        my_response_num = ((integer)llGetSubString(llGetLinkName(my_link_num), 7, -1));
    }
    touch_start(integer nd)
    {
        if(llDetectedKey(0) == owner)
        {
            if(my_link_num != 1)
            {
                open_pos = llGetLocalPos();
                open_rot = llGetLocalRot();
                llSetLocalRot(closed_rot);
                llSetPos(closed_pos);
                state normal;
            }
            else
            llRemoveInventory(llGetScriptName());
        }
    }
}
state normal
{
    state_entry()
    {
        llOwnerSay("/me is active!");
    }
    touch_start(integer nd)
    {
        llMessageLinked(LINK_SET, my_response_num, "", "");
    }
    link_message(integer sender, integer num, string str, key id)
    {
        if(num == my_response_num)
        Drawer();
    }
}

Script Delivery Script

// V4 //
 
default
{
    state_entry()
    {
        integer count;
        integer links = llGetNumberOfPrims();
        do
        {
            string name = llGetLinkName(count);
            if(llGetSubString(name, 0, 5) == "drawer")
            {
                key link_key = llGetLinkKey(count);
                llGiveInventory(link_key, "Linkypooz"); // This is why the other script needs to be called "Linkypooz"
            }                                           // You can change it if you like.
        }
        while((++count) < (links + 1));
        llOwnerSay("\n\nNow take the object to inventory and re-rez.
        \n\nOpen an edit on the object.
        \n\nGo to the tools menu and, at the bottom of the menu click \"Set Scripts Running in Selection\".
        \n\nEdit all the prims of the drawers from the closed position/rotation to the open position/rotation.
        \n\nWhen all the prims of the drawers are set open (you can do one prim at a time or all together, which ever you prefer), touch each prim.
        \n\nWhen the prim is touched it will automatically close.
        \n\nWhen all the prims of all the drawers are in the closed position/rotation the scripts are fully set up.
        \n\nThey will chat that they are active when ready.
        \n\nNow touch the root and the script in it will self delete.
        \n\nThat's all!!");
        llRemoveInventory(llGetScriptName());
    }
}

Auto Set Group Joiner

// V2 //
 
key group_key;
 
Function()
{
    group_key = llList2Key(llGetObjectDetails(llGetKey(), [OBJECT_GROUP]), 0);
    if(group_key != NULL_KEY)
    llHTTPRequest("http://world.secondlife.com/group/" + ((string)group_key), [], "");
    else
    {
        llSay(0, "\nSince you are not wearing a group tag I am not set to any group." +
                 "\nWear a group tag and try again." +
                 "\nThis script will self delete.");
        llRemoveInventory(llGetScriptName());
    }
}
 
default
{
    state_entry()
    {
        Function();
    }
    on_rez(integer param)
    {
        Function();
    }
    http_response(key q, integer status, list metadata, string body)
    {
        if(status == 200)
        {
            integer name_start = (llSubStringIndex(body, "<title>") + 7);
            integer name_end = (llSubStringIndex(body, "</title>") - 1);
            integer tex_key_start = (llSubStringIndex(body, "imageid") + 18);
            integer tex_key_end = (tex_key_start + 35);
            string group_name = llGetSubString(body, name_start, name_end);
            llSetObjectName("Join " + group_name);
            key group_tex = llGetSubString(body, tex_key_start, tex_key_end);
            if(group_tex != NULL_KEY)
            llSetTexture(group_tex, ALL_SIDES);
            else
            llSetTexture(TEXTURE_BLANK, ALL_SIDES);
        }
        else
        {
            llOwnerSay("HTTP Request failed. Trying again in 60 seconds. Please wait.");
            llSleep(60.0);
            llHTTPRequest("http://world.secondlife.com/group/" + ((string)group_key), [], "");
        }
    }
    touch_start(integer nd)
    {
        llSay(0, "/me by clicking this link\nsecondlife:///app/group/" + ((string)group_key) + "/about");
    }
}

Percentage Paying (optional) Tip Jar

Pays the percentage (if chosen) to the founder of the group you set the object to.

UNDER CERTAIN CONDITIONS (That you set and agree to) THIS SCRIPT WILL TAKE MONEY FROM YOUR ACCOUNT.

// V2 //
 
key owner;
 
integer debit_perms = FALSE;
 
integer pay_price = 0;
 
list pay_buttons = [20, 50, 100, 250];
 
integer percentage = 50; // Percentage to pay to the founder of the group the object is set to.
 
key beneficiary;
 
string default_message = "/me is very grateful for the generous contribution from ";
 
string beneficiary_message = "% of which has been paid to the founder of ";
 
key group_key;
 
string group_name;
 
default
{
    on_rez(integer param) {
        llResetScript();
    }
    state_entry() {
        owner = llGetOwner();
        llSetObjectName(llKey2Name(owner) + "'s Money Box");
        llSetPayPrice(pay_price, pay_buttons);
        if (percentage) {
            llRequestPermissions(owner, PERMISSION_DEBIT);
        }
    }
    run_time_permissions(integer perms) {
        if (perms & PERMISSION_DEBIT) {
            debit_perms = TRUE;
            group_key = llList2Key(llGetObjectDetails(llGetKey(), [OBJECT_GROUP]), 0);
            if (group_key != NULL_KEY) {
                llHTTPRequest("http://world.secondlife.com/group/" + ((string)group_key), [], "");
            }
        } else {
            llOwnerSay("Permissions must be granted for this script to function.");
            llRequestPermissions(owner, PERMISSION_DEBIT);
        }
    }
    http_response(key q, integer status, list metadata, string body) {
        if(status == 200) {
            integer name_start = (llSubStringIndex(body, "<title>") + 7);
            integer name_end = (llSubStringIndex(body, "</title>") - 1);
            integer founder_key_start = (llSubStringIndex(body, "founderid") + 20);
            integer founder_key_end = (founder_key_start + 35);
            beneficiary = llGetSubString(body, founder_key_start, founder_key_end);
            group_name = llGetSubString(body, name_start, name_end);
        } else if (status != 404) {
            llOwnerSay("There is a problem O.o");
            llSleep(10.0);
            llHTTPRequest("http://world.secondlife.com/group/" + ((string)group_key), [], "");
        } else {
            llOwnerSay("Catastrophic failure! Run for you life!!");
        }
    }
    money(key id, integer amount)
    {
        string message = "";
        integer dividend;
        string payer = llKey2Name(id);
        if (!percentage) {
            message = (default_message + payer);
        } else {
            dividend = llFloor((((float)amount)/100.0) * ((float)percentage));
            if (dividend) {
                if (debit_perms) {
                    message = (default_message + payer + ".\n" + ((string)percentage) + beneficiary_message + group_name);
                    llGiveMoney(beneficiary, dividend);
                } else {
                    message = (default_message + payer);
                }
            }
        }
        llSay(PUBLIC_CHANNEL, message);
        // OR llInstantMessage(id, message);
    }
}

Grid Status Updater

NOTE: Since LL Viewer v5.0.4.324646 "you can now add a Grid Status button to your screen from the Toolbox (Me -> Toolbar)" which utilizes and connects you to secondlife-status.statuspage.io.
  • If the button is added:
    • The button will turn orange when a status update is added, alerting you to current and/or pending issues.
    • If clicked, your browser will open to show various details about the grid status in chronologically descending order (newest at the top).
This built in viewer functionality is long overdue, welcome and far better for you and everyone around you than the use of this script.
NOTE: The format of the source of the Grid Status has changed many times since the creation of this script, and there's therefore every reason to assume it may change again. Should this happen, the output of this script may be malformed. I endeavour to keep up to date with the changes, but should really rebuild this script to parse whatever is thrown at it; don't hold your breath!
  • However, due to the changes mentioned in the note above, this script may no longer be of any practical use (except example).

Checks the Second Life Grid Status every five minutes to see if there are any new issues. If there are it will IM you.

Drop this script onto any prim that is currently not expected to do something else (e.g. a wall or floor etc) and let it run. If it is in an attachment it will work fine but, only while you are logged in. The script will maintain the name of the prim (or object if in a root) but when sending an update will use a special name set by you. This is simply more aesthetically pleasing. Getting an update from "Ceiling Fan" can seem a little odd.

// V25 //
 
float update_rate = 300.0; // How many second between checking for updates.
 
string alert_name = "Grid Status Update"; // What we call the object while it messages us.
 
////////////////////////////////////////////////////////////////////////////////////////////////////
 
string last; // Used to store the last update so we can tell if the latest is new.
 
key iq; // Used to verify the source of the HTTPRequest.
 
list timezones = [ 7, "PDT", 8, "PST" ];
 
list lookup_months = [ "January ",
                       "February ",
                       "March ",
                       "April ",
                       "May ",
                       "June ",
                       "July ",
                       "August ",
                       "September ",
                       "October ",
                       "November ",
                       "December " ];
 
string prettyTimestamp( string ts ) {
    list stamp_parts = llParseString2List( ts, [ "T", "-", ":" ], [] );
    string date =  llList2String( lookup_months, llList2Integer( stamp_parts, 1 ) - 1 ) + llList2String( stamp_parts, 2 ) + ", " + llList2String( stamp_parts, 0 );
    string time = llDumpList2String( llList2List( stamp_parts, 3, 4 ), ":" );
    string tz = llList2String( timezones, llListFindList( timezones, [ llList2Integer( stamp_parts, 6 ) ] ) + 1 );
    return date + " at " + time + " " + tz;
}
 
list exchange = [
    "&amp;", "&",
    "&nbsp;", " ",
    "&lt;p&gt;", "",
    "&lt;/p&gt;", "",
    "&lt;br&gt;", "",
    "&lt;br /&gt;", "",
    "&lt;small&gt;", "",
    "&lt;/small&gt;", "",
    "&lt;strong&gt;", ": ",
    "&lt;/strong&gt;", "" ]; // Various strings we find in the HTTP response that we may wish to bulk exchange.
 
string multiStringReplace( string src ) {
    integer index = 0;
    integer lc = 0;
    integer ll = llGetListLength( exchange );
    string this;
    do {
        this = llList2String( exchange, lc );
        ++lc;
        while ( ( index = llSubStringIndex( src, this ) ) != -1 ) {
            src = llInsertString( llDeleteSubString( src, index, index + ( llStringLength( this ) - 1 ) ), index, llList2String( exchange, lc ) );
        }
    } while ( ++lc < ll );
    return src;
}
 
messageOwner( string msg ) {
    string my_proper_name = llGetObjectName();
    llSetObjectName( alert_name );
    llInstantMessage( llGetOwner(), msg );
    llSetObjectName( my_proper_name );
}
 
checkForUpdates() {
    iq = llHTTPRequest( "http://status.secondlifegrid.net/history.atom", [], "" );
}
 
default {
    on_rez( integer param ) {
        llResetScript();
    }
    state_entry() {
        llSetTimerEvent( update_rate );
        checkForUpdates();
    }
    timer() {
        checkForUpdates();
    }
    http_response( key q, integer status, list meta, string body ) {
        if ( q == iq ) {
            if ( status == 200 ) {
                body = multiStringReplace( llGetSubString( body, llSubStringIndex( body, "<entry>" ) + 6, -1 ) );
                string latest = llGetSubString( body, llSubStringIndex( body, "<content type=\"html\">" ) + 21,
                                                      llSubStringIndex( body, "</content>" ) - 1 );
                if ( latest != last ) {
                    last = latest;
                    string issue = "ISSUE --> " + llGetSubString( body, llSubStringIndex( body, "<title>" ) + 7,
                                                                        llSubStringIndex( body, "</title>" ) - 1 );
                    string time = "\n\nTIME --> " + prettyTimestamp( llGetSubString( body, llSubStringIndex( body, "<updated>" ) + 9,
                                                                                           llSubStringIndex( body, "</updated>" ) - 1 ) );
                    string more = "\n\nMORE --> " + llGetSubString( body, llSubStringIndex( body, "href=\"" ) + 6,
                                                                          llSubStringIndex( body, "\"/>" ) - 1 );
                    string update = "\n\nLATEST --> " + latest;
                    string all = issue + time + update + more;
                    integer total = llStringLength( all );
                    if ( total > 1000 ) {
                        all = issue + time + llDeleteSubString( update, total - 1000, -1 ) + " ... (cont.)" + more;
                    }
                    messageOwner( all );
                }
            } else {
                messageOwner( "Feed not responding with anything useful.\n" +
                              "Trying again in " + ( string )llRound( update_rate / 60 ) + " minutes." );
            }
        }
    }
}

Simple Texturing Helpers

Touch Texture Getter

Put this script in the root prim of an object and touch whichever face of whichever prim you want the texture UUID of. It will be chatted to you. If you do not have permission to get the UUID you will not get it! A long held touch will delete the script.

// V2 //
 
integer tc;
 
key owner;
 
default
{
    state_entry()
    {
        owner = llGetOwner();
    }
    touch_end(integer nd)
    {
        while(nd)
        {
            if(llDetectedKey(--nd) == owner)
            {
                tc = 0;
                llOwnerSay(llList2String(llGetLinkPrimitiveParams(llDetectedLinkNumber(nd), [PRIM_TEXTURE, llDetectedTouchFace(nd)]), 0));
            }
        }
    }
    touch(integer nd)
    {
        while(nd)
        {
            if(llDetectedKey(--nd) == owner)
            {
                if((++tc) == 20)
                llRemoveInventory(llGetScriptName());
            }
        }
    }
}

Touch Texture Setter

Fill out the UUID for the texture to set. Drop the script in the root prim of the object to texture. The texture then sets on each face touched. A long held touch will delete the script.

// V3 //
 
key texture_uuid = "f05755e7-d31c-116d-9cf2-a4840bdfc56b"; // Fence texture
 
integer tc;
 
key owner;
 
default
{
    state_entry()
    {
        owner = llGetOwner();
    }
    touch_end(integer nd)
    {
        while(nd)
        {
            if(llDetectedKey(--nd) == owner)
            {
                tc = 0;
                llSetLinkTexture(llDetectedLinkNumber(nd), texture_uuid, llDetectedTouchFace(nd));
            }
        }
    }
    touch(integer nd)
    {
        while(nd)
        {
            if(llDetectedKey(--nd) == owner)
            {
                if((++tc) == 20)
                llRemoveInventory(llGetScriptName());
            }
        }
    }
}

Enzeroizer (Rotation Fixer)

Drop this into a single prim or the root of your linked object. It will set the rotations to whatever they were but with the smallest 3 decimal places made 000.

  • E.g. <75.458392, 128,038754, 298.836580> will become <75.458000, 128,038000, 298.836000>.

This will make minor rotational drifts that occur due to one of our favorite bugs less of an issue.

// V4 //
 
string enzeroizer( float f ) {
    return llGetSubString( ( string )f, 0, -5 ) + ( string )llRound( ( float )llGetSubString( ( string )f, -4, -1 ) / 1000 ) + "000";
}
 
rotation enzeroized( rotation rot ) {
    vector euler = llRot2Euler( rot ) * RAD_TO_DEG;
    return llEuler2Rot( ( vector )( "<" + llList2CSV( [ enzeroizer( euler.x ),
                                                        enzeroizer( euler.y ),
                                                        enzeroizer( euler.z ) ] ) + ">" ) * DEG_TO_RAD );
}
 
resetRotations( integer ln ) {
    llSetLinkPrimitiveParamsFast( ln, [ PRIM_ROT_LOCAL, enzeroized( llList2Rot( llGetLinkPrimitiveParams( ln, [ PRIM_ROT_LOCAL ] ), 0 ) ) ] );
}
 
default {
    state_entry() {
        integer links = llGetObjectPrimCount( llGetKey() );
        if ( links == 1 ) {
            resetRotations( 0 );
        } else {
            while ( links ) {
                resetRotations( --links );
            }
        }
    }
}

Pose Stand

Multi type, multi sex, multi story car park? Nope it just does poses.

Create a fresh prim and drop this script on it. You have an instant pose stand. Then fill it with various poses and animations and copy the names of the animations into the lists at the top of the script. As you can see there are categories for 3 sex types and 3 body types. You could change these to suit (e.g. 3 styles (action, silly, erotic)) and 3 other things if you liked.

Just put the names in the list that it makes most sense to put it in. As you sit on the stand (maybe these things should be called pose seats) you will be posted a dialog menu asking for "What type" then "What sex" then the list of anims appropriate for those choices. After making the animation choice, to recall the dialog menu click the pose stand.

I kinda rushed to the finish with this one because something else came up. I will probably get back to it sometime but for now it seems to work ok.

ANIMATIONS WITH A BUILT IN OFFSET MAY BE POSITIONED BADLY.

// V4 //
 
///////////////////////////////////////////////////////////////////
//YOU CAN CHANGE THESE MESSAGES. DON'T MAKE THEM TOO LONG THOUGH.//
///////////////////////////////////////////////////////////////////
 
string dialog_msg_type = "What type are you?";
 
string dialog_msg_sex = "What sex are you?";
 
string dialog_msg_anims = "Select the pose/animation to play";
 
/////////////////////////////////////////////////////////////////////////////
//////////WRITE INTO EACH LIST CATEGORY THE NAMES OF THE ANIMATIONS//////////
//APPROPRIATE FOR THAT CATEGORY. ANIMS MUST BE IN THE POSE STAND INVENTORY.//
/////////////////////////////////////////////////////////////////////////////
 
// Each of these lists can hold up to 72 names. However, if you filled them all to the max...
// ...you may encounter memory problems (not you, the script).
 
list tiny_male_anims = ["Tiny Male 1",
                        "Tiny Male 2",
                        "Tiny Male 3",
                        "Tiny Male 4",
                        "Tiny Male 5",
                        "Tiny Male 6",
                        "Tiny Male 7",
                        "Tiny Male 8",
                        "Tiny Male 9",
                        "Tiny Male 10",
                        "Tiny Male 11",
                        "Tiny Male 12",
                        "Tiny Male 13"];
 
list tiny_female_anims = ["Tiny Female 1", "Tiny Female 2", "Tiny Female 3"];
 
list tiny_thingy_anims = [];
 
 
list humanoid_male_anims = [];
 
list humanoid_female_anims = [];
 
list humanoid_thingy_anims = [];
 
 
list quadruped_male_anims = [];
 
list quadruped_female_anims = [];
 
list quadruped_thingy_anims = ["Quad Wotsit"];
 
///////////////////////////////////////////////////////////////////
//DON'T EDIT BELOW HERE UNLESS YOU ARE SURE OF WHAT YOU ARE DOING//
///////////////////////////////////////////////////////////////////
 
integer ousted;
 
integer last;
 
integer next;
 
string playing;
 
key agent = NULL_KEY;
 
string agent_name;
 
integer channel = -7463792;
 
integer lis;
 
list dialog_buttons_type = [];
 
list dialog_buttons_sex = [];
 
list agent_anim_set = [];
 
string type;
 
string sex;
 
CreatePoseStand()
{
    llSetPrimitiveParams([7, <1.0, 1.0, 0.1>,
                          9, 1, 0, <0.0, 1.0, 0.0>, 0.0, <0.0, 0.0, 0.0>, <0.9, 0.9, 0.0>, <0.0, 0.0, 0.0>,
                          17, 0, "5748decc-f629-461c-9a36-a35a221fe21f", <3.0, 3.0, 0.0>, <0.0, 0.0, 0.0>, 0.0,
                          17, 1, "5748decc-f629-461c-9a36-a35a221fe21f", <0.35, 2.0, 0.0>, <0.0, 0.0, 0.0>, 1.570796,
                          17, 2, "5748decc-f629-461c-9a36-a35a221fe21f", <1.0, 1.0, 0.0>, <0.0, 0.0, 0.0>, 0.0,
                          18, -1, <0.0, 0.0, 0.0>, 1.0,
                          19, 0, 3, 17,
                          19, 1, 3, 13,
                          19, 2, 3, 0]);
    SetName();
    llSitTarget(<0.0,0.0,1.5>, ZERO_ROTATION);
    llSetClickAction(CLICK_ACTION_SIT);
}
 
SetName()
{
    string name = llKey2Name(llGetOwner());
    llSetObjectName(((llGetSubString(name, 0, (llSubStringIndex(name, " ") - 1)) + "'s") + " Pose Stand"));
}
 
TypeCast()
{
    next = 0;
    dialog_buttons_type = [];
    if((llGetListLength(tiny_male_anims)) | (llGetListLength(tiny_female_anims)) | (llGetListLength(tiny_thingy_anims)))
    dialog_buttons_type += ["Tiny"];
    if((llGetListLength(humanoid_male_anims)) | (llGetListLength(humanoid_female_anims)) | (llGetListLength(humanoid_thingy_anims)))
    dialog_buttons_type += ["Humanoid"];
    if((llGetListLength(quadruped_male_anims)) | (llGetListLength(quadruped_female_anims)) | (llGetListLength(quadruped_thingy_anims)))
    dialog_buttons_type += ["Quadruped"];
    llListenRemove(lis);
    if(llGetListLength(dialog_buttons_type) && llGetInventoryNumber(INVENTORY_ANIMATION))
    {
        lis = llListen(channel, agent_name, agent, "");
        if(agent != NULL_KEY)
        llDialog(agent, ("\n" + dialog_msg_type), dialog_buttons_type, channel);
    }
    else
    {
        dialog_buttons_type = [];
        if(agent != NULL_KEY)
        llInstantMessage(agent, "There are no poses/animations available");
        if(agent != NULL_KEY)
        llUnSit(agent);
    }
}
 
SexCast()
{
    dialog_buttons_sex = [];
    if(type == "Tiny")
    {
        if(llGetListLength(tiny_male_anims))
        dialog_buttons_sex += ["Male"];
        if(llGetListLength(tiny_female_anims))
        dialog_buttons_sex += ["Female"];
        if(llGetListLength(tiny_thingy_anims))
        dialog_buttons_sex += ["Thingy"];
    }
    else if(type == "Humanoid")
    {
        if(llGetListLength(humanoid_male_anims))
        dialog_buttons_sex += ["Male"];
        if(llGetListLength(humanoid_female_anims))
        dialog_buttons_sex += ["Female"];
        if(llGetListLength(humanoid_thingy_anims))
        dialog_buttons_sex += ["Thingy"];
    }
    else if(type == "Quadruped")
    {
        if(llGetListLength(quadruped_male_anims))
        dialog_buttons_sex += ["Male"];
        if(llGetListLength(quadruped_female_anims))
        dialog_buttons_sex += ["Female"];
        if(llGetListLength(quadruped_thingy_anims))
        dialog_buttons_sex += ["Thingy"];
    }
    llListenRemove(lis);
    lis = llListen(channel, agent_name, agent, "");
    if(agent != NULL_KEY)
    llDialog(agent, ("\n" + dialog_msg_sex), dialog_buttons_sex, channel);
}
 
AnimSet()
{
    agent_anim_set = [];
    if(sex == "Male")
    {
        if(type == "Tiny")
        agent_anim_set = tiny_male_anims;
        else if(type == "Humanoid")
        agent_anim_set = humanoid_male_anims;
        else
        agent_anim_set = quadruped_male_anims;
    }
    else if(sex == "Female")
    {
        if(type == "Tiny")
        agent_anim_set = tiny_female_anims;
        else if(type == "Humanoid")
        agent_anim_set = humanoid_female_anims;
        else
        agent_anim_set = quadruped_female_anims;
    }
    else
    {
        if(type == "Tiny")
        agent_anim_set = tiny_thingy_anims;
        else if(type == "Humanoid")
        agent_anim_set = humanoid_thingy_anims;
        else
        agent_anim_set = quadruped_thingy_anims;
    }
}
 
SortDialog(integer b)
{
    last = b;
    string fore = "-";
    string dialog_anims = "";
    list dialog_buttons = [];
    integer count = b;
    integer max = (b + 10);
    do
    {
        string anim_name = llList2String(agent_anim_set, count);
        if(anim_name != "")
        {
            dialog_anims += ("\n" + ((string)(++count)) + " - " + anim_name);
            dialog_buttons += [((string)count)];
        }
        else
        count = max;
    }
    while(count < max);
    if(llGetListLength(agent_anim_set) > llGetListLength(dialog_buttons))
    {
        fore = ">>";
        if(max < llGetListLength(agent_anim_set))
        next = max;
        else
        next = 0;
    }
    dialog_buttons = llListInsertList(dialog_buttons, ["RESET", fore], 0);
    llListenRemove(lis);
    lis = llListen(channel, agent_name, agent, "");
    if(agent != NULL_KEY)
    llDialog(agent, dialog_anims, dialog_buttons, channel);
}
 
default
{
    state_entry()
    {
        CreatePoseStand();
    }
    changed(integer change)
    {
        if(change & CHANGED_LINK)
        {
            integer NOP = llGetNumberOfPrims();
            if(NOP == 1)
            {
                ousted = FALSE;
                agent = NULL_KEY;
                llListenRemove(lis);
                if(playing != "")
                {
                    llStopAnimation(playing);
                    playing = "";
                }
                llSetClickAction(CLICK_ACTION_SIT);
            }
            else if(NOP == 2)
            {
                if(!ousted)
                {
                    agent = llAvatarOnSitTarget();
                    agent_name = llKey2Name(agent);
                    llRequestPermissions(agent, PERMISSION_TRIGGER_ANIMATION);
                }
            }
            else if(NOP == 3)
            {
                llUnSit(llGetLinkKey(3));
                ousted = TRUE;
            }
        }
        else if(change & CHANGED_OWNER)
        SetName();
    }
    run_time_permissions(integer perm)
    {
        if(perm & PERMISSION_TRIGGER_ANIMATION)
        {
            if(agent != NULL_KEY)
            {
                llStopAnimation("Sit");
                if(agent != NULL_KEY)
                llInstantMessage(agent, "Don't forget to turn off your AO.");
                TypeCast();
            }
        }
    }
    touch_start(integer nd)
    {
        integer count;
        do
        {
            if(llDetectedKey(count) == agent)
            SortDialog(last);
        }
        while((++count) < nd);
    }
    listen(integer chan, string name, key id, string msg)
    {
        llListenRemove(lis);
        if(msg != "RESET")
        {
            if((msg != ">>") && (msg != "-"))
            {
                if(llListFindList(dialog_buttons_type, [msg]) != -1)
                {
                    type = msg;
                    dialog_buttons_type = [];
                    SexCast();
                }
                else if(llListFindList(dialog_buttons_sex, [msg]) != -1)
                {
                    sex = msg;
                    dialog_buttons_sex = [];
                    AnimSet();
                    SortDialog(0);
                    llSetClickAction(CLICK_ACTION_TOUCH);
                }
                else
                {
                    string inv_name = llList2String(agent_anim_set, (((integer)msg) - 1));
                    if(llGetInventoryType(inv_name) == INVENTORY_ANIMATION)
                    {
                        if(playing != "")
                        llStopAnimation(playing);
                        playing = inv_name;
                        if(agent != NULL_KEY)
                        llStartAnimation(inv_name);
                    }
                    else
                    {
                        if(agent != NULL_KEY)
                        llInstantMessage(agent, "\"" + inv_name + "\" is missing from the pose stand inventory.");
                    }
                }
            }
            else
            {
                if(msg == ">>")
                SortDialog(next);
                else if(msg == "-")
                SortDialog(last);
            }
            return;
        }
        TypeCast();
    }
}

More Scripts...

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