ソラマメブログ

2008年07月25日

NPC・ペットの会話・対応するLSL

NPCやペットで周囲の会話に反応・対応するためのLSLです。

オーナーがたっちすれば 動作をON-OFFできます。

会話の応対するための 言葉は ノートカードで作成して 読み込むタイプです、

【聞き取りの判定のキーワード:文字短すぎない程度】         こんにちは
【返事をするキーワード:応答メッセージ:コメント文字1行以内】   こんにちは^^ビーム ~(ノ=^‥^)‥‥…━━━━━☆
【聞き取りの判定のキーワード:文字短すぎない程度】         おはよう
【返事をするキーワード:応答メッセージ:コメント文字1行以内】   おはようです^^b

データは必要な実際の言葉を、改行して 順番にひたすら並べてあるだけでokです

//NPC 会話対応
//会話を常時LISTEN 聞き取りをするための基本、
//読み込みデータと 一致するものが 含まれているかチェックすだけの作業です
//100個のキーワードで実施して、5000程フリーメモリが残っていましたので、200ワードくらいが限界です
//キーワードが短い、ひらがなだけであるものは いろいろな言葉に重複してしまうので 注意してください
//文字列の中に 含まれているか? という判定なので 会話のはじめでなくても 判定ができます
//逆に 希望・想定していない文字に反応しないように キーワードは意味のある長さの文字であるようでないといけません
//たとえばひらがな2文字の ”よろ”に登録すると ”よろしく” だけでなく ”よろい” ”よろけた” ”よろこび” に判定できちゃいます
<参考LSL>

list DATA=[];//聞き取りの判定 キーワード
list SAY_DATA=[];//返事をする キーワード または文章として 1行で準備する
string notecard_name = "list Note";//読み込むノートカードの名前
integer MAX_count;//聞き取りの判定 キーワードの数
integer say_flag_last;//発信したフレーズ
float say_time_last;//発信した時間
float repeat_time=10.0;//同じフレーズを発信しない制限時間

integer read_line;
key query_id;
integer L_ON;//LISTENコントロール
integer flag;//動作ON-OFF

//異なるフレーズであれば 反応する
//同じフレーズであれば、 繰り返して連続しない 少しだけの間制限する
say_data(integer i ){
    //llSleep(1.0);  //反応を遅くしておく^^
    if (say_flag_last!=i){
        say_flag_last=i;
        llSay(0,llList2String(SAY_DATA,i));
        say_time_last=llGetTimeOfDay();
    }else if(llGetTimeOfDay()-say_time_last >repeat_time){
        llSay(0,llList2String(SAY_DATA,i));
        say_time_last=llGetTimeOfDay();
    }
}

//ノートカードの読み込み開始
load_start(){
    llOwnerSay(" Now Loading..");
    read_line = 0;
    if (llGetInventoryType(notecard_name) == INVENTORY_NOTECARD) {
        query_id = llGetNotecardLine(notecard_name, read_line); // request first line
    }else{
        llOwnerSay("Not found notecard '" + notecard_name );
    }
}
// ノートカード読込をして準備します
default{
    state_entry(){
        load_start();
    }
    dataserver(key queryid, string data) {
        if (queryid == query_id) {
            if (data != EOF) {
                // ここで読み取ったデータの準備・リストへ記憶します
                if (read_line%2 ==0) DATA+=(list)data;
                else SAY_DATA+=(list)data;
                read_line ++;
                query_id = llGetNotecardLine(notecard_name, read_line);
            }else{
                llOwnerSay("Loading complete.  メモリFREE : "+  (string)llGetFreeMemory());
                state main; // メイン処理を行うステートへ
            }
        }
    }
}
//会話をLISTEN 聞き取りをします、
//読み込みデータと 一致するものが 含まれているかチェックするものです
state main{
    state_entry(){
        say_flag_last=-1;
        say_time_last=llGetTimeOfDay();
        MAX_count=llGetListLength(DATA);
        flag=1;
        L_ON=llListen(0,"",NULL_KEY,"");
    }
    //聞き取りした会話をすべてチェック作業をします
    listen(integer channel, string name, key id, string msg)
    {
        integer i;
        string TEMP;
        integer NUMBER;
        if (llGetAgentInfo(id)>0 ) { //アバターである==アバタは動作しているとき、ZEROではない時
            for (i = 0; i < MAX_count; ++i){
                TEMP=llList2String(DATA,i);
                NUMBER=llSubStringIndex(msg, TEMP);
                if (NUMBER>=0){
                    //一致するものが 含まれているものを発見した場合だけ キーワード番号=say_flag
                    say_data(i);
                    return;
                }
            }
        }
    }
    touch_start(integer total_number)
    {
        if (llDetectedKey(0)==llGetOwner()){
            flag++;
            if (flag==1){
                llListenControl(L_ON,TRUE);
                llOwnerSay("会話:起動しました");
            }else{
                flag=0;
                llListenControl(L_ON,FALSE);
                llOwnerSay("会話:一時停止しました");
            }
        }
    }
    on_rez(integer param){llResetScript(); }
}


Posted by しんいち at 10:25│Comments(0)NPC会話・対応
 
<ご注意>
書き込まれた内容は公開され、ブログの持ち主だけが削除できます。