I have a notecard with a different word on each line, and I'd like to be able to select from the lines randomly. How can I do that?
-
This is an answer to a question posed in the Script Academy group. Posted here to preserve it for posterity. – btubbs Jun 24 '09 at 19:49
-
I'm voting this up just because it's a question about Linden Scripting Language for Second Life! :) – Tad Donaghe Jun 24 '09 at 20:01
2 Answers
First, as you mention, you need a notecard. For this example, I'm using one named "colors" with the following contents:
red
blue
green
yellow
orange
purple
With that notecard present, the following script will read and chat a random line from the card each time the prim is touched.
//this script will grab and chat a random line from the "colors" notecard each time the prim is touched.
string card = "colors";
key linecountid;
key lineid;
integer linemax;
integer random_integer( integer min, integer max )
{
return min + (integer)( llFrand( max - min + 1 ) );
}
default
{
state_entry()
{
//get the number of notecard lines
linecountid = llGetNumberOfNotecardLines(card);
}
touch_start(integer total_number)
{
lineid = llGetNotecardLine(card, random_integer(0, linemax));
}
dataserver(key id, string data)
{
if (id == linecountid)
{
linemax = (integer)data - 1;
}
else if (id == lineid)
{
llSay(0, data);
}
}
}

- 1,845
- 1
- 16
- 19
It's not clear why you do such unnecessary math with adding one and then substracting it again later in the answer you give yourself above.
If you want to make sure you have a more random number as there are known issues with the randomness of llFrand
you could do (without checking whether the number is even or odd):
integer max;
integer random = llFrand((integer)(max/2)) + llFrand((integer)(max/2));
The second issue with your code above is that you are not checking against CHANGED_INVENTORY
and I'm not quite sure why you'd not do that. Following up on this second issue, why do you ask a question to get a random notecard line number and give an answer that provides a random within a range? And what will you do if the notecard changes? Change the code and the notecard? This seems to be redundant to me.
NOTECARD named colors
or whatever you set in the script:
blue
red
green
yellow
black
SCRIPT within the same prim:
// this script reads from a notecard which is named whatever you set in init
// in this example from a notecard named "colors"
string ncName;
key ncNumOfLinesReqId;
key ncReqId;
integer numOfLines;
init()
{
// Put the name of your notecard as in the prim's inventory here.
ncName = "colors";
}
default
{
changed(integer change)
{
// reset script to make sure you have the current number of lines
// CHANGED_OWNER has the integer value 0x80 (128)
// CHANGED_INVENTORY has the integer value 0x01 (1)
if (change & (CHANGED_OWNER | CHANGED_INVENTORY))
{
llResetScript();
}
}
state_entry()
{
init();
// get the number of notecard lines
ncNumOfLinesReqId = llGetNumberOfNotecardLines(ncName);
}
touch_start(integer num_detected)
{
// if the number of lines is 0
if (!numOfLines)
{
// PUBLIC_CHANNEL has the integer value 0
llSay(PUBLIC_CHANNEL, "~!~ Unconfigured, check notecard ~!~");
}
else // if number of lines not 0
{
ncReqId = llGetNotecardLine(ncName, (integer)llFrand(numOfLines));
}
}
dataserver(key reqId, string data)
{
if (reqId == ncNumOfLinesReqId)
{
// make sure you typecast!
numOfLines = (integer)data;
}
else if (reqId == ncReqId)
{
// PUBLIC_CHANNEL has the integer value 0
llSay(PUBLIC_CHANNEL, data);
}
}
}
Further information:
The notecard you are reading from does not necessarily have to be in the same prim. If you know the UUID
of the notecard, you can read from it as long as it's transferable (and not deleted). Be warned that changing the contents of the notecard and saving, stores the new content under a different UUID
. But if you're that skilled, you might as well store the text on a web service and get the text snippet count and text snippets from there.
More on the official Second Life wiki.

- 1
- 1