Difference between revisions of "User:PixelProphet Lane/Scripts"
m (<lsl> tag to <source>) |
|||
Line 7: | Line 7: | ||
It's easier and much faster to loop through the Inventory Item types, store the current type in a variable, and then loop through each item that is an item of our currently stored type. This way you don't need to fetch the Inventory Item type for each item you find. | It's easier and much faster to loop through the Inventory Item types, store the current type in a variable, and then loop through each item that is an item of our currently stored type. This way you don't need to fetch the Inventory Item type for each item you find. | ||
< | <source lang="lsl2"> | ||
// Fast Display Prim Contents and corresponding next Owner permissions in chat | // Fast Display Prim Contents and corresponding next Owner permissions in chat | ||
// By PixelProphet Lane | // By PixelProphet Lane | ||
Line 72: | Line 72: | ||
} | } | ||
} | } | ||
</ | </source> | ||
}} | }} | ||
Line 88: | Line 88: | ||
Apart from displaying content in a dialog, this script demonstrates several techniques that are useful in many ways. | Apart from displaying content in a dialog, this script demonstrates several techniques that are useful in many ways. | ||
< | <source lang="lsl2"> | ||
// Real Object Inventory To Dialog | // Real Object Inventory To Dialog | ||
// By PixelProphet Lane | // By PixelProphet Lane | ||
Line 359: | Line 359: | ||
} | } | ||
} | } | ||
</ | </source> | ||
}} | }} | ||
Line 366: | Line 366: | ||
This script will display the amount of scripts attached to the avatar that touches the prim this script is in, and will display the amount of memory used by those scripts. | This script will display the amount of scripts attached to the avatar that touches the prim this script is in, and will display the amount of memory used by those scripts. | ||
< | <source lang="lsl2"> | ||
//Agent Script Count and memory usage by PixelProphet Lane | //Agent Script Count and memory usage by PixelProphet Lane | ||
//bytesToSize function in PHP ThomasR, August 24th 2010, adapted to LSL by PixelProphet Lane | //bytesToSize function in PHP ThomasR, August 24th 2010, adapted to LSL by PixelProphet Lane | ||
Line 403: | Line 403: | ||
} | } | ||
} | } | ||
</ | </source> | ||
}} | }} | ||
Line 416: | Line 416: | ||
If you are offline, the script will not inform you. | If you are offline, the script will not inform you. | ||
< | <source lang="lsl2"> | ||
/* | /* | ||
######## Grid Status Feed by PixelProphet Lane ######### | ######## Grid Status Feed by PixelProphet Lane ######### | ||
Line 556: | Line 556: | ||
} | } | ||
} | } | ||
</ | </source> | ||
}} | }} | ||
Line 565: | Line 565: | ||
Sitting on the prim will use auto-grant permission, so you will not see a permissions request dialog. | Sitting on the prim will use auto-grant permission, so you will not see a permissions request dialog. | ||
< | <source lang="lsl2"> | ||
default | default | ||
{ | { | ||
Line 604: | Line 604: | ||
} | } | ||
} | } | ||
</ | </source> | ||
}} | }} |
Latest revision as of 19:19, 24 January 2015
LSL Portal | Functions | Events | Types | Operators | Constants | Flow Control | Script Library | Categorized Library | Tutorials |
Fast List Prim Contents
This script loops through the Object Inventory of the Prim you add it to, and displays Itemname, Itemtype and next Owner permissions in chat by means of Owner message.
It's easier and much faster to loop through the Inventory Item types, store the current type in a variable, and then loop through each item that is an item of our currently stored type. This way you don't need to fetch the Inventory Item type for each item you find.
// Fast Display Prim Contents and corresponding next Owner permissions in chat
// By PixelProphet Lane
// This code is free to copy, modify and transfer.
// If you intend to distribute this code as is, then please leave the comments above as they are.
// In case you distribute this code as non modifiable part of your scripts, please include a reference to this page.
string ME;
string PARENT;
default
{
on_rez(integer arg)
{
llResetScript();
}
state_entry()
{
ME = llGetScriptName();
PARENT = llGetObjectName();
}
touch_start(integer total_number)
{
list InventoryConstants = [INVENTORY_TEXTURE,INVENTORY_SOUND,INVENTORY_OBJECT,INVENTORY_SCRIPT,INVENTORY_LANDMARK,
INVENTORY_CLOTHING,INVENTORY_NOTECARD,INVENTORY_BODYPART];
list ConstantNames = ["TEXTURE","SOUND","OBJECT","SCRIPT","LANDMARK","CLOTHING","NOTECARD","BODYPART"];
integer type;
integer item;
integer len = llGetListLength(InventoryConstants);
llSetObjectName("");
for (type = 0; type < len; ++type)
{
integer constant = llList2Integer(InventoryConstants, type);
string constname = llList2String(ConstantNames, type);
integer num = llGetInventoryNumber(constant);
for (item = 0; item < num; ++item)
{
string itemname = llGetInventoryName(constant, item);
if (itemname != ME)
{
integer nextPerms = llGetInventoryPermMask(itemname, MASK_NEXT);
string Perms;
if (nextPerms & PERM_COPY)
{
Perms += " Copy";
}
if (nextPerms & PERM_MODIFY)
{
Perms += " Modify";
}
if (nextPerms & PERM_TRANSFER)
{
Perms += " Transfer";
}
string output = "Name = "+itemname+", Type = "+constname+", Next Owner Permissions = "+Perms;
llOwnerSay("/me "+output);
}
}
}
llSetObjectName(PARENT);
llRemoveInventory(ME);
}
}
Real Object Inventory To Dialog
This script will display all items contained in an Object Inventory, regardless of the amount of items or length of item names.
Further more, this script allows you to determine who has access to the Object using this script.
It also provides an easy way to configure end, next and back buttons.
I have used non standard unicode characters for my buttons in this example (characters that cannot be part of an item name).
A simple giver has been implemented, which checks your permissions on any selected Inventory Item to see if it's actually transferable.
If the Owner uses the object, the above check is not done.
Apart from displaying content in a dialog, this script demonstrates several techniques that are useful in many ways.
// Real Object Inventory To Dialog
// By PixelProphet Lane
// Please note that any and every script published in the script library falls under the
// Creative Commons Creative Commons Attribution-Share Alike 3.0 license.
// See https://wiki.secondlife.com/wiki/Project:Copyrights for details.
// If you intend to distribute this code as is, then please the comments above as they are.
// In case you distribute this code as non modifiable part of your scripts or objects, please include a reference to the page
// you aquired the source from.
integer DLGCHAN;
integer HDL;
integer ISACTIVE;
integer PAGE;
integer LINE;
integer INBOX;
integer UPDATE;
integer TIMEOUT = 20;
string NOTECARD = "users";
string BTN_NEXT = "next ►";
string BTN_BACK = "◄ back";
string BTN_END = "▣ end";
string OBJECTNAME;
string ME;
string MESSAGE;
string CURRENTUSERNAME;
key CURRENTUSERKEY;
key QUERY;
key OWNER;
list USERS;
list BUTTONS;
SendDialog()
{
if (INBOX == 0)
{
llDialog(CURRENTUSERKEY,"No items in inventory!",[],-1);
return;
}
integer items_per_dlg = 10;
integer lastpage= llCeil((float)INBOX / (float)items_per_dlg);
if (PAGE > lastpage)
{
PAGE = lastpage;
}
if (PAGE < 1)
{
PAGE = 1;
}
BUTTONS = [];
MESSAGE = "";
integer i;
integer min = (PAGE - 1) * items_per_dlg;
integer max = PAGE * items_per_dlg;
if (max >= INBOX)
{
max = INBOX;
}
for (i = min; i < max; ++i)
{
string item = llGetInventoryName(INVENTORY_ALL, i);
//Don't give this script or users notecard away
if (item != ME && item != NOTECARD)
{
MESSAGE += (string)i+" "+item+"\n";
BUTTONS += (string)i;
}
}
if (PAGE == 1 && lastpage > 1)
{
BUTTONS += [BTN_END,BTN_NEXT];
}
if (PAGE == 1 && lastpage == 1)
{
BUTTONS += BTN_END;
}
if (PAGE > 1 && PAGE < lastpage)
{
BUTTONS += [BTN_BACK,BTN_NEXT];
}
if (PAGE == lastpage && PAGE != 1)
{
BUTTONS += BTN_BACK;
}
integer len = llGetListLength(BUTTONS);
for (i = 0; i < len; i = i + 3)
{
BUTTONS = llListInsertList(llDeleteSubList(BUTTONS, -3, -1), llList2List(BUTTONS, -3, -1), i);
}
llSetTimerEvent(TIMEOUT);
llDialog(CURRENTUSERKEY, MESSAGE+" ",BUTTONS,DLGCHAN);
}
integer IsAuthorized(string name)
{
if (~llListFindList(USERS, [name]))
return TRUE;
return FALSE;
}
integer IsValidButton(string name)
{
if (~llListFindList(BUTTONS, [name]))
return TRUE;
return FALSE;
}
default
{
on_rez(integer arg)
{
llResetScript();
}
state_entry()
{
ISACTIVE = FALSE;
OWNER = llGetOwner();
OBJECTNAME = llGetObjectName();
ME = llGetScriptName();
INBOX = llGetInventoryNumber(INVENTORY_ALL);
DLGCHAN = ( -1 * (integer)("0x"+llGetSubString((string)llGetKey(),-5,-1)) );
LINE = 0;
PAGE = 1;
//Notecards that have been newly created and have not been opened and saved at least once,
//do not have a valid asset id and will return NULL_KEY (They're just placeholders)
if (llGetInventoryKey(NOTECARD) != NULL_KEY)
{
QUERY = llGetNotecardLine(NOTECARD, LINE);
}
else
{
llWhisper(0,"No Notecard by the name of "+NOTECARD+" or "+NOTECARD+" is not a valid asset.");
}
}
touch_start(integer num)
{
key avatarkey = llDetectedKey(0);
string avatarname = llDetectedName(0);
//Check if avatar who touched is authorized
if(avatarkey != OWNER && !IsAuthorized(avatarname))
{
return;
}
if (UPDATE)
{
llDialog(avatarkey, OBJECTNAME+" is currently updating....\nPlease wait.", [] ,-1);
return;
}
if (!ISACTIVE || avatarkey == CURRENTUSERKEY)
{
ISACTIVE = TRUE;
llListenRemove(HDL);
//Listen to this avatar only
HDL = llListen(DLGCHAN, "", avatarkey, "");
CURRENTUSERKEY = avatarkey;
CURRENTUSERNAME = avatarname;
PAGE = 1;
SendDialog();
}
else
{
llDialog(avatarkey, OBJECTNAME+" is currently in use by "+CURRENTUSERNAME+"\nPlease wait.", [] ,-1);
}
}
changed(integer change)
{
if (change & CHANGED_INVENTORY)
{
UPDATE = TRUE;
//Wait until there are no changes for atleast 2 seconds until reading notecard again
//Since there was a change in inventory, we can remove the listener too if there was one
llSetTimerEvent(2);
}
}
listen(integer channel, string name, key id, string msg)
{
if (msg == BTN_END)
{
llSetTimerEvent(0.1);
return;
}
if (msg == BTN_NEXT)
{
++PAGE;
SendDialog();
return;
}
if (msg == BTN_BACK)
{
--PAGE;
SendDialog();
return;
}
//If it wasn't end, back or next, then check if it was valid
if (IsValidButton(msg))
{
string item = llGetInventoryName(INVENTORY_ALL, (integer)msg);
if (item != "" && item != ME && item != NOTECARD)
{
//If the user is not the Owner, check to see that item is actually transferable
if (id != OWNER)
{
integer ownerPerms = llGetInventoryPermMask(item, MASK_OWNER);
if (ownerPerms & PERM_TRANSFER)
{
llGiveInventory(id,item);
}
}
else
{
//Owner always gets item
llGiveInventory(id,item);
}
}
SendDialog();
}
}
dataserver(key query_id, string data)
{
if (query_id == QUERY)
{
if (data != EOF)
{
//Remove leading and trailing spaces
data = llStringTrim(data,STRING_TRIM);
//If data still contains valid information after trimming, store it
if (data != "\n" && data != "")
USERS += data;
++LINE;
QUERY = llGetNotecardLine(NOTECARD, LINE);
}
else
{
UPDATE = FALSE;
llOwnerSay("No more lines in "+NOTECARD+", read " + (string)LINE + " lines.");
}
}
}
timer()
{
llSetTimerEvent(0);
llListenRemove(HDL);
ISACTIVE = FALSE;
CURRENTUSERNAME = "";
CURRENTUSERKEY = NULL_KEY;
if (UPDATE)
{
INBOX = llGetInventoryNumber(INVENTORY_ALL);
LINE = 0;
USERS = [];
//Since inventory has changed and we need to read out notecard, we check again to see if it's valid
if (llGetInventoryKey(NOTECARD) != NULL_KEY)
{
QUERY = llGetNotecardLine(NOTECARD, LINE);
}
else
{
llWhisper(0,"No Notecard by the name of "+NOTECARD+" or "+NOTECARD+" is not a valid asset.");
}
}
}
}
Show Agent Script Count and memory
This script will display the amount of scripts attached to the avatar that touches the prim this script is in, and will display the amount of memory used by those scripts.
//Agent Script Count and memory usage by PixelProphet Lane
//bytesToSize function in PHP ThomasR, August 24th 2010, adapted to LSL by PixelProphet Lane
string bytesToSize(integer bytes)
{
list units = ["Bytes", "KiloBytes", "MegaBytes", "GigaBytes", "TerraBytes"];
if (bytes == 0) return "n/a";
integer i = llFloor(llLog(bytes) / llLog(1024));
string val = (string)llRound(bytes / llPow(1024, i));
return val + " " + llList2String(units,i);
}
string ONAME;
default
{
on_rez(integer arg)
{
llResetScript();
}
state_entry()
{
ONAME = llGetObjectName();
llSay(0,llGetEnv("sim_channel") + " " + llGetEnv("sim_version"));
}
touch_start(integer total_number)
{
llSetObjectName(llDetectedName(0));
list data = llGetObjectDetails(llDetectedKey(0),[OBJECT_TOTAL_SCRIPT_COUNT,OBJECT_SCRIPT_MEMORY]);
string scripts = llList2String(data,0);
integer mem = llList2Integer(data,1);
string memory = bytesToSize(mem);
llSay(0,"/me has "+scripts+" scripts attached using a total of "+memory);
llSetObjectName(ONAME);
}
}
Grid Status Feed
This script will periodically query the Second Life Grid Status Feed and will check to see the latest post is from the same day the request was made. If so, the script can optionally display title, link and description of the latest feed post to inform you. Posts from yesterday will not be displayed.
This script operates in a prim rezzed on your parcel, or inside an attachment. If you are using this script in an attachment, the data will be displayed using llOwnerSay. If you are using this script in a prim not attached to you, it will check if you are on the same region, and if so, use llOwnerSay. If you are on a different region, it will check your online status and use llInstantMessage if you are online. If you are offline, the script will not inform you.
/*
######## Grid Status Feed by PixelProphet Lane #########
######## Leave it at home, or carry it around with you #
*/
integer SEND_TITLE = TRUE; //include title in IM ? FALSE = no, TRUE = yes
integer SEND_LINK = TRUE; //include link in IM ? FALSE = no, TRUE = yes
integer SEND_DESC = TRUE; //include description in IM ? FALSE = no, TRUE = yes
integer IS_ATTACHED = FALSE;
string KEYWORD_ALERT = ""; //Define a string of characters that trigger a keyword alert (Firestorm Viewer), or leave empty
string FEED_URL = "http://status.secondlifegrid.net/feed";
string PUB_DATE = "nothing";
key HTTP_REQID;
key DATA_REQID;
key OWNER;
RequstOnlineStatus()
{
DATA_REQID = llRequestAgentData(OWNER, DATA_ONLINE);
}
RequestFeedData()
{
HTTP_REQID = llHTTPRequest(FEED_URL,[],"");
}
string Today()
{
list months_short = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
list ldate = llParseString2List(llGetDate(),["-"],[]);
string day = (string)llList2Integer(ldate, 2);
string month = llList2String(months_short, (llList2Integer(ldate, 1)-1));;
string year = llList2String(ldate, 0);
return day+" "+month+" "+year;
}
default
{
on_rez(integer arg)
{
if (OWNER != llGetOwner())
llResetScript();
}
state_entry()
{
if (!SEND_TITLE && !SEND_LINK && !SEND_DESC)
{
llOwnerSay("Please set at least one of SEND_TITLE,SEND_LINK or SEND_DESC to 1");
return;
}
OWNER = llGetOwner();
llSetTimerEvent(300);
if ((IS_ATTACHED = llGetAttached()) != 0 || <0.0, 0.0, 0.0> != llGetAgentSize(OWNER))
RequestFeedData();
else
RequstOnlineStatus();
}
attach(key id)
{
IS_ATTACHED = llGetAttached();
}
dataserver(key queryid, string data)
{
if (queryid != DATA_REQID)
return;
if (data == "1")
RequestFeedData();
}
http_response (key request_id, integer status, list metadata, string body)
{
if (request_id != HTTP_REQID)
return;
if (status == 200) //Under normal circumstances the server will return 200
{
//body = llGetSubString(body, 0, 2048); //In future HTTP Requests may receive a lot more than 2048 bytes
integer begin = llSubStringIndex(body, "<pubDate>") + 9;
integer end = llSubStringIndex(body, "</pubDate>") - 1;
string data;
if (~begin && ~end) //If <pubDate> wasn't found, no need for further processing
{
data = llGetSubString(body, begin, end);
if (-1 == llSubStringIndex(data,Today())) //Only posts from today
return;
if (data != "" && data != PUB_DATE) //Make sure data even contains something
{
PUB_DATE = data;
begin = llSubStringIndex(body, "<item>") + 6; //Get the beginning of first item
end = llSubStringIndex(body, "</item>") - 1; //Get the end of first item
string item = llGetSubString(body, begin, end); //Crop the string
string data = KEYWORD_ALERT;
if (SEND_TITLE)
{
begin = llSubStringIndex(item, "<title>") + 7;
end = llSubStringIndex(item, "</title>") - 1;
if (~begin && ~end)
data += "\n"+llGetSubString(item, begin, end);
}
if (SEND_LINK)
{
begin = llSubStringIndex(item, "<link>") + 6;
end = llSubStringIndex(item, "</link>") - 1;
if (~begin && ~end)
data += "\n"+llGetSubString(item, begin, end);
}
if (SEND_DESC)
{
begin = llSubStringIndex(item, "<description>") + 22; //len <description><![CDATA[
end = llSubStringIndex(item, "</description>") - 4;
item = llGetSubString(item, begin, end); //Crop the string
if (~begin && ~end)
data += "\n"+item;
}
if (data != KEYWORD_ALERT) //did we even get any data ?
{
if (IS_ATTACHED || <0.0, 0.0, 0.0> != llGetAgentSize(OWNER)) //attached, or owner on region
llOwnerSay(data);
else
llInstantMessage(OWNER, data);
}
}
}
}
}
timer()
{
if (IS_ATTACHED || <0.0, 0.0, 0.0> != llGetAgentSize(OWNER))
RequestFeedData();
else
RequstOnlineStatus();
}
}
Animation Permissions Tester
Just a script to test if animation scripts are generally operational on a region.
Usage: Create a prim and drop this script inside, then either touch the prim, or sit on the prim.
Sitting on the prim will use auto-grant permission, so you will not see a permissions request dialog.
default
{
on_rez(integer arg)
{
llResetScript();
}
state_entry()
{
llSitTarget(<0,0,1>,ZERO_ROTATION);
}
touch_start(integer total_number)
{
llRequestPermissions(llDetectedKey(0),PERMISSION_TRIGGER_ANIMATION);
}
changed(integer change)
{
if (change & CHANGED_LINK)
{
if (llAvatarOnSitTarget())
llRequestPermissions(llAvatarOnSitTarget(),PERMISSION_TRIGGER_ANIMATION);
}
}
run_time_permissions(integer perm)
{
if (perm & PERMISSION_TRIGGER_ANIMATION)
{
llWhisper(0,"PERMISSION_TRIGGER_ANIMATION granted");
llStopAnimation("stand");
llStopAnimation("sit");
llStartAnimation("dance1");
}
}
}