Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

llDialog error

Azul Wilder
Registered User
Join date: 29 Jan 2007
Posts: 87
05-03-2007 07:41
Hi!

I'm writting a script that uses a llDialog to create a menu with several options. The script reads a note in the object inventory to get the texts for the buttons, but when I test the script it gives this error: "llDialog: button labels must be 24 or fewer characters long"

I know that the script reads the note correctly. And the texts for the buttons have less than 24 characters everyone of them. Do you know why this happen?

Thanks.
_____________________
First goes before
AW Devices
bucky Barkley
Registered User
Join date: 15 May 2006
Posts: 200
05-03-2007 08:37
Check for leading or trailing spaces ...

Check to see if you are accidentally concatenating the text for more than one button.
_____________________
Bucky Barkley -- Mammal, Scripter, Builder, Lover
Azul Wilder
Registered User
Join date: 29 Jan 2007
Posts: 87
05-03-2007 08:47
Checked that is not the problem. In the note card there are only simple words with no special characters
_____________________
First goes before
AW Devices
Lex Neva
wears dorky glasses
Join date: 27 Nov 2004
Posts: 1,361
05-03-2007 08:47
Replace your llDialog call with a llSay that lets you see EXACTLY what you're sending to the llDialog function. That should shed some light on what's going on.
Azul Wilder
Registered User
Join date: 29 Jan 2007
Posts: 87
05-03-2007 10:47
I have made that and I found some mistakes in the code (it was reading the keys) now they are solved and the error now says

Object1: llDialog: all buttons must have label strings

For some reason it is not reading the strings in the note. The strings come empty. I used LLSay and it says "Object1: "

Maybe the dataserver is not beeing triggered?
_____________________
First goes before
AW Devices
Milambus Oh
Registered User
Join date: 6 Apr 2007
Posts: 224
05-03-2007 10:50
Try posting you code? People will be able to look through it better then.
Azul Wilder
Registered User
Join date: 29 Jan 2007
Posts: 87
05-10-2007 00:28
Sorry for the delay here I write the code (more or less)

CODE


string Note = "dest";

key dest1;
key dest2;
key dest3;
key nom1;
key nom2;
key nom3;


string boton1;
string boton2;
string boton3;
vector desti1;
vector desti2;
vector desti3;

vector PosIni;
vector myPos;

vector origin;
vector destination;

float primerPaso_x;
float primerPaso_y;
float primerPaso_z;

float recorrido_x;
float recorrido_y;
float recorrido_z;

float distance_x;
float distance_y;
float distance_z;

float pasos_x;
float pasos_y;
float pasos_z;

string lines;

default
{
state_entry()
{
llSetStatus(STATUS_PHYSICS,FALSE);
llSetSitText("SIT");

llSetCameraEyeOffset(<-2, 0, 1>);
llSetCameraAtOffset(<-1, 0, 1>);

llListen(26962,"",llGetKey(),"");
}

touch_start(integer total_number)
{
llSay(0, "Right Click and SIT");
}

changed(integer change)
{
if (change & CHANGED_LINK)
{
integer itemtype = llGetInventoryType(Note);
if(INVENTORY_NOTECARD == itemtype)
{
nom1 = llGetNotecardLine(Nota, 4);
dest1 = llGetNotecardLine(Nota, 5);
nom2 = llGetNotecardLine(Nota, 8);
dest2 = llGetNotecardLine(Nota, 9);
nom3 = llGetNotecardLine(Nota, 12);
dest3 = llGetNotecardLine(Nota, 13);
}
else
llOwnerSay("Error - No existe esa Nota en el inventario");

list destinos = [boton1, boton2, boton3];
key sujeto = llDetectedKey(0);
llDialog(sujeto, "Choose a destination to go: ", destinos, 26962);
}
}

dataserver (key queryid, string data)
{

if (llAvatarOnSitTarget() != NULL_KEY)
{

if (queryid == nom1)
boton1 = data;
if (queryid == nom2)
boton2 = data;
if (queryid == nom3)
boton3 = data;
if (queryid == dest1)
desti1 = (vector)data;
if (queryid == dest2)
desti2 = (vector)data;
if (queryid == dest3)
desti3 = (vector)data;
}
else
llOwnerSay("No AV sitted, not possible to read the note");
}

listen(integer chan, string name, key id, string cmd)
{

if (id == llGetKey() && cmd == boton1)
{
origin = llGetPos();
destination = dest1;

recorrido_x = origin.x - destination.x;
recorrido_y = origin.y - destination.y;
recorrido_z = origin.z - destination.z;

primerPaso_x = (integer)recorrido_x % 10;
primerPaso_y = (integer)recorrido_y % 10;
primerPaso_z = (integer)recorrido_z % 10;

llSetPos(origin + <primerPaso_x, primerPaso_y, primerPaso_z>);
llSleep(0.1);

origin = llGetPos();

distance_x = llFabs(origin.x - destination.x);
distance_y = llFabs(origin.y - destination.y);
distance_z = llFabs(origin.z - destination.z);

pasos_x = distance_x/10;
pasos_y = distance_y/10;
pasos_z = distance_z/10;

integer a = 0;
integer b = 0;
integer c = 0;

do
{
llSetPos(origin + <0,0,10>);
llSleep(0.1);
origin = llGetPos();
a ++;
}

while (a < pasos_z);

do
{
llSetPos(origin + <10,0,0>);
llSleep(0.1);
origin = llGetPos();
b ++;
}

while (b < pasos_x);

do
{
llSetPos(origin + <0,10,0>);
llSleep(0.1);
origin = llGetPos();
c ++;
}

while (c < pasos_y);


llSleep(1);
myPos = llGetPos();

if (myPos == destino)
llOwnerSay("Here we are, now you can stand UP and take me back to your inventory");
else
{
llSetPos(destination);
llSleep(1);
llOwnerSay("Here we are, now you can stand UP and take me back to your inventory");
}
}

}
}



