Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

problem with Lists

psimagus Hax
Registered User
Join date: 3 Jul 2007
Posts: 73
05-26-2008 18:19
I'm having trouble with this piece of script, and I wondered if some kind expert out there could point me back onto the path (I've been blundering up dead-ends for several days now! :() It's supposed to allow people to delete entries in a list, but only if they made them originally. The messages are stored in a list (messageList), and the names are stored in a parallel list (avList) - so the position in each list matches user to message.

For clarity I've simplified the default and Running states (they're working fine, and would make this post needlessly large.)

When I run the script, it ploughs straight through to the 5th message, without offering the delete option for any earlier messages, and then, if I say "yes", immediately deletes the 1st message (as evidenced by the llSay result at the end,) and goes to state Running.

It OUGHT to offer me the delete option for messages 2, 4 and 5 (one at a time,) since those are matched by my name at the relevant positions in avList, and only then go to state Running. And if "Joe Bloggs" used it, it ought to offer to delete message 3, etc.

Another (quite possibly related) problem seems to be that the string currentname doesn't seem to hold its value between state changes - at least it isn't displaying my name in the message it gives when it changes to state Running. So I suspect it is already blank in state editing, when it's supposed to use it to compare with the names in avList (I just don't have a clear idea of how to fix it.)

Anyway, here it is - and thanks in advance for any pointers in the right direction!



integer counter = 0;
integer position;
integer totalnumber;
string avname;
string currentname;
string message;
// these lists are only temporarily prepopulated here for purposes of this example:
list messageList = ["Message 1", "Message 2", "Message 3", "Message 4", "Message 5", "Message 6"]; // list containing messages, each definable by 'position'
list avList = ["John Doe", "psimagus Hax", "Joe Bloggs", "psimagus Hax", "psimagus Hax", "John Doe"]; // which should match the 'position' of each name in this list since they're incremented in the same code block

default
{
state_entry()
{
}
touch_start(integer total_number)
{
string currentname = llDetectedName(0);
llSay (0, "STARTING LIST EDITOR...\n";);
if ((list)messageList == [" "]) // Get this out of the way, if the list is empty
{
llSay(0, "There are no entries in the queue to edit. Returning to normal operation...";);
state Running;
}
else {
// determine totalnumber of entries and go to editing mode
integer totalnumber = (llGetListLength(messageList) -1);
state editing;
}
}
}


state editing
{
state_entry()
{
integer counter = 0;
llSay (0, "EDITING MENU:\n";);
integer totalnumber = (llGetListLength(messageList) - 1);
for (; position < totalnumber; position++)
{
string TMPmessage = llList2String(messageList, position);
string avname = llList2String(avList, position);
if ((string)avname == (string)currentname) // *************
{ // *************
llSay (0, "Would you like to delete this entry?:\n(Just type 'yes' or 'no')\n" + (string)TMPmessage + "\n\n";) ;
llListen( 0, "", currentname, "" );
// Add a timer here, so if the user fails to conclude the process, it will time out and return to state Running:
llSetTimerEvent(60.0);
else // *************
{ // *************
return;
}
}


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

//string currentname = llKey2Name(id);
integer position = 0;
if (message == "yes";)
{
messageList = llDeleteSubList(messageList, position, position);
avList = llDeleteSubList(avList, position, position);
llSay( 0, "Thankyou " + (string)currentname + ", your entry has been deleted.";);
}
else
{
// otherwise don't delete entries if "no" (or anything else) is typed:
llSay (0, "Okay " + (string)currentname + " - this entry has not been deleted.";);
}

if (position == totalnumber)
{
llSay(0, "You have reached the end of the queue. Saving message queue, and returning to normal operation...";);
state Running;
}
else

{
return;
}
}



timer()
{
// if user fails to conclude any operation, or provide any input when prompted.
llSay(0, "60 seconds have passed with no input.\nReturning to normal operation...";);
state Running;
}

}

state Running
{
state_entry()
{
integer totalnumber = (llGetListLength(messageList));
llSay(0,"Returned to state running " + (string)currentname);
llSay(0,(string)messageList + (string)avList);
llSetText((string)totalnumber + " entries", <1.0,1.0,1.0>, 1);
}
}
Kidd Krasner
Registered User
Join date: 1 Jan 2007
Posts: 1,938
05-26-2008 20:21
You never actually use the avname, so there's no code to make sure that only the right person can delete things.

Event handlers in LSL always run to completion before running any other handlers in the same script. So when you loop through the list in the state_entry handler of the editing state, you're going to loop through all of them before you ever get the first listen event. If you require either a response or a timeout before going on to the next, you need to just do the first one in the state_entry handler. Then the listen handler and timer handler both must be prepared to move on to the next entry. Obviously, this calls for consolidating the code into a function. It can get a little tricky, because you can't be sure when the user will actually type something.
psimagus Hax
Registered User
Join date: 3 Jul 2007
Posts: 73
05-27-2008 03:49
Oops! Sorry - I pasted in the wrong example (I've been trying so many different variations, I'm beginning to get more confused than usual.) I've edited the original post to include the "if ((string)avname == (string)currentname)" (added lines annotated "// *************";) .
This too doesn't work, because currentname seems to be blank. But I don't know how to make it 'carry over' from the default state to the editing state. And even without this, (as originally posted,) it isn't stopping at each message to ask whether to delete.
Have I done something wrong with the "for" loop perhaps? I admit I find it hard to cope with a "for" without an explicit "next", though it is at least displaying each message (when I don't check avname,) so it appears to be incrementing the loop properly.

Sometimes I feel like I'll never get the hang of this scripting lark - my brain just doesn't seem to work the right way :(
psimagus Hax
Registered User
Join date: 3 Jul 2007
Posts: 73
05-27-2008 03:52
From: Kidd Krasner
So when you loop through the list in the state_entry handler of the editing state, you're going to loop through all of them before you ever get the first listen event. If you require either a response or a timeout before going on to the next, you need to just do the first one in the state_entry handler.


Ah, thanks - I think I understand that. So I need to put the name check and deletion query INSIDE the "for" loop, or it runs the whole loop before starting either?