User:Lynnore Vaher

From Second Life Wiki
Jump to: navigation, search


A little dump of what i made, started scripting a few months ago. Things can be better i know, but this works so i'm good with it.

Menu Pagination Script <lsl> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // PageScript by Lynnore Vaher // Version number 1.00 // // !Important: // - Give me credit if you use parts or fully use this script, eg: mention as special thanks or something. // - If you like this script, please consider a small(or big) donation. // - This script can NOT be resold as full perm since i offer this for free. // - This script CAN be given away/copied but the top text has to stay. // - You can not ask me for help, if you have this script i assume you have scripting experience. // // Notes: // - Can handle only 1 person at a time. // - Don't feel like explaining the whole thing. // // BugFixes: // - Fixed a bug where a back button got added with lists just above 12 items. // - Fixed llPagesFunc start wich gave an error with lists with less then 12 items. // - Deleted a line of code wich wasn't suppose to be there, this cause a wrong display of the menu. // // Usage: // - Put all the functions and variables in your script. // - Call the menu with llPagesFunc(LISTNAME, USERKEY), where LISTNAME is the list of buttons you want and // USERKEY is the key of the person to send the dialog to. This is NEEDED before calling the next and back functions // - Call the next pages with llPagesNext(LISTNAME, USERKEY). // - Call the previous pages with llPagesBack(LISTNAME, USERKEY). // - This is a fully working example and requires some experience with scripting. // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// Start Global Variables // ----------------------- integer curPage = 0; // Current page, Do not change this. integer curStart = 0; // The start of the buttonlist, don't change. integer curEnd = 9; // The end of the buttonlist, do not change this. integer curLength = 0; // Length of the list, will be changed by the script. integer curChan = 0; // Random channel, script will change this. integer curListen = 0; // Listen number, again script will change this. integer maxPerDia = 9; // Max items per dialog, don't change this. integer itemBusy = FALSE; // Check if dialog is in use FALSE = no, TRUE = yes. integer totalPages = 0; // Total of pages, script will calculate this.

float curDelay = 60.0; // Time before the listen will time out.

string curMsg = "Select wich notecard you want to load."; // Dialog message

list FirstAdd = [" ", "Exit", "Next >"]; // Added on the first page list MidAdd = ["< Back", "Exit", "Next >"]; // Added on middle pages list BackAdd = ["< Back", "Exit", " "]; // Added on last page list notes = ["1", "2"]; // This is the actual list that will be split in pages // -------------------- // End Global Variables

// Start Functions // ---------------- llReset(){ // Reset the global variables

   curStart = 0;
   curEnd = 0;
   maxPerDia = 9;
   itemBusy = TRUE;

} llPagesFunc(list notes, key user){ // Create the start dialog

   list curButtons = [];
   llReset();
   curLength = llGetListLength(notes); 
   totalPages = llCeil((float)curLength / 9.0);
   if(curLength <= 12){
       totalPages = 1;
       for(curStart=0;curStart<curLength;curStart++){
           curButtons += llList2String(notes, curStart);
       }
       curButtons = FillMenu(curButtons);
   }else if(curLength > 12){
       totalPages = llCeil((float)curLength / 9.0);
       for(curStart=0;curStart<maxPerDia;curStart++){
           curButtons += llList2String(notes, curStart);
       }
       curEnd = 9;
       curButtons = FillMenu(curButtons) + FirstAdd;
   }
   curPage = 1;
   llGiveDialog(user, RestackMenu(curButtons));

}

llPagesNext(list notes, key user){ // Create the next page

   list curButtons = [];
   curEnd = curEnd + 9;
   if(curEnd >= curLength){
       curEnd = curLength;
       for(curStart;curStart<curEnd;curStart++){
           curButtons += llList2String(notes, curStart);
       }
       curButtons = FillMenu(curButtons) + BackAdd;
   }else if (curEnd < curLength){
       for(curStart;curStart<curEnd;curStart++){
           curButtons += llList2String(notes, curStart);
       }
       curButtons = FillMenu(curButtons) + MidAdd;
   }
   curPage++;
   llGiveDialog(user, RestackMenu(curButtons));

}