I have reduced the code, don't take into account if any spelling faults. What I need to know is why it is not reading the note.

Thanks a lot.
_____________________
First goes before
AW Devices
Newgate Ludd
Out of Chesse Error
Join date: 8 Apr 2005
Posts: 2,103
05-10-2007 03:20
Azul,
Your notecard variable is Note yet the script tries to read a variable called Nota.

You appear to be requesting the notecard data when the avatar sits but then display a dialog using the expected results immediatedly without having waited for the dataserver to respond?

You have your dataserver event embedded inside the changed event.

You start a listen in state entry listening to itself?
CODE
llListen(26962,"",llGetKey(),"");

You never appear to change the listen so it will never hear the user.

You set up the camera (in state_entry) and yet never request camera control permissions.
I also think that camera functiosn will only work on an avatar, I dont think they are persistent within the prim.

I'd suggest that you read the notecard on start up or change of inventory.
I'd also suggest that you read it sequentially rather than fire them all off in one go, at least that way you can track when you have finished reading the data. (You cannot guarentee when or even IF you will get a reply from the data server.)
_____________________
I'm back......
Tiarnalalon Sismondi
Registered User
Join date: 1 Jun 2006
Posts: 402
05-10-2007 07:08
Actually Newgate, the camera offsets are prim properties like sit targets, so he's fine with that part. He's not really controlling the camera, just setting where it will start at when someone sits on it.

One thing I would recommend here: Do not read the notecard on the changed event.

