Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Help jumpstarting project: keyword listener

Dylan Rickenbacker
Animator
Join date: 11 Oct 2006
Posts: 365
11-01-2007 04:32
Hi, I'm only pretending to be a scripter and want to try my hand on something more complex than I've ever done before. I want to script a keyword listener, that is, an attachment that listens to public chat and plays a sound whenever one of the words listed in a notecard comes up in public chat.

Before I actually start coding, I'd like to think aloud here about how to proceed. Please bear with me and yank my reins if I'm running the wrong way. Thanks!

Okay, I'm assuming that my script has to convert the contents of the notecard into a list. That is, it has to

- find out how many lines the notecard has (llGetNumberOfNotecardLines),

- then use some kind of loop (I'm guessing "while";) to define a variable for each notecard line,

- then declare the list containing those variables.

Right so far?

Next, I have to set up the listener. What is the best way to do that? Can I compare to the whole list in one step or do I have to set up a loop again to compare to each list item in turn?

Lastly, "if" variable == list item - llPlaySound. Question: The sound should only be audible to the object owner. How do I do that?

Thanks a lot for reading and commenting! :-)
Kahiro Watanabe
Registered User
Join date: 28 Sep 2007
Posts: 572
11-01-2007 04:44
You have all the answers in: lslwiki.net

Notecard: http://lslwiki.net/lslwiki/wakka.php?wakka=llGetNotecardLine

The best way to setup the listener... you should make a loop (while) the list doesn't end and why the word doesn't match with the chat will continue searching.

While (!notecardEnd & chat != word)
{

readNotecardLine();

}

if (chat == word)
llPlaySound("souind";);

------------------------------------------------------------------------------
That is *****pseudocode***** , i don't have time to write it in LSL now, but i think it will help.

A way to play a sound that only owner can listens is attaching object to hud and play the sound from there, with llTriggerSound() anybody can hear it with llPlaySound only you.
Lyn Mimistrobell
(waiting)
Join date: 11 Jan 2007
Posts: 179
11-01-2007 08:42
I would read the notecard into a list during entry_start. The part that'll take most time is to compare every word in a chat to every word that you've read from the notecard.

If the notecard list is shorter than the chat list (words in a chat), loop thru the words in the notecard and use llListFindList to see if it's in the chat. If the chat list is shorter, loop thru the words in the chat and use llListFindList to see if it's in the notecard list.
Ziggy Puff
Registered User
Join date: 15 Jul 2005
Posts: 1,143
11-01-2007 10:07
You can also do a substring search, so:

for each word in keyword list
see if the word occurs in the chat string

For reading notecards - this is a well understood and described problem, look it up on the wiki. You'll need to have some understanding of asynchronous events, reading a notecard is a multi-step process because of how LSL handles notecards (i.e. the dataserver stuff).
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
11-01-2007 10:28
actually I'd stick with testing chat against the list, so you don't have to reconvert the index you find to be useful to play specific sounds... something like this
CODE

//-- assume: vLstKW = your list of kewords, vLstChatLine = your list of chatted words, & a list of sounds to play for each KW
integer vIntCounter = llGetListLength( vLstChatLine );
do{
--vIntCounter;
vIntFound = llListFindList( vLstKW, (list)llList2String( vLstChatLine, vIntCounter ) );
if (~vIntFound){ //-- same as (vIntFound != -1)
//--play sound from list index vIntFound
}
}while (vIntCounter);

sounds in huds only play for the owner, but IIRC won't play if the land you're on has "restrict spatialized sound to this parcel" checked

if the KW will be the only one said, you COULD set up an individual listen for each KW then test to see which one it is like
CODE

integer vIntCounter = llGetListLength( vLstKW );
while( vIntCounter ){
--vIntCounter;
llListen( 0, "", "", llList2String( vLstKW, vIntCounter ) );
}

you can also do this with gestures, each gesture is a KW, and plays a sound that goes with it, but this will play the sound for everyone, and only tracks the owners KWs

and a simplified notecard reader...
CODE

//-- assume: notecard called 'config', each 2 line group contains a KW & a sound name
integer vIntLineNumber;
list vLstKW;
list vLstSounds;

default{
state_entry(){
llGetNotecardLine( "config", vIntLineNumber );
}

dataserver( key vKeyNull, string vStrData ){
if (vStrData != EOF){
if (++vIntLineNumber % 2){
vLstKW += (list)vStrData;
}else{
vLstSounds += (list)vStrData;
}
llGetNotecardLine( "config", vIntLineNumber );
}else{
state vsMain;
}
}
}