llPagesBack(list notes, key user){ // Recreate the previous page

   curPage--;
   list curButtons = [];
   curStart = curStart - 9;
   integer tempEnd = curEnd - 9;
   integer tempStart = curStart - 9;
   if(curEnd == curLength){
       if(curPage == 1){
           curStart = curStart - (curLength % 9);
           curEnd = curStart + 9;
           for(curStart;curStart<curEnd;curStart++){
               curButtons += llList2String(notes, curStart);
           }
           curButtons = FillMenu(curButtons) + FirstAdd;
       }else{
           curStart = curStart - (curLength % 9);
           curEnd = curStart + 9;
           for(curStart;curStart<curEnd;curStart++){
               curButtons += llList2String(notes, curStart);
           }
           curButtons = FillMenu(curButtons) + MidAdd;
       }
   }else if((tempEnd != 9) && (tempStart != 0) && (curEnd < curLength)){
       curStart = curStart - 9;
       curEnd = curEnd - 9;
       for(curStart;curStart < curEnd;curStart++){
           curButtons += llList2String(notes, curStart);
       }
       curButtons = FillMenu(curButtons) + MidAdd;
   }else if(tempStart == 0){ 
       llPagesFunc(notes,user);
       return;
   }
   llGiveDialog(user, RestackMenu(curButtons));

} llGiveDialog(key user, list buttons){ // This will give the dialog

   curListen = llListen(curChan, "", user, "");
   llDialog(user, curMsg + "\n\n\n\nPage: " + (string)curPage + "/" + (string)totalPages, buttons, curChan);
   llSetTimerEvent(curDelay);

} list FillMenu(list in){ // Fill the menu

   while (llGetListLength(in) != 3 
       && llGetListLength(in) != 6 
       && llGetListLength(in) != 9 
       && llGetListLength(in) < 12){
           in += [" "];
   }
   return in;

}

list RestackMenu(list in){ // Restack the manu so the order is correct

   list out = llList2List(in, 9, 11);
   out += llList2List(in, 6, 8);
   out += llList2List(in, 3, 5);    
   out += llList2List(in, 0, 2);    
   return out;

}

llShowError(key user, integer errorNum){ // Show an error, errorNum is used to add errors without changing much

   string errorMsg = "";
   if(errorNum == 1) errorMsg = "\n\nDialog currently in use, try again in 60 seconds.";
   llDialog(user, errorMsg, ["Ok"], 465465);

} llCloseAll(){ // Close listen, tell the menu can be used again.

   itemBusy = FALSE;
   llListenRemove(curListen);

} // ------------- // End Functions

default {

   state_entry()
   {
       curChan =  ( -1 * (integer)("0x"+llGetSubString((string)llGetKey(),-5,-1)) );
   }
   touch_start(integer num){
       if(itemBusy) llShowError(llDetectedKey(0),1);
       else llPagesFunc(notes,llDetectedKey(0));
   }
   listen(integer _c, string _n, key _id, string _m){
       if(_m == "Next >") llPagesNext(notes,_id);
       else if(_m == "< Back") llPagesBack(notes,_id);
       else if(_m == "Exit") llCloseAll();
   }
   timer(){
       llCloseAll();
   }

} </lsl>

Open Mouth Script (For gag or whatever.)

<lsl> default {

   state_entry()
   {
       llRequestPermissions(llGetOwner(), PERMISSION_TRIGGER_ANIMATION);
   }
   run_time_permissions(integer perm)
   {
       if (perm & PERMISSION_TRIGGER_ANIMATION)
       {
           llSetTimerEvent(1.0);
       }
   }
   timer()
   {
       llSetTimerEvent(1.0);
       llStopAnimation("express_open_mouth");
       llStartAnimation("express_open_mouth");
   }

} </lsl>

Notecard handler
This script reads data from a notecard and sends it to script via linked messages, the timer script below is an example script that will get its data from the notecard. The one below that is an example notecard.

Main notecard reader script <lsl> /////////////////////////////////////////////////////////////////////////////////////////////// // Notecard.Handle script by Lynnore Vaher // Description: // - Reads out the notes and sends the data to the scripts with a linked message. // /////////////////////////////////////////////////////////////////////////////////////////////

string notecard_name = "Setup"; // name of notecard goes here

