Multiple objects, avs, and dialog boxes in close vicinity
|
|
Ziggy Puff
Registered User
Join date: 15 Jul 2005
Posts: 1,143
|
07-25-2006 10:57
The scenario: There are a group of people within chat range of each other. They're all wearing an attachment. This attachment presents a dialog box when touched. Each attachment needs to interact with the owner, as well as the others in the room.
The problem (as I see it): I don't think I can open listeners for specific av keys, because that would break if two people overlapped between touching the attachment and clicking the dialog box button. But if I keep an open listener, then every attachment hears every button click that was meant for any other attachment, right. So there's no easy way of knowing if the button text message is for me.
Possible solutions, none of which work too well: Randomize the listen channels. This requires opening and closing listeners, which I think I can handle by using a guard timer, and resetting the timer every time the object is touched, and I close the listener only on timeout, not on receiving a chat message (because that would break the 'multiple people touch it together' scenario). This would probably 'statistically work', but it's not air-tight.
Maintain list of 'touchers', check the chat key against the list, act on the command if it matches and delete the entry from the list. Even this isn't foolproof, because an av could touch one person's attachments, ignore the dialog box, then touch another person's attachment, and the first one would respond.
Any other ideas? Has anyone else had to do something like this before?
Thanks, Ziggy
|
|
Adrian Zobel
Registered User
Join date: 4 Jan 2006
Posts: 49
|
07-25-2006 12:41
In my latest project I do both. My items are stationary, not attachments, so it's a bit easier for me. On startup I randomize my channel and shout on that channel... if there's a response I choose a different channel (actually llResetScript).
When someone requests a sensitive menu I save their key in a global variable called toucherkey. When the menu response comes (if it ever does), I check that it matches the key of the speaker; if it doesn't match I give no response, just silently fail. Slower people might think 'hey I chose from the menu and nothing happened', but in my case doing nothing is harmless. That pretty much solves the two-different-people problem.
There's still the issue of same-person-twice. Setting toucherkey = NULL_KEY isn't a solution, you could still get same-person-thrice. Fortunately, in my case that doesn't matter, it's safe for me to react to *that person* according to the most-recently-presented status, as long as I don't respond to *someone else* according to the most-recently-presented status.
For a more extensive solution consider this: each menu key displays only 10 or so characters to the user, but is able to return 24. That leaves you the last 14 characters to put in some sort of identifier so you can tell which menu was answered.
|
|
Ziggy Puff
Registered User
Join date: 15 Jul 2005
Posts: 1,143
|
07-25-2006 12:49
Hmm... I think I might be able to get away with doing nothing, that would certainly be less annoying than doing the wrong thing. So then I could use a 'last person who touched me' global variable. Let me run that by product management and see if they think that's acceptable Making longer button strings is an interesting idea. Add enough spaces to get past the displayable characters, then put in some kind of a key. Thanks for the help 
|
|
Joannah Cramer
Registered User
Join date: 12 Apr 2006
Posts: 1,539
|
07-25-2006 12:58
From: Ziggy Puff Randomize the listen channels. (..)
Maintain list of 'touchers' (..)
Any other ideas? You could possibly get the desired effect by combining both of these -- each attachment has its own randomized channel, and checks the responses in the listen() event vs list of people who recently touched it. This way the scenario of 'person touches attachment, then ignores it and touches another in vicinity' is very unlikely to have wrong effect, as the chance of two attachments sharing the same channel is minimal.
|
|
Ziggy Puff
Registered User
Join date: 15 Jul 2005
Posts: 1,143
|
07-25-2006 13:02
True, I could get it down to "very unlikely this will break" without too much effort. But like I said, it's not completely foolproof. And maybe that's the best I can do, or rather, maybe it's not worth the effort to try and write something that won't break.
|
|
Joannah Cramer
Registered User
Join date: 12 Apr 2006
Posts: 1,539
|
07-25-2006 13:11
From: Ziggy Puff True, I could get it down to "very unlikely this will break" without too much effort. But like I said, it's not completely foolproof. I suppose on top of that you could have the attachment itself speak out on its command channel when someone initializes a dialog. Some sort of pre-defined command like "dialog_open <av key>" or something. Then if two attachments happen to share the channel, this allows them to both become aware of this fact, and to react accordingly in whatever way you see fit. o.O
|
|
Ziggy Puff
Registered User
Join date: 15 Jul 2005
Posts: 1,143
|
07-25-2006 13:56
LOL. That's a good idea too. Though thinking about the "react in whatever way I see fit" part makes me think that I might be better off not trying to implement that kind of corrective action 
|
|
Angela Salome
Registered User
Join date: 6 Oct 2005
Posts: 224
|
07-25-2006 15:22
From: Ziggy Puff Any other ideas? Has anyone else had to do something like this before? Use zero, one or two specific listeners.
|
|
Thraxis Epsilon
Registered User
Join date: 31 Aug 2005
Posts: 211
|
07-25-2006 15:46
This code (untested) should generate a unique channel for any AV pairing for llDialog communication. list handles;
//Used in the generation of the hash, best to make this at least 64 characters. string feed = "How much wood would a wood chuck chuck if a wood chuck could chuck wood?";
integer pseudo_random(string text, integer nonce, integer start, integer end) {//(c)(cc-by) Strife Onizuka, http://creativecommons.org/licenses/by/2.5/ return (integer)("0x"+llGetSubString(llMD5String(text, nonce), start, end)); }
integer Key2Integer(string input, integer start, integer end) { return (integer)("0x"+llGetSubString((string)llParseString2List(input,["-"],[]),start, end)); }
default { state_entry() { handles = []; } touch_start(integer num) { integer x; integer chan; for (x=0; x < num; x++) { handles = (handles=[]) + handles + [llListen(chan = pseudo_random(feed + llKey2Name(llGetOwner()), Key2Integer(llDetectedKey(x),0,7), 0, 7), "", "", "")]; llDialog(llDetectedKey(x), "Pick an option!", ["YES","NO"], chan); } llSetTimerEvent(30); // Remove a listen handle every 30 seconds } listen(integer channel, string name, key id, string message) { llSay(0,name + " picked " + message); } timer() { llListenRemove(llList2Integer(handles, 0)); handles = (handles = []) + llList2List(handles, 1, -1); if (handles == []) { // The listen handles list is empty, stop the timer. llSetTimerEvent(0); } } }
|
|
Ziggy Puff
Registered User
Join date: 15 Jul 2005
Posts: 1,143
|
07-25-2006 16:40
Thanks, that looks like what I need. I was starting to think along those lines, i.e. seed the random chat channel with the av keys, but this is better than anything I would have come up with.
|