Jump to content

LepreKhaun

Resident
  • Posts

    1,384
  • Joined

  • Last visited

Everything posted by LepreKhaun

  1. Dora Gustafson wrote: LepreKhaun wrote: Dora Gustafson wrote: I am talking about two ways to compute a suited communications channel number (1) 0x80000000 | (integer)("0x"+(string)toucherKey)(2) (integer)llFrand( 8388608.0 ) | 0x80000000 In the example at hand (1) expose a risk immensely reduced by (2) Try to figure out why :smileysurprised::smileyvery-happy: In (1) there is a hexadecimal number of length 8 being used. When one reduces a number pool by a factor of 32 (which is what you're doing here) the risk increases by a factor of 32, not the other way around. Wrong: (1) returns the same number for the same key and for all keys having 8 identical first digits in it The probability that the same toucher generates the same number in any number of tries is 1 (2) returns a random number each time it is called The probability that the same toucher generates the same number two times in a row is 1/8388608 :smileysurprised::smileyvery-happy: Unsure what your point is. It doesn't matter if the same number is used each time for the same avatar. If the listen handler is being closed properly each time it's used (which it is in the script I gave), chance of collision is 0 for that avatar. 1/8388608(Yours) > 1/268435458(Mine) > 0(Reality within the script)
  2. Dora Gustafson wrote: I am talking about two ways to compute a suited communications channel number (1) 0x80000000 | (integer)("0x"+(string)toucherKey)(2) (integer)llFrand( 8388608.0 ) | 0x80000000 In the example at hand (1) expose a risk immensely reduced by (2) Try to figure out why :smileysurprised::smileyvery-happy: In (1) there is a hexadecimal number of length 8 being used. When one reduces a number pool by a factor of 32 (which is what you're doing here) the risk increases by a factor of 32, not the other way around.
  3. JohnathanMacBride wrote: ... So to break it down link number 0 needs to affect 1 and 2 and link number 3 needs to affect 4 and 5 but 3 should not affect 1 and 2 and 0 should not affect 4 and 5. ... You first need to get a grasp on how link numbers work. Within an object composed of 2 or more prims, there is no link number 0. The Root Prim is 1 and then the numbers go up from there. The only time there is a link number 0 is in the case of a solo, unlinked prim. OK?
  4. 1. What you have to realize here is that LSL has two kinds of variables (lists or otherwise)- named and literal. A named variable takes the form of list myList;myList = ["1","2","3","4","5","6","7","8","9","10","11"]; This takes two distinctive parts- the declaration of the named variable in the first line and the assignment of that variable in the second (These can and often are combined into one statement.). The main point in seperating the two parts is that the second line assigns a literal (actually written out in the code) value to a named variable (which is a pointer to the value of that variable). When your code is compiled, having values written out in your code results in literal values held within your code body, resulting in increased script memory. Usage of a named variable in two or more places may result in a smaller size of your script memory but at the time-cost of having the VM reference the name to obtain the value. However, this is done so quickly that I seriously doubt one would ever notice any "lag" and the memory benefit will almost always win. Use the "Rule of 3" for this, if it appears 3 or more times within a script, a named variable is called for. And that goes double if the value is being obtained from an invariant function call (such as llGetOwner()). 2. Makes a difference in time performance, use else if to chain conditional test(s) unless you require something further down the chain to happen (rarely, if at all within LSL). 3. No difference. But note that (b == a) may sometimes be preferable to (a == b), just to catch the cases of when b is a constant but only to catch the (a = b) newbie error. 4. Any type casting, whether needed or not, will "slow" performance (LSL doesn't optimize away unneeded instances AFAIK), However, I doubt you'd ever notice the difference, I can't with 10,000 repetitions. 5. Unsure what you mean by "length of a timer".The timer is a event handler and will be triggered no more often than llSetTimer(1.0); has set the timer to fire (once every one second in this case). No events ever interrupt another; once an event has been triggered, the code within its event handler must finish executing completely before any further events (which a queued) can next be triggered. Performance may be hampered in any event handler that fails to execute and exit in a timely manner. Other events may be triggered while the timer is counting down in the meantime. 6. Phantom objects have no positive impact on physics computation. 7. Do not use llSetMemoryLimit(llGetUsedMemory()+0x1000);. You are essentially asking for 4K more than the "high tide" level at that point of your script. The script might well require more than that later. Either way, it will not make your script any more efficient timewise.
  5. Dora Gustafson wrote: You are partly right but It is not closed until the menu is actually used, so it is possible for one person to open more menus using the same channel at the same time In everyday use it probably is not a big problem :smileysurprised::smileyvery-happy: Incorrect. When listen handles are correctly opened only when needed and closed properly, any one script (as I solved it) can only be listening for no more than 20 seconds (which could even be shortened further!). Unless there is an active listen handler on a specific channel opened at any given moment, it doesn't matter what is being chatted on ANY channel by ANYONE. As I said in the beginning, "the listen event handler is being mishandled, common to many early scripts such as this one." The solution I gave is entirely correct, though other aspects of the script could be improved.
  6. Dora Gustafson wrote: When I come to think of it, a random channel would be better: dlgChannel = (integer)llFrand( 8388608.0 ) | 0x80000000; Because by the other approach the number is always the same for the same person clicking So if one person clicks more prims with the script you end up in the same situation as with a constant number :smileysurprised::smileyvery-happy: Ahhh, but the listen is opened and closed only as needed. The main problem with the original script was having the listen always open, never a good idea.
  7. Please link to scripts found elsewhere from now on. Your problem is that the listen event handler is being mishandled, common to many early scripts such as this one. Please study http://wiki.secondlife.com/wiki/Dialog_Menus to understand what a listen handler is and how to open and close them correctly. [Edited to remove unneeded key id references in script. Edited again to remove error introduced by the first edit.] // Original script by Viktoria Dovgal 8/4/2008// found at http://forums-archive.secondlife.com/54/8b/274487/1.html// Script modified by LepreKhaun 4/8/2014 to handle listen properly// Add this script into a prim with dances and touch the prim to start.//// You can put as many dances as will fit into memory. If you put in too many,// you will get a nice friendly stack/heap collision error. If that happens, take// out some dances and reset the script. Isn't that fun?list dances;list danceButtons;integer danceNumber;// Stuff for the menuinteger dlgSlots = 9; // available buttons in a multipage dialoginteger dlgMax = 12; // number of buttons in a plain old dialoginteger dlgLength; // size of the button listinteger dlgLastPage; // how many pages do we have?integer dlgChannel;// See http://wiki.secondlife.com/wiki/Dialog_Menusinteger listenHandle; // Required for correct listen operation!!!key toucherKey; // Keep track of who touched us// Stop dances and play the next, if any.PlayDance() { integer totalDances = llGetInventoryNumber(INVENTORY_ANIMATION); integer i = 0; while(i < totalDances) llStopAnimation(llGetInventoryName(INVENTORY_ANIMATION, i++)); if(danceNumber > -1) { llStartAnimation(llGetInventoryName(INVENTORY_ANIMATION, danceNumber)); }}// Hunt through inventory and load any animiations found.LoadDances() { integer totalDances = llGetInventoryNumber(INVENTORY_ANIMATION); dances = []; danceButtons = []; integer i = 0; while(i < totalDances){ dances = (dances = []) + dances + [(string)(++i) + " " + llGetInventoryName(INVENTORY_ANIMATION, i)]; danceButtons = (danceButtons = []) + danceButtons + (string)i; } dlgLength = llGetListLength(danceButtons); // Add a stop button if we won't need a paged menu. if (dlgLength > 0 && dlgLength < dlgMax) { danceButtons = (danceButtons = []) + "[sTOP]" + danceButtons; dlgLength++; } dlgLastPage = (dlgLength - 1) / dlgSlots;}Dialog(integer page) { if (danceButtons == []) { llInstantMessage(toucherKey, "No dances to play, feed me!"); return; } if (llList2String(danceButtons, 0) == "[sTOP]") { // plain old dialog llSetTimerEvent(20.0); listenHandle = llListen(dlgChannel, "", toucherKey, ""); llDialog(toucherKey, llDumpList2String(dances, "\n"), danceButtons, dlgChannel); } else { // paged dialog integer firstButton = page * dlgSlots; list allButtons = llList2List(danceButtons, firstButton, firstButton + dlgSlots - 1); // figure out what the next and previous page are. integer nextPage = page + 1; if (nextPage > dlgLastPage) nextPage = 0; integer prevPage = page - 1; if (prevPage < 0) prevPage = dlgLastPage; allButtons = (allButtons=[]) + ["<< " + (string) prevPage, "[sTOP]", ">> " + (string) nextPage] + allButtons; llSetTimerEvent(20.0); listenHandle = llListen(dlgChannel, "", toucherKey, ""); llDialog( toucherKey, llDumpList2String(llList2List(dances, firstButton, firstButton + dlgSlots - 1), "\n"), allButtons, dlgChannel ); }}default { state_entry() { LoadDances(); } changed (integer change) { if (change & CHANGED_INVENTORY) LoadDances(); } touch_start(integer total_number) { toucherKey = llDetectedKey(0); dlgChannel = 0x80000000 | (integer)("0x"+(string)toucherKey); Dialog(0); } listen(integer channel, string name, key toucherKey, string message) { llListenRemove(listenHandle); string pageCheck = llGetSubString(message, 0, 2); if (pageCheck == "<< " || pageCheck == ">> ") { if (message != pageCheck) // actually more than the arrow markers? Dialog((integer) llGetSubString(message, 3, -1)); return; // no need to mess with animations this time } else if (message == "[sTOP]") { danceNumber = -1; } else { danceNumber = (integer)message - 1; } // If we still hold animation permission for this avatar, we don't // need to ask again. if ((toucherKey == llGetPermissionsKey()) && (llGetPermissions() & PERMISSION_TRIGGER_ANIMATION)) PlayDance(); else llRequestPermissions(toucherKey, PERMISSION_TRIGGER_ANIMATION); } run_time_permissions(integer perms) { if(perms & PERMISSION_TRIGGER_ANIMATION) PlayDance(); } timer() { llSetTimerEvent(0.0); llListenRemove(listenHandle); llRegionSayTo(toucherKey, 0, "Sorry. You snooze; you lose."); } }
  8. Karlos Zero wrote: Well LepreKhaun, I think my statement is clear, as I mentioned above, this discussion and all code used is for educational purposes on my end. Yes, and I do hope you learned something.
  9. GavotteValentine wrote: I'm trying to create a water faucet so that it drips a group of X water particles each burst, pause for X seconds, then drip again. As far as I know it's not possible to do this with particle settings alone (_BURST_RATE and _BURST_PART_COUNT etc) because setting _BURST_PART_COUNT to say 20 will only cause all 20 particles to be stacked into 1 particle (no idea why it does this as it seems pointless to me) instead of a stream of 20 particles. So the only thing I can think of is to have _PART_COUNT set to 1 and _BURST_RATE set to 0, emit particles for say 2 seconds, then pause for 2 seconds, and loop it. The problem is how do I achieve this? I've tried llSensorRepeat and it doesn't work at all when inside an if statement. list MENU_CHOICES = ["HIDE","drip","stop"];//menu creator codelisten(integer channel, string name, key id, string choice) { if (choice == "HIDE") { //hide } else if (choice == "drip") { llSensorRepeat("", "", SCRIPTED, 0, 0, 2); } else if (choice == "stop") { //stop water drip } ... ... sensor(integer number_detected) { //particle script } Thanks. You're just using the wrong event handler is all. It's no_sensor not sensor when setting up a secondary timer. Everything else is just getting your particle emitter tuned. [ETA] Oh, and look for "RootBeerDrinking Lampshade" to make certain no_sensor gets triggered all the time! :smileyvery-happy: Hope that helps!
  10. Paraphrasing what Rolig said- "To make scripts, one must learn scripting". If you want someone to write out a solution for you, please ask in the Wanted or (if you have the Linden Bucks to invest in your dream) Inworld Employment forum. If you encounter a specific problem while writing a script (other than just being unable to write it to begin with :smileytongue:), this would be the correct forum to seek help.
  11. Adding to that thought (and, yes, a bit off-topic but specific to LSL scripts found elsewhere): In our everyday lives, we are faced with a number of ethical choices and the best course of action, always without exception, is to treat others with respect and dignity while showing love to one another. This is how we survive! When that fundamental principle is ignored, then we'll write our collective obituary- "We didn't respect one another". Respecting another script writer means following their wishes in the (re)publication of their intellectual property (otherwise known as "code" or "scripts").. They may have initially published their work into a specific venue to get ad revenue, make their blog more popular, enhance their posting ranking, educate the community while garnering a modicum of recognition, etc, etc. It doesn't matter, the original author never allows anyone to repost their intellectual efforts unless they've explicitly stated "Given into the Public Domain without restriction". But, even then, the ToS of this forum requires you to only post your own intellectual content (not once but at least half a dozen times). In other words, failing to respect the original author's intellectual property rights, as well as any addititional copyrights added in (re)publication, may result in suspension and possible termination of your SL account. And no one here would want to see that... ...Or, as I'm apt to say whenever nobody else speaks up first- Don't do it! [edited for correct emphasis]
  12. Karlos Zero wrote: Hi LepreKhaun, The script I have here will not be the final one to be used, it will only be a part of a larger one that has more than just a dialog box or a sensor. I am using this script for now to get my head around how it's done but my final script will be far from this. I have no intentions on using it "as is" this is only for my learning purposes. That's why I am asking for help with the things I can not figure with my limited knowledge resources. I actually post here as a last resourse after I can not figure how to get things done from the Wiki and online resources. I understand that beginners usually get started by modifying the scripts they find elsewhere and, for the most part, that is why they are there and why we have script repositories. At this point, you should at least be aware of the time and effort that goes into crafting a working script. Please respect the creators of this content and their efforts by linking to their work from now on. OK?
  13. Wandering Soulstar wrote: Jenny .. putting the sleep in both the changed and the state_entry events worked ... strange really but hey if it works :-) Not too strange when one understands what's happening. The sim server, which is running your script, doesn't directly keep your inventory but has to request it from the asset servers. Without the llSleep(), the local copy that your sim server requires isn't updated fast enough and by the time it does have that information, script execution has gotten past that point it was needed.
  14. There are other ways to communicate, but you need to study how chat works for this.
  15. Karlos Zero wrote: Hi, I am writing a script... No you're not. You're copy and pasting a script from a web archive. Please don't do that.
  16. Wandering Soulstar wrote: LepreKhaun, Thanks for the response, guess I was not clear enough. All the Keys are strings, this is cut from my code and I did not include all the declarations, but every key is a 'Constant' set to equal a unique string. So both SIZE & FACE are strings. Good point on just assigning the vector to SIZE without the sub parts, will have to check the rest of my code to see if there was a reason for that. And as to FACE 'complicating things' it would if a Prim only had one face, but this needs to be able to hold the specific values for an individual face, and ME can have multiple Faces. It does seem that my problem is elsewhere, as the key question I had you answered: 'Your third snippet would write the entire ME object, as you defined it in the other script, to the Value of the BASE_PRIM Key of TEXTURE_PARAMS' And that was what I was wondering, if it was going to be written there as a JSON that I could then query., Ahhhh, all that makes sense then. Yes, you're on the right track. However I could make a suggestion that will radically improve the performance: Get away from using JSON objects and just go with nested arrays. The reason I suggest this is that both memory and speed are adversely affected as the JSON text lengthens. The JSON manipulations begin to bog down very quickly and heap memory will grow rapidly in a short time. You can sprinkle a few llOwnerSay(llGetFreeMemory()); statements around to see exactly what I'm refering to. So, the idea is to keep your JSON text as short as possible, and the JSON array can't be beat. Just change your constant assignments from strings to integers that represent where in the array the Value is to be accessed. As in: // Use these to access the index of the required ValueSET_TYPE = 0;HORIZ_AXIS = 1;VERT_AXIS = 2;SET_TEXT = 3;SET_COLOUR = 4;SET_ROT = 5;SET_VERT = 6;SET_HORIZ = 7;BASE_PRIM = 8;TEXTURE_PARAMS = llList2Json(JSON_ARRAY,[ MATCH, X, Z, FALSE, FALSE, FALSE, FALSE, FALSE, ""]); And, BASE_PRIM would later become a nested array, along the same lines. Follow? This works because you are writing the JSON arrays and have complete control over what is going where. One only needs to use the JSON object (with its associated weight of the "Keys") when communicating with another program, which may order the elements differently.
  17. Wandering Soulstar wrote: Hi All, I am working on a new project, and am using JSON structures for the first time. One of my modules is having a problem and while I am in the process of debugging, on the train this morning a question came to mind, and since it will likely be hours until I am back home again and able to go in world to continue testing, I thought I'd check here if I am doing something basically wrong. Lets assume in script_main I define the following Global variable: TEXTURE_PARAMS = llList2Json(JSON_OBJECT,[ SET_TYPE, MATCH, HORIZ_AXIS, X, VERT_AXIS, Z, SET_TEXT, (string)FALSE, SET_COLOUR, (string)FALSE, SET_ROT, (string)FALSE, SET_VERT, (string)FALSE, SET_HORIZ, (string)FALSE, BASE_PRIM, EMPTY_STR]); Key to note, and where I am wondering if there is a problem is in the last node (BASE_PRIM) which is initialized to = "". In another script I execute the following: ME = llList2Json(JSON_OBJECT,[ SIZE, llList2Json(JSON_OBJECT, [ X, (string)size.x, Y, (string)size.y, Z, (string)size.z ]), FACE, llList2Json(JSON_OBJECT, [ NUMBER, (string)touchFace, TEXTURE, llList2String(attribs, 0), COLOUR, (string)llGetColor(touchFace), ROT, llList2String(attribs, 3), HORIZ, (string)texSize.x, VERT, (string)texSize.y ])]);llMessageLinked(LINK_THIS, CTRL_CHANNEL, llList2Json(JSON_OBJECT, [ACTION, ST_CLICK, PARAMETER, ME]), NULL_KEY); This message call is then picked up in script_main where after a few checks the following is executed: if (llJsonGetValue(TEXTURE_PARAMS, [bASE_PRIM]) == EMPTY_STR){ //Add the passed ME to the return structure for future Child calls TEXTURE_PARAMS = llJsonSetValue(TEXTURE_PARAMS, [bASE_PRIM], llJsonGetValue(message, [PARAMETER])); response = PARENT;} So, now to my question. Is the set statement valid? What I am trying to do is set the node BASE_PRIM to hold the JSON structure ME that was passed in the linked message call (also as part of a JSON). I am assuming this works but had a doubt as to what this actually looked like under the covers and perhaps was losing some sort of detail in the moving around. Thanks in advance! This is all a rough draft of an idea, merely psuedo-code that needs a lot more work before it will be remotely compilable. Keep in mind that a JSON object consists of "Key":Value pairs, where the "Key" must be a string. So: // Globally declared string TextureParams; // Assigned within an event handler TextureParams = llList2Json(JSON_OBJECT,[ "SetType", "match", "HorizAxis", x, "VertAxis", y, "SetText", FALSE, "SetColor", FALSE, "SetRot", FALSE, "SetVert", FALSE, "SetHoriz, FALSE, "BasePrim", ""]); Note: I've gotten away from the all caps and underscores, too easily to confuse that way of writing with the LSL constants. Also note that I'm not stringifying the LSL FALSE, no need of that. The variables x and y must need be declared as floats somewhere and assigned to. Your second snippet is even more confusing. Both SIZE and FACE must be strings. The Value of "Size" ought to simply be a vector. You're complicating things by having a deeper JSON object as a Value for "Face". You can do it, just keep in mind that you'll need to write: integer faceNumber = (integer)llJsonGetValue(ME, ["face", "number"]); Your llMessageLinked is, again, not forming a JSON object with strings as the "Keys". Your third snippet would write the entire ME object, as you defined it in the other script, to the Value of the BASE_PRIM Key of TEXTURE_PARAMS if, and only if, you changed everything throughout to where you were using strings for "Keys". Looking at your rough draft here, I get the impression you feel the Values all have to be strings. It's the other way around, all the "Keys" must be strings. OK? [ETA] When you're using llJsonSetValue, you do have to set the value you're supplying to string but with llList2Json you don't, just alternate the string "Keys" and their associated Values within the supplied list. Oh, and always remember, everything that comes out of a JSON text is always coming out as a string, regardless of what it was going in.
  18. I second using Audacity for sound editing. It's feature rich, powerful and flexible, with a user interface I wish Blender had. Plenty of tutorials on the web for using it and a wealth of plugins as well. And the cost is free! I've used it since 2004 for various tasks and have not considered any other program since. It does have a few format limitations but those shouldn't vex anyone other than professional broadcasters that are limited to proprietory formats.
  19. Correct, there are a number of possible solutions to this problem. And it should be pointed out that any recursive function can be made into a more elementary loop (as I showed earlier), any non-recursive function can be inlined and any inlined code can also be made into a function. Which is most appropriate in any given script should be determined by the programmer on a case by case basis.
  20. Back to the topic at hand: To find the total matches of an element in a list, it is sub-optimal to loop through all of the list indices. And it grows more sub-optimal as the size of the list increases, with the worse case being no occurances at all. Much better is to use an algorithm that will only loop as many times as the element occurs., where the worse case would be all the elements in the list matching. In the case of an integer within an ordered or sorted list, irihapeti has furnished an adequate a very good [Edited for correctness] solution. For the more general case of counting any variable within any list, there's mine. Use either as needed.
  21. irihapeti wrote: yes. my bad. 0 - -1 != 0 fixed. is a bit more efficient as well by the tools integer NumberOf(list lst, integer this){ integer i = llListFindList(lst, [this]); integer j = i; if (i >= 0) while(llList2Integer(lst, (++j)) == this); return j - i;} + am curious why you recommending a deletion search to novices given the amount of memory thrashing that LSL lists incur when copying. Can understand why to use a deletion search in a special case. Just not getting why that might be recommended in the general case of getting counts can see tho how it might seem more efficient in the case of unsorted. Altho probably have to do a whole bunch of tests on typical inputs for the particular app to make a determination as to its efficiency compared to a straightout counting algo. Given that they both O(n) linear search algos is good tho that you did provide a non-recursive alternative. Recursion can blow the stack if not careful and should probably only be recommended to novices for the special case I agree that any looping construct, elementary (for, while, do...while) or extended (recursive, dataserver, etc) , can "blow the stack if not careful". And though "the amount of memory thrashing that LSL lists incur when copying" sounds scary, you do realize that LSL is pass by value to any and all functions, yes? Which means every call to a Linden Library list manipulation function is resulting in a copy of the list being made. I reckon we'll just have to live with beating that poor memory to death if we're going to deal with lists. Hopefully the screams won't keep anyone awake at night. Anyway, I'm glad you worked out your attempt to count the occurances of an integer in an ordered list finally. Keep up the good work! [ETA: FYI- You've gotten your definitions backwards; any subset of a group is regarded as a "special case" of the entire grouping, which is called the "general case". So, an ordered list is a "special case" of lists in general, not the other way around. ]
  22. 1.) Set your mesh to phantom. It doesn't need to be anything else to show a texture. 2.) Scale your mesh to fit by making certain you are using only the interior faces of the prims. Use up to eight materials to make faces and UV map everything in Blender. Since these are interior surfaces, break your LoD's down accordingly (they won't be seen at a distance, in other words!).
  23. Of course, I do realize that recursion may be beyond the grasp of most novice programmers. Here's my solution (which works for the general case as well as the specifc case of an ordered list) done within a loop: integer numberTimesFound(list theList, list item){ integer place; integer count = 0; while (~(place = llListFindList(theList, item))) { theList = llDeleteSubList(theList, 0, place); ++count; } return count;}
  24. Yamil Dagger wrote: I have followed multiple examples to a T and have gotten not a single one to work correctly... I have been able to send data but the website and/or SQL database never recieves anything. I am guessing they are all old and nolonger working so I need an updated one. Anybody have one they KNOW works? The best that can be said here is what you're wanting to do is not trivial and there are no simple, on-size-fits-all solution available to any of us. If you're willing to pay someone that has mastered this aspect of programming (which entails much more than LSL) please use the Inworld Employment forum to seek them out.
×
×
  • Create New...