// internals integer DEBUG = FALSE; integer line; key queryhandle; // to separate Dataserver requests key notecarduuid; float delay = 60.0; key owner; integer loadChan; integer loadListen;

init() {

   if(llGetInventoryKey(notecard_name) != NULL_KEY)
   {
       queryhandle = llGetNotecardLine(notecard_name, line = 0);// request line
       notecarduuid = llGetInventoryKey(notecard_name);
   }
   else
   {
       llOwnerSay("Setup notecard not found.");
   }

}

// Config data loaded from notecard, with some sane defaults default {

   state_entry()
   {
       init();
   }

   dataserver(key query_id, string data)
   {
       if (query_id == queryhandle)
       {
           if (data != EOF)
           {
               if(data != "")
               {
                   list cmd = llCSV2List(data);
                   if(llList2String(cmd,0) == "WAIT")
                   {
                       llSleep((float)llList2String(cmd,1));
                   }
                   else
                   {
                       data = llStringTrim(data, STRING_TRIM_HEAD);
                       if (llGetSubString (data, 0, 0) != "#") llMessageLinked(LINK_SET, 0, data, NULL_KEY); 
                   }
               }
               queryhandle = llGetNotecardLine(notecard_name, ++line);
           }
           else
           {
               state finished;
           }
       }
   }
   changed(integer change)         
   {
       // We want to reload channel notecard if it changed
       if (change & CHANGED_INVENTORY)
           if(notecarduuid != llGetInventoryKey(notecard_name))
               init();
   }

}

state finished {

   state_entry()
   {
       owner = llGetOwner();
       loadChan =  ( -1 * (integer)("0x"+llGetSubString((string)llGetKey(),-5,-1)) );  
       llOwnerSay("Setup Complete.");
   }
   changed(integer change)         
   {
       // We want to reload channel notecard if it changed
       if (change & CHANGED_INVENTORY)
       {
           llOwnerSay("The inventory has changed. If you added a new script, changed a scriptname or changed the configuration notecard... please press [YES]. Setting will be reloaded in " + (string)delay + " seconds.");
           loadListen = llListen(loadChan, "", owner, "");
           llDialog(owner, "Would you like to reload the settings?", ["YES", "NO"], loadChan);
           llSetTimerEvent(delay);
       }
       else if(change & CHANGED_OWNER)
       {
           llResetScript();
       }
   }
   listen(integer channel, string name, key id, string choice) 
   {
       if (choice == "YES") 
       {
           llOwnerSay("Reloading.. Please wait.");
           llListenRemove(loadListen);
           llResetScript();
       }
       else if (choice == "NO") 
       {
           llOwnerSay("Reload aborted.");
           llListenRemove(loadListen);
           llSetTimerEvent(0);
       }
   }
   timer()
   {
       llOwnerSay("Reloading.. Please wait.");
       llListenRemove(loadListen);
       llResetScript();
   }

} </lsl>

A timer script that get the data from the notecard reader

<lsl> /////////////////////////////////////////////////////////////////////////////////////////////// // Timer.Handle script by Lynnore Vaher // Description: // - Adjustable minimum and maximum random times // - This script sends a "@random" command to a script at random times. // /////////////////////////////////////////////////////////////////////////////////////////////

// START FUNCTIONS list ListItemDelete(list mylist,string element_old) {

   integer placeinlist = llListFindList(mylist, [element_old]);
   if (placeinlist != -1)
       return llDeleteSubList(mylist, placeinlist, placeinlist);
   return mylist;

}

SendRandom() {

   randomScript = fri(0, scriptCount);
   randomTimer = fri((integer)minTime, (integer)maxTime);
   string script = llList2String(scriptNames, randomScript);
   
   while(script == "" || script == " ")
   {
       randomScript = fri(0, scriptCount);
       script = llList2String(scriptNames, randomScript);
   }
   
   llMessageLinked(LINK_SET, 0, script + ",@random", NULL_KEY);
   if(DEBUG) llSay(DEBUG_CHANNEL, "Random time: " + (string)randomTimer);
   llSetTimerEvent(randomTimer);

}

integer fri( integer min, integer max ) {

 return min + (integer)llFrand( max - min + 1 );

} // END FUNCTIONS

