Is there a way to remove an item from a list?
|
|
Jesse Barnett
500,000 scoville units
Join date: 21 May 2006
Posts: 4,160
|
09-21-2006 01:08
Actually two questions and I made the following script to illustrate them. Hope it works, I put the questions as comments in the script. //This list is permanent and I don't have ot worry about //loosing data with reset script list menu_test=[ "Brenda", "Rita", "Greta", "Carla", "Add", "Remove" ];
integer chan=9; integer chan2=0;
default { state_entry() { llListen(chan,"",NULL_KEY,""); llListen(chan2,"",NULL_KEY,""); } touch_start(integer total_number) { llDialog(llDetectedKey(0), "Who do you love?", menu_test, chan); } listen(integer channel, string name, key id, string msg) { if(llListFindList(menu_test,[msg]) != -1) { llSay(0,name + "loves" + msg + "."); } { if (msg == "Add") llOwnerSay("Who do you want to add"); state addname; } { if (msg == "Add") llOwnerSay("Who do you want to add"); state remname; } } timer() { llListenRemove( chan ); llListenRemove( chan2); llSetTimerEvent( 0 ); } } state addname // This part works partially correct. It will append the list // and a new menu button shows up. //I know a script can not write a notecard but is it possible //to edit itself and add new name in up top?? { state_entry() { llListen(0,"",NULL_KEY,""); } listen(integer channel, string name, key id, string newmsg) { menu_test = menu_test + [newmsg]; llOwnerSay ("I love " + newmsg); state default; } }
state remname //Is there anyway to subtract from a list???? //It will not compile with this added in { state_entry() { llListen(chan2,"",NULL_KEY,""); } listen(integer channel, string name, key id, string remmsg) { menu_test = menu_test - [remmsg]; llOwnerSay ("I don't love anymore " + remmsg); state default; } }
|
|
Jesse Barnett
500,000 scoville units
Join date: 21 May 2006
Posts: 4,160
|
09-21-2006 01:13
Oooops the "Add" should have need a "Remove".
|
|
Newgate Ludd
Out of Chesse Error
Join date: 8 Apr 2005
Posts: 2,103
|
09-21-2006 01:29
Not actually tried it, I usually add to the end of the list, but i think adding should be straight forward : Mylist = [ newname ] + MyList; Usual caveats about list sizes applies. Not sure if the memory saver trick would work in this instance : Mylist = [ newname ] + (MyList = []) + MyList; Would MyList already be truncated before it tried to Add? Anyone?As for removing try llListRemoveList
|
|
Kayla Stonecutter
Scripting Oncalupen
Join date: 9 Sep 2005
Posts: 224
|
09-21-2006 01:53
Actually thats for replacing one value with another. To remove you want llDeleteSubList(). Example(not compiled inworld): listfind = llListFindList(menu_test,[msg]); if(listfind != -1) { menu_test = llDeleteSubList(menu_test, listfind, listfind); } Note that llDeleteSubList() does not change the list itself but returns the new list, which you'll need to store back again, as shown. As for your question on adding to the list at the top of the script: Not permanetly as I think you mean. You can add to the list in memory as you are already doing, but not to the variable declaration at the top of the script.
|
|
Newgate Ludd
Out of Chesse Error
Join date: 8 Apr 2005
Posts: 2,103
|
09-21-2006 03:42
From: Kayla Stonecutter Actually thats for replacing one value with another. To remove you want llDeleteSubList(). Example(not compiled inworld): listfind = llListFindList(menu_test,[msg]); if(listfind != -1) { menu_test = llDeleteSubList(menu_test, listfind, listfind); } Note that llDeleteSubList() does not change the list itself but returns the new list, which you'll need to store back again, as shown. As for your question on adding to the list at the top of the script: Not permanetly as I think you mean. You can add to the list in memory as you are already doing, but not to the variable declaration at the top of the script. oops yep sorry, got my wires crossed again. 
|
|
Jesse Barnett
500,000 scoville units
Join date: 21 May 2006
Posts: 4,160
|
09-21-2006 08:41
Yeah I kind of figured there was no way for the script to rewrite itself and append the list but it was worth asking. Errrrrrrrr!!!! I've come so far but still have a little ways to go. The script in present form does work except for a cpl problems. When I push the "Options" button it brings up the "Options" menu but it also chats that I love "Options"!! When I push the "Back" button, the "Main" menu does not come up. The "Remove" part works fine UNLESS I chat a name that is not in list. Then the script will hang. I know I need to change it to an "if" and "else". But don't know how to do the "else" part. Any ideas? ///This list is permanent and I don't have to worry about loosing data with reset script list menu_name=["Brenda", "Rita", "Greta", "Carla", "Options"];
list menu_options=["List", "Add", "Remove", "Back"];
integer chan=9; integer chan2=0;
default { state_entry() { llListen(chan,"",NULL_KEY,""); llListen(chan2,"",NULL_KEY,""); } touch_start(integer total_number) { llDialog(llDetectedKey(0), "Who do you love?", menu_name, chan); } listen(integer channel, string name, key id, string msg) { if (llListFindList(menu_name + menu_options, [msg]) != -1) { if (msg == "Options") { llDialog(id, "Pick an option!", menu_options, chan);//HELP!!!Brings up options menu but also says I love options } if (msg == "Back")//HELP!!!! This doesn't return me to the main menu { llDialog(llDetectedKey(0), "Who do you love?", menu_name, chan); } else if (msg == "Add") { llOwnerSay("Who do you want to add"); state addname; } else if (msg == "Remove")//HELP!!!! I need an if and else here. If the name is not in list then the script hangs { llOwnerSay("Who do you want to remove"); state remname; } else if (msg == "List") { integer i; if(llGetListLength(menu_name) > 0) { for (i = 0; i < llGetListLength(menu_name); i+=1) { string names = llList2String(menu_name, i); llOwnerSay(names); } } else//I am going to change the "List" section. No need for the "else" part { llOwnerSay("You do not love anyone."); } } else if(llListFindList(menu_name,[msg]) != -1) { llSay(0,name + " loves " + msg + "."); } } } timer() { llListenRemove( chan ); llListenRemove( chan2); llSetTimerEvent( 0 ); } } state addname { state_entry() { llListen(0,"",NULL_KEY,""); } listen(integer chan2, string name, key id, string newmsg) { menu_name = menu_name + [newmsg];//Yes you can append to end of list llOwnerSay ("I love " + newmsg); state default; } }
state remname { state_entry() { llListen(0,"",NULL_KEY,""); } listen(integer chan2, string name, key id, string remmsg) { integer names = llListFindList(menu_name,[remmsg]); if(names != -1) { menu_name = llDeleteSubList(menu_name, names, names); llOwnerSay ("I don't love " + remmsg + " anymore"); state default; } } }
PS. Yes I know it is a corny demo script but it was fun and I can wrap my mind around it.
|
|
Newgate Ludd
Out of Chesse Error
Join date: 8 Apr 2005
Posts: 2,103
|
I Love Options
09-21-2006 09:08
Ok first error is that you should have used an else if not an if on the back option. You code was dropping through to the menu search and since options is in the menu .... The second problem is that you trying to use llDetectedKey inside a listen, it doesnt work. You should be using id if (msg == "Options") { llDialog(id, "Pick an option!", menu_options, chan);// HELP!!!Brings up options menu but also says I love options } else if (msg == "Back") // Was an If statement. { llDialog(id, "Who do you love?", menu_name, chan); }
The last problem is that you dont cater for the name not being on the list, you only ever return to the default state if the name is found. Move the state default outside of the test. state remname { state_entry() { llListen(0,"",NULL_KEY,""); } listen(integer chan2, string name, key id, string remmsg) { integer names = llListFindList(menu_name,[remmsg]); if(names != -1) { menu_name = llDeleteSubList(menu_name, names, names); llOwnerSay ("I don't love " + remmsg + " anymore"); } state default; } }
You could also tighten the code up somewhat, only set up listens for when you need them and only listen to the specific user not everyone. Also remove them when finished with or on a timer if the user doesn't do anything.
|
|
Jesse Barnett
500,000 scoville units
Join date: 21 May 2006
Posts: 4,160
|
09-21-2006 15:57
Yep I had my head up my butt when I called that llDetectedKey. I remembered to call off the timers but just plain forgot to set it. But speaking of timers. Which is better scripting practice to set the listens and a timer like I did in beginning. Then I listened again in the other two states, which kinda doesn't make sense.
Or would it be better to not specify the channel integers in the beginning. Instead just specify channels in the Listens and just set a timer event in the beginning and set it again at end of default for 0.
Or set the pertinent listen and timer events in each specific state.
errrr so many ways you could write this. Playing with this simple example I would rather learn to do it best way before going on to the next script. Plus once it is optimized I might comment it all over and offer it for examples. I didn't see any in Library that were easy to understand when combining a menu with lists. Might as well try to help someone else since people are helping me.
|
|
Newgate Ludd
Out of Chesse Error
Join date: 8 Apr 2005
Posts: 2,103
|
09-22-2006 01:35
Listens ARE state specific. If you set a listen in state default and then switch to another state it wont hear anything unless you also set up a listen. I'm still relatively new to LSL so I'm probably guilty of more than my fair of silly mistakes. If it was me then I'd write it like this, // This list is permanent and I don't have to worry about loosing data with reset script list menu_name=["Brenda", "Rita", "Greta", "Carla"]; list menu_options=["List", "Add", "Remove", "Back"];
integer Channel; integer Listening; key user;
// Functions UpdateListen(key id) { CancelListen(); Listening = llListen(Channel,"",id,""); llSetTimerEvent(30); }
CancelListen() { if(Listening > 0) llListenRemove(Listening); Listening = 0; llSetTimerEvent(0); }
ShowMainMenu(key id) { list Choices = menu_name + ["Options"]; llDialog(id, "Who do you love?", Choices, Channel); UpdateListen(id); }
ShowMenuRemove(key id) { llDialog(id, "Who don't you love?", menu_name, Channel); UpdateListen(id); }
ShowMenuOptions(key id) { llDialog(id, "Pick an option!", menu_options, Channel); UpdateListen(id); }
ShowAddMenu(key id) { string text = "Who do you want to add?\nType /"+(string)Channel+"Name to add i.e.\n /" + (string)Channel + "Newgate"; llDialog(id, text, [], Channel); UpdateListen(id); }
ListNames() { integer i; if(llGetListLength(menu_name) > 0) { for (i = 0; i < llGetListLength(menu_name); i+=1) { string names = llList2String(menu_name, i); llOwnerSay(names); } } else // I am going to change the "List" section. No need for the "else" part { llOwnerSay("You do not love anyone."); } }
RemoveName(string name) { integer names = llListFindList(menu_name,[name]); if(names != -1) { menu_name = llDeleteSubList(menu_name, names, names); llOwnerSay ("I don't love " + name + " anymore"); } }
AddName(string name) { integer names = llListFindList(menu_name,[name]); if(names == -1) { menu_name = menu_name + [name]; llOwnerSay ("I love " + name); } }
default { state_entry() { Channel = 9; } touch_start(integer total_number) { ShowMainMenu(llDetectedKey(0)); } listen(integer channel, string name, key id, string msg) { if (llListFindList(menu_name + menu_options, [msg]) != -1) { if (msg == "Options") { ShowMenuOptions(id); } else if (msg == "Back") { ShowMainMenu(id); } else if (msg == "Add") { user = id; state addname; } else if (msg == "Remove") { state remname; } else if (msg == "List") { ListNames(); } else if(llListFindList(menu_name,[msg]) != -1) { llSay(0,name + " loves " + msg + "."); } } } timer() { CancelListen(); } } state addname { state_entry() { ShowAddMenu(user); } listen(integer channel, string name, key id, string message) { user = NULL_KEY; CancelListen(); AddName(message); state default; } timer() { user = NULL_KEY; CancelListen(); state default; } // rather than reset the script and lose any data changes jsut call a fake timer on_rez(integer number) { llSetTimerEvent(0.5); } }
state remname { state_entry() { ShowMenuRemove(user); } listen(integer channel, string name, key id, string message) { user = NULL_KEY; CancelListen(); RemoveName(message); state default; } timer() { user = NULL_KEY; CancelListen(); state default; }
// rather than reset the script and lose any data changes jsut call a fake timer on_rez(integer number) { llSetTimerEvent(0.5); } }
Be aware of the 12 item limit in Dialogs though. llDialog will crash if there is more than 12 items in the list passed to it. if you dont aleready use them I suggest you get Notepad++ or Scite-Ez and LSLint, they make offline LSL editing so much easier.
|