LSL学习笔记(2)

 常用函数 :

string llList2String(list src, integer index)
List 里获取其中的一个元素 , 并转为 string. index begin from 0.
Example:
llList2String(foo, 0); // returns the first element in the list
 
 
string llDumpList2String(list src, string separator)
通过第二个参数指定的字符把 List 里的所有 element 连成一个 string.
llParseString2List 是与该方法刚好相反
Example:
list foo = ["a", "b", 5, ZERO_VECTOR];
// outputs: "a + b + 5 + <0.000000, 0.000000, 0.000000>"
llSay(0, llDumpList2String(foo, " + ")); 
 
list llParseString2List(string src, list separators, list spacers)
把参数src根据参数separators and spacers来分成list.
其中参数separators和spacers都是拆分符,都是数组变量,他们之间的区别在于:
splitting at and discarding separators , and splitting at and keeping spacers
见下面的例子
Example:
llParseString2List("one,two,three,'four','five,six' ",[","],[]);
返回结果是:
["one", "two", "three", "'four'", "'five", "six' "]
 
llParseString2List("one,two,three,'four','five,six' ",[",","'"],[]);
返回结果是:
["one", "two", "three", "four", "five", "six", " "]
 
llParseString2List("AllCowsEatGrass", ["A", "C", "E", "G"], []);
返回结果是:
["ll", "ows", "at", "rass"]
 
llParseString2List("AllCowsEatGrass", [], ["A", "C", "E", "G"]);
返回结果是:
["A", "ll", "C", "ows", "E", "at", "G", "rass"]
 
 
 
key llGetOwner()
返回该scripted object的拥有者(不是创造者, 因为object可以转让, 也不是touch该object的user)的key.
注意 : 由于 object 可以转让 , 这就会给你的 script 造成一个问题 : 例如你的 script 有调用 llListen or llRequestPermissions 方法 , 而且方法里用到 llGetOwner, 那么就可能会出问题 . 因为如果 object 转让给别人之后 , listen 的还是原来那个拥有者 , 而不是新的拥有者 .
解决方案是 : on_rez event 里调用方法 llResetScript , or even llListen in on_rez . 还要记得通过调用 llListenRemove remove old listens .
 
integer llListen(integer channel, string name, key id, string msg)
很重要的一个方法 : 调用该方法会令 object 能够 listen 特定的 object/avatar 通过特定的 channel 发送的消息 . 注意不是监听 object 周围所有的 channel 所有的 object/avatar 的消息 . 当监听到消息时 , 会调用 listen() event handler .
 
参数 channel 就是指定监听的 channel. 比较特殊的值是 0, 表示 channel public chat channel, 即只要在你平时用来聊天的 chat channel 里输入命令 ,object 就会 listen .
 
参数 name 和参数 id 是用来指定监听的 object/avatar, 如果设置 name empty string and id NULL_KEY , 那么就会监听所有的 object/avatar channel 上发送的消息 .
其中的参数 name 是指定 name 为该参数值的 object/avatar, 参数 id 是指定 key 为该参数值的 object/avatar
 
返回值是该 listener handle, 用于将来通过调用 llListenControl and llListenRemove 方法来 deactivate or remove listener. 强烈建议在不需要 listener 时要把它 remove , 这是因为即使 object state 发生改变 , listener 不会自动的消失 .
The returned handles start at 1, so you can set your handle variable to 0 (zero) when you deactivate a channel and test for that elsewhere when you need to know if it's active or not.
 
过度的使用llListen方法会影响object的性能, 如果可以有其他方案(例如: llMessageLinked)来代替使用llListen,那么就要尽量不要使用llListen
 
接收到的消息的长度问题 : If a script with an llListen "hears" a string longer than the script's amount of available free memory, it will halt with a "stack/heap collision" error before your code in the listen() event handler has a chance to begin executing. As of SL v1.13, a single chat string on any channel can be up to 1023 bytes in length.
 
Examples:
 
Establishes a completely open filter for avatar chat ( 一个最大限度开放的 listener)
integer handle = llListen( 0, "", NULL_KEY, "" );
 
监听来自object owner在public chat发送来的消息
integer handle = llListen( 0, "", llGetOwner(), "" );
 
监听来自name为button的object在96号channel发送来的消息
integer handle = llListen( 96, "button", NULL_KEY, "" );
上面这个例子也有实际用途。例如:一个elevator object在不同的楼层都有button object,所有的button object都具有相同的name,但发送的消息里包含的floor number不同。
 
监听来自avatar的public chat channel的消息常会被见到,但来自object发送的消息是无法从public chat channel传送,那么就象上面最后一个例子那样,监听”值不为0”的channel。好!问题来了:object如何通过某个channel来发送消息?有三个方法可以调用来发送消息:
llWhisper(integer channel, string text)
llShout(integer channel, string text)
 
example:
【Message listener】
integer handle = llListen( 96, "button", NULL_KEY, "" );
 
【Message sender: object named button】
llSay(96, “hello”);
 
