Simple Notecard Reader

From Lucinda Bulloch via the scripting forum:

this is a basic one but shows you how it works

list datalist = []; //the lines of the card will be placed here

key conquery; // the key that the server gives you data

integer dataend = 0; //line counter

string notecardname = "name of card here"; //name of card to be read

default
{
  on_rez(integer start_param)
   {
    llResetScript(); //reset and clear memory on rez
   }
   
  state_entry()
   {
    conquery = llGetNotecardLine(notecardname ,dataend); //ask data server to get a line from the notecard
   }

dataserver(key query_id, string data)
  {
   if(query_id == conquery) //is the key the one i want
    {
     if (data != EOF) // has it reached the end of the file?
      {  
       datalist += data; //add the line to the data list
       dataend ++;       //increase to the next line
       conquery = llGetNotecardLine(notecardname,dataend); // get the next line
      }
     else
      {
        dataend =0;//all data got and ready to read another card
        // the card is loaded into list do something
        // if you have another card to load - then start a new key to load a diff list
        // or if using the same list, overwrite notecardname with the new name
        // and call conquery = llGetNotecardLine(notecardname,dataend) again          
            
      } 
    }
  } 
}

 

Multiple Notecard Giver

// Script to present a dialog populated with a list of notecards
// from the prims inventory
//
// Note that only the first 24 characters of the notecard names
// are actually used - as only 24 chars can be placed in a dialog
// button.  This means that if two notecards have the first 24 chars
// the same, the second will be ignored ...
//
// Note however that usually, buttons don't display more than, say,
// around 10 or so characters anyway!!
//
// Kimm Paulino
// Written for Vikki Hastings, June 2011
 
// Configure the behaviour we want
string  gFloatingText = "Click for notecards";  // Set to "" to disable
vector  gFloatingTextColour = <1 .0, 1.0, 1.0>;
float   gFloatingTextAlpha = 1.0;
 
integer gChannel;
integer gMenuPage;
integer gNumNotecards;
list gNotecards;
 
string MENU_NEXT="Next>";
string MENU_TOP="Top";
string MENU_BACK="= num_pages)
    {
        // gMenuPage is an index starting at 0...
        // max is a 1...
        gMenuPage = num_pages-1;
    }
 
    // Note: This yields notecards counting as follows:
    // 0 to 8 = first page,
    // 9 to 17 = next page, etc
    integer first_nc = gMenuPage * 9;
    integer last_nc = first_nc + 9 - 1;
    if (last_nc >= gNumNotecards)
    {
        // recall last_nc indexed from 0, but
        // gNumNotecards is indexed from 1
        last_nc = gNumNotecards-1;
    }
 
//    llOwnerSay ("Menu Page: " + (string)gMenuPage);
//    llOwnerSay ("First NC: " + (string)first_nc);
//    llOwnerSay ("Last NC: " + (string)last_nc);
 
    if (gMenuPage > 0)
    {
        buttons += [MENU_BACK];
    }
    else
    {
        buttons += [MENU_SPACE];
    }
 
    if (gMenuPage == 0)
    {
        buttons += [MENU_SPACE];
    }
    else
    {
 
        buttons += [MENU_TOP];
    }
 
    // If not on the last page, and there are more pages to come ...
    if (gNumNotecards > 9 && gMenuPage <(num_pages-1))
    {
        buttons += [MENU_NEXT];
    }
    else
    {
        buttons += [MENU_SPACE];
    }
 
    integer i;
    for (i=first_nc; (i <= last_nc) && (i < gNumNotecards); i++)
    {
        buttons += [llList2String (gNotecards, i)];
    }
 
    llDialog (id, "\n\n(click \"Ignore\" when done)", buttons, gChannel);
}
 
default
{
    on_rez (integer start_param)
    {
        llResetScript();
    }
 
    state_entry()
    {
        llSetText (gFloatingText, gFloatingTextColour, gFloatingTextAlpha);
        read_notecards();
        gMenuPage = 0;
        gChannel = getRandomChannel();
 
        // Would be less laggy to close listen when not in use
        // but then if two people attempted to use the giver,
        // it wouldn't be able to cope.  This way, they can both
        // use it at the same time ...
        llListen (gChannel, "", "", ""); 
    }
 
    touch_start(integer total_number)
    {
        // Start menu system again. Note that I don't do anything special
        // with several people trying to touch it at the same time - it will
        // always overlap the processing of gMenuPage, but all that will
        // happen is that peoples next/back might be a bit quirky for a while.
        // Eventually, they will sort themselves out!
        gMenuPage = 0;
        show_dialog (llDetectedKey(0));
    }
 
    listen (integer channel, string name, key id, string msg)
    {
        if (channel == gChannel)
        {
            if (msg == MENU_BACK)
            {
                gMenuPage--;
                show_dialog (id);
            }
            else if (msg == MENU_TOP)
            {
                gMenuPage = 0;
                show_dialog (id);
            }
            else if (msg == MENU_NEXT)
            {
                gMenuPage++;
                show_dialog (id);
            }            
            else
            {
                // should be something in the inventory to give out
                give_notecard (id, msg);
            }
        }
    }
 
    changed (integer change)
    {
        if (change & CHANGED_INVENTORY)
        {
            llResetScript();
        }
    }
}

 

