Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Random listen channel and llDialog

Diag Anzac
Registered User
Join date: 27 Oct 2006
Posts: 45
02-19-2007 00:35
Hello.

I'm sure this is something simple. I've searched this forum and the wiki but haven't found any clues yet.
I'm creating a simple script that will change the colour, or turn off, a single light source, using llDialog for input. There may be several of these light sources close to each other, so I want to generate a random listen channel for each light.

It would seem simple, but I don't know where to define the randomised channel variable. The current version errors with "Name not defined in scope" on the llDialog call under touch_start.

CODE

list COLOURS = ["blue", "yellow", "orange", "OFF", "white"];

default
{
state_entry() {
// Define our random channel
integer CHANNEL = (integer)llFrand(89999.0) + 10000;
llListen(CHANNEL, "", NULL_KEY, "");
}

listen(integer channel, string name, key id, string message)
{
if (message == "OFF") {llSetPrimitiveParams([PRIM_POINT_LIGHT, FALSE, <1, 1, 1>, 1.0, 10.0, 0.75]); }
else if (message == "white") {llSetPrimitiveParams([PRIM_POINT_LIGHT, TRUE, <1, 1, 1>, 1.0, 10.0, 0.75]); }
// more colours here, removed for brevity.
}

touch_start(integer total_number)
{
// I get the error on the next line, CHANNEL not defined in scope
llDialog(llDetectedKey(0), "\nSelect a color for this light, or turn it off :", COLOURS, CHANNEL);
}
}


Many thanks for any help :)
Stephen Zenith
Registered User
Join date: 15 May 2006
Posts: 1,029
02-19-2007 01:21
You want to do it like this:

CODE

list COLOURS = ["blue", "yellow", "orange", "OFF", "white"];
integer CHANNEL;

default
{
state_entry() {
// Define our random channel
CHANNEL = (integer)llFrand(89999.0) + 10000;
llListen(CHANNEL, "", NULL_KEY, "");
}

listen(integer channel, string name, key id, string message)
{
if (message == "OFF") {llSetPrimitiveParams([PRIM_POINT_LIGHT, FALSE, <1, 1, 1>, 1.0, 10.0, 0.75]); }
else if (message == "white") {llSetPrimitiveParams([PRIM_POINT_LIGHT, TRUE, <1, 1, 1>, 1.0, 10.0, 0.75]); }
// more colours here, removed for brevity.
}

touch_start(integer total_number)
{
// I get the error on the next line, CHANNEL not defined in scope
llDialog(llDetectedKey(0), "\nSelect a color for this light, or turn it off :", COLOURS, CHANNEL);
}
}


If you declare a variable inside a block beginning and ending with {...}, the variable can only be used inside that block, which caused you problems when you wanted to use the variable in the llDialog call.

Something else to note - when people put a variable name in all capitals, it's generally because they're treating it as constant - ie it won't change. Strictly speaking, the variable is changing here so you may want to make it lower case. Totally your call though, it won't alter how the code works at all.
_____________________
Diag Anzac
Registered User
Join date: 27 Oct 2006
Posts: 45
02-19-2007 01:36
Thank you so much Stephen. It works perfectly. So simple. Thanks also for the tip re capitalization.
Newgate Ludd
Out of Chesse Error
Join date: 8 Apr 2005
Posts: 2,103
02-19-2007 01:44
Actually you I'd suggest you use something more like this :-

CODE

list COLOURS = ["blue", "yellow", "orange", "OFF", "white"];

integer CHANNEL = 0;

integer Listening = 0;

UpdateListen(key id)
{
CancelListen();
CHANNEL = - (integer)llFrand(2147483648);
Listening = llListen(CHANNEL,"",id,"");
llDialog(id, "\nSelect a color for this light, or turn it off :", COLOURS, CHANNEL);
llSetTimerEvent(30);
}

CancelListen()
{
if(Listening > 0) llListenRemove(Listening);
Listening = 0;
llSetTimerEvent(0);
}

default
{
state_entry()
{
CancelListen();
}

touch_start(integer total_number)
{
key id = llDetectedKey(0);
UpdateListen(id);
}

listen(integer channel, string name, key id, string message)
{
CancelListen();

if (message == "OFF") {llSetPrimitiveParams([PRIM_POINT_LIGHT, FALSE, <1, 1, 1>, 1.0, 10.0, 0.75]); }
else if (message == "white") {llSetPrimitiveParams([PRIM_POINT_LIGHT, TRUE, <1, 1, 1>, 1.0, 10.0, 0.75]); }
// more colours here, removed for brevity.
}

timer()
{
//so the menu timeout and close its listener
CancelListen();
}


}


But thats just how I would do it.
Stephen Zenith
Registered User
Join date: 15 May 2006
Posts: 1,029
02-19-2007 02:12
Oh, if you're going to do it properly...

CODE

