Difference between revisions of "User:Mr Lovenkraft"
(4 intermediate revisions by the same user not shown) | |||
Line 540: | Line 540: | ||
} | } | ||
</lsl> | </lsl> | ||
---- | |||
===Tip Jar with option to keep a percentage=== | |||
This tip jar is very simple to use, just edit the settings notecard | |||
and type in "TRUE" or "FALSE" as to keep or not, then type in your | |||
percent to keep. Notecard example provided below. | |||
====The Notecard==== | |||
# TipJar by Mr Lovenkraft | |||
# Lines with " # " are comments, do not modify this card without knowledge of the scripting structure | |||
# Below are the settings for the TipJar | |||
# The lines with "" are just quoted, the quotes are not needed. | |||
# | |||
#Do you want to keep a %? (Use " TRUE " or " FALSE " below) | |||
TRUE | |||
#Kept TRUE or FALSE above | |||
# | |||
#Amount to keep in % below. | |||
20 | |||
====The Script==== | |||
<lsl> | |||
//TipJar by Mr Lovenkraft | |||
//======================= | |||
//Global variables============== | |||
//Do not modify if you have | |||
//No idea what each line does :) | |||
//============================== | |||
//Start globals | |||
key owner; | |||
key user; | |||
key notecard; | |||
list settings; | |||
integer line; | |||
integer percent_kept; | |||
integer inuse; | |||
integer keeping; | |||
integer paid; | |||
integer totalt; | |||
integer ta; | |||
integer lt; | |||
string note = "*Settings"; | |||
set_text() | |||
{ | |||
if (inuse == TRUE) | |||
{ | |||
//This is for the actual amount. | |||
llSetText(llKey2Name(user) + " logged in.\nLast tip: "+ | |||
(string)lt+ "\nTotal tips: " + (string)ta, <0,1,0>, 1.0); | |||
//This line is for settext with only what the logged in actually get. | |||
// llSetText(llKey2Name(user) + " logged in.\nLast tip: "+ | |||
// (string)paid+ "\nTotal tips: " + (string)totalt, <0,1,0>, 1.0); | |||
} | |||
else if (inuse == FALSE) | |||
{ | |||
llSetText("Not in use. Touch to log in.", <1,0,0>, 1.0); | |||
} | |||
} | |||
divide(integer amount) | |||
{ | |||
integer kept; | |||
kept = ((amount * percent_kept) / 100); | |||
paid = (amount - kept); | |||
pay(user, paid); | |||
totalt += paid; | |||
set_text(); | |||
debug((string)kept + " kept. Amount paid: "+(string)paid); | |||
} | |||
pay(key av, integer amount) | |||
{ | |||
llGiveMoney(av, amount); | |||
} | |||
debug(string DEBUG) | |||
{ | |||
//llOwnerSay(DEBUG);//Remove commented lines "//" when you want to debug, else add them to turn off debugging | |||
} | |||
//End globals | |||
default | |||
{ | |||
on_rez(integer r) | |||
{ | |||
llResetScript(); | |||
} | |||
state_entry() | |||
{ | |||
owner = llGetOwner(); | |||
line = 0; | |||
totalt = 0; | |||
ta = 0; | |||
lt = 0; | |||
keeping = FALSE; | |||
inuse = FALSE; | |||
settings = []; | |||
user = NULL_KEY; | |||
set_text(); | |||
llSetPayPrice(PAY_HIDE, [PAY_HIDE, PAY_HIDE, PAY_HIDE, PAY_HIDE]); | |||
if (llGetInventoryNumber(INVENTORY_NOTECARD) <= 0) | |||
{ | |||
llOwnerSay(note +" not found, please put this notecard in and re-rez."); | |||
} | |||
else if (llGetInventoryNumber(INVENTORY_NOTECARD) == 1) | |||
{ | |||
notecard = llGetNotecardLine(note, line); | |||
} | |||
else if (llGetInventoryNumber(INVENTORY_NOTECARD) >= 2) | |||
{ | |||
integer num = llGetInventoryNumber(INVENTORY_NOTECARD); | |||
integer i; | |||
for(i = 0; i < num; i++) | |||
{ | |||
llRemoveInventory(llGetInventoryName(INVENTORY_NOTECARD, i)); | |||
} | |||
llOwnerSay(note +" not found, please put this notecard in and re-rez."); | |||
} | |||
} | |||
touch_start(integer total_number) | |||
{ | |||
if (inuse == FALSE) | |||
{ | |||
paid = 0; | |||
totalt = 0; | |||
user = llDetectedKey(0); | |||
inuse = TRUE; | |||
set_text(); | |||
debug("Not in use, adding: "+llDetectedName(0)); | |||
} | |||
else if (inuse == TRUE) | |||
{ | |||
if (llDetectedKey(0) == user) | |||
{ | |||
debug("In use, logging out: "+llDetectedName(0)); | |||
inuse = FALSE; | |||
set_text(); | |||
user = NULL_KEY; | |||
} | |||
else | |||
{ | |||
llInstantMessage(llDetectedKey(0), "This tipjar is in use, please try another."); | |||
} | |||
} | |||
} | |||
money(key id, integer amount) | |||
{ | |||
if (user != NULL_KEY) | |||
{ | |||
lt = amount; | |||
ta += amount; | |||
if (keeping == TRUE) | |||
{ | |||
debug("keeping a percent"); | |||
divide(amount); | |||
} | |||
else if (keeping == FALSE) | |||
{ | |||
debug("not keeping a percent"); | |||
if (inuse == TRUE) | |||
{ | |||
pay(user, amount); | |||
} | |||
else if (inuse == FALSE) | |||
{ | |||
pay(id, amount); | |||
llInstantMessage(id, "This tipjar is not in use, money refuned."); | |||
} | |||
} | |||
} | |||
else if (user == NULL_KEY) | |||
{ | |||
pay(id, amount); | |||
llInstantMessage(id, "This tipjar is not in use, money refuned."); | |||
} | |||
} | |||
run_time_permissions(integer perm) | |||
{ | |||
if (perm & PERMISSION_DEBIT) | |||
{ | |||
debug("Got permissions"); | |||
llSetPayPrice(20, [25, 50, 75, 100]); | |||
} | |||
} | |||
dataserver(key Qid, string data) | |||
{ | |||
if (Qid == notecard) | |||
{ | |||
if (data != EOF) | |||
{ | |||
if (llGetSubString(data, 0, 0) != "#") | |||
{ | |||
settings += [data]; | |||
line += 1; | |||
notecard = llGetNotecardLine(note, line); | |||
} | |||
else if (llGetSubString(data, 0, 0) == "#"); | |||
{ | |||
line += 1; | |||
notecard = llGetNotecardLine(note, line); | |||
} | |||
} | |||
else | |||
{ | |||
llRequestPermissions(owner, PERMISSION_DEBIT); | |||
llOwnerSay("Settings loaded."); | |||
if ((integer)llList2String(settings, 0) == 0) | |||
{ | |||
keeping = TRUE; | |||
} | |||
else if ((integer)llList2String(settings, 0) == 1) | |||
{ | |||
keeping = FALSE; | |||
} | |||
percent_kept = (integer)llList2String(settings, 1); | |||
line = 0; | |||
debug("Keeping? " + (string)keeping + " What percent if kept: "+(string)percent_kept); | |||
} | |||
} | |||
} | |||
} | |||
</lsl> | |||
==Useful snippets== | ==Useful snippets== | ||
Codes here are not supported by me, they are for learning purposes only | Codes here are not supported by me, they are for learning purposes only |
Latest revision as of 14:57, 1 March 2008
Open source codes from Mr Lovenkraft
I've just starting this page in the hopes of having quite a few codes open sourced for those of you who either can't find what you are looking for, or just want an easy place to look for codes :)
Removable prim clothing script
This script is written to be placed in the root prim of an object. <lsl> //Removable clothing by Mr Lovenkraft, free to use by anyone. //Fully open source, but credit going to Mr Lovenkraft for his effort :) key user; //Person touching the clothing. key owner; //The owner of course O.o integer diaChan; //Random Dialog channel to prevent other clothing items from listening.. integer listenNum; //Used to start a listen, and remove it. list buttons = ["Tear", "Look", "Flick", "Tug"];//Buttons to click on of course. integer touchable = TRUE; integer removeable; int()//The actual starting menu and calculating random channel to listen on. {
touchable = FALSE; diaChan = llCeil(llFrand(-9999999)); if(diaChan >= 0) //Just in case it returns 0, we want a negative listen :) { diaChan += llRound(llFrand(-9999999)); //Recalculate } listenNum = llListen(diaChan, "", "", "");//Listen handler to remove listen when done. llDialog(user, "What would you like to do?", buttons, diaChan); //Menu with the buttons o.o llSetTimerEvent(15); //Menu time out, in case someone doesn't pick an option :)
} default {
on_rez(integer r) { owner = llGetOwner(); //Of course it gets the owner O.o } state_entry() { owner = llGetOwner(); //Again just in case it didn't get the point. } touch_start(integer total_number) { if(touchable) //If it hasn't been touched, let it be touched { user = llDetectedKey(0); //Makes the person touching, the owner. int(); //When touched, get the random channel. } } attach(key av) { if(av) { removeable = TRUE; //If actually on an av, allow clothing to request permissions for detach. } else { removeable = FALSE; //Oposite if no av :) } } run_time_permissions(integer perm) { if(perm & PERMISSION_ATTACH) { llWhisper(0, llKey2Name(user) + " rips " + llKey2Name(owner) +"'s clothing right off!"); llDetachFromAvatar( ); //Detach from av of course. } } listen(integer chan, string name, key id, string msg) { if(llToLower(msg)=="tug") //We use llToLower(msg) so that it's not case sensitive. :) { llWhisper(0, llKey2Name(user) + " tugs on " + llKey2Name(owner) +"'s clothing."); } if(llToLower(msg)=="flick") { llWhisper(0, llKey2Name(user) + " flicks " + llKey2Name(owner) +"'s clothing."); } if(llToLower(msg)=="look") { llWhisper(0, llKey2Name(user) + " looks at " + llKey2Name(owner) +"'s clothing."); } if(llToLower(msg)=="tear") { if(removeable) { llRequestPermissions(owner, PERMISSION_ATTACH); } else { llWhisper(0, "Can not remove clothing that is not worn."); } } touchable = TRUE; llListenRemove(listenNum); //Stop listening to prevent lag :) } timer() { touchable = TRUE; llSetTimerEvent(0.0); //Stops the timer llWhisper(0, "Menu time out..."); }
} </lsl>
Stop all animations: basic
<lsl> //Stop all animations by Mr Lovenkraft //Useful learning codes from the large inventory of Mr Lovenkraft ;) list anims; key av; default {
touch_start(integer total_number) { llRequestPermissions(llDetectedKey(0), PERMISSION_TRIGGER_ANIMATION);//Dur, requests permissions. av = llDetectedKey(0); //Person to stop animations for. } run_time_permissions(integer perm)//Runs if we get permissions. { anims = []; //Clears the list of any past animations. anims = llGetAnimationList(av); //Gets the current users animations playing. integer index = llGetListLength(anims); //The amount of animations for stopping. integer i; //Starting place for our loop. for(i=0; i<index; i++)//Runs through for each animation in the list. { llStopAnimation(llList2String(anims, i)); //Stops the animation in the list at point i. } }
} </lsl>
Single pose: pose ball
Single animation poseball that uses the animation in the inventory <lsl> //Basic Poseball script default {
state_entry() { llSitTarget(<0.0, 0.0, -0.5>, ZERO_ROTATION);//Sets a sit target to actually work } changed(integer change) { if (change & CHANGED_LINK) { key av = llAvatarOnSitTarget(); if (av)//If there is an av on it { llRequestPermissions(av, PERMISSION_TRIGGER_ANIMATION);//Ask permissions } } } run_time_permissions(integer perm) { if(perm & PERMISSION_TRIGGER_ANIMATION) { llStopAnimation("sit");//Stops the default sit llStartAnimation(llGetInventoryName(INVENTORY_ANIMATION,0));//Start the animation inside the prim } }
} </lsl>
Cycle pose ball: touch cycle
<lsl> //Multi poseball/pole by Mr lovenkraft //Open sourced ;) list anims; key av; integer pos; integer listSize; integer sat_on; int() {
if(sat_on) { llRequestPermissions(av, PERMISSION_TRIGGER_ANIMATION);//Request permissions to get the next animation } else { llWhisper(0, "No one sitting on this object."); }
} default {
state_entry() { pos = 0; anims = []; llSitTarget(<0.0, 0.0, 0.1>, ZERO_ROTATION);//Sets the sit pose for the target } changed(integer change)//something has changed with this object { if(change & CHANGED_INVENTORY)//if only the inventory is changed of course ;) { pos = 0;//start the post over anims = []; //clear the list integer i; integer totA = llGetInventoryNumber(INVENTORY_ANIMATION);//gets the total animations for(i=0; i<totA; i++) { anims += [llGetInventoryName(INVENTORY_ANIMATION, i)];//adds each animation name to list } llOwnerSay("Animaions inside: " + llList2CSV(anims));//Tell the owner how many animations inside } if(change & CHANGED_LINK) { av = llAvatarOnSitTarget(); if(av) //if there is really someone sitting on it { sat_on = TRUE; //If someone is sitting make it true int();//Start animation } else { sat_on = FALSE; } } } run_time_permissions(integer perm)//got permissions from user { if(perm & PERMISSION_TRIGGER_ANIMATION) { llStopAnimation(llGetInventoryName(INVENTORY_ANIMATION, pos));//Stop last animation pos += 1;//go to next in list if(pos >= listSize)//if at the end of the list { pos = 0; } llStopAnimation("sit"); llStartAnimation(llGetInventoryName(INVENTORY_ANIMATION, pos));//Start the next animation } } touch_start(integer total_number) { listSize = llGetListLength(anims); int(); //start the new animation }
} </lsl>
Basic notecard access list
This is an example notecard, goes in the room prim of lockable object
Mr Lovenkraft Fname2 Lastname2 Fname3 Lastname3
This also goes in your object you wish to lock/unlock etc <lsl> list allowed = []; string allow_list = "Allow"; key owner; key note_card; integer line; integer list_pos; integer i; integer locked; int(integer on) {
if(on==0) { llWhisper(0, "Locked, only allowed may use."); locked = TRUE; } if(on==1) { llWhisper(0, "Unlocked, anyone may use."); locked = FALSE; } if(on==3) { allowed = []; note_card = llGetNotecardLine(allow_list, line); }
} default {
on_rez(integer r) { list_pos = 0; line = 0; int(3); owner = llGetOwner(); } state_entry() { int(3); list_pos = 0; line = 0; llListen(0, "", owner, ""); note_card = llGetNotecardLine(allow_list, line); llOwnerSay((string)llGetFreeMemory()); } changed(integer change) { if(change & CHANGED_INVENTORY) { int(3); } } listen(integer chan, string name, key id, string msg) { if(llToLower(msg)=="lock") { int(0); } if(llToLower(msg)=="unlock") { int(1); } } touch_start(integer t) { if(locked) { string Ntest = llDetectedName(0); integer index = llListFindList(allowed, [Ntest]); if(index != -1) { llWhisper(0,"Opened for: "+llList2String(allowed, index)+"."); } else { llWhisper(0, "You are not on the access list."); } } else { llWhisper(0, "Opened."); } } dataserver(key Qid, string data) { if (Qid == note_card) { if (data != EOF) { allowed += data; line += 1; note_card = llGetNotecardLine(allow_list, line); } else { line = 0; llOwnerSay("Done."); llOwnerSay(llList2CSV(allowed)); llOwnerSay("Memory left: "+(string)llGetFreeMemory()); } } }
}
</lsl>
Greeter: landmark/notecard giver
This uses two scripts, one for detect and give, and one for handling the list and seeing if that person has been given a notecard/landmark.
Greeter <lsl> //Greeter by Mr Lovenkraft key owner; integer counter; //Total amount of people greeted key user; //Person to greet default {
on_rez(integer r) { llResetScript(); } state_entry() { counter = 0; llMessageLinked(LINK_THIS, 0, "clear", NULL_KEY); //Clears the greeted list owner = llGetOwner(); //Gets the new owner } collision_start(integer c) { user = llDetectedKey(0); //Person colliding with the object is the user if(counter >= 70)//If our counter goes to 70 or higher (this prevents the list from getting to big) { llMessageLinked(LINK_THIS, 0, "clear", NULL_KEY);//Clear the list again counter = 0;//Reset the counter } llMessageLinked(LINK_THIS, 10, llDetectedName(0), NULL_KEY);//Sends the name to be greeted } link_message(integer sender, integer num, string str, key id) { if(str=="give") { llGiveInventory(user, llGetInventoryName(INVENTORY_NOTECARD, 0));//Give notecard llGiveInventory(user, llGetInventoryName(INVENTORY_LANDMARK, 0));//Give landmark counter += 1;//Add one to our counter } }
} </lsl>
User handler: List to keep track of people, so that it prevents multiple copies to the same user <lsl> list names;//Names of people greeted since last reset string test;//Name to test with the list integer index; default {
on_rez(integer r) { llResetScript(); } state_entry() { names = [];//Clear the names on rez } link_message(integer sender, integer num, string str, key id) { if(str == "clear") { names = [];//Resets the list } if(num == 10) { test = str;//Makes the name sent by the greeter the test index = llListFindList(names, [test]); //Checks to see if it is in the list if(index == -1)//If not found in the list { names += str;//Add the name to the list if not found llMessageLinked(LINK_THIS, 0, "give", NULL_KEY);//Greet the new user } } }
} </lsl>
Texture Organizer
This is just a simple texture organizer for those with to many textures for their own good hehe, I didn't comment this one but it works fine :) <lsl> //Texture organizer by Mr Lovenkraft key owner; key texture_key; string texture_name; integer inventory_pos; integer diaChan; integer listen_handler; integer invTotal; list button_options = ["Prev", "Next", "Give"]; dia() {
diaChan = llRound(llFrand(-9999999)); if(diaChan >= 0) { diaChan += llRound(llFrand(-9999999)); } listen_handler = llListen(diaChan, "", "", ""); llDialog(owner, "Pick your option below", button_options, diaChan); llSetTimerEvent(30);
} change(string choice) {
if(choice == "next") { inventory_pos += 1; if(inventory_pos >= invTotal) { inventory_pos = 0; } } if(choice == "prev") { inventory_pos -= 1; if(inventory_pos <= -1) { inventory_pos = invTotal; } } llSetTexture(llGetInventoryName(INVENTORY_TEXTURE, inventory_pos), ALL_SIDES); llSetText("Texture Name: "+llGetInventoryName(INVENTORY_TEXTURE, inventory_pos) +"\nTexture Key: "+(string)llGetInventoryKey(llGetInventoryName(INVENTORY_TEXTURE, inventory_pos)) , <1,1,1>, 1.0);
} default {
on_rez(integer r) { llResetScript(); } state_entry() { owner = llGetOwner(); inventory_pos = 0; texture_name = ""; texture_key = ""; invTotal = llGetInventoryNumber(INVENTORY_TEXTURE); } changed(integer change) { if(change & CHANGED_INVENTORY) { invTotal = llGetInventoryNumber(INVENTORY_TEXTURE); } } touch_start(integer t) { if(llDetectedKey(0)==owner) { dia(); } else { llWhisper(0, "Owner only."); } } listen(integer chan, string name, key id, string msg) { llSetTimerEvent(30); if(llToLower(msg)=="next") { change("next"); } if(llToLower(msg)=="prev") { change("prev"); } if(llToLower(msg)=="give") { llGiveInventory(owner, llGetInventoryName(INVENTORY_TEXTURE, inventory_pos)); } dia(); } timer() { if(listen_handler) { llWhisper(0, "Option not chose, menu timed out."); llListenRemove(listen_handler); llSetTimerEvent(0); } }
} </lsl>
Tip Jar with option to keep a percentage
This tip jar is very simple to use, just edit the settings notecard and type in "TRUE" or "FALSE" as to keep or not, then type in your percent to keep. Notecard example provided below.
The Notecard
# TipJar by Mr Lovenkraft # Lines with " # " are comments, do not modify this card without knowledge of the scripting structure # Below are the settings for the TipJar # The lines with "" are just quoted, the quotes are not needed. # #Do you want to keep a %? (Use " TRUE " or " FALSE " below) TRUE #Kept TRUE or FALSE above # #Amount to keep in % below. 20
The Script
<lsl> //TipJar by Mr Lovenkraft //=======================
//Global variables============== //Do not modify if you have //No idea what each line does :) //============================== //Start globals key owner; key user; key notecard; list settings; integer line; integer percent_kept; integer inuse; integer keeping; integer paid; integer totalt; integer ta; integer lt; string note = "*Settings"; set_text() {
if (inuse == TRUE) { //This is for the actual amount. llSetText(llKey2Name(user) + " logged in.\nLast tip: "+ (string)lt+ "\nTotal tips: " + (string)ta, <0,1,0>, 1.0);
//This line is for settext with only what the logged in actually get. // llSetText(llKey2Name(user) + " logged in.\nLast tip: "+ // (string)paid+ "\nTotal tips: " + (string)totalt, <0,1,0>, 1.0);
} else if (inuse == FALSE) { llSetText("Not in use. Touch to log in.", <1,0,0>, 1.0); }
} divide(integer amount) {
integer kept; kept = ((amount * percent_kept) / 100); paid = (amount - kept); pay(user, paid); totalt += paid; set_text(); debug((string)kept + " kept. Amount paid: "+(string)paid);
} pay(key av, integer amount) {
llGiveMoney(av, amount);
}
debug(string DEBUG) {
//llOwnerSay(DEBUG);//Remove commented lines "//" when you want to debug, else add them to turn off debugging
} //End globals default {
on_rez(integer r) { llResetScript(); } state_entry() { owner = llGetOwner(); line = 0; totalt = 0; ta = 0; lt = 0; keeping = FALSE; inuse = FALSE; settings = []; user = NULL_KEY; set_text(); llSetPayPrice(PAY_HIDE, [PAY_HIDE, PAY_HIDE, PAY_HIDE, PAY_HIDE]); if (llGetInventoryNumber(INVENTORY_NOTECARD) <= 0) { llOwnerSay(note +" not found, please put this notecard in and re-rez."); } else if (llGetInventoryNumber(INVENTORY_NOTECARD) == 1) { notecard = llGetNotecardLine(note, line); } else if (llGetInventoryNumber(INVENTORY_NOTECARD) >= 2) { integer num = llGetInventoryNumber(INVENTORY_NOTECARD); integer i; for(i = 0; i < num; i++) { llRemoveInventory(llGetInventoryName(INVENTORY_NOTECARD, i)); } llOwnerSay(note +" not found, please put this notecard in and re-rez."); } } touch_start(integer total_number) { if (inuse == FALSE) { paid = 0; totalt = 0; user = llDetectedKey(0); inuse = TRUE; set_text(); debug("Not in use, adding: "+llDetectedName(0)); } else if (inuse == TRUE) { if (llDetectedKey(0) == user) { debug("In use, logging out: "+llDetectedName(0)); inuse = FALSE; set_text(); user = NULL_KEY; } else { llInstantMessage(llDetectedKey(0), "This tipjar is in use, please try another."); } } } money(key id, integer amount) { if (user != NULL_KEY) { lt = amount; ta += amount; if (keeping == TRUE) { debug("keeping a percent"); divide(amount); } else if (keeping == FALSE) { debug("not keeping a percent"); if (inuse == TRUE) { pay(user, amount); } else if (inuse == FALSE) { pay(id, amount); llInstantMessage(id, "This tipjar is not in use, money refuned."); } } } else if (user == NULL_KEY) { pay(id, amount); llInstantMessage(id, "This tipjar is not in use, money refuned."); } } run_time_permissions(integer perm) { if (perm & PERMISSION_DEBIT) { debug("Got permissions"); llSetPayPrice(20, [25, 50, 75, 100]); } } dataserver(key Qid, string data) { if (Qid == notecard) { if (data != EOF) { if (llGetSubString(data, 0, 0) != "#") { settings += [data]; line += 1; notecard = llGetNotecardLine(note, line); } else if (llGetSubString(data, 0, 0) == "#"); { line += 1; notecard = llGetNotecardLine(note, line); } } else { llRequestPermissions(owner, PERMISSION_DEBIT); llOwnerSay("Settings loaded."); if ((integer)llList2String(settings, 0) == 0) { keeping = TRUE; } else if ((integer)llList2String(settings, 0) == 1) { keeping = FALSE; } percent_kept = (integer)llList2String(settings, 1); line = 0; debug("Keeping? " + (string)keeping + " What percent if kept: "+(string)percent_kept); } } }
} </lsl>
Useful snippets
Codes here are not supported by me, they are for learning purposes only use at your own risk :)
Max list length
This will only allow a list to hold a max #, after that number is met it will update the oldest <lsl> list words; integer index; string test; integer listlength; integer i; default {
state_entry() { i = 0; llListen(0, "", "", ""); } listen(integer chan, string name, key id, string msg) { if(llToLower(llGetSubString(msg, 0, 3)) == "add ") { listlength = llGetListLength(words); test = llGetSubString(msg, 4, -1); index = llListFindList(words, [test]); list max = [test]; if(listlength <= 2) { if(index == -1) { words += [test]; llWhisper(0, test + " was stored. "+ "Total words: "+(string)(listlength + 1)); return; } if(index != -1) { llWhisper(0, "Word is already in list."); } return; } if(listlength >= 3) { if(index == -1) { if(i <= listlength) { llOwnerSay("Max words added, removing oldest."); words = llListReplaceList(words, max, i, i); i += 1; return; } if(i >= listlength) { i = 0; llOwnerSay("Max words added, removing oldest."); words = llListReplaceList(words, max, i, i); return; } } if(index != -1) { llWhisper(0, "Word is already in list."); } } } if(llToLower(msg)=="list") { llWhisper(0, llDumpList2String(words, ".\n")+"."); } }
} </lsl>