I would put those lines on state entry and add (assuming I don't make a silly mistake)

CODE
if (change & CHANGE_INVENTORY)
{
llOwnerSay("Reloading destinations...");
llResetScript();
}


I'm pasting the whole code where I can read it easier and I'll post back any other things in a while, but I will say that it looks like you've called your llAvatarOnSitTarget in the wrong place as well, and will probably cause it to pull a dataserver event everytime someone sits or stands, which I think is really unnecessary, but if you put in my snippet above it would remove the dataserver event from this section.
Tiarnalalon Sismondi
Registered User
Join date: 1 Jun 2006
Posts: 402
05-10-2007 07:38
Here is an editted version that should at least function better. I didn't have time to bother with going through anything below the dataserver event, so if you still have problems that's where it probably is

CODE
  string Note = "dest";

key dest1;
key dest2;
key dest3;
key nom1;
key nom2;
key nom3;


string boton1;
string boton2;
string boton3;
vector desti1;
vector desti2;
vector desti3;

vector PosIni;
vector myPos;

vector origin;
vector destination;

float primerPaso_x;
float primerPaso_y;
float primerPaso_z;

float recorrido_x;
float recorrido_y;
float recorrido_z;

float distance_x;
float distance_y;
float distance_z;

float pasos_x;
float pasos_y;
float pasos_z;

list destinos;

string lines;

default
{
state_entry()
{
destinos = [];

llSetStatus(STATUS_PHYSICS,FALSE);
llSetSitText("SIT");

llSetCameraEyeOffset(<-2, 0, 1>);
llSetCameraAtOffset(<-1, 0, 1>);

llListen(26962,"",llGetOwner(),"");

integer itemtype = llGetInventoryType(Note);
if(INVENTORY_NOTECARD == itemtype)
{
nom1 = llGetNotecardLine(Note, 4);
dest1 = llGetNotecardLine(Note, 5);
nom2 = llGetNotecardLine(Note, 8);
dest2 = llGetNotecardLine(Note, 9);
nom3 = llGetNotecardLine(Note, 12);
dest3 = llGetNotecardLine(Note, 13);
}
else
llOwnerSay("Error - No existe esa Nota en el inventario");

}

touch_start(integer total_number)
{
llSay(0, "Right Click and SIT"); //You can get rid of this entire state altogether by changing the prim on the properties when you edit it to Sit On Touch
}

changed(integer change)
{
if (change & CHANGED_LINK)
{

key sitter = llAvatarOnSitTarget();

if (sitter == llGetOwner()) //You have been setting it to only listen to the owner…if you want anyone to be able to use it, this will need to change

llDialog(llGetOwner(), "Choose a destination to go: ", destinos, 26962); //You were calling the dialog before you’d given the script a chance to pull the data from the notecard, hence why I moved it to the state entry

else if ((sitter != NULL_KEY) && (sitter != llGetOwner())

llSay(0,”You are not authorized to use this teleporter.”);
}

if (change & CHANGED_INVENTORY)

{

llOwnerSay(“Reloading Destinations…”);

llResetScript();

}
}

dataserver (key queryid, string data)
{


if (queryid == nom1)

{

boton1 = data;

destinos = destinos + boton1;

if (llGetListLength(destinos) == 3)

llOwnerSay(“Destinations Loaded.”);

}

if (queryid == nom2)

{

boton2 = data;

destinos = destinos + boton2;

if (llGetListLength(destinos) == 3)

llOwnerSay(“Destinations Loaded.”);



}

if (queryid == nom3)

{

boton3 = data;

destinos = destinos + boton3;

if (llGetListLength(destinos) == 3)

llOwnerSay(“Destinations Loaded.”);

}

if (queryid == dest1)
desti1 = (vector)data;
if (queryid == dest2)
desti2 = (vector)data;
if (queryid == dest3)
desti3 = (vector)data;

}

listen(integer chan, string name, key id, string cmd)
{

if (id == llGetKey() && cmd == boton1)
{
origin = llGetPos();
destination = dest1;

recorrido_x = origin.x - destination.x;
recorrido_y = origin.y - destination.y;
recorrido_z = origin.z - destination.z;

primerPaso_x = (integer)recorrido_x % 10;
primerPaso_y = (integer)recorrido_y % 10;
primerPaso_z = (integer)recorrido_z % 10;

llSetPos(origin + <primerPaso_x, primerPaso_y, primerPaso_z>);
llSleep(0.1);

origin = llGetPos();

distance_x = llFabs(origin.x - destination.x);
distance_y = llFabs(origin.y - destination.y);
distance_z = llFabs(origin.z - destination.z);

pasos_x = distance_x/10;
pasos_y = distance_y/10;
pasos_z = distance_z/10;

integer a = 0;
integer b = 0;
integer c = 0;

do
{
llSetPos(origin + <0,0,10>);
llSleep(0.1);
origin = llGetPos();
a ++;
}

while (a < pasos_z);

do
{
llSetPos(origin + <10,0,0>);
llSleep(0.1);
origin = llGetPos();
b ++;
}

while (b < pasos_x);

do
{
llSetPos(origin + <0,10,0>);
llSleep(0.1);
origin = llGetPos();
c ++;
}

while (c < pasos_y);


llSleep(1);
myPos = llGetPos();

if (myPos == destino)
llOwnerSay("Here we are, now you can stand UP and take me back to your inventory");
else
{
llSetPos(destination);
llSleep(1);
llOwnerSay("Here we are, now you can stand UP and take me back to your inventory");
}
}

}
}


EDIT: Which I just read through parts of the bottom and it appears you keep using the command llGetKey(). This pulls only the key of the object the script is in. You need to use a different command like llGetOwner().
Newgate Ludd
Out of Chesse Error
Join date: 8 Apr 2005
Posts: 2,103
05-10-2007 07:55
From: Tiarnalalon Sismondi
Actually Newgate, the camera offsets are prim properties like sit targets, so he's fine with that part. He's not really controlling the camera, just setting where it will start at when someone sits on it.

I stand, or rather slouch, corrected. I wasnt aware that they where prim parameters, especially since the WIKKI states that you need camera permissions before you can use them?

From: Tiarnalalon Sismondi
One thing I would recommend here: Do not read the notecard on the changed event.

I would put those lines on state entry and add (assuming I don't make a silly mistake)

CODE
if (change & CHANGE_INVENTORY)
{
llOwnerSay("Reloading destinations...");
llResetScript();
}



Thats what I meant when I said about "on a change of inventory".

From: Tiarnalalon Sismondi
I'm pasting the whole code where I can read it easier and I'll post back any other things in a while, but I will say that it looks like you've called your llAvatarOnSitTarget in the wrong place as well, and will probably cause it to pull a dataserver event everytime someone sits or stands, which I think is really unnecessary, but if you put in my snippet above it would remove the dataserver event from this section.


Not the way it is curently written it wouldn't :)
As you say, and I think I did earlier, the way its written the notecard is reread whenever an avatar sits, which is incredibly inefficient. Personally I prefer to read all constant data, i.e. notecards, at start up and then switch to a running state. Because there is no guarentee of dataserver event order I also prefer to sequential reads rather than block reads.

Personally I'd replace the movement code with a call to WarpPos.

Newgy-ised version
CODE

string Note = "dest";
integer channel = 26962;

key id;

string boton1;
string boton2;
string boton3;

vector desti1;
vector desti2;
vector desti3;

list linenumbers = [ 4, 5, 8, 9, 12, 13 ];
integer index = 0;

ReadLine()
{
llSetTimerEvent(10.);
id = llGetNotecardLine(Note, llList2Integer(linenumbers,index));
}

default
{
state_entry()
{
integer itemtype = llGetInventoryType(Note);
if(INVENTORY_NOTECARD == itemtype)
{
llSetText("Reading Configuration data. Please Wait.",<1.,0.,0.>,1.);
ReadLine();
}
else
llOwnerSay("Error - No existe esa Nota en el inventario");
}


dataserver (key queryid, string data)
{
if(queryid == id)
{
llSetTimerEvent(0.);
if (0 == index) boton1 = data;
else if (1 == index) desti1 = (vector)data;
else if (2 == index) boton2 = data;
else if (3 == index) desti2 = (vector)data;
else if (4 == index) boton3 = data;
else if (5 == index) desti3 = (vector)data;

++index;
if(index == 6) state running;

ReadLine();
}
}

changed(integer change)
{
if(change & CHANGED_INVENTORY)
{
llResetScript();
}
}

timer()
{
llSetTimerEvent(0.);
llOwnerSay("Error - dataserver timed out. Aborting.");
state running;
}
}

state running
{
state_entry()
{
llSetStatus(STATUS_PHYSICS,FALSE);
llSetSitText("SIT");

llSetCameraEyeOffset(<-2, 0, 1>);
llSetCameraAtOffset(<-1, 0, 1>);

}

touch_start(integer total_number)
{
llSay(0, "Right Click and SIT");
}

changed(integer change)
{
if (change & CHANGED_LINK)
{
list destinos;
// Add the button text - but only if valid
if(boton1 != "") destinos += [ boton1 ];
if(boton2 != "") destinos += [ boton2 ];
if(boton3 != "") destinos += [ boton3 ];

// Display the dialog
key sujeto = llDetectedKey(0);
llListen(channel,"",sujeto,"");
llDialog(sujeto, "Choose a destination to go: ", destinos, channel);
}
else if(change & CHANGED_INVENTORY)
{
llResetScript();
}
}

listen(integer chan, string name, key userid, string cmd)
{
llSetTimerEvent(0.);
integer valid = FALSE;

vector destination;

if (cmd == boton1) { destination = desti1; valid = TRUE; }
else if (cmd == boton2) { destination = desti2; valid = TRUE; }
else if (cmd == boton3) { destination = desti3; valid = TRUE; }

if(valid)
{
// Movement code here........
}
}
}
_____________________
I'm back......
Tiarnalalon Sismondi
Registered User
Join date: 1 Jun 2006
Posts: 402
05-10-2007 08:30
Yea, but you know me....posting at work so I ran through what I could really quick heh. I didn't even look at the bottom at all until my edit.

Which, to expand on the previous point, any of the camera functions listed at the top here: http://lslwiki.net/lslwiki/wakka.php?wakka=Camera

...that says something that they do to the camera when an AV sits on the object are things you can set without requesting permissions.

I've noticed that the offset ones are persistent and stay with a prim even without the code like a sit target. The ForceMouselook I'm not sure if it is persistent or not since I don't use it.
Newgate Ludd
Out of Chesse Error
Join date: 8 Apr 2005
Posts: 2,103
05-10-2007 09:00
From: Tiarnalalon Sismondi
Yea, but you know me....posting at work so I ran through what I could really quick heh. I didn't even look at the bottom at all until my edit.

Which, to expand on the previous point, any of the camera functions listed at the top here: http://lslwiki.net/lslwiki/wakka.php?wakka=Camera

...that says something that they do to the camera when an AV sits on the object are things you can set without requesting permissions.

I've noticed that the offset ones are persistent and stay with a prim even without the code like a sit target. The ForceMouselook I'm not sure if it is persistent or not since I don't use it.


heheh, same here :) it passes the time while waiting for real code to compile.....
_____________________
I'm back......
Azul Wilder
Registered User
Join date: 29 Jan 2007
Posts: 87
05-10-2007 09:30
Thanks to both

Now I'll test the changes and I will let you know.

The camara was working well. Tiarnalalon is right.

Let me try it.

Thanks.
_____________________
First goes before
AW Devices
Talarus Luan
Ancient Archaean Dragon
Join date: 18 Mar 2006
Posts: 4,831
05-10-2007 09:57
To be precise, only llForceMouselook(), llSetCameraAtOffset(), and llSetCameraEyeOffset() are prim properties that do not require some kind of permission be requested beforehand. llSetCameraParams(), llReleaseCamera(), and llClearCameraParams() are NOT prim properties, and require permissions to be requested and granted before they will work. It is true that sitting/attaching will automatically grant the permissions without asking the user via blue dialog, but like all permissions in the same situation, they must still be requested first anyway.

Also concur on the main problem being solved by reading the notecard in first before using llDialog. Secondarily, the listen was problematic as well.
Azul Wilder
Registered User
Join date: 29 Jan 2007
Posts: 87
05-10-2007 10:47
Hi!

I've tried the script. Iti is not working. The part that is not working is this
CODE

if (change & CHANGED_LINK)
{
key sitter = llAvatarOnSitTarget();

if (sitter == llGetOwner())
llDialog(llGetOwner(), "Choose a destination to go: ", destinos, 26962);
else if (sitter != NULL_KEY && sitter != llGetOwner())
llSay(0,"You are not authorized to use this teleporter.");
else
llOwnerSay("Key not detected or no owner sitted");
}


I wrote after "key sitter"
llOwnerSay("The one sittted is " + (string)sitter);
an it says 0000000....

The else I added after the else if triggers so it is not detecting the AV's key.
_____________________
First goes before
AW Devices
Newgate Ludd
Out of Chesse Error
Join date: 8 Apr 2005
Posts: 2,103
05-10-2007 15:52
You need to set a sit target or llAvatarOnSitTarget will always return NULL_KEY.
_____________________
I'm back......
Azul Wilder
Registered User
Join date: 29 Jan 2007
Posts: 87
05-10-2007 23:58
That's right. I'm really dense these days.

I'll keep you informed.

Thanks.
_____________________
First goes before
AW Devices
Azul Wilder
Registered User
Join date: 29 Jan 2007
Posts: 87
05-11-2007 01:42
now it works, thanks a lot to all of you dudes.

it just need a few adjustments in the movements.
_____________________
First goes before
AW Devices
Newgate Ludd
Out of Chesse Error
Join date: 8 Apr 2005
Posts: 2,103
05-11-2007 02:00
From: Azul Wilder
now it works, thanks a lot to all of you dudes.

it just need a few adjustments in the movements.



Take a look at WarpPos in the library, it is the defacto "standard" for long distance TP's
_____________________
I'm back......
Tiarnalalon Sismondi
Registered User
Join date: 1 Jun 2006
Posts: 402
05-11-2007 05:05
Well I'm glad it's working, though this part seems a little redundant.

CODE
	else
llOwnerSay("Key not detected or no owner sitted");


As since the only key left is NULL_KEY, and this means that the teleporter is going to say this everytime someone stands up since the changed event gets fired in that case too.