Tattooshop Posted March 17, 2020 Share Posted March 17, 2020 (edited) Hello! I have a single dance machine animator script, but it works a little incorrectly. when I add the first animation it gives an error "llDialog: must supply a message" if I click it, when I add the second - menu shows only one animation. and so on, one animation is always missing. what's wrong with it? (sorry for the long script) integer i = 0; integer chat_channel() { return (integer)("0x" + llGetSubString(llMD5String((string) llGetOwner(), 1), 0, 6)) - 479; } integer total_dances = 0; integer dance_number = -1; integer page = 1; integer page_dances = 0; integer dance_starter = 0; list dances_list = []; list dance_buttons = []; string dances_text_list = ""; string exclude_first_page = ""; string exclude_last_page = ""; // Stop all dancing animations function, one by one stopAllDances() { i = 0; while (i < total_dances) { if (llList2String(dances_list, i) != "") { llStopAnimation(llList2String(dances_list, i)); } ++i; } } // Build dances list (text for dialog, buttons for options) for user depending on selected page and send it via dialog box // If the page is last or first use "---" instead of button with page number - detect this via counting overall dances list or check if the current dances list is < than 9 showMenu(key userTouched, integer page) { if (page > 1) { dance_starter = (page * 9) - 9; } else { dance_starter = 0; } page_dances = 0; dance_buttons = []; dances_text_list = ""; while (page_dances < 9) { if (llList2String(dances_list, dance_starter) != "") { dance_buttons = (dance_buttons = []) + dance_buttons + (string) dance_starter; dances_text_list = (dances_text_list = "") + dances_text_list + (string)(dance_starter) + ") " + llList2String(dances_list, dance_starter) + "\n"; } ++page_dances; ++dance_starter; } if (page == 1) { exclude_first_page = "---"; } else { exclude_first_page = "PAGE " + (string)(page - 1); } if (llGetListLength(dance_buttons) < 9 || (page * 9) >= total_dances) { exclude_last_page = "---"; } else { exclude_last_page = "PAGE " + (string)(page + 1); } dance_buttons = (dance_buttons = []) + "STOP DANCE" + exclude_first_page + exclude_last_page + dance_buttons; llDialog(userTouched, dances_text_list, dance_buttons, chat_channel()); } // String cutter function string stristr(string haystack, string needle, integer after_needle) { if (haystack) { //we have a haystack, it's not "" //Now find us a needle! integer pos = llSubStringIndex(haystack, needle); if (~pos) { //We have found a needle! if (after_needle) //return what comes after needle return llGetSubString(haystack, pos + llStringLength(needle), -1); return llDeleteSubString(haystack, pos, -1); } } return ""; } // Search for a word in string function integer like(string value, string mask) { integer tmpy = (llGetSubString(mask, 0, 0) == "%") | ((llGetSubString(mask, -1, -1) == "%") << 1); if (tmpy) mask = llDeleteSubString(mask, (tmpy / -2), -(tmpy == 2)); integer tmpx = llSubStringIndex(value, mask); if (~tmpx) { integer diff = llStringLength(value) - llStringLength(mask); return ((!tmpy && !diff) || ((tmpy == 1) && (tmpx == diff)) || ((tmpy == 2) && !tmpx) || (tmpy == 3)); } return FALSE; } // Execute script, main part default { // Reset script at object rezz on_rez(integer start_param) { llResetScript(); } // Crawl through dances and load them all to the list at script start / reset only to save region CPU power // Builded list will be later just called at touch/page reload, not rebuilded like in original work // Start listening to the unique channel for commands state_entry() { total_dances = llGetInventoryNumber(INVENTORY_ANIMATION); i = 0; while (i < total_dances) { dances_list = (dances_list = []) + dances_list + (string) llGetInventoryName(INVENTORY_ANIMATION, ++i); } llListen(chat_channel(), "", NULL_KEY, ""); } // Show menu at touch to the person who touched object, page 1 touch_start(integer total_number) { showMenu(llDetectedKey(0), 1); } // Automatiacally reset whole script if dance was added or removed from object's inventory // So you don't must to use "reset script" in your viewer, when you add something new changed(integer change) { if (change & CHANGED_INVENTORY) { llResetScript(); } } // Get dance from user interaction and start dance, stop dance or send next page listen(integer channel, string name, key id, string message) { if (message == "STOP DANCE") { dance_number = -1; llRequestPermissions(id, PERMISSION_TRIGGER_ANIMATION); } else if (like(message, "PAGE%")) { showMenu(id, (integer) stristr(message, "PAGE ", TRUE)); } else if (message == "---") { // Do nothing here } else { dance_number = (integer) message; llRequestPermissions(id, PERMISSION_TRIGGER_ANIMATION); } } // Ask for permissions and change dances // If dance number is under 0, then just stop dancing without calling any new animation run_time_permissions(integer perms) { if (perms & PERMISSION_TRIGGER_ANIMATION) { stopAllDances(); if (dance_number > -1) { llStartAnimation(llList2String(dances_list, dance_number)); } } } } Edited March 17, 2020 by Tattooshop Link to comment Share on other sites More sharing options...
Rolig Loon Posted March 17, 2020 Share Posted March 17, 2020 (edited) Your problem is right here i = 0; while (i < total_dances) { dances_list = (dances_list = []) + dances_list + (string) llGetInventoryName(INVENTORY_ANIMATION, ++i); } If you do it that way, you are always updating i before you need to. You'll never see llGetInventoryName(INVENTORY_ANIMATION, 0), and your script will try to load a non-existent final animation labeled llGetInventoryName(INVENTORY_ANIMATION, total_dances). Always watch your list indices. The best way to find error like this is to include a test statement that says llOwnerSay(llList2CSV(dances_list)); after you think you have loaded the list, just to see what's really in it. EDIT: BTW, you really don't need to do that business of dances_list = (dances_list = []) + dances_list +... Just write dances_list += [ llGetInventoryName(INVENTORY_ANIMATION, i)]; Edited March 17, 2020 by Rolig Loon You don;t need to typecast llGetInventoryName either. It's already a string 1 Link to comment Share on other sites More sharing options...
Tattooshop Posted March 17, 2020 Author Share Posted March 17, 2020 39 minutes ago, Rolig Loon said: Your problem is right here i = 0; while (i < total_dances) { dances_list = (dances_list = []) + dances_list + (string) llGetInventoryName(INVENTORY_ANIMATION, ++i); } Just write dances_list += [(string) llGetInventoryName(INVENTORY_ANIMATION, i)]; Thank you very much for your answer! So I simply replaced the line, but I did something wrong and it do not respond on click at all state_entry() { total_dances = llGetInventoryNumber(INVENTORY_ANIMATION); i = 0; while(i < total_dances) { dances_list += [(string) llGetInventoryName(INVENTORY_ANIMATION, i)]; } llListen(chat_channel(), "", NULL_KEY, ""); } Link to comment Share on other sites More sharing options...
Rolig Loon Posted March 17, 2020 Share Posted March 17, 2020 2 minutes ago, Tattooshop said: So I simply replaced the line, but I did something wrong and it do not respond on click at all Oh, well, you have the same problem elsewhere. Look at your touch_start event. It's calling showMenu(llDetectedKey(0), 1); but what you really want it to do is show you the first page of menu entries, which is page ZERO: showMenu(llDetectedKey(0),0); Lists start with index 0, and your showMenu routine is specifically looking for the first page with if (page > 1) { dance_starter = (page * 9) - 9; } else { dance_starter = 0; // <<< See? } 1 Link to comment Share on other sites More sharing options...
Tattooshop Posted March 17, 2020 Author Share Posted March 17, 2020 37 minutes ago, Rolig Loon said: Oh, well, you have the same problem elsewhere. Look at your touch_start event. It's calling showMenu(llDetectedKey(0), 1); but what you really want it to do is show you the first page of menu entries, which is page ZERO: showMenu(llDetectedKey(0),0); Lists start with index 0, and your showMenu routine is specifically looking for the first page with if (page > 1) { dance_starter = (page * 9) - 9; } else { dance_starter = 0; // <<< See? } I replaced everything that is possible, tried to change ones to zeros, but the script does not respond and after some time gives an error. what am i doing wrong? 🤔 I removed comments lines to make script look shorter integer i = 0; integer chat_channel() { return (integer)("0x" + llGetSubString(llMD5String((string) llGetOwner(), 1), 0, 6)) - 479; } integer total_dances = 0; integer dance_number = -1; integer page = 1; integer page_dances = 0; integer dance_starter = 0; list dances_list = []; list dance_buttons = []; string dances_text_list = ""; string exclude_first_page = ""; string exclude_last_page = ""; stopAllDances() { i = 0; while (i < total_dances) { if (llList2String(dances_list, i) != "") { llStopAnimation(llList2String(dances_list, i)); } ++i; } } showMenu(key userTouched, integer page) { if (page > 0) { dance_starter = (page * 9) - 9; } else { dance_starter = 0; } page_dances = 0; dance_buttons = []; dances_text_list = ""; while (page_dances < 9) { if (llList2String(dances_list, dance_starter) != "") { dance_buttons = (dance_buttons = []) + dance_buttons + (string) dance_starter; dances_text_list = (dances_text_list = "") + dances_text_list + (string)(dance_starter) + ") " + llList2String(dances_list, dance_starter) + "\n"; } ++page_dances; ++dance_starter; } if (page == 1) { exclude_first_page = "---"; } else { exclude_first_page = "PAGE " + (string)(page - 1); } if (llGetListLength(dance_buttons) < 9 || (page * 9) >= total_dances) { exclude_last_page = "---"; } else { exclude_last_page = "PAGE " + (string)(page + 1); } dance_buttons = (dance_buttons = []) + "STOP DANCE" + exclude_first_page + exclude_last_page + dance_buttons; llDialog(userTouched, dances_text_list, dance_buttons, chat_channel()); } string stristr(string haystack, string needle, integer after_needle) { if (haystack) { integer pos = llSubStringIndex(haystack, needle); if (~pos) { if (after_needle) return llGetSubString(haystack, pos + llStringLength(needle), -1); return llDeleteSubString(haystack, pos, -1); } } return ""; } integer like(string value, string mask) { integer tmpy = (llGetSubString(mask, 0, 0) == "%") | ((llGetSubString(mask, -1, -1) == "%") << 1); if (tmpy) mask = llDeleteSubString(mask, (tmpy / -2), -(tmpy == 2)); integer tmpx = llSubStringIndex(value, mask); if (~tmpx) { integer diff = llStringLength(value) - llStringLength(mask); return ((!tmpy && !diff) || ((tmpy == 1) && (tmpx == diff)) || ((tmpy == 2) && !tmpx) || (tmpy == 3)); } return FALSE; } default { on_rez(integer start_param) { llResetScript(); } state_entry() { total_dances = llGetInventoryNumber(INVENTORY_ANIMATION); i = 0; while (i < total_dances) { dances_list += [(string) llGetInventoryName(INVENTORY_ANIMATION, i)]; } llListen(chat_channel(), "", NULL_KEY, ""); } touch_start(integer total_number) { showMenu(llDetectedKey(0), 0); } changed(integer change) { if (change & CHANGED_INVENTORY) { llResetScript(); } } listen(integer channel, string name, key id, string message) { if (message == "STOP DANCE") { dance_number = -1; llRequestPermissions(id, PERMISSION_TRIGGER_ANIMATION); } else if (like(message, "PAGE%")) { showMenu(id, (integer) stristr(message, "PAGE ", TRUE)); } else if (message == "---") { // Do nothing here } else { dance_number = (integer) message; llRequestPermissions(id, PERMISSION_TRIGGER_ANIMATION); } } run_time_permissions(integer perms) { if (perms & PERMISSION_TRIGGER_ANIMATION) { stopAllDances(); if (dance_number > -1) { llStartAnimation(llList2String(dances_list, dance_number)); } } } } Link to comment Share on other sites More sharing options...
Rolig Loon Posted March 17, 2020 Share Posted March 17, 2020 5 minutes ago, Tattooshop said: I replaced everything that is possible, tried to change ones to zeros, but the script does not respond and after some time gives an error. what am i doing wrong? 🤔 At this point, it's hard to tell from a distance. You're working with a script that someone else wrote (and so am I), and I can't test the thing. But you can. I suggest two steps. First, clarify what that error message is telling you. That's at least a place to start. Second, start putting diagnostic llOwnerSay statements in key places to find out what the script is actually doing, as opposed to what you think it is doing. I have pointed out a couple of obvious things that needed attention, but only you can do the rest of the sleuthing from here on. (Parenthetically, this is one of the reasons why it's usually a good idea to write your own scripts instead of using someone else's. If you write a script, you know why you did each little thing, even if you did it wrong. You can usually follow your own logic better than some stranger's. Not only that, but you can't ever trust that the other scripter didn't make his own mistakes, which you have now inherited.) Of course, someone else with a fresh pair of eyes may wander in here and see something that I haven't ..... 😉 1 Link to comment Share on other sites More sharing options...
Nova Convair Posted March 17, 2020 Share Posted March 17, 2020 total_dances = llGetInventoryNumber(INVENTORY_ANIMATION); i = 0; while (i < total_dances) { dances_list += [(string) llGetInventoryName(INVENTORY_ANIMATION, i)]; } llListen(chat_channel(), "", NULL_KEY, ""); you don't increase i so the loop will run forever and the script will never process any events. your loop needs to go from 0 to total_dances-1 and requires an increment of i in each round. There are several possibilities to make a loop:http://wiki.secondlife.com/wiki/User:Kireji_Haiku/How_to_deal_with_lists_in_LSL 1 Link to comment Share on other sites More sharing options...
Rolig Loon Posted March 17, 2020 Share Posted March 17, 2020 7 minutes ago, Nova Convair said: you don't increase i so the loop will run forever and the script will never process any events. your loop needs to go from 0 to total_dances-1 and requires an increment of i in each round. Thank you, Nova. I didn't go back to check that he was still incrementing i. Nice catch, Link to comment Share on other sites More sharing options...
Tattooshop Posted March 17, 2020 Author Share Posted March 17, 2020 Is the problem so serious? I thought there maybe just need to change the one to zero ... unfortunately I am not that good at scripting yet. Link to comment Share on other sites More sharing options...
Rolig Loon Posted March 17, 2020 Share Posted March 17, 2020 2 minutes ago, Tattooshop said: Is the problem so serious? Serious? No, just an oversight. I should have spotted that you left that part out. Your original script incremented i by putting ++i inside the llGetScriptName function, so it was increasing the value before asking for the name of the animation. You still need to increment i, as Nova pointed out. You have to increment i after you get the current animation name, so the loop is ready to look for the next one. So: total_dances = llGetInventoryNumber(INVENTORY_ANIMATION); i = 0; while (i < total_dances) { dances_list += [(string) llGetInventoryName(INVENTORY_ANIMATION, i)]; ++i; //<< Increment HERE } llListen(chat_channel(), "", NULL_KEY, ""); 1 Link to comment Share on other sites More sharing options...
Tattooshop Posted March 18, 2020 Author Share Posted March 18, 2020 9 hours ago, Rolig Loon said: Serious? No, just an oversight. I should have spotted that you left that part out. Your original script incremented i by putting ++i inside the llGetScriptName function, so it was increasing the value before asking for the name of the animation. You still need to increment i, as Nova pointed out. You have to increment i after you get the current animation name, so the loop is ready to look for the next one. So: total_dances = llGetInventoryNumber(INVENTORY_ANIMATION); i = 0; while (i < total_dances) { dances_list += [(string) llGetInventoryName(INVENTORY_ANIMATION, i)]; ++i; //<< Increment HERE } llListen(chat_channel(), "", NULL_KEY, ""); 10 hours ago, Nova Convair said: total_dances = llGetInventoryNumber(INVENTORY_ANIMATION); i = 0; while (i < total_dances) { dances_list += [(string) llGetInventoryName(INVENTORY_ANIMATION, i)]; } llListen(chat_channel(), "", NULL_KEY, ""); you don't increase i so the loop will run forever and the script will never process any events. your loop needs to go from 0 to total_dances-1 and requires an increment of i in each round. There are several possibilities to make a loop:http://wiki.secondlife.com/wiki/User:Kireji_Haiku/How_to_deal_with_lists_in_LSL Thank you both very much! Now everything works as it should! integer i = 0; integer chat_channel() { return (integer)("0x" + llGetSubString(llMD5String((string) llGetOwner(), 1), 0, 6)) - 479; } integer total_dances = 0; integer dance_number = -1; integer page = 1; integer page_dances = 0; integer dance_starter = 0; list dances_list = []; list dance_buttons = []; string dances_text_list = ""; string exclude_first_page = ""; string exclude_last_page = ""; stopAllDances() { i = 0; while (i < total_dances) { if (llList2String(dances_list, i) != "") { llStopAnimation(llList2String(dances_list, i)); } ++i; } } showMenu(key userTouched, integer page) { if (page > 0) { dance_starter = (page * 9) - 9; } else { dance_starter = 0; } page_dances = 0; dance_buttons = []; dances_text_list = ""; while (page_dances < 9) { if (llList2String(dances_list, dance_starter) != "") { dance_buttons = (dance_buttons = []) + dance_buttons + (string) dance_starter; dances_text_list = (dances_text_list = "") + dances_text_list + (string)(dance_starter) + ") " + llList2String(dances_list, dance_starter) + "\n"; } ++page_dances; ++dance_starter; } if (page == 1) { exclude_first_page = "---"; } else { exclude_first_page = "PAGE " + (string)(page - 1); } if (llGetListLength(dance_buttons) < 9 || (page * 9) >= total_dances) { exclude_last_page = "---"; } else { exclude_last_page = "PAGE " + (string)(page + 1); } dance_buttons = (dance_buttons = []) + "STOP DANCE" + exclude_first_page + exclude_last_page + dance_buttons; llDialog(userTouched, dances_text_list, dance_buttons, chat_channel()); } string stristr(string haystack, string needle, integer after_needle) { if (haystack) { integer pos = llSubStringIndex(haystack, needle); if (~pos) { if (after_needle) return llGetSubString(haystack, pos + llStringLength(needle), -1); return llDeleteSubString(haystack, pos, -1); } } return ""; } integer like(string value, string mask) { integer tmpy = (llGetSubString(mask, 0, 0) == "%") | ((llGetSubString(mask, -1, -1) == "%") << 1); if (tmpy) mask = llDeleteSubString(mask, (tmpy / -2), -(tmpy == 2)); integer tmpx = llSubStringIndex(value, mask); if (~tmpx) { integer diff = llStringLength(value) - llStringLength(mask); return ((!tmpy && !diff) || ((tmpy == 1) && (tmpx == diff)) || ((tmpy == 2) && !tmpx) || (tmpy == 3)); } return FALSE; } default { on_rez(integer start_param) { llResetScript(); } state_entry() { total_dances = llGetInventoryNumber(INVENTORY_ANIMATION); i = 0; while (i < total_dances) { dances_list += [(string) llGetInventoryName(INVENTORY_ANIMATION, i)]; ++i; } llListen(chat_channel(), "", NULL_KEY, ""); } touch_start(integer total_number) { showMenu(llDetectedKey(0), 0); } changed(integer change) { if (change & CHANGED_INVENTORY) { llResetScript(); } } listen(integer channel, string name, key id, string message) { if (message == "STOP DANCE") { dance_number = -1; llRequestPermissions(id, PERMISSION_TRIGGER_ANIMATION); } else if (like(message, "PAGE%")) { showMenu(id, (integer) stristr(message, "PAGE ", TRUE)); } else if (message == "---") { } else { dance_number = (integer) message; llRequestPermissions(id, PERMISSION_TRIGGER_ANIMATION); } } run_time_permissions(integer perms) { if (perms & PERMISSION_TRIGGER_ANIMATION) { stopAllDances(); if (dance_number > -1) { llStartAnimation(llList2String(dances_list, dance_number)); } } } } 2 Link to comment Share on other sites More sharing options...
Rolig Loon Posted March 18, 2020 Share Posted March 18, 2020 4 hours ago, Tattooshop said: Thank you both very much! Now everything works as it should! YAY! Keep looking for challenging ways to build your skills. 1 1 Link to comment Share on other sites More sharing options...
Recommended Posts
Please take a moment to consider if this thread is worth bumping.
Please sign in to comment
You will be able to leave a comment after signing in
Sign In Now