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