state vsMain{
//-- everything else here
}
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -
Ziggy Puff
Registered User
Join date: 15 Jul 2005
Posts: 1,143
11-01-2007 10:47
From: someone
actually I'd stick with testing chat against the list


Now consider efficiency. Your loop operation is:

vIntFound = llListFindList( vLstKW, (list)llList2String( vLstChatLine, vIntCounter ) );

AFAIK, LSL internally cannot access an arbitrary list element directly, it has to walk the list from the front to find the entry you're looking for, even though you've specified an index. So List2String will walk the chat list each time to return each word. Then you walk the keyword list again, comparing against each element.

The other way, you have List2String on the keyword list (which is presumably shorter than the chat string), and then string comparisons, which should be lighter than list comparisons.

From: someone
so you don't have to reconvert the index you find to be useful to play specific sounds


I don't understand. If you walk the keyword list and compare each entry to the chat string, you know your index in the keyword list, so you know what sound to play. Where's the re-conversion?

for (i = 1 to number of keywords)
keyword = List2String(KeywordList, i)
if (keyword found as substring in chat line)
play sound
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
Doh,... need caffiene =)
11-01-2007 11:02
From: Ziggy Puff

I don't understand. If you walk the keyword list and compare each entry to the chat string, you know your index in the keyword list, so you know what sound to play. Where's the re-conversion?

you're right, mental lapse =)

From: someone
for (i = 1 to number of keywords)
keyword = List2String(KeywordList, i)
if (keyword found as substring in chat line)
play sound


you know, that is a much more elegant solution, in fact I'm going to consider adding it to another project possibly, thanks=)

although I prefer 'i = #-of-KW' and then decrement to save a variable and test time (and if listLength is stored after creation, even better);
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -
Kahiro Watanabe
Registered User
Join date: 28 Sep 2007
Posts: 572
11-01-2007 11:39
Yes, for is more elegant than a while but this last one consume less memory.
Dylan Rickenbacker
Animator
Join date: 11 Oct 2006
Posts: 365
11-01-2007 11:50
Wow, thanks a lot to all who got into this! Lots of stuff for me to get my head around.

BTW, I should have made it clearer that I don't need different sounds for different words ... just one sound that is to be played whenever any of the keywords appears in chat.
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
11-01-2007 13:04
definitely use Ziggy's
CODE

interger vIntCounter = llGetListLength( vLstKW );
while (vIntCounter){
--vIntCounter;
if (~llGetSubStringIndex( vStrChatLine, llList2String( vLstKW, vIntCounter ) )){
//play sound
}
}


just be aware it'll also pick KW out of other words
example
kw = it
will also pick up 'sit' & 'item' & 'position'

to combat that you could add a space to the end/begining of your chat line, and do the same with your KW
when reading the notecard use
vLstKey += (list)(" " + llStringTrim( vStrData, STRING_TRIM ) + " ";);
//-- we use trim to prevent users from adding extra spaces

and in your listen
vStrChatHeard = " " + vStrChatHeard + " ";
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -
DoteDote Edison
Thinks Too Much
Join date: 6 Jun 2004
Posts: 790
11-01-2007 16:17
I made a simple version to listen for my name in chat... in case I'm not paying attention or scripting or something. It's a HUD attachment, and changes color to show whether it is ON or OFF.

From: someone
string NAME = "dote";
string DING = "sfx_bell";

integer switch;
integer handle;

default {
touch_start(integer num) {
if(!switch) handle = llListen(0, "", "", "";);
else llListenRemove(handle);
switch = !switch;
llSetColor(<!switch, switch, 0>, ALL_SIDES);
}
listen(integer ch, string n, key id, string msg) {
if (~llSubStringIndex(llToLower(msg), NAME)) llTriggerSound(DING, 1);
}
}
Jesse Barnett
500,000 scoville units
Join date: 21 May 2006
Posts: 4,160
11-01-2007 17:42
From: DoteDote Edison
I made a simple version to listen for my name in chat... in case I'm not paying attention or scripting or something. It's a HUD attachment, and changes color to show whether it is ON or OFF.

WOW, wish I would have had that real life for my Ex. Instead of changing colors, maybe it could have delivered a jolt of electricty? Maybe then they would have heard when I was talking to them.

"Huh? What? Did you say something?

O well, I digress...................
_____________________
I (who is a she not a he) reserve the right to exercise selective comprehension of the OP's question at anytime.
From: someone
I am still around, just no longer here. See you across the aisle. Hope LL burns in hell for archiving this forum