如何从LSL中的记录卡中读取随机行?

时间:2021-06-01 20:44:47

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?

我有一张记录卡,每行都有不同的单词,我希望能够随机选择这些行。我怎样才能做到这一点?

2 个解决方案

#1


First, as you mention, you need a notecard. For this example, I'm using one named "colors" with the following contents:

首先,正如您所提到的,您需要一张记录卡。在这个例子中,我使用了一个名为“colors”的内容,其中包含以下内容:

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.

使用该记录卡,每次触摸prim时,以下脚本将读取并聊天卡中的随机行。

//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);
        }
    }
}

#2


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):

目前尚不清楚为什么你做这种不必要的数学运算,加上一个,然后在你上面给出的答案中再次减去它。如果你想确保你有一个更随机的数字,因为你可以做llFrand随机性的已知问题(不检查数字是偶数还是奇数):

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.

上面代码的第二个问题是你没有检查CHANGED_INVENTORY,我不太清楚为什么你不这样做。继续第二个问题,你为什么要问一个问题来获得一个随机的记录卡行号并给出一个在一个范围内随机提供的答案?如果记录卡改变了你会怎么做?更改代码和记录卡?这似乎对我来说是多余的。

NOTECARD named colors or whatever you set in the script:

NOTECARD命名颜色或您在脚本中设置的任何内容:

blue
red
green
yellow
black

SCRIPT within the same prim:

SCRIPT在同一个原子中:

//  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.

你正在阅读的记录卡不一定必须是同一个原子。如果您知道记录卡的UUID,只要它可以转移(而不是删除),您就可以从中读取。请注意,更改记录卡的内容并保存,将新内容存储在不同的UUID下。但是,如果你是熟练的,你也可以将文本存储在Web服务上,并从那里获取文本片段数和文本片段。

More on the official Second Life wiki.

更多关于官方Second Life维基。

#1


First, as you mention, you need a notecard. For this example, I'm using one named "colors" with the following contents:

首先,正如您所提到的,您需要一张记录卡。在这个例子中,我使用了一个名为“colors”的内容,其中包含以下内容:

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.

使用该记录卡,每次触摸prim时,以下脚本将读取并聊天卡中的随机行。

//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);
        }
    }
}

#2


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):

目前尚不清楚为什么你做这种不必要的数学运算,加上一个,然后在你上面给出的答案中再次减去它。如果你想确保你有一个更随机的数字,因为你可以做llFrand随机性的已知问题(不检查数字是偶数还是奇数):

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.

上面代码的第二个问题是你没有检查CHANGED_INVENTORY,我不太清楚为什么你不这样做。继续第二个问题,你为什么要问一个问题来获得一个随机的记录卡行号并给出一个在一个范围内随机提供的答案?如果记录卡改变了你会怎么做?更改代码和记录卡?这似乎对我来说是多余的。

NOTECARD named colors or whatever you set in the script:

NOTECARD命名颜色或您在脚本中设置的任何内容:

blue
red
green
yellow
black

SCRIPT within the same prim:

SCRIPT在同一个原子中:

//  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.

你正在阅读的记录卡不一定必须是同一个原子。如果您知道记录卡的UUID,只要它可以转移(而不是删除),您就可以从中读取。请注意,更改记录卡的内容并保存,将新内容存储在不同的UUID下。但是,如果你是熟练的,你也可以将文本存储在Web服务上,并从那里获取文本片段数和文本片段。

More on the official Second Life wiki.

更多关于官方Second Life维基。