// START VARIABLES float maxTime = 3600.0000; // Maximum time in seconds. float minTime = 10.0000; // Minimum time in seconds. float randomTimer; // Random time wich will be changed quite often.

string rdmCMD = "@random"; // The command wich is sent to other scripts.

integer loadedTime = FALSE; // See if the time is loaded. integer loadedScripts = FALSE; // See if the scripts lsit is loaded. integer DEBUG = FALSE;

//Settings to be set at script start. string scriptName = ""; // Name of the script. integer scriptCount = 0; // Amount of scripts. integer randomScript = 0; // umber to pick a random script. list scriptNames = []; // List of scriptnames. // END VARIABLES

default {

   state_entry()
   {
       scriptName = llGetScriptName();                         // Set the scriptname, to prevent load on the linked messages.
   }
   link_message(integer sender_num, integer num, string msg, key id) 
   {
       list cmd = llCSV2List(msg);                                 // Convert the CSV into a list of commands.
       
       if(llList2String(cmd, 0) == scriptName)                     // If the command is ment for this script.
       {
           if(llList2String(cmd, 1) == "TIME")                     // If the command is TIME, grab the next 2 values
                                                                   // to set the new minimum and maximum times.
           {
               maxTime         = (float)llList2String(cmd, 2);     // Set the new maximum time in seconds.
               minTime         = (float)llList2String(cmd, 3);     // Set the new minimum time in seconds.
               if(DEBUG) llSay(DEBUG_CHANNEL, "New min: " + (string)minTime + ", new max: " + (string)maxTime);
               loadedTime     = TRUE;                             // Timer settings are loaded.
           }
           else if (llList2String(cmd, 1) == "SCRIPTS")            // If the command is "SCRIPTS" 
                                                                   // then put the scriptnames in a list.
           {
               list temp       = ListItemDelete(cmd,scriptName);   // Delete the scriptname from the list.
               temp            = ListItemDelete(temp,"SCRIPTS");    // Delete the command from the list.
               scriptNames     = temp;                             // Create the list with scriptnames.
               if(DEBUG) llSay(DEBUG_CHANNEL, (string)scriptNames);
               scriptCount     = llGetListLength(scriptNames);     // Count how many scripts there are,
                                                                   // will be used as max random value.
               loadedScripts   = TRUE;                             // Script list is loaded.
           }
           else if (msg == "@RESET")
           {
               llResetScript();                                    // Reset the script if the command is given.
           }
           
           if(loadedTime == TRUE & loadedScripts == TRUE)
           {
               state running;                                      // Everything is loaded, go to the running state.
           }
       }
   } 

}

state running {

   state_entry()
   {
       randomScript = fri(0, scriptCount);                     //Create a random number that will be used
                                                               // to get a random scriptname.
       randomTimer = fri((integer)minTime, (integer)maxTime);  //Create a random number as a random time.
       llSetTimerEvent(randomTimer);                           //Start the timer.
       if(DEBUG) llSay(DEBUG_CHANNEL, "Entered running state.");
   }
   timer()
   {
       SendRandom();
   }
   link_message(integer sender_num, integer num, string msg, key id) 
   {
       list cmd = llCSV2List(msg);                             //Convert the CSV into a list of commands.
       
       if(llList2String(cmd, 0) == scriptName)                 // If the command is ment for this script.
       {
           if(llList2String(cmd, 1) == "@ON")                  // If the command is "@ON", enable the timer.
           {
               llSetTimerEvent(randomTimer);
           }
           else if(llList2String(cmd, 1) == "@OFF")            // If the command is "@OFF", disable the timer.
           {
               llSetTimerEvent(0);
           }
           else if(llList2String(cmd, 1) == "@RESET")
           {
               llResetScript();                                 //Reset the script if the command is given.
           }
           else if(llList2String(cmd, 1) == "@NOW")             // If the command is "@NOW", 
                                                                // instantly send a new restriction and new timer.
           {
               SendRandom();
           }
       }
       if(llList2String(cmd, 0) == "DEBUG")
       {
           if(llList2String(cmd, 1) == "ON")                  // If the command is "@ON", enable the timer.
           {
               DEBUG = TRUE;
           }
           else if(llList2String(cmd, 1) == "OFF")            // If the command is "@OFF", disable the timer.
           {
               DEBUG = FALSE;
           }
       }
   }        

} </lsl>