另外llListen还有一个很实际的应用:就是用来接收avatar在llDialog窗口里选择的信息。例如script常常会popup a dialog window,然后avatar选择Yes or No。那么就通过listen event handle来receive avatar’s response。
Example:
key owner=llGetOwner();
listenID=llListen(85, "", owner, "");
llDialog(owner, "Do you like it?", ["Yes", "No"], 85)
。。。。
listen(integer channel, string name, key id, string msg){
       if(channel == 85) //come from dialog
              。。。。。。
       }
}
 
一个object可以同时监听多个不同的channel( 注意:但不能同时监听不同的object/avatar使用同一个channel ――但好像目前版本支持)(最多监听64个),具体做法很简单,就是调用多个llListen方法,只是参数不同。但要记住,不管来自哪个channel,哪个object/avatar的消息,都会trigger listen() event handler。
 
 
llDialog(key id, string message, list buttons, integer chat_channel)
该方法会向参数 id 所对应的 avatar 弹出一个 dialog window ,该 dialog 会包含参数 message and buttons info, 还会包含一个 ignore button 。当 avatar select 其中一个 button 时,就相当于 avatar 在参数 chat_channel 所指定的 channel 里发送了一条消息(消息内容是该 button text ),从而会 trigger listen() event handler

如果参数 chat_channel 的值为 DEBUG_CHANNEL ,那么 avatar 选择 button 时发送的消息不是该 button text ,而是该 button name
 
l      参数message的值不能超过512个字符,也不可以为空。可以包含”/n” and “/t”等字符
 
参数buttons有以下要注意的:
l      必须是 a list of strings,其他类型不行
l      buttons list包含的元素个数不能超过12个,但可以为0个。如果是0个的话,dialog会提供一个“OK” button
l      buttons里的每个string的长度不能超过24个字符,否则会出错
 
如果user选择了dialog自身提供的“ignore” button,将不会trigger listen() event handler。
 
Example:
integer CHANNEL = 42; // dialog channel
list MENU_MAIN = ["Sit", "Stand", "Fly"]; // the main menu
default {
    state_entry() {
         // listen for dialog answers (from multiple users)
        llListen(CHANNEL, "" , NULL_KEY, "" );
    }
   
touch_start( integer total_number)
{
    // llDetectedKey 函数返回的是激活了dialog的user的key
        llDialog( llDetectedKey(0 ), "What do you do?" , MENU_MAIN, CHANNEL);
    }
   
    listen( integer channel, string name, key id, string message)
{
    // llListFindList 函数是检查 message 是否是 MENU_MAIN 的元素
    if ( llListFindList (MENU_MAIN, [ message ] ) != -1) {
         // output the avatar name and the selected button text
       llSay(0, name + " picked the option '" + message + "'." );
     }
    }
}
 
 
至于在 dialog 里各个 button 的摆放位置的问题,请详见 http://www.lslwiki.net/lslwiki/wakka.php?wakka=lldialog
 
还有就是强烈建议对 llDialog 设置 timeout ,用来防止 popup dialog 之后, user 并没有选择任何 button 的情况!代码类似下面:
integer handle = -1;
integer CHANNEL = 42;
float TIMEOUT = 60.0;
list MENU = ["yes", "no"];

default
{
    state_entry()
    {
        if ( handle != -1 )
        {
            llListenRemove( handle );
            handle = -1;
        }
    }

    touch_start( integer total_num )
    {
       
handle = llListen( CHANNEL, "", llDetectedKey(0), "" );
        llDialog( llDetectedKey(0), "Are you sure?", MENU, CHANNEL );
       
llSetTimerEvent( TIMEOUT );
    }

    listen( integer chan, string name, key id, string msg )
    {
        if (
llListFindList ( MENU, [msg] ) != -1 )
        {
            if ( msg == "yes" )
            {
                // Do your stuff...
            }
            else if ( msg == "no" )
            {
               // Don't do your stuff...
            }
 
          llListenRemove( handle );
            handle = -1;
            llSetTimerEvent(0.0);
        }
    }

    timer()
    {
        if ( handle != -1 )
        {
            llListenRemove( handle );
            handle = -1;
        }
    }
}
 
key llDetectedKey(integer number)
返回根据参数 number 指定的 detected object key 。(如果 detect 到的 object 数为 0 ,或者参数 number 的值无效,返回值为 NULL_KEY
 
所有以 llDetected 开头的 Detection 函数主要是用来获取被 sensors, touch, and collision events detect 到的 objects and agents info

所有的 Detection 函数都需要一个 integer 参数,该参数值指定的是 sensor, touch, or collision event detect 到的所有 objects/avatars 中你想要的 object/avatar index 该值从 0 detect 到的 object/avatar total_number - 1 )

If a detection function is called from a user-defined function, the function inherits the data from the event that called it.
 
l      非常要注意的知识点:
所有的 Detection 函数只能够在 collision , collision_start , collision_end , sensor , touch , touch_start , or touch_end events 方法里 里调用,在其他地方调用是完全不起作用的!
 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值