exchangeTLTP
exchangeTLML
exchangeTLMLRenderer
Sample Code:
Sample TLML browser:
// TLTP Browser Engine
// Version 0.51
// Supports: TLTP v0.4
integer debug = 0;
// constants
key nullk = NULL_KEY;
vector zerov = ZERO_VECTOR;
string tltp_str = "TLTP"; // for email comm
float max_sleep = 10.0; // for the W commands
key source; // if set to null key, listen anyone, else only listen this key
// info about browser
list current_url; // maintained into full URL format
integer status = 2; // browser's display is visible, and listening to adverts and other stuff
integer browsing_channel; // channel for receiving answers if chat
integer browsing_handle; // handle for receiving answers if chat
// info about inventory reading
key page_key; // remote notecard key
key page_query; // for reading remote notecards
integer page_line;
key joint_page_key; // remote joint notecard key
key joint_page_query; // for reading remote joint notecards
integer joint_page_line;
// info about display
integer link_offset = 2; // link number of first display prim
integer max_prim_used; // highest index of display prim in use
integer emailer; // index of unused display prim for email sending
// courtesy of Strife Onizuka
list TightListParse(string a)
{
string b = llGetSubString(a,0,0);//save memory
return llParseStringKeepNulls(llDeleteSubString(a,0,0), [b],[]);
}
string TightListDump(list a, string b)
{ string c = (string)a;
if(llStringLength(b)==1)
if(llSubStringIndex(c,b) == -1)
jump end;
integer d = -llStringLength(b += "|\\/?!@#$%^&*()_=:;~{}[],\n\" qQxXzZ");
while(1+llSubStringIndex(c,llGetSubString(b,d,d)) && d)
++d;
b = llGetSubString(b,d,d);
@end;
c = "";//save memory
return b + llDumpList2String(a, b);
}
go(string url)
{
if(debug)//$[E20012]
llOwnerSay(url);
list t = TightListParse(url) + current_url;
integer argc = llGetListLength(t);
if (argc < 5) { llOwnerSay("Missing arguments in URL: " + url); return; } // sanity check
// extracting info from the URL
current_url = llDeleteSubList(t, -4, argc - 9);
request(current_url);
}
request(list u)
{
if (llGetListLength(u) != 4) { llOwnerSay("Bad URL format"); return; }
string thename = llList2String(u, 3);
if (llStringLength(thename))
{
llSetText("Browsing " + thename, <0,1,1>, 0.8);
} else llSetText("", zerov, 0.0);
if (llList2String(u, 1) == "0"){
// requesting a page to a chat server
if ((integer)llList2String(u, 2) == 0)
{
llOwnerSay("Bad server channel.");
return;
}
source = "";
llListenRemove(browsing_handle);
do;while(!(browsing_channel = (integer)llFrand(65536.0) | ((integer)llFrand(65536.0) << 16)));
browsing_handle = llListen(browsing_channel, "", "", "");
// object name is optional and only included here because of the specifications
llShout((integer)llList2String(u, 2), "U" + TightListDump([llList2String(u, 0), "0", (string)browsing_channel, llGetObjectName()], "&"));
}
else if (llList2String(u, 1) == "1"){
// requesting a page to an email server
source = "";
// using the last unused display prim as remailer
if (emailer <= max_prim_used + link_offset) emailer = llGetNumberOfPrims();
// same as above, name is included for following the specifications
llMessageLinked(emailer, 1100, TightListDump([emailer, llList2String(u, 2), tltp_str], ";"), (key)("U" + TightListDump([llList2String(u, 0), "1", llGetKey(), llGetObjectName()], "&") ) );
emailer = emailer - 1;
}
else if (llList2String(u, 1) == "2"){
// read a joint notecard page
joint_page_key = llList2String(u, 0);
joint_page_line = (integer)llList2String(u, 2);
joint_page_query = llGetNotecardLine(joint_page_key, joint_page_line);
} else {
llOwnerSay("Unknown transport method for URL: " + llList2CSV(u));
return;
}
}
parse(string command, string hook)
{
string a = llGetSubString(command, 0, 0);
command = llDeleteSubString(command, 0, 0);
integer b = llListFindList(["A","a",2,"K","k",5,"P","p"],[a]);
if (b+1) //animations, keys, permissions all handled by a specialized script.
{
if ((~status & 4) && ((b == 0) || (b == 1)))
return;
llMessageLinked(LINK_THIS, b + 2010, command, llGetOwner());
} else if (a == "U") {
// received URL
go(command);
} else if ((b = (a == "T")) || a == "J") {
// received TLML
if(hook == "")
hook = TightListDump([TightListDump(current_url, "#"), llGetLocalRot(), llList2String(current_url, 0), llList2String(current_url, 3)], "&");
if(b)
tlml(command, hook);
else
{
// this is an internal command that only works for TLML-L pages
// It is used to navigate a TLML-L page.
llMessageLinked(LINK_SET, 6000, command, hook);
}
} else if (a == "t") {
// received TLML key
page_key = command;
page_line = 0;
page_query = llGetNotecardLine(page_key, page_line);
} else if ((b = (a == "x")) || a == "X") {
// received XTM or XTMP
llMessageLinked(LINK_SET, (!b) * 3000 + b * 3100, command,
(key)TightListDump([llList2String(current_url, 2),
llList2String(current_url, 0)], "*"));
} else if (a == "c") {
// received owner chat request
llOwnerSay(command);
} else if (a == "W") {
// received sleep request
if ((float)command > max_sleep) { llSleep(max_sleep); } else
llSleep((float)command);
} else if (a == "s") {
llStopSound();
} else {
list com = TightListParse(command);
if (a == "C") {
// received chat request
if (llGetListLength(com) > 1)
llShout((integer)llList2String(com, 0), llList2String(com, 1));
else llSay(0, llList2String(com, 0));
} else if (a == "D") {
if(0 > b = (integer)llList2String(com,0))
b = 0;
integer c = b;
if (llGetListLength(com) > 1)
{
c = (integer)llList2String(com,1);
if(c < b)
c = b;
};
do //this is intentional.
llMessageLinked(b + link_offset, 8999,"individual","");
while(++b < c);
} else if (1 + b = llListFindList(["S", "L","l"],[a])) {
if(status & 2)
{ // received sound key
float v = (float)llList2String(com, 1);
a = llList2String(com, 0);
if (v <= 0.0)
v = 0.5;
if(b == 2)
llLoopSound(a, v);
else if(b == 1)
llPlaySound(a, v);
else
llTriggerSound(a, v);
}
} else if (a == "N") {
// texture notecard go
llMessageLinked(LINK_SET, 5200, llList2String(com,0),
TightListDump(llDeleteSubList(com, 0, 0), "*"));
} else if (a == "R") {
// received RPC command
if (status & 8)
llMessageLinked(LINK_THIS, 4400, llList2String(com,0),
TightListDump(llDeleteSubList(com, 0, 0), "*"));
} else if (a == "Z") {
// received RemoteLoad command
if (status & 0x10)
llMessageLinked(LINK_SET, 8998, "", "");
} else if (a == "M") {
b = -llGetListLength(com);
while(b)
parse(llList2String(com,b++), hook);
}
}
}
tlml(string t, string hook)
{
// extracting the target display prim number
integer ind = llSubStringIndex(llDeleteSubString(t, 0, 0), llGetSubString(t, 0, 0));
integer target = (integer)llGetSubString(t, 1, ind);
if (target >= 0) {
// sending the TLML to the display
if (target > llGetNumberOfPrims() - link_offset)
{
llOwnerSay("Not enough prims to display this page.");
return;
}
if (target > max_prim_used) max_prim_used = target;
llMessageLinked(target + link_offset, 1000, llDeleteSubString(t, 0, ind), hook);
} else {
if (target == -99) { clear(); } else
if (target == -1) { llOwnerSay("Server is unavailable !"); } else
if (target == -2) { llOwnerSay("Server error !"); } else
if (target == -3) { llOwnerSay("Access denied !"); } else
if (target == -4) { llOwnerSay("Page not found !"); } else
if (target == -97)
{
float delay = (float)llDeleteSubString(t, 0, ind);
if (delay > max_sleep) delay = max_sleep;
llSleep(delay);
} else if (target != -98) {
llOwnerSay("Server response not recognized: " + t);
}
}
}
clear()
{
llMessageLinked(LINK_ALL_OTHERS, 8999, "nevermind", nullk);
max_prim_used = 0;
}
string generate_hook(list page, string server)
{
return TightListDump([TightListDump(page , "#"), llGetLocalRot(), server], "&");
}
default
{
state_entry()
{
llSetTimerEvent(6.0);
browsing_handle = 0;
current_url = ["", "", "", ""];
llSetText("", zerov, 0.0);
}
dataserver(key id, string data)
{
if (id == page_query)
{
// reading of remote notecards
if (data != EOF)
{
parse(data, "");
page_line = page_line + 1;
page_query = llGetNotecardLine(page_key, page_line);
}
} else if (id == joint_page_query)
{
// reading of remote joint notecards
llMessageLinked(LINK_ALL_OTHERS, 6000, data,
generate_hook([joint_page_line, 2, joint_page_key, llList2String(current_url,3)], joint_page_key));
}
}
timer()
{
llGetNextEmail("", "");
}
email(string time, string address, string subj, string message, integer left)
{
integer n = 0;
if (debug) llOwnerSay("Received email: " + subj + ": " + message);//$[E20012]
if (subj == tltp_str)
{
n = llSubStringIndex(message, "\n\n");
message = llDeleteSubString(message, 0, n + 1);
key newsource = (key)llGetSubString(address, 0, llStringLength(message) - 20);
if (llStringLength(source))
{
if (source != newsource)
{
llOwnerSay("Message from unknown source, discarded.");
}
} else {
source = newsource;
newsource = "";
}
if(llGetSubString(address,-19, -1) == "@lsl.secondlife.com")
{
current_url = llListReplaceList(current_url, [(string)source], 2, 2);
}
else
current_url = llListReplaceList(current_url, [address], 2, 2);
list commands = llParseStringKeepNulls(message, ["\n"], []);
integer m = llGetListLength(commands);
for(n = 0; n < m; ++n)
parse(llList2String(commands, n), "");
if (left > 0) llGetNextEmail("", "");
}
}
listen(integer chan, string name, key id, string msg)
{
if (source)
{
if (source == id)
{
parse(msg, "");
} else {
llOwnerSay("Message from unknown source, discarded.");
}
} else {
source = id;
parse(msg, "");
}
}
link_message(integer part, integer code, string msg, key id)
{
if (code == 2000)
{
parse(msg, id);
} else if (code == 12345)
{
status = (integer)msg;
if (~status & 2)
{
llStopSound();
}
}
}
}
// TLTP Browser Interface
// Version 0.5
integer debug = 0;
// constants
key nullk = NULL_KEY;
vector zerov = ZERO_VECTOR;
// info about browser
integer status = 2; // browser's display is visible, and listening to adverts and other stuff
// 0x1: listening to adverts (used in this script)
// 0x2: sound on
// 0x4: anims on (off by default)
// 0x8: RPC/Plugins on (off by default)
// 0x10: RemoteScript on (off by default)
integer advert_channel = -9;
integer advert_handle;
integer channel; // channel for menu
integer handle; // handle for menu
integer action; // selected menu option
float discovery_timeout = 6.0; // halftime before forgetting a server
// info about available servers
list advertised_names;
list advertised_urls;
list advertised_still;
list bookmarked_names;
list bookmarked_urls;
integer bkm_part; // slice of the bookmarks to display
integer adv_part; // slice of the adverts to display
string current_url;
// info about inventory reading
key query;
integer line;
// colors
vector color_flash = <1,0,0>;
vector color_on = <1,1,0>;
vector color_off = <0.2, 0.2, 0.2>;
// courtesy of Strife Onizuka
list TightListParse(string a)
{
string b = llGetSubString(a,0,0);//save memory
return llParseStringKeepNulls(llDeleteSubString(a,0,0), [b],[]);
}
string TightListDump(list a, string b)
{
string c = (string)a;
if(llStringLength(b)==1)
if(llSubStringIndex(c,b) == -1)
jump end;
integer d = -llStringLength(b += "|\\/?!@#$%^&*()_=:;~{}[],\n\" qQxXzZ");
while(1+llSubStringIndex(c,llGetSubString(b,d,d)) && d)
++d;
b = llGetSubString(b,d,d);
@end;
c = "";//save memory
return b + llDumpList2String(a, b);
}
clear()
{
llMessageLinked(LINK_THIS, 2000, "T/-99", nullk);
}
go(string url)
{
llOwnerSay("Fetching page.");
current_url = url;
llMessageLinked(LINK_THIS, 2000, "U" + url, nullk);
}
on()
{
status = status | 1;
llSetColor(color_on, ALL_SIDES);
llListenRemove(advert_handle);
advert_handle = llListen(advert_channel, "", "", "");
llSetTimerEvent(discovery_timeout);
}
off()
{
status = status & -2;
llSetColor(color_off, ALL_SIDES);
llListenRemove(advert_handle);
llSetTimerEvent(0.0);
advertised_names = [];
advertised_still = [];
advertised_urls = [];
current_url = "";
}
config(string msg)
{
if(action && msg == "Back")
{
action = 0;
menu();
}
else if (action && msg == "More")
{
if(action == 1)
bkm_part = (bkm_part + 1) % llGetListLength(bookmarked_names);
else
adv_part = (adv_part + 1) % llGetListLength(advertised_names);
menu();
}
else
{
if (action == 1)
{
// from bookmarks menu
integer i = llListFindList(bookmarked_names, [msg]);
if (i < 0)
llOwnerSay("Bookmark not found.");
else
go(llList2String(bookmarked_urls, i));
}
else if (action == 2)
{
// from adverts menu
integer i = llListFindList(advertised_names, [msg]);
if (i < 0)
llOwnerSay("Server not found.");
else
go(llList2String(advertised_urls, i));
} else {
if (action = (1 + llListFindList(["Bookmarks", "Connect"],[msg])))
{
menu();
return;
}
else
{
if (msg == "Reload")
go(current_url);
else if (msg == "On")
{
on();
}
else if (msg == "Off")
{
off();
}
else if (msg == "Close") {
current_url = "";
llSetText("", zerov, 0.0);
clear();
}
else if (msg == "Sound Off" || msg == "Sound On")
{
status = (status & -3) | (2 * (msg == "Sound On"));
update(status);
}
else if (msg == "Anims Off" || msg == "Anims On")
{
status = (status & -5) | (4 * (msg == "Anims On"));
update(status);
}
else if (msg == "Plugins Off" || msg == "Plugins On")
{
status = (status & -9) | (8 * (msg == "Plugins On"));
update(status);
}
}
}
llListenRemove(handle);
}
}
update(integer u)
{
llMessageLinked(LINK_THIS, 12345, (string)u, "");
}
menu()
{
string opt;
list btns;
if (action == 0)
{
// main menu
opt = "Detected servers: " + (string)llGetListLength(advertised_urls);
if (status & 1)
{
btns = ["Off"];
} else {
btns = ["On"];
}
btns += ["ExitMenu", "Options"];
if (llGetListLength(bookmarked_names) > 0) btns += ["Bookmarks"];
if (llGetListLength(advertised_urls) > 0) btns += ["Connect"];
if (llStringLength(current_url)) btns += ["Close", "Reload"];
} else if (action == 1) {
// display bookmarks
opt = "Connect to:";
if (llGetListLength(bookmarked_names) < 12)
{
btns = bookmarked_names + ["Back"];
} else {
btns = llList2List(bookmarked_names, bkm_part * 10, bkm_part * 10 + 9) + ["More", "Back"];
}
} else if (action == 2) {
// display adverts
opt = "Connect to:";
if (llGetListLength(advertised_names) < 12)
{
btns = advertised_names + ["Back"];
} else {
btns = llList2List(advertised_names, adv_part * 10, adv_part * 10 + 9) + ["More", "Back"];
}
} else {
// display options
opt = "Sound:\t";
if (status & 2)
{
opt += "On";
btns = ["Sound Off"];
} else {
opt += "Off";
btns = ["Sound On"];
}
opt = "\nAnimations:\t";
if (status & 4)
{
opt += "On";
btns = ["Anims Off"];
} else {
opt += "Off";
btns = ["Anims On"];
}
opt = "\nPlugins:\t";
if (status & 8)
{
opt += "On";
btns = ["Plugins Off"];
} else {
opt += "Off";
btns = ["Plugins On"];
}
btns += ["Back", "ExitMenu"];
}
llDialog(llGetOwner(), opt, btns, channel);
}
default
{
state_entry()
{
bkm_part = 0;
adv_part = 0;
current_url = "";
llSetText("", zerov, 0.0);
if (status & 1) on();
}
changed(integer c)
{
if (c & CHANGED_INVENTORY)
{
if (llGetInventoryNumber(INVENTORY_NOTECARD) > 0)
{
line = 0;
llOwnerSay("Adding bookmarks...");
query = llGetNotecardLine(llGetInventoryName(INVENTORY_NOTECARD, 0), line);
}
}
}
dataserver(key id, string data)
{
if (id == query)
{
if (data != EOF)
{
// adding a bookmark from notecard
if (llGetSubString(data, 0, 0) != "U") return;
list l = TightListParse(llDeleteSubString(data, 0, 0));
if (llGetListLength(l) != 4)
{
llOwnerSay("Bad bookmark skipped: " + data);
} else {
if (llListFindList(bookmarked_urls, [data]) < 0)
{
string name_to_bkm = llList2String(l, 3);
if (llStringLength(name_to_bkm) > 24)
name_to_bkm = llGetSubString(name_to_bkm, 0, 23);
bookmarked_names += [name_to_bkm];
bookmarked_urls += [llDeleteSubString(data, 0, 0)];
} else llOwnerSay("Redundant bookmark skipped: " + data);
}
line = line + 1;
query = llGetNotecardLine(llGetInventoryName(INVENTORY_NOTECARD, 0), line);
} else {
llRemoveInventory(llGetInventoryName(INVENTORY_NOTECARD, 0));
if (llGetInventoryNumber(INVENTORY_NOTECARD) > 0)
{
line = 0;
llOwnerSay("Adding more bookmarks...");
query = llGetNotecardLine(llGetInventoryName(INVENTORY_NOTECARD, 0), line);
} else llOwnerSay("Done adding bookmarks.");
}
}
}
timer()
{
if (llGetTime() > discovery_timeout)
{
integer i;
integer max = llGetListLength(advertised_names);
llResetTime();
for (i = 0; i < max; ++i)
{
if (llList2Integer(advertised_still, i))
{
// server still present
advertised_still = llListReplaceList(advertised_still, [0], i, i);
} else {
// server wasn't there last time, remove it
advertised_names = llDeleteSubList(advertised_names, i, i);
advertised_urls = llDeleteSubList(advertised_urls, i, i);
advertised_still = llDeleteSubList(advertised_still, i, i);
}
}
if (llGetListLength(advertised_names) == 0)
llSetColor(color_on, ALL_SIDES);
}
}
touch_start(integer c)
{
if (llDetectedKey(0) != llGetOwner()) return;
action = 0;
adv_part = 0;
bkm_part = 0;
llListenRemove(handle);
channel = (integer)llFrand(500000000) - 800000000;
handle = llListen(channel, "", llGetOwner(), "");
llResetTime();
menu();
}
listen(integer chan, string name, key id, string msg)
{
if (chan == channel)
{
// configuration command received
llResetTime();
config(msg);
} else if (chan == advert_channel)
{
if (llGetSubString(msg, 0, 0) == "U") // only URLs
{
integer inde = llListFindList(advertised_urls, [llDeleteSubString(msg, 0, 0)]);
if (inde < 0)// only URLs we don't have
{
list temp = TightListParse(llDeleteSubString(msg, 0, 0));
if (llGetListLength(temp) >= 4) // skip incomplete URLs
{
llSetColor(color_flash, ALL_SIDES);
string na = llList2String(temp, 3);
llOwnerSay("Found server: " + na);
if (llStringLength(na) > 24)
na = llGetSubString(na, 0, 23);
advertised_names += [na];
advertised_urls += [llDeleteSubString(msg, 0, 0)];
advertised_still += [1];
}
else if(debug)
llOwnerSay("Incomplete broadcasted URL");
} else {
// refreshing the server if it exists in the list
advertised_still = llListReplaceList(advertised_still, [1], inde, inde);
}
}
}
}
}
TLTP Browser - Permissions Handler:
Untested, you don't need this but if you want to play animations etc then you need this.
Not to mention that the key handler hasn't been writen, nor the specs for how it should be writen
// TLTP Browser - Permissions Handler
// Version 0.11
// Script handles anything that requires permissions.
list ANIMATIONS;
list keys;
list anim;
list ranim;
list sanim;
integer perms;
integer request_perms;
integer status;
list ianim;
integer ianimi;
list key_masks;
list key_urls;
key user;
list TightListParse(string a)
{
string b = llGetSubString(a,0,0);//save memory
return llParseStringKeepNulls(llDeleteSubString(a,0,0), [a=b],[]);
}
string TightListDump(list a, string b)
{
string c = (string)a;
if(llStringLength(b)==1)
if(llSubStringIndex(c,b) == -1)
jump end;
integer d = -llStringLength(b += "|\\/?!@#$%^&*()_=:;~{}[],\n\" ");
while(1+llSubStringIndex(c,llGetSubString(b,d,d)) && d)
++d;
b = llGetSubString(b,d,d);
@end;
c = "";//save memory
return b + llDumpList2String(a, b);
}
string getAnim(string c)
{
if(llGetInventoryType(c) == INVENTORY_ANIMATION);
else if(llListFindList(ANIMATIONS,[c = llToLower(c)]) != -1);
else
{
//Don't use case sensative seperators!!!
integer a = llListFindList(TightListParse(llToLower(TightListDump(ianim,""))),[c]);
c = llList2String(ianim + [""], a);
}
return c;
}
integer PermCheck(integer a, integer b, key d)
{
if(d == "")
d = llGetOwner();
if(user != d)
request_perms = perms = 0;
if(perms & a)
return 1;
else
{
status = status | b;
user = d;
request_perms = request_perms | perms | a;
if(!(status & 16))
llSetTimerEvent(1.0);
status = status | 16;
}
return 0;
}
stopAllAnim(key d)
{
if (PermCheck(PERMISSION_TRIGGER_ANIMATION, 1, d))
{
integer a = -llGetListLength(ranim);
integer b;
string c;
while(a)
{
llStopAnimation(c = llList2String(ranim, a++));
if(1 + b = llListFindList(ranim, [llToLower(c)]))
ranim = llDeleteSubList(ranim,b,b);
}
sanim = ranim = [];
}
}
stopAnim(string c, key d)
{
if (PermCheck(PERMISSION_TRIGGER_ANIMATION, 2, d))
{
llStopAnimation(c);
integer b = llListFindList(ranim, [llToLower(c)]);
if(1 + b)
ranim = llDeleteSubList(ranim,b,b);
}
else
sanim += c;
}
startAnim(string c, key d)
{
if (PermCheck(PERMISSION_TRIGGER_ANIMATION, 4, d))
{
if(llGetInventoryType(c) == INVENTORY_ANIMATION);
else if(llListFindList(ANIMATIONS,[c = llToLower(c)]) != -1);
else
{
// llOwnerSay("Animation \"" + c + "\"not found");
jump skip;
}
llStartAnimation(c);
if(-1 == llListFindList(ranim, [c = llToLower(c)]))
ranim += c;
} else {
anim += c;
}
@skip;
}
takeKeys()
{//will write this later
keys = [];
}
release_key(string c, key d)
{;}
release_keys()
{;}
refresh()
{
integer a = llGetInventoryNumber(INVENTORY_ANIMATION);
if(a != ianimi)
{//we coud do a better check then this but i'm too lazy :P
ianim = [];
ianimi = a;
while(--a)
ianim += llGetInventoryName(INVENTORY_ANIMATION,a);
}
}
default
{
state_entry()
{
ANIMATIONS = ["aim_l_bow","aim_r_bazooka","aim_r_handgun","aim_r_rifle",
"angry_fingerwag","angry_tantrum","away","backflip","blowkiss","bow","brush",
"busy","clap","courtbow","crouch","crouchwalk","dance1","dance2","dance3",
"dance4","dance5","dance6","dance7","dance8","dead","drink","express_afraid",
"express_afraid_emote","express_anger","express_anger_emote","express_bored",
"express_bored_emote","express_cry","express_cry_emote","express_disdain",
"express_embarrased","express_embarrassed_emote","express_frown","express_kiss",
"express_laugh","express_laugh_emote","express_open_mouth","express_repulsed",
"express_repulsed_emote","express_sad","express_sad_emote","express_shrug",
"express_shrug_emote","express_smile","express_surprise","express_surprise_emote",
"express_tongue_out","express_toothsmile","express_wink","express_wink_emote",
"express_worry","express_worry_emote"," falldown","female_walk","fist_pump","fly",
"flyslow","hello","hold_l_bow","hold_r_bazooka"]+["hold_r_handgun","hold_r_rifle",
"hold_throw_r","hover","hover_down","hover_up","impatient","jump","jumpforjoy",
"kick_roundhouse_r","kissmybutt","land","laugh_short","motorcycle_sit","musclebeach",
"no_head","no_unhappy","nyanya","peace","point_me","point_you","prejump","punch_l",
"punch_onetwo","punch_r","rps_countdown","rps_paper","rps_rock","rps_scissors","run",
"salute","shoot_l_bow","shout","sit","sit_female","sit_generic","sit_ground",
"sit_to_stand","sleep","smoke_idle","smoke_inhale","smoke_throw_down","snapshot",
"soft_land","","stand","stand_1","stand_2","stand_3","stand_4","standup","stretch",
"stride","surf","sword_strike_r","talk","throw_r","tryon_shirt","turn_180",
"turnback_180","turnleft","turnright","type","walk","whisper","whistle",
"wink_hollywood","yes_happy","yes_head","yoga_float"];
refresh();
}
link_message(integer a, integer b, string c, key d)
{
if(b == 2012)
stopAllAnim(d);
else if(b == 2010)
startAnim(c,d);
else if(b == 2011)
stopAnim(c,d);
else if(b == 2013)
{
keys += c;
if(PermCheck(PERMISSION_TAKE_CONTROLS, 8, d))
takeKeys();
}
else if(b == 2014)
release_key(c,d);
else if(b == 2015)
release_keys();
else if(b == 2016)
PermCheck((integer)c, request_perms = perms = 0, d);
else if(b == 2017)
PermCheck((integer)c, 0, d);
}
run_time_permissions(integer p)
{
user = llGetPermissionsKey();
perms = p;
if(p & PERMISSION_TAKE_CONTROLS && (status & 8))
takeKeys();
if (p & PERMISSION_TRIGGER_ANIMATION)
{
integer a = -llGetListLength(anim);
string b;
if(a)
{
do
{
llStartAnimation(b = llList2String(anim, a));
if(-1 == llListFindList(ranim, [b = llToLower(b)]))
ranim += b;
}
while(++a);
anim = [];
}
if(a = -llGetListLength(sanim))
{
integer c;
do
{
llStopAnimation(b = llList2String(sanim, a));
if(1 + c = llListFindList(ranim, [llToLower(b)]))
ranim = llDeleteSubList(ranim,c,c);
}
while(++a);
sanim = [];
}
}
}
changed(integer a)
{
if(a & CHANGED_INVENTORY)
refresh();
}
timer()
{
llRequestPermissions(user, request_perms);
request_perms = 0;
llSetTimerEvent(0.0);
status = status & -17;
}
// control(key a, integer b, integer c)
// {
// llMessageLinked(LINK_THIS,url_code,"","")
// }
}