Pull Info from Notecard

string gName = "Testnotecard";    // name of a notecard in the object's inventory
integer gLine = 0;        // current line number
key gQueryID; // id used to identify dataserver queries

default 
{
    state_entry() 
    {
        gQueryID = llGetNotecardLine(gName, gLine);    // request first line
        gLine++;                // increase line count
    }

    dataserver(key query_id, string data) 
    {
        if (query_id == gQueryID) 
        {
            if (data != EOF) 
            {    // not at the end of the notecard
                llSay(0, data);    // output the line
                gQueryID = llGetNotecardLine(gName, gLine);    // request next line
                gLine++;                // increase line count
            }
        }
    }
}

 

Make a notecard called "Testnotecard" put in any information you need and this script will say it to you in-world.  This is a great example of how to script for a notecard

Example of a notecard Reader

Example of how a notecard is read from a script (the notecard needs to be named 'config'):

//Remove this line for this script to work.

//This script is an example of how to read a notecard. It will allow you to set the configurations of Hovertext using a Notecard.


//PLEASE NOTE: THE NOTECARD WE WANT TO READ MUST BE IN THE SAME OBJECTS CONTENTS FOLDER AS THIS SCRIPT.


//Notecards are read form the first line BUT the first line is given the value of 0 so a 5 line notecard would be read like this:

// Line 0: This is the first line.
// Line 1: This is the second line.
// Line 2: This is the third line.
// Line 3: This is the forth line.
// Line 4: This is the fifth line.


string gName = "config";    //Name of notecard we wish to read

key HTextKey; //This is the key we will use to call for hovertext
key ColorKey; //This is the key we will use to call the color
key AlphaKey; //This is the key we will use to call the transparancy of teh text.


//Declaring variables to be used later.
string Htext;
vector Color;
float Alpha;
list temp;
default 
{
    state_entry() 
    {
        //Using the key below we can ask the script to read the notecard on certain lines..
        HTextKey = llGetNotecardLine(gName, 0);
        ColorKey = llGetNotecardLine(gName, 1);
        AlphaKey = llGetNotecardLine(gName, 2);
    }

    dataserver(key query_id, string data) 
    {
        temp = [];
        if(query_id == HTextKey)//Filtering the call
        {
            
            if (data != EOF) // not at the end of the notecard
            {
                temp = llParseString2List(data,[" = "],[]);
                Htext = (string)llList2String(temp,1); //Give Htext the same value as data.
                              //Data being what is read on the notecard.
            }
        }
        if(query_id == ColorKey)//Filtering the call
        {
            if (data != EOF) // not at the end of the notecard
            {
                temp = llParseString2List(data,[" = "],[]);
                Color = (vector)llList2String(temp,1); //Give Color the same value as data.
                                       //Data being what is read from the notecard
                                       //Also note that data is being casted as a vector as that is what we will need to set the color.
            }
        }
        if(query_id == AlphaKey)//Filtering the call
        {
            if (data != EOF) // not at the end of the notecard
            {
                temp = llParseString2List(data,[" = "],[]);
                Alpha = (float)llList2String(temp,1);//Give Alpha the same value as data.
                                     //data being what is read from the notecard.
                                     //Also note that data is being casted as a float as that is what is needed for the alpha.
 
 
                //Using the infomation retrieved we can now set up the hovertext.
                llSetText(Htext, Color, Alpha);
            }
        }
        llOwnerSay(Htext + "  " + (string)Color + "  " + (string)Alpha);
    }
    
    on_rez(integer start_param)
    {
        llResetScript();
    }
}

 

Read info from a notecard in LSL

Since LSL scripts are not meant for storing permanent data, the best way to achieve this, besides using a database, is using a notecard. This is widely used in a lot of products so the end user can easily configure some settings without the need to modify a script.

 

