// (DS) Bad Listener
// created by diamond Marchant, Diamond Synthesis
// abbynormal brain... do not use
// failure modes
// 1. if the same agent touches twice, clicks OK to both, a listener is orphaned. Both dialogs give candy.
// 2. if agent 1 touches, agent 2 touches, agent 2 clicks OK, agent 1 clicks OK, a listener is orphaned. Both agents get candy.
// 3. if agent 1 touches, agent 2 touches, agent 1 clicks OK, agent 2 clicks OK, a listener is orphaned. Only agent 1 gets candy.
integer TIMEOUT = 60;
integer STOP_TIMER = 0;
integer gListenHandle;
integer gCount = 0;
integer randomChannel() {
return (integer)llFrand(-200000) - 100;
}
showDialog(key id, string text, list buttons) {
integer cmdChannel = randomChannel();
llDialog(id, text, buttons, cmdChannel);
// only keep track of last listener
gListenHandle = llListen(cmdChannel, "", id, ""

llSetTimerEvent(TIMEOUT);
}
cleanupListenHandle() {
llListenRemove(gListenHandle);
llSetTimerEvent(STOP_TIMER);
}
default {
on_rez(integer param)
{
llResetScript();
}
state_entry()
{
}
touch_start(integer total_number)
{
showDialog(llDetectedKey(0), "Candy?",[]);
}
listen(integer channel, string name, key id, string message)
{
cleanupListenHandle();
gCount++;
if (message == "OK"

llWhisper(0, "I would give "+llKey2Name(id)+" some if I had any ("+(string) gCount+"


}
timer() {
llWhisper(0,"Listener Timed Out"

cleanupListenHandle();
}
}
// end script
The situation is improved by making gListenHandle into a list and keeping track of listeners by key. Here is an improved candy bowl. Making it actually give candy is an exercise left to the reader. Enjoy!
Note: This post has been edited to correct a cmdChannel bug. If you are only going to keep one listener per agent, you need to use the same cmdChannel for all Dialogs for that agent. Otherwise, if the agent clicks Ignore, then opens another Dialog on a new (random) cmdChannel, the original Listener will not hear it.
// (DS) Better Listener
// created by diamond Marchant, Diamond Synthesis
// use if you like
// desired behavior
// 1. if the same agent touches twice, clicks OK to both, the only listener is removed. Only one dialog gives candy.
// 2. if agent 1 touches, agent 2 touches, agent 2 clicks OK, agent 1 clicks OK, both listeners are removed. Both agents get candy.
// 3. if agent 1 touches, agent 2 touches, agent 1 clicks OK, agent 2 clicks OK, both listeners are removed. Both agents get candy.
integer TIMEOUT = 60;
integer STOP_TIMER = 0;
list gListenHandles; // list holds one listen handle per agent
integer gCount = 0;
integer randomChannel() {
return (integer)llFrand(-200000) - 100;
}
showDialog(key id, string text, list buttons) {
integer cmdChannel;
integer i = llListFindList(gListenHandles, [id]);
if (i == -1)
cmdChannel = randomChannel();
else
// keep using same cmdChannel if this agent already has a listener
cmdChannel = llList2Integer(gListenHandles, i+2);
llDialog(id, text, buttons, cmdChannel);
if (i == -1)
// only add a listener for this agent if one does not exist
gListenHandles += [ id, llListen(cmdChannel, "", id, ""

llSetTimerEvent(TIMEOUT);
}
cleanupListenHandle(key id) {
if (id == NULL_KEY) {
// on timeout, remove all listeners
integer i;
integer n = llGetListLength(gListenHandles);
for (i=0; i < n; i+=3) { // list stride length is 3
llListenRemove(llList2Integer(gListenHandles, i+1));
}
gListenHandles = [];
llSetTimerEvent(STOP_TIMER);
}
else {
// remove the listener for this agent
integer i = llListFindList(gListenHandles, [id]);
if (i != -1) {
llListenRemove(llList2Integer(gListenHandles, i+1));
gListenHandles= llDeleteSubList(gListenHandles, i, i+2);
}
if (llGetListLength(gListenHandles) ==0)
llSetTimerEvent(STOP_TIMER);
}
}
default {
state_entry()
{
}
touch_start(integer total_number)
{
integer i;
// handle multiple touches, sim may be laggy
for (i=0;i < total_number;i++) {
showDialog(llDetectedKey(i), "Candy?",[]);
}
}
listen(integer channel, string name, key id, string message)
{
cleanupListenHandle(id);
gCount++;
if (message == "OK"

llWhisper(0, "I would give "+llKey2Name(id)+" some if I had any ("+(string) gCount+"


}
timer() {
llWhisper(0,"Listener Timed Out"

cleanupListenHandle(NULL_KEY);
}
}