Tattooshop Posted February 24, 2020 Share Posted February 24, 2020 Hello! how to make this script work not from the prim numbers but from the names of the buttons in the hud? (it plays different animations) StopAnims() { llStopAnimation("anim1"); llStopAnimation("anim2"); llStopAnimation("anim3"); } default { state_entry() { llRequestPermissions(llGetOwner(), PERMISSION_TRIGGER_ANIMATION); } run_time_permissions(integer perm) { if (perm & PERMISSION_TRIGGER_ANIMATION) { StopAnims(); } } changed(integer change) { if (change & CHANGED_OWNER) { llResetScript(); } } touch_start(integer num) { integer button = llDetectedLinkNumber(0); { if (button == 5) { StopAnims(); llStartAnimation("anim1"); } if (button == 4) { StopAnims(); llStartAnimation("anim2"); } if (button == 3) { StopAnims(); llStartAnimation("anim3"); } if (button == 2) { StopAnims(); } } } } I tried this but it doesn’t work. string button1; string button2; string button3; string stop; StopAnims() { llStopAnimation("anim1"); llStopAnimation("anim2"); llStopAnimation("anim3"); } default { state_entry() { llRequestPermissions(llGetOwner(), PERMISSION_TRIGGER_ANIMATION); } run_time_permissions(integer perm) { if (perm & PERMISSION_TRIGGER_ANIMATION) { StopAnims(); } } changed(integer change) { if (change & CHANGED_OWNER) { llResetScript(); } } touch_start(integer num) { integer i = llGetNumberOfPrims(); for (; i >= 0; --i) { if (llGetLinkName(i) == button1) { StopAnims(); llStartAnimation("anim1"); } if (llGetLinkName(i) == button2) { StopAnims(); llStartAnimation("anim2"); } if (llGetLinkName(i) == button3) { StopAnims(); llStartAnimation("anim3"); } if (llGetLinkName(i) == stop) { StopAnims(); } } } } Link to comment Share on other sites More sharing options...
Rolig Loon Posted February 24, 2020 Share Posted February 24, 2020 Your solution would work if you had assigned values to the variables button1, button2, button3, and stop. As it is. the variables exist but their values are all " ". And, of course, you have to actually name the button prims with those values. 1 Link to comment Share on other sites More sharing options...
Tattooshop Posted February 24, 2020 Author Share Posted February 24, 2020 11 minutes ago, Rolig Loon said: Your solution would work if you had assigned values to the variables button1, button2, button3, and stop. As it is. the variables exist but their values are all " ". And, of course, you have to actually name the button prims with those values. Thank you! So i added integer button1 = 5; integer button2 = 4; integer button3 = 3; integer stop = 2; but it says Type mismatch error. Something I am doing wrong. But is it possible to do it without prim numbers at all? Link to comment Share on other sites More sharing options...
Tattooshop Posted February 24, 2020 Author Share Posted February 24, 2020 And yes buttons named button1, etc Link to comment Share on other sites More sharing options...
Rolig Loon Posted February 24, 2020 Share Posted February 24, 2020 2, 3, 4, and 5 are integers. Your prim's names are strings. If you really want to use numerals as the prim names, then assign their string values to the string variables button1, button2, button3, and stop. string button1 = "5"; string button2 = "4"; string button3 = "3"; string stop = "2"; 1 Link to comment Share on other sites More sharing options...
Fenix Eldritch Posted February 24, 2020 Share Posted February 24, 2020 At the top of your second script, you defined the string variables as button1, button2, etc. but those are just the names of the variables. You still need to give those variables a value. If the names of the child prims are "button1", "button2", etc, then you need to assign that to the string variables. For example: string button1 = "button1"; //the variable identified as button1 contains the value "buton1" 1 Link to comment Share on other sites More sharing options...
Rolig Loon Posted February 24, 2020 Share Posted February 24, 2020 3 minutes ago, Tattooshop said: And yes buttons named button1, etc Oh? In that case, string button1 = "button1"; string button2 = "button2"; string button3 = "button3"; string stop = "stop"; 1 Link to comment Share on other sites More sharing options...
Rolig Loon Posted February 24, 2020 Share Posted February 24, 2020 A variable is a container that holds a value. Distinguish between the two. In each case, your script has to ask, "What is the value that is currently in the container (the variable) named button1 ( or button2, button3, stop) ?" 1 1 Link to comment Share on other sites More sharing options...
Fenix Eldritch Posted February 24, 2020 Share Posted February 24, 2020 (edited) Even after you get your variables cleared up, there is still a lingering flaw in your second script that will cause undesirable behavior (as I understand it). In your touch_start event, you are going to loop over every prim in the hud's linkset. On each iteration of the loop, your script will perform a series of checks to see what the name of the current child pim is... and then stop all animations and start the one that corresponds to a given name. Do you see the problem here? You aren't checking what link number was clicked. Your loop is going to inspect EVERY prim in the linkset, so all of those IF tests will eventually pass. Even the "stop" one. Depending on the order of your links, one of those bits of code is always going to be the last one executed, no matter what. Edited February 24, 2020 by Fenix Eldritch 1 Link to comment Share on other sites More sharing options...
Tattooshop Posted February 24, 2020 Author Share Posted February 24, 2020 (edited) 8 minutes ago, Fenix Eldritch said: Even after you get your variables cleared up, there is still a lingering flaw in your second script that will cause undesirable behavior (as I understand it). In your touch_start event, you are going to loop over every prim in the hud's linkset. On each iteration of the loop, your script will perform a series of checks to see what the name of the current child pim is... and then stop all animations and start the one that corresponds to a given name. Do you see the problem here? You aren't checking what link number was clicked. Your loop is going to inspect EVERY prim in the linkset, so all of those IF tests will eventually pass. Even the "stop" one. Depending on the order of your links, one of those bits of code is always going to be the last one executed, no matter what. Yes, I just wanted to write about it. avatar reacts strangely to button presses. I added llSay(0, "Touched1") for the test and this is what comes out when any button is pressed [07:18] Object: Touched1 [07:18] Object: Touched2 [07:18] Object: Touched3 string button1 = "button1"; string button2 = "button2"; string button3 = "button3"; string stop = "stop"; StopAnims() { llStopAnimation("anim1"); llStopAnimation("anim2"); llStopAnimation("anim3"); } default { state_entry() { llRequestPermissions(llGetOwner(), PERMISSION_TRIGGER_ANIMATION); } run_time_permissions(integer perm) { if (perm & PERMISSION_TRIGGER_ANIMATION) { StopAnims(); } } changed(integer change) { if (change & CHANGED_OWNER) { llResetScript(); } } touch_start(integer num) { integer i = llGetNumberOfPrims(); for (; i >= 0; --i) { if (llGetLinkName(i) == button1) { StopAnims(); llStartAnimation("anim1"); llSay(0, "Touched1"); } if (llGetLinkName(i) == button2) { StopAnims(); llStartAnimation("anim2"); llSay(0, "Touched2"); } if (llGetLinkName(i) == button3) { StopAnims(); llStartAnimation("anim3"); llSay(0, "Touched3"); } if (llGetLinkName(i) == stop) { StopAnims(); } } } } Edited February 24, 2020 by Tattooshop Link to comment Share on other sites More sharing options...
Tattooshop Posted February 24, 2020 Author Share Posted February 24, 2020 I took this example from here http://wiki.secondlife.com/wiki/LlGetLinkName and don’t quite understand what this line does for (; i >= 0; --i) and what to do next... Link to comment Share on other sites More sharing options...
Tattooshop Posted February 24, 2020 Author Share Posted February 24, 2020 18 minutes ago, Fenix Eldritch said: You aren't checking what link number was clicked. And how to check it? Link to comment Share on other sites More sharing options...
Fenix Eldritch Posted February 24, 2020 Share Posted February 24, 2020 (edited) That is a for loop. It is a method of making a block of code repeat itself, to iterate over a range of values. As I mentioned above, your code as written in the second script is going to blindly loop with no regard to what button was actually clicked. It's inspecting every prim in the linkset and doing those IF tests on each prim. Which means it's going to do everything instead of just acting on a specific button's code. I suggest you revisit your first script, as it is a simple matter to convert it to use link names instead of pure link numbers. You would essentially follow the exact same logic. No need for a loop. In the touch_start event, change the button variable to a string instead of an integer. This will be the variable to contain the name of whatever child prim was clicked and then we will do the same IF checks, without a loop, and updated to work with your specified names. You would use a combination of llGetLinkName and feed it the return value of llDetectedLinkNumber(0). This essentially is saying "get the name of the link that was just clicked". This would be the template: string button = llGetLinkName(llDetectedLinkNumber(0)); if (button == "button1") { //do stuff for button1 } Edited February 24, 2020 by Fenix Eldritch typos 1 1 Link to comment Share on other sites More sharing options...
Rolig Loon Posted February 24, 2020 Share Posted February 24, 2020 I don't want to beat a dead horse, but to be sure that I have been clear ...... Think of your computer's physical innards as a warehouse full of empty shelves. Your script's job is to put labeled boxes (variables) on those shelves, put specific items (values) in the boxes, and then manipulate those values (move them around from box to box, compare them to each other or to things outside the warehouse ...). At the top of your script, you are creating the boxes and telling the computer what type of things you will be putting in them: string button1; // a box labeled button1 will contain items of type string. Then you will put something in each of the boxes: button1 = "button1"; // The box labeled button1 now has the string "button1" in it. (You can combine those first two steps as string button1 = "button1"; ) And then your script will later ask "Does the physical thing that I have just touched have a name (a value) that is the same as the value that I put into the box labeled button1?" if ( llGetLinkName( llDetectedLinkNumber(0) ) == button1) { // do something } 1 1 Link to comment Share on other sites More sharing options...
Tattooshop Posted February 24, 2020 Author Share Posted February 24, 2020 26 minutes ago, Fenix Eldritch said: In the touch_start event, change the button variable to a string instead of an integer. This will be the variable to contain the name of whatever child prim was clicked and then we will do the same IF checks, without a loop, and updated to work with your specified names. You would use a combination of llGetLinkName and feed it the return value of llDetectedLinkNumber(0). This essentially is saying "get the name of the link that was just clicked". This would be the template: string button = llGetLinkName(llDetectedLinkNumber(0)); if (button == "button1") { //do stuff for button1 } 26 minutes ago, Rolig Loon said: (You can combine those first two steps as string button1 = "button1"; ) And then your script will later ask "Does the physical thing that I have just touched have a name (a value) that is the same as the value that I put into the box labeled button1?" if ( llGetLinkName( llDetectedLinkNumber(0) ) == button1) { // do something } Thank you both a lot! I now have two wonderful working script versions! ❤️ StopAnims() { llStopAnimation("anim1"); llStopAnimation("anim2"); llStopAnimation("anim3"); } default { state_entry() { llRequestPermissions(llGetOwner(), PERMISSION_TRIGGER_ANIMATION); } run_time_permissions(integer perm) { if (perm & PERMISSION_TRIGGER_ANIMATION) { StopAnims(); } } changed(integer change) { if (change & CHANGED_OWNER) { llResetScript(); } } touch_start(integer num) { string button = llGetLinkName(llDetectedLinkNumber(0)); { if (button == "button1") { StopAnims(); llStartAnimation("anim1"); } if (button == "button2") { StopAnims(); llStartAnimation("anim2"); } if (button == "button3") { StopAnims(); llStartAnimation("anim3"); } if (button == "stop") { StopAnims(); } } } } string button1 = "button1"; string button2 = "button2"; string button3 = "button3"; string stop = "stop"; StopAnims() { // list of your animations: llStopAnimation("anim1"); llStopAnimation("anim2"); llStopAnimation("anim3"); } default { state_entry() { llRequestPermissions(llGetOwner(), PERMISSION_TRIGGER_ANIMATION); } run_time_permissions(integer perm) { if (perm & PERMISSION_TRIGGER_ANIMATION) { StopAnims(); } } changed(integer change) { if (change & CHANGED_OWNER) { llResetScript(); } } touch_start(integer num) { { if (llGetLinkName(llDetectedLinkNumber(0)) == button1) { StopAnims(); llStartAnimation("anim1"); } if (llGetLinkName(llDetectedLinkNumber(0)) == button2) { StopAnims(); llStartAnimation("anim2"); } if (llGetLinkName(llDetectedLinkNumber(0)) == button3) { StopAnims(); llStartAnimation("anim3"); } if (llGetLinkName(llDetectedLinkNumber(0)) == stop) { StopAnims(); } } } } Link to comment Share on other sites More sharing options...
Rolig Loon Posted February 24, 2020 Share Posted February 24, 2020 As a further refinement, consider creating two global lists: list lButtonNames = ["button1", "button2", "button3", "stop"]; list lAnims = ["anim1", "anim2", "anim3"]; and then rewriting the touch_start event as touch_start(integer num) { integer idx = llListFindList( lButtonNames, [ llGetLinkName( llDetectedLinkNumber(0) ) ]); if ( ~idx ) // that is, "if idx is a non-negative integer ..." { StopAnims(); // Stop anims regardless of which valid button you clicked if (idx < 3 ) // that is, "if idx is 0, 1, or 2 ..." { llStartAnimation( llList2String( lAnims, idx ) ); } } } That's quite a bit more compact, so it saves having to write and execute all of those separate if tests. Aside from making your script more elegant -- always a plus -- the real benefit is that it helps you focus on the logic of what you are trying to accomplish. After all, scripting is above all else an exercise in logic. Writing the touch_start event in terms of list management helps you see that this is basically an exercise in identifying whether you have touched a button that has one of a small number of predetermined names. If the button name matches one of the names in your lButtonNames list, then you not only know that it was a valid touch but you also know exactly which anim to start from lAnims, because idx refers to the same index in both lists. 1 1 Link to comment Share on other sites More sharing options...
Tattooshop Posted February 26, 2020 Author Share Posted February 26, 2020 list lButtonNames = ["button1", "button2", "button3", "stop"]; list lAnims = ["anim1", "anim2", "anim3"]; StopAnims() { // list of your animations: llStopAnimation("anim1"); llStopAnimation("anim2"); llStopAnimation("anim3"); } default { state_entry() { llRequestPermissions(llGetOwner(), PERMISSION_TRIGGER_ANIMATION); } run_time_permissions(integer perm) { if (perm & PERMISSION_TRIGGER_ANIMATION) { StopAnims(); } } changed(integer change) { if (change & CHANGED_OWNER) { llResetScript(); } } touch_start(integer num) { integer idx = llListFindList(lButtonNames, [llGetLinkName(llDetectedLinkNumber(0))]); if (~idx) // that is, "if idx is a non-negative integer ..." { StopAnims(); // Stop anims regardless of which valid button you clicked if (idx < 3) // that is, "if idx is 0, 1, or 2 ..." { llStartAnimation(llList2String(lAnims, idx)); } } } } 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