In this example I will show you how you can use a notecard to store some information and use it inside the script, in this case the script simply turns a light on off, thanks to the information stored in the notecard a user can set the color radius intensity and falloff values of the light:

 

The Script:

 

// www.lsleditor.org  by Alphons van der Heijden (SL: Alphons Jano)
// Configuration notecard example by Kahiro Watanabe (2009)

//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.

string notecardName;
integer notecardLine;

vector color;
float intensity;
float radius;
float falloff;

key query;

integer isLightOn;

lightOff()  // A simple function to turn light off
{
    llSetPrimitiveParams([PRIM_POINT_LIGHT,FALSE,ZERO_VECTOR,0,0.0,0.0]);
}

lightOn(vector color, float intensity, float radius, float falloff)  // A generic function to turn a light on with the given parameters (you can use this function in any script!)
{
    llSetPrimitiveParams([PRIM_POINT_LIGHT,TRUE,color,intensity,radius,falloff]);
}

switchLight(integer on)
{
    if (on)
    {
        lightOff();
    }
    else
    {
        lightOn(color,intensity,radius,falloff);
    }
}

default
{
    state_entry()
    {
        notecardLine = 0;
        notecardName = llGetInventoryName(INVENTORY_NOTECARD,0);
        if (notecardName != "")
        {
            llOwnerSay("Getting configuration data...");
            query = llGetNotecardLine(notecardName,notecardLine);
        }
        else
        {
            llOwnerSay("There is no notecard in object's inventory, please add a config notecard.");
        }
    }

    changed(integer change)
    {
        if (change & CHANGED_INVENTORY) // If notecard changes script is resetted.
        {
            llOwnerSay("Resetting script");
            llResetScript();
        }
    }

    on_rez(integer number)
    {
        llResetScript();
    }

    touch_start(integer total_number)
    {
        llSay(0, "Touched: "+(string)total_number);
    }

    dataserver(key requested, string data)
    {
        if (requested == query)
        {
            if (data != EOF)
            {
                //ignore lines that start with # and blank lines
                if ( (llGetSubString(data,0,0) != "#") && (data != "") )
                {
                    list tempData = llParseString2List(data,[":"],[]);
                    string command = llToLower(llList2String(tempData,0));

                    if (command == "color")
                    {
                        color = (vector)llList2String(tempData,1); // This converts a string to a vector 

                        // Set up the color vector properly (max should be 1 instead of 255)//
                        color.x = color.x / 255;
                        color.y = color.y / 255;
                        color.z = color.z / 255;
                        llOwnerSay(command + ": " + (string)color);
                    }
                    else if (command == "intensity")
                    {
                        intensity = llList2Float(tempData,1);
                        llOwnerSay(command + ": " + (string)intensity);
                    }
                    else if (command == "radius")
                    {
                        radius = llList2Float(tempData,1);
                        llOwnerSay(command + ": " + (string)radius);
                    }
                    else if (command == "falloff")
                    {
                        falloff = llList2Float(tempData,1);
                        llOwnerSay(command + ": " + (string)falloff);
                    }
                }
                notecardLine++;
                query = llGetNotecardLine(notecardName,notecardLine);
            }
            else
            {
                //End of notecard reached, we go to the ready state.
                state ready;
            }
        }
    }
}

state ready
{
    state_entry()
    {
        llOwnerSay("Ready!.");

        // Turn off lights as default;
        isLightOn = FALSE;
        lightOff();                      // Function call check line nº 14
    }

    on_rez(integer number)               // Reset script when object is rezzed;
    {
        llResetScript();
    }

    changed(integer change)
    {
        if (change & CHANGED_INVENTORY)  // If notecard changes script is resetted.
        {
            llResetScript();
        }
    }

    touch_start(integer totalNumber)
    {
        switchLight(isLightOn);
        isLightOn = !isLightOn;  // the "!" command is the logical "NOT" if the variable is true it will make it false and viceversa.
    }
}

 

The Notecard:

#Notecard Configuration Example
#Every line that starts with the ‘#’ symbol will be ignored by the script, empty lines will also be ignored
#This script will take data from this notecard to set light properties of the object. Then you will be able to turn on/off the light by touching it.
#The Information taken from the notecard is: Color,Intensity,Radius,Falloff the “:” symbol is used to separate the property name from the
#property value

Color:<0,255,0>
Intensity: 1
Radius: 10
Falloff: 0.9

The script is divided in two states: configuration and ready. I made it that way because the dataserver() method is asynchronous, this means that the script keeps running while the notecard is being read. Once the end of the notecard is reached then the script goes to the ready state where by touch the light can be turned on/off.