The notecard

###### START Timer.Handle Setup #####

# This script requires a reset to run properly, THIS HAS TO STAY ON TOP
Timer.Handle,@RESET

# Let the reader wait 10 second to give the script time to reset
WAIT,10

# Maximum and Minimum random time
Timer.Handle,TIME,30.0,5.0

# Script list
Timer.Handle,SCRIPTS,&Chat

###### END Timer.Handle Setup ######

# DEBUG On or Off
DEBUG,OFF

Plugin Menu Creator

This basicly lists scripts with "*" in front of their name and gives a dialog with them in it. Example: You have 2 scripts "*Example" and "*Example 1". The script will list those scripts and give a menu with buttons like "Example ..." and "Example 1 ...". If one of those buttons get pressed, it will send a linked message to those scripts.

<lsl>////////////////////////////////////////////////////////////////////////////////////////////// // Basic Plugin menu creator // by Lynnore Vaher // Added: // - Whitespaces added to full up the dialog, function from OpenCollar used // - Added a function to restack the menu so it starts from the top, also code from OpenCollar // - Menu items changed, added "..." to improve visual ^^ // - Fixed a small bug, script now correctly creates the menu after rezzing. //////////////////////////////////////////////////////////////////////////////////////////////

list invItems; integer x; integer pluginsCreated = FALSE; list FillMenu(list in) {

   //adds empty buttons until the list length is multiple of 3, to max of 12
   while (llGetListLength(in) != 3 && llGetListLength(in) != 6 && llGetListLength(in) != 9 && llGetListLength(in) < 12)
   {
       in += [" "];
   }
   return in;

}

list RestackMenu(list in) {

   //re-orders a list so dialog buttons start in the top row
   list out = llList2List(in, 9, 11);
   out += llList2List(in, 6, 8);
   out += llList2List(in, 3, 5);    
   out += llList2List(in, 0, 2);    
   return out;

} integer channel = 0; default {

   state_entry()
   {
       channel = (integer)(llFrand(-1000000000.0) - 1000000000.0);
       llListen(channel,"", NULL_KEY, "");
       if(pluginsCreated == FALSE)
       {
           state createPluginList;
       }
   }
   listen(integer c, string n, key id, string m)
   {
       integer index = llListFindList(invItems, [m]);
       if(~llListFindList(invItems, (list)m))
       {
           llMessageLinked(LINK_THIS, 0, llList2String(invItems, index - 1), "");
       }
   }
   changed(integer change)
   {
       if (change & CHANGED_INVENTORY)
       {
           invItems = [];
           llSleep(2.0);
           state createPluginList;
       }
       if (change & CHANGED_OWNER) 
       {
           llResetScript();
       }
   }
   link_message(integer sender_num, integer num, string x, key id) {
       if (num == 20)
       {
           llDialog(id,"Plugin list", RestackMenu(FillMenu(llList2ListStrided(llDeleteSubList(invItems, 0, 0), 0, -1, 2))), channel);
       }
   }
   on_rez(integer l)
   {
       llResetScript();
   }

} state createPluginList {

   state_entry()
   {
       invItems = [];
       integer length = llGetInventoryNumber(INVENTORY_SCRIPT);
       for (x = 0; x < length; x++)
       {
           string PlugName = llGetInventoryName(INVENTORY_SCRIPT, x);
           if (~llSubStringIndex(PlugName, "*"))
           {
               string PlugMenuName = llGetSubString(PlugName, 1, -1);
               invItems += [PlugMenuName, PlugMenuName + "..."];
           }
       }
       llOwnerSay("Plugins are ready.");
       pluginsCreated = TRUE;
       channel = (integer)(llFrand(-1000000000.0) - 1000000000.0);
       state default;
   }

}</lsl>

*Example This is an example for the plugin menu creator. <lsl> string scriptname = ""; default {

   state_entry()
   {
       scriptname  = llGetSubString(llGetScriptName(), 1, -1);
   }
   link_message(integer sender_num, integer num, string msg, key id) {
       
       if(msg == scriptname)
       {
           //execute code
       }
   }

} </lsl>