list COLOUR_NAMES = ["blue", "yellow", "orange", "OFF", "white"];
list COLOURS = [<0.0, 0.0, 1.0>, <1.0, 1.0, 0.0>, <1.0, 0.65, 0.0>, <0.0, 0.0, 0.0>, <1.0, 1.0, 1.0>];
list LIGHT_ON = [TRUE, TRUE, TRUE, FALSE, TRUE];

integer CHANNEL = 0;

integer Listening = 0;

UpdateListen(key id)
{
CancelListen();
CHANNEL = - (integer)llFrand(2147483648);
Listening = llListen(CHANNEL,"",id,"");
llDialog(id, "\nSelect a color for this light, or turn it off :", COLOUR_NAMES, CHANNEL);
llSetTimerEvent(30);
}

CancelListen()
{
if(Listening > 0) llListenRemove(Listening);
Listening = 0;
llSetTimerEvent(0);
}

default
{
state_entry()
{
CancelListen();
}

touch_start(integer total_number)
{
key id = llDetectedKey(0);
UpdateListen(id);
}

listen(integer channel, string name, key id, string message)
{
CancelListen();
integer colourIndex = llListFindList (COLOUR_NAMES, [message]);
if (colourIndex < 0)
{
// llDialog managed to return a colour we don't know of, somehow.
llSay (0, "Oh noes!");
}
else
{
vector colour = llList2Vector (COLOURS, colourIndex);
integer lightOn = llList2Integer (LIGHT_ON, colourIndex);
llSetPrimitiveParams ([PRIM_POINT_LIGHT, lightOn, colour, 1.0, 10.0, 0.75]);
}
}

timer()
{
//so the menu timeout and close its listener
CancelListen();
}


}


But that's just me. Actually I'd read the lists from a notecard, but that's a lesson for another day. Not in-world, so don't blame me if it doesn't compile, or it drinks all of your beer.
_____________________
Newgate Ludd
Out of Chesse Error
Join date: 8 Apr 2005
Posts: 2,103
02-19-2007 02:39
You're LIGHT_ON list is overkill, its not needs as a simple check of the message being OFF is more efficient, especially as the number of colours increases.

I disagree with using a notecard for this, especially if you have a huge number of colours. My own system has 140+ colours and reading from a notecard on initialisation takes 30+ seconds, far too long. Instead I have a seperate colour server script which has the values hardcoded, it initialises much quicker ( ~ 5 sec) and is just as easy to maintain.
Stephen Zenith
Registered User
Join date: 15 May 2006
Posts: 1,029
02-19-2007 02:52
From: Newgate Ludd
You're LIGHT_ON list is overkill, its not needs as a simple check of the message being OFF is more efficient, especially as the number of colours increases.

I disagree with using a notecard for this, especially if you have a huge number of colours. My own system has 140+ colours and reading from a notecard on initialisation takes 30+ seconds, far too long. Instead I have a seperate colour server script which has the values hardcoded, it initialises much quicker ( ~ 5 sec) and is just as easy to maintain.


Unless you want to change the text of the button for Off, into e.g. other languages.

I prefer the flexibility of using a notecard over changing and recompiling code, especially when it's going to be used by a non-scripter. I also think obsessing over every single open listener is overkill personally, but each to their own. And perhaps 140+ colours could also be described as overkill.
_____________________
Newgate Ludd
Out of Chesse Error
Join date: 8 Apr 2005
Posts: 2,103
02-19-2007 03:08
From: Stephen Zenith
Unless you want to change the text of the button for Off, into e.g. other languages.

I prefer the flexibility of using a notecard over changing and recompiling code, especially when it's going to be used by a non-scripter. I also think obsessing over every single open listener is overkill personally, but each to their own. And perhaps 140+ colours could also be described as overkill.


The langauge aspect is a valid point and one that can be handled by a notecard entry. I prefer the notecard name method over the dataserver system for such small items.

Open listens are lag inducing and with the current state of SL we need to be as efficient as we can. But its always good practise to be as efficient as possible.

I agree about not making users edit and recompile code, which is why the colour server supplys such a large number of colours.

As you say to each their own, at the end of the day theres more than one way to skin a cat...
Pale Spectre
Registered User
Join date: 2 Sep 2005
Posts: 586
02-19-2007 03:29
I broadly agree with your approach, Newgate, but out of curiosity, why do you CancelListen() in state_entry()? This is starting to look like an obsession. :D
Diag Anzac
Registered User
Join date: 27 Oct 2006
Posts: 45
02-19-2007 04:40
I'm glad to see I sparked some interesting conversation :) Thanks all. Very interesting.
Newgate Ludd
Out of Chesse Error
Join date: 8 Apr 2005
Posts: 2,103
02-19-2007 05:45
From: Pale Spectre
I broadly agree with your approach, Newgate, but out of curiosity, why do you CancelListen() in state_entry()? This is starting to look like an obsession. :D


May be it is obsessive, just the kind of RL programming practises I use so I've carried them with me into SL. It just makes sense to always make sure you know your current state. I agree in this instance it isnt actually required since even if we do have a timer running it will be cancelled by the script reset.