Jump to content

Sylvia Wasp

Resident
  • Content Count

    227
  • Joined

  • Last visited

Everything posted by Sylvia Wasp

  1. Cool. I wish there were another way around the 16 avatar limit than getting a list of every avatar in a sim though which may be very long and unwieldy for my purposes, but it’s something I’ll have to try. The original idea was for a HUD that would be used in a busy store or a dance floor situation. Basically scanning the avatars around you, that you can see. Collecting the whole sim means collecting avatars in other contexts doing other things that the user can neither see nor in many cases is even aware of, which may be confusing for them besides being a possible invasion of privacy. Only collecting 16 avatars seems far too few and trying to collect the whole sim seems like overkill. 30 or so would be perfect, but if those are the only choices then I will have to pick one or the other. Perhaps I can collect the whole sim, then sort by distance and mask out those avatars clearly out of range of the present location/context of the user. It will be interesting to try. I might also try the numbered buttons thing after all as it (foolishly) didn’t occur to to me that there would be a text based ‘key’ to the numbered buttons as you describe above. My frustration with numbered buttons was more because blank numbered buttons don’t convey anything to the user, as in my example of a piece of furniture that just presents the user with buttons labelled 1-12 for poses. Thanks again for all the help. Sylvia
  2. Very interesting. A part of the reason I hate code is that I find it difficult to get that clear conception in my head. When I'm painting a picture, or making something out of prims, or using a design/paint program I *begin* with a definite, clear, "vision" if you will of exactly what it looks like when it's finished then I just keep working until the reality matches the vision. With code on the other hand I usually feel like I'm crawling across a bumpy floor in complete darkness looking for "stuff" and only about half-way through (if I'm lucky) do I get a clear vision of what it is I should be doing or working towards. In any case, due to the help that I've received here, I've managed to correct all the stupid errors (I think) and had a long talk with Grandmother about what it is I'm doing. She said ... that what I want in the end is avatar keys, and what I want for the dialogue box is avatar names and I want them associated together. So what I really want is a database. The closest thing to a database in SL is the strided list, so I spent a day reading up on strided lists and re-wrote the thing from that perspective and with (most) stupid errors removed. It's not that different but at least it finally works OK and could be said to be "finished" in terms of my original question at the top of the thread. It scans the area for avatars, produces a nice button list of their names, and clicking on a button gives you their name and their key so you can "do stuff" with it. There are some things I'd like to make it work better though. 1) I had no idea that sensor was limited to 16 avatars! Is there any way around that at all? 2) It sometimes errors out saying that I have a button with more than 24 characters (when obviously I don't). So far this has only happened in a Linden Hub where the crowd is mostly griefers, racists, paedophiles, & Trump supporters, so I'm thinking it's either LAG or shenanigans of some kind. 2b) if it's LAG, is there any way to assure that bits of the script don't execute in the wrong order or that every part of it waits properly before continuing in a high lag environment? 2c) if it's shenanigans, that suggests that a player can "do something" to their display name to screw up my code. Is that really possible? Edit: Just realised that the avatar_list = ["SCAN"]; at the beginning of the sensor is probably unnecessary or should be blank. // ====== Sylvia's Avatar Detect v2 ====== integer cmdChannel; integer gMenuPos; integer gListen; float sensor_range = 96.0; list detected_list; list avatar_list; integer Key2Chan(key ID) { return 0x80000000 | (integer)("0x"+(string)ID); } multipage_dialogue() { integer lastPage; list buttons; integer listLength = llGetListLength(avatar_list); if(gMenuPos >= 9) { buttons += " <----"; if((listLength - gMenuPos) > 11) { buttons += " ---->"; } else { lastPage = TRUE; } } else if (listLength > gMenuPos+9) { if((listLength - gMenuPos) > 11) { buttons += " ---->"; } else { lastPage = TRUE; } } else { lastPage = TRUE; } if (listLength > 0) { integer b_count; integer num_of_buttons = llGetListLength(buttons); for(b_count = gMenuPos + num_of_buttons + lastPage - 1 ; (num_of_buttons < 12) && (b_count < listLength); ++b_count) { buttons = buttons + [llList2String(avatar_list,b_count)]; num_of_buttons = llGetListLength(buttons); } } gListen = llListen(cmdChannel,"","",""); llSetTimerEvent(10.0); llDialog(llGetOwner()," \n",buttons,cmdChannel); } default { state_entry() { cmdChannel = Key2Chan(llGetOwner()); llListen(cmdChannel, "", llGetOwner(), ""); } touch_start(integer total_number) { avatar_list = ["SCAN"]; multipage_dialogue(); llListenRemove(gListen); gMenuPos = 0; } sensor( integer number_detected ) { avatar_list = ["SCAN"]; detected_list = []; integer i; for( i = 0; i < number_detected; i++ ){ if( llDetectedKey( i ) != llGetOwner() ){ string detected_name = llGetSubString(llGetDisplayName(llDetectedKey( i )), 0, 11); key detected_key = llDetectedKey( i); detected_list += detected_name; detected_list += detected_key; } } avatar_list = llList2ListStrided(detected_list, 0, -1, 2); multipage_dialogue(); } listen( integer channel, string name, key id, string message ) { llListenRemove(gListen); llSetTimerEvent(0.0); if( message == "SCAN" ){ llOwnerSay( "scanning for avatars within 96m ..." ); llSensor("", NULL_KEY, AGENT, sensor_range, PI); } else if (~llSubStringIndex(message,"---->")) { gMenuPos += 10; multipage_dialogue(); } else if (~llSubStringIndex(message,"<----")) { gMenuPos -= 10; multipage_dialogue (); } else { llOwnerSay(message); llOwnerSay((string) llList2String(detected_list, (llListFindList(detected_list,[message]) + 1))); multipage_dialogue (); } } timer() { llSetTimerEvent(0.0); llListenRemove(gListen); } }
  3. Thanks for chiming in Rolig, I realise that these questions must be both a bit on the easy/boring side, as well as one's you've been asked many times before. In my searching for answers I found evidence of you helping out in the past on scripts very similar to mine (several times!). I realised my mistake about calling llDialog instead of the multipage routine right after I posted last time, so that's fixed already. The reason I am using llDIalog on the first touch, and then the multi-page routine later, is that I think what I want to do works best as a Menu/subMenu combination. The first menu (llDialog) presents the user with an announcement of what's going to happen and presents the "SCAN" button ... then the results of the scan are (necessarily) dropped into the multipage menu system, which handles the data. I'm not sure if it's correct, but that was the logic behind the choice. The trouble is that these two calls to Dialogue boxes are now fighting with each other. I press the "SCAN" button on the first dialogue box and it sometimes replaces with a blank box with an "OK" button for a moment, before then being replaced by the multipage dialogue box with the correct data. Because the whole scanning and invoking of the multipage dialogue box takes a while, I made it work by putting in the llSLeep command, but then what is displayed is the last (old) data from the previous scan (in multipage format), before a moment later being replaced by the new, correct, scan data. Either one creates a horrible user interaction and llSleep is definitely a kludge I don't want to use anyway. Sadly, I've also lost confidence that I even have the right approach for the task at hand. I realised that I probably need the avatars keys to do anything worthwhile with the named buttons at the end and I don't think you can find an avatars key with just the first 12 characters of their display names. I can collect the keys instead, but then I need a whole other routine (in the listen?) to parse that data into display names before dumping them in the dialogue? Or I need to collect two lists in the sensor (keys and names) and then associate them in a data structure with strided lists or something? Ack! The whole thing is a mess really, lol. the relevant code section: touch_start(integer total_number) { llDialog(llDetectedKey(0),"\n~Press SCAN for a list of avatars~\n", ["SCAN"],cmdChannel); llListenRemove(gListen); gMenuPos = 0; } sensor( integer number_detected ) { avatar_list = ["SCAN"]; integer i; for( i = 0; i < number_detected; i++ ){ if( llDetectedKey( i ) != llGetOwner() ){ string detected_name = llGetDisplayName(llDetectedKey( i )); avatar_list += llGetSubString(detected_name, 0, 11); } } llSleep(2.0); multipage_dialogue(); }
  4. Okay, so ... here is the code where I combined the multi-page button dialogue into what I already had as well as taking KT's simplification notes into account. I renamed a lot of stuff and formatted it so it's clearer because I'm a super visual person (thus why I suck at code), and I simply can't even read it unless I do that. It (sorta) works? Obviously there is a problem with the touch_start event in that I'm calling my original dialogue box and then calling the multi-page dialogue box function right after. If I comment out one or the other then it doesn't work at all, but the way it is currently, if I'm quick with hitting the SCAN button, then eventually it works fine and I get a multi-page dialogue with the correct forward and backward arrows and all the names of the avatars correctly formatted etc. So I'm 90% of the way there? I mean it's working ... but with problems, lol. I'm thinking that what I want is a first page menu where I invoke the scan and then the multipage dialogue thingie is a *sub menu of that? But I'm not sure how to do that either, lol. Anyway, here is what I have now for anyone still interested and thanks for all the help so far: Sylvia // Sylvia's avatar scan code (combined) // integer cmdChannel; integer gMenuPos; integer gListen; float sensor_range = 96.0; list avatar_list; integer Key2Chan(key ID) { return 0x80000000 | (integer)("0x"+(string)ID); } dialogue_box() { integer lastPage; list buttons; integer listLength = llGetListLength(avatar_list); if(gMenuPos >= 9) { buttons += " <----"; if((listLength - gMenuPos) > 11) { buttons += " ---->"; } else { lastPage = TRUE; } } else if (listLength > gMenuPos+9) { if((listLength - gMenuPos) > 11) { buttons += " ---->"; } else { lastPage = TRUE; } } else { lastPage = TRUE; } if (listLength > 0) { integer b_count; integer num_of_buttons = llGetListLength(buttons); for(b_count = gMenuPos + num_of_buttons + lastPage - 1 ; (num_of_buttons < 12) && (b_count < listLength); ++b_count) { buttons = buttons + [llList2String(avatar_list,b_count)]; num_of_buttons = llGetListLength(buttons); } } gListen = llListen(cmdChannel,"","",""); llSetTimerEvent(10.0); llDialog(llGetOwner()," \n",buttons,cmdChannel); } default { state_entry() { cmdChannel = Key2Chan(llGetOwner()); llListen(cmdChannel, "", llGetOwner(), ""); } touch_start(integer total_number) { llDialog(llDetectedKey(0),"\n~AVATAR LIST~\n", ["SCAN"],cmdChannel); llListenRemove(gListen); gMenuPos = 0; dialogue_box(); } sensor( integer number_detected ) { avatar_list = ["SCAN"]; integer i; for( i = 0; i < number_detected; i++ ){ if( llDetectedKey( i ) != llGetOwner() ){ string detected_name = llGetDisplayName(llDetectedKey( i )); avatar_list += llGetSubString(detected_name, 0, 11); } } llDialog(llGetOwner(), "\n avatars found ...", avatar_list, cmdChannel); } listen( integer channel, string name, key id, string message ) { llListenRemove(gListen); llSetTimerEvent(0.0); if( message == "SCAN" ){ llOwnerSay( "scanning for avatars within 96m ..." ); llSensor("", NULL_KEY, AGENT, sensor_range, PI); } else if (~llSubStringIndex(message,"---->")) { gMenuPos += 10; dialogue_box(); } else if (~llSubStringIndex(message,"<----")) { gMenuPos -= 10; dialogue_box (); } else { llOwnerSay(message); } } timer() { llSetTimerEvent(0.0); llListenRemove(gListen); } }
  5. thanks KT, all great suggestions I feel like a dummy for not seeing that easier list reset. So obvious once you see it, lol. I base most of my decisions on finding some example elsewhere, so lots of times it works, but is inappropriate to the setting or overly complicated. Sylvia
  6. Well, I would also like it to be as efficient and "clean" as possible, but yes it's most important that it fit the situation it was made for. OK, so if anyone's still interested, here is a "version 2" of the thing. - I've successfully dumped the list to "llDialog". - I've changed the sensor to read Display Names instead of the actual avatar names (no one seems to use those anymore) and truncated them at twelve characters. - I've made the sensor scan reset the list each time so it doesn't just get bigger and bigger with each scan, (which allowed me to remove the "reset" button). - I've simplified the nomenclature a bit and chopped out as much unnecessary stuff as possible. - I've added a bit to the end of the listen which would serve as an "action" for the avatar name buttons (currently it just says the name). I haven't dealt with the 12 button limit yet, because my intention is to (later on) dump the avatar_list to a multi-page dialog that expands to fit however long the list gets. I'm still working on understanding that part. I also need to add the "SCAN" button to the llDialog that lists the avatars names for better UI flow. What I don't understand is why I can't blend the "list" part with the "scan" part. Every time I put the llDialog command after the scan, (within the same else-if as the scan), it reads as either empty or as just the first name in the list. I seem to be forced to scan and list separately. Other than that, and the fact that I'm still not checking for the button limit (and the fact that I'm probably not dealing with the listen handle as I should), it seems to work. // Sylvia's avatar scan code (take 2) integer cmdChannel; list avatar_list; float sensor_range = 96.0; integer Key2Chan(key ID) { return 0x80000000 | (integer)("0x"+(string)ID); } default { state_entry() { cmdChannel = Key2Chan(llGetOwner()); llListen(cmdChannel, "", llGetOwner(), ""); } touch_start(integer total_number) { llDialog(llDetectedKey(0),"\n~AVATAR LIST~\n", ["SCAN","list"],cmdChannel); } sensor( integer number_detected ) { avatar_list = llDeleteSubList(avatar_list, 0, llGetListLength(avatar_list)); integer i; for( i = 0; i < number_detected; i++ ){ if( llDetectedKey( i ) != llGetOwner() ){ string detected_name = llGetDisplayName(llDetectedKey( i )); avatar_list += llGetSubString(detected_name, 0, 11); } } } listen( integer channel, string name, key id, string message ) { if( id != llGetOwner() ){ return; } else if( message == "SCAN" ){ llOwnerSay( "scanning for avatars within 96m ..." ); llSensor("", NULL_KEY, AGENT, sensor_range, PI); // why can't I put "llDialog" here? } else if( message == "list" ){ llDialog(llGetOwner(), "\n avatars found ...", avatar_list, cmdChannel); } else { llOwnerSay(message); } } }
  7. Thanks Rolig, It will take me a while to ingest this stuff of course but the multi-page dialogue code will be especially useful indeed. I probably won't use the numbered buttons thing. Scriptors won't understand this of course, but regular folks don't actually like numbers or numbered buttons. Even the worst formatted, garbled name is better than numbers. There is nothing worse than a dialogue on a piece of furniture that just has numbers for the poses for example. Currently the avatar list is a "scan once and done" kind of deal, I was intending to replace it with something that appends new names and removes names of avatars no longer detected. I was going to stick with a manual "rescan" button however, rather than rely on a timer as it seemed more efficient. Most of the time you're only going to scan once anyway and constantly scanning around for avatars seems resource wasteful no matter how you do it. As for what to do with the names once compiled, each name will be a button so I was thinking that any response from the dialogue that *wasn't* an expected command would obviously be someone pressing a button with an avatars name on it. So I would have an else-if at the end of the listen that executed the code on the avatars names. I will deal with all the avatar names as they are character-wise. Those who have chosen ridiculous (and ridiculously long) avatar names will just be out of luck (for being ridiculous), and it will be their loss. I'm a bit worried about escape characters, but I'm sure there is some way to deal with that. If I can identify a particularly useless sub-set of characters to screen out of the name strings I might do that, but with all the silly font nonsense that people do nowadays, it's unlikely that any particular character can be safely eliminated in that fashion. Probably I will just take the first twelve characters and truncate the name. thanks again, Sylvia
  8. Hello, I've been trying to write a script to scan for avatars in the area and turn the returned list into a set of dialogue buttons. I've got part of the way there. I can invoke the dialogue, and I've figured out the scanner part, but when it comes to feeding that info back into the dialogue I'm lost and so far the wiki has been no real help. I know in some cases the dialogue part is handled by a separate script instead of being included in the main script. Is that the way to go? here is the code I have already: // Sylvia's avatar scan code integer cmdChannel; list visitor_list; float sensor_range = 96.0; integer Key2Chan(key ID) { return 0x80000000 | (integer)("0x"+(string)ID); } integer isNameOnList( string name ) { integer len = llGetListLength( visitor_list ); integer i; for( i = 0; i < len; i++ ){ if( llList2String(visitor_list, i) == name ){ return TRUE; } } return FALSE; } default { state_entry() { cmdChannel = Key2Chan(llGetOwner()); llListen(cmdChannel, "", llGetOwner(), ""); } touch_start(integer total_number) { llDialog(llDetectedKey(0),"\n~VISITOR LIST~\n", ["find avatars","list","reset"],cmdChannel); } sensor( integer number_detected ) { integer i; for( i = 0; i < number_detected; i++ ){ if( llDetectedKey( i ) != llGetOwner() ){ string detected_name = llDetectedName( i ); if( isNameOnList( detected_name ) == FALSE ){ visitor_list += detected_name; } } } } listen( integer channel, string name, key id, string message ) { if( id != llGetOwner() ){ return; } else if( message == "find avatars" ){ llOwnerSay( "scanning for avatars within 96m ..." ); llSensor("", NULL_KEY, AGENT, sensor_range, PI); } else if( message == "list" ){ llOwnerSay( "avatar List:" ); integer len = llGetListLength( visitor_list ); integer i; for( i = 0; i < len; i++ ){ llOwnerSay( llList2String(visitor_list, i) ); } llOwnerSay("Total = " + (string)len ); } else if( message == "reset" ){ visitor_list = llDeleteSubList(visitor_list, 0, llGetListLength(visitor_list)); llOwnerSay("completed reset"); } } }
  9. Thanks for making the effort Qie, but I'm no closer to finding out *why* it might not be working for me. I followed the same instructions, checked the syntax a million times, etc. and it doesn't work for me on my own parcel. Yet, when I walk over to my neighbours parcel in the same sim, my windlights changes to her settings, (at least I'm assuming she uses parcel settings because the entire sim is a whiteout due to EEP otherwise) so obviously it should also work for mine. What I find missing in the Firestorm wiki on the subject is what settings in the viewer itself need to be ticked to make it all work. Like these: (see attached) as well as the little environment settings popup on the lower righthand bar. I'm assuming that the setting for my parcel is correct but I'm not seeing it because my Firestorm preferences are incorrect? Maybe? There is also no information anywhere on the horror that is EEP (which is the reason I'm trying to do this in the first place) and how that may or may not interact with Firestorms Windlight and Parcel settings. As I said my sim has been borked by EEP (thanks Linden Labs!) for over nine months now with no word on when if ever it will be fixed or what to do about it. It's difficult to troubleshoot a windlights problem when there is some un-named, un-known, and un-explainable "problem" with windlights settings in general. Especially when Linden Labs won't even talk about it.
  10. Hi, I've been trying to make parcel windlights work lately (because EEP has completely ruined my sim's wind light for the last 9 months or so), and I found this thread. I'd just like to say that it *doesn't* work for me at all, and that the Firestorm wiki that everyone points to (above) doesn't actually help at all! It tells you how to set it, but it's pretty silent on what to do if it doesn't work, or what the settings in Firestorm are that allow you to see it. I've tried all the settings and checked my syntax a zillion times and it just doesn't work and there is *nothing* from Firestorm that I can find on what to do if it doesn't work or possible reasons why it doesn't work etc. It *does* work on other people's parcels in the same sim as me so ... WTF?
  11. I can't mesh OR script, lol. I rely on full perm mesh to make my clothes and the pickings are mighty slim indeed. I am a superb prim-smith and can make almost anything with them but sadly that skill is completely redundant now too
  12. Thanks Rolig, This will get me started at least. I was looking in-world for your store, but I guess you meant "used to have a store"? Sylvia
  13. "Holovendor!" that was the word I couldn't remember, lol.
  14. Good info, thanks I'm thinking if I had any at all, I might have like, one in my shop. I'm not thinking of replacing my regular vendors with them. Since I wrote my own vendors, I believe I could probably handle the code if I got some clues as to where to start. I think they might be a good option for things like skirts & panties etc., in that these items often sell in multi-packs with a texture changing HUD, but the buyer only really wants that one skirt or that one panty set. The seller's options are either to have a whole wall of product, or to sell one product with a HUD full of questionable texture options Also, a lot of sellers seem to think that a $150 skirt, with a 12 texture HUD is actually worth 12 x $150 (minus some tiny discount), when it's really not worth anything like that to the buyer because 10 of those 12 textures will never be used. I know this situation really frustrates me when I go to buy things. If a temp rez skirt/panty vendor displayed say a hundred items, then the buyer could simply pick the three colours/patterns they like instead of buying multiple texture packs. It would be more honest, more like a real store and definitely better for the buyer. I think it also might give the seller more money in the end anyway. Sylvia Edit: I forgot all this time to say another big reason I'm interested ... I put a lot of time and effort into the textures and especially the materials effects on my clothes, but the box art can't really convey this, so displaying the item in a "real-world" environment so you can see the shine or the normal map effects etc. is a definite bonus. Items look far better "in person" with the new materials effects than they ever could in a picture.
  15. Hello, This may not make sense to anyone who hasn't been in SL for a long while but I was thinking that it would be nice to have a 3D vendor again, (they go by many names but that's what my friends and I used to call them). The idea was that using PRIM_TEMP_ON_REZ, a vendor (which was usually just a plinth with forward and backward arrows), would rez the actual prim object (as TEMP) floating just above the plinth. The user could then use the arrows to cycle through the products. Each one being rezzed in similar fashion. Right-clicking on the temp object, would initiate the sale of the real object from inside the vendor. So first off ... is this still possible or has it been deprecated? Secondly, if it's possible, does anyone have code? I already have old-school vendors that I made myself with a central prim and the two backward and forward arrows, so it seems to me that this version would be easily adaptable to the code I already have. In terms of why people stopped using them, I remember that they could be laggy, and that complicated objects took a while to appear. However, I'm thinking in the age of mesh that we are now in, that rendering would be lickety-split as it were for single mesh objects, when the user is standing literally right in front of the vendor. For instance a skirt vendor, might only have two or three mesh objects in an inventory of hundreds of skirts because the thing that differentiates the skirts would primarily be the pattern. Anyone have any ideas or input on this thing? I think these vendors were seriously cool and would love to have them again. 🙂 If it's possible at all, what I'm looking for is code to modify my own vendors so that instead of just changing the picture on the vendor, it actually displays a temp rez mesh above or in front of the vendor. Sylvia Edit: I'm also looking for all the myriad reasons & opinions (I'm sure they are out there, lol) as to why this isn't a good idea. Let me have it! 😄
  16. Right. Well, I think I know what to do now. Tomorrow I have to derive a final script from all the advice. I will use your app_id concept, except I will call it productID as that makes more sense for my use (I don't and never will create "apps" lol). I will probably move the script to the root and I might use the listen handler thingie too, but maybe not since my usage is again so simple. For tonight ... shopping! Thanks again for all the advice (and to all the others that answered this thread as well). I'm sure that many people besides myself will find it useful. Sylvia
  17. Well, this is exactly what I do of course. I have my own "label" that I use as a root prim on all the clothes I make. But I've been putting the texture changing script in the mesh itself rather than the root, since the mesh is the thing that's having it's texture changed. I suppose this is bad practice as well? I imagine I could probably put it in the root and just change the LINK_THIS in the llSetLinkPrimitiveParamsFast to "1" though. It just seemed more sensible at the time to put it in the mesh rather than figure out which link was which all the time, but perhaps not. Most of the time it's just going to be the mesh and the label in the same relationship to each other.
  18. OK, so I actually think I'm understanding this and I have two different sets of working scripts which is certainly progress! Here is a working set of HUD script and mesh script a la 'Wolfie" (if I understand everything correctly) HUD: //===== Texture Changing HUD - by Sylvia Wasp ===== // installed in the root prim of a linkset // where the other prims are *named* buttons //================================================= integer cmdChannel; string HUD_Name = "Product HUD"; integer Key2Chan(key ID) { return 0x80000000 | (integer)("0x"+(string)ID); } default { state_entry () { llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_NAME,HUD_Name]); cmdChannel = Key2Chan(llGetOwner()); } touch_start(integer n) { string button = llGetLinkName(llDetectedLinkNumber(0)); llRegionSayTo(llGetOwner(),cmdChannel, button); llSay(cmdChannel, button); // delete when testing complete } } Mesh: //===== Texture Changer (Mesh) - by Sylvia Wasp ======== // installed in an item of mesh clothing, // receives messages from "Texture Changing HUD" //====================================================== integer cmdChannel; key texture_01 = "36e9d64c-3f58-92d1-b2d1-807ddc996558"; key texture_02 = "1db31c0c-622a-d120-23dd-52519592d253"; key texture_03 = "614544ae-4bdf-c8d6-2cb3-0115a990943b"; key texture_04 = "06943dd0-0216-16c7-83de-4f40c6185106"; key texture_05 = "33a2a763-dae0-e4b9-d908-b56d9c50fb47"; key texture_06 = "bfba4c48-cea2-3523-b62d-52beafcb3a77"; integer Key2Chan(key ID) { return 0x80000000 | (integer)("0x"+(string)ID); } default { state_entry () { cmdChannel = Key2Chan(llGetOwner()); llListen(cmdChannel, "Product HUD", NULL_KEY, ""); } listen(integer channel, string name, key id, string message) { if (message == "button_01" ) { llSetLinkPrimitiveParamsFast(LINK_THIS,[ PRIM_TEXTURE, ALL_SIDES, texture_01, <1.0, 1.0, 1.0>,ZERO_VECTOR, 0.0 ]); } else if (message == "button_02") { llSetLinkPrimitiveParamsFast(LINK_THIS,[ PRIM_TEXTURE, ALL_SIDES, texture_02, <1.0, 1.0, 1.0>,ZERO_VECTOR, 0.0 ]); } if (message == "button_03" ) { llSetLinkPrimitiveParamsFast(LINK_THIS,[ PRIM_TEXTURE, ALL_SIDES, texture_03, <1.0, 1.0, 1.0>,ZERO_VECTOR, 0.0 ]); } else if (message == "button_04") { llSetLinkPrimitiveParamsFast(LINK_THIS,[ PRIM_TEXTURE, ALL_SIDES, texture_04, <1.0, 1.0, 1.0>,ZERO_VECTOR, 0.0 ]); } if (message == "button_05" ) { llSetLinkPrimitiveParamsFast(LINK_THIS,[ PRIM_TEXTURE, ALL_SIDES, texture_05, <1.0, 1.0, 1.0>,ZERO_VECTOR, 0.0 ]); } else if (message == "button_06") { llSetLinkPrimitiveParamsFast(LINK_THIS,[ PRIM_TEXTURE, ALL_SIDES, texture_06, <1.0, 1.0, 1.0>,ZERO_VECTOR, 0.0 ]); } } } I've added an extraneous llSay to the HUD part because when I'm testing a new dress the mesh isn't actually being worn by me and therefore llRegionSayTo fails on the basis of it not being attached. Here is my version of the same thing using Molly's advice instead. HUD: //===== Texture Changing HUD - by Sylvia Wasp ===== // installed in the root prim of a linkset // where the other prims are *named* buttons //================================================= integer cmdChannel; integer app_id = 73245; string HUD_Name = "Product HUD"; default { state_entry () { llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_NAME,HUD_Name]); cmdChannel = (integer)("0x"+(string)llGetOwner()); if (cmdChannel == app_id) ++app_id; cmdChannel = cmdChannel ^ app_id | 0x80000000; } touch_start(integer n) { string button = llGetLinkName(llDetectedLinkNumber(0)); llRegionSayTo(llGetOwner(),cmdChannel, button); llSay(cmdChannel, button); // delete when done } } Mesh: //===== Texture Changer (Mesh) - by Sylvia Wasp ======== // installed in an item of mesh clothing, // receives messages from "Texture Changing HUD" //====================================================== integer cmdChannel; integer app_id = 73245; key texture_01 = "36e9d64c-3f58-92d1-b2d1-807ddc996558"; key texture_02 = "1db31c0c-622a-d120-23dd-52519592d253"; key texture_03 = "614544ae-4bdf-c8d6-2cb3-0115a990943b"; key texture_04 = "06943dd0-0216-16c7-83de-4f40c6185106"; key texture_05 = "33a2a763-dae0-e4b9-d908-b56d9c50fb47"; key texture_06 = "bfba4c48-cea2-3523-b62d-52beafcb3a77"; default { state_entry () { cmdChannel = (integer)("0x"+(string)llGetOwner()); if (cmdChannel == app_id) ++app_id; cmdChannel = cmdChannel ^ app_id | 0x80000000; llListen(cmdChannel, "Product HUD", NULL_KEY, ""); } listen(integer channel, string name, key id, string message) { key msg_owner = llGetOwnerKey(id); key msg_creator = llList2Key(llGetObjectDetails(id, [OBJECT_CREATOR]), 0); if ((msg_owner == llGetOwner()) && (msg_creator == llGetCreator())) { llOwnerSay("Hi! I am good thank you"); } if (message == "button_01" ) { llSetLinkPrimitiveParamsFast(LINK_THIS,[ PRIM_TEXTURE, ALL_SIDES, texture_01, <1.0, 1.0, 1.0>,ZERO_VECTOR, 0.0 ]); } else if (message == "button_02") { llSetLinkPrimitiveParamsFast(LINK_THIS,[ PRIM_TEXTURE, ALL_SIDES, texture_02, <1.0, 1.0, 1.0>,ZERO_VECTOR, 0.0 ]); } if (message == "button_03" ) { llSetLinkPrimitiveParamsFast(LINK_THIS,[ PRIM_TEXTURE, ALL_SIDES, texture_03, <1.0, 1.0, 1.0>,ZERO_VECTOR, 0.0 ]); } else if (message == "button_04") { llSetLinkPrimitiveParamsFast(LINK_THIS,[ PRIM_TEXTURE, ALL_SIDES, texture_04, <1.0, 1.0, 1.0>,ZERO_VECTOR, 0.0 ]); } if (message == "button_05" ) { llSetLinkPrimitiveParamsFast(LINK_THIS,[ PRIM_TEXTURE, ALL_SIDES, texture_05, <1.0, 1.0, 1.0>,ZERO_VECTOR, 0.0 ]); } else if (message == "button_06") { llSetLinkPrimitiveParamsFast(LINK_THIS,[ PRIM_TEXTURE, ALL_SIDES, texture_06, <1.0, 1.0, 1.0>,ZERO_VECTOR, 0.0 ]); } } } The only thing I'm concerned about is that the message owner and creator comparison check in the Mesh part seems to fail, but perhaps that is because I didn't actually create the mesh? Please point out my "mistakes" (I won't get mad) Sylvia Edit: I just saw your other advice (too late!). You are suggesting to create a sort of second custom listen and removing the first one? Makes it more private and secure I suppose? I will try to incorporate but perhaps we are entering into overkill territory again? Also if my Owner/Creator check is going to fail, then it won't work for this situation, no? Thanks again, Sylvia
  19. The more I read these scripts the more brilliant they seem. I had no idea that one could query the owner of the message sent from within the listen for instance, nor get the details on the owner of the object that sent them. This is of course the actual answer to my problem. wouldn't this bit though ... app_channel = (integer)("0x"+(string)llGetOwner()); if (app_channel == app_id) ++app_id; app_channel = app_channel ^ app_id | 0x80000000; mean that app_channel could be different on occasion between the sender and receiver (and thus the message fails)? It seems that you know what you're doing so I guess I'm almost certainly incorrect about that, but you'll have to excuse me as I'm still getting my head around it. I find I have to rewrite a script (and sit with it for a week) before I completely "get it", lol. Anyway thanks so much for all of this I think it will solve all. Sylvia
  20. No problem. Sorry I missed that. I account for typing mistakes and I don't generally copy and paste. I may not be the best scripter but I'm no dummy. Unfortunately, most scriptures I've met and talked to over the years assume that if you can't script you must just be stupid, when in fact it's a very specific skill. Not everyone can paint a picture and not everyone can script (despite Apples' mantra that they can).
  21. Thanks. I will try this again and I will incorporate that change. The reason I wasn't using llRegionSay is because based on the name, one would assume that it was going to spam the entire region, which I guess it does. I thought I was being more specific with the llSay and the objects are usually only within a metre of each other anyway. The error on the button thing was just the (singularly unhelpful) "syntax" error I think, which is to say "you did something wrong but it could be anywhere in the script", lol. I even tried casting "button" specifically as a string (although I shouldn't have to I thought) and it still wouldn't do it. My listen handler in the mesh object is still completely deaf to this HUD though. Assuming the Key2Chan stuff works, that is still the real problem. I do already filter for the name of the HUD and NULL_KEY and empty string, so it's obviously the Channel argument that isn't working, (the cmdChannel in the example is not right obvs.) but I still can't get my head around what to put there. state_entry () { llListen(cmdChannel, "Product HUD", NULL_KEY, ""); } How can a listen in the mesh object, listen for a unique channel that's generated in the HUD? My only thought is to get the mesh to just listen to any and all channels the HUD might be communicating on but I have failed to find that method so far. I thought that simply putting "integer Channel" would get me what I want, but that wouldn't compile either and I'm really just guessing at this point. EDIT: I used llRegionSay as suggested but then that leads to why have the if and else if at all? The new HUD script is even simpler: //===== Texture Changing HUD - by Sylvia Wasp === // // installed in the root prim of a linkset // where the other prims are buttons named // "button_01", "button_02", etc. //=============================================== integer cmdChannel; string HUD_Name = "Product HUD"; integer Key2Chan(key ID) { return 0x80000000 | (integer)("0x"+(string)ID); } default { state_entry () { llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_NAME,HUD_Name]); cmdChannel = Key2Chan(llGetOwner()); } touch_start(integer n) { string button = llGetLinkName(llDetectedLinkNumber(0)); llRegionSay(cmdChannel, button); } } which makes me very happy however, the mesh still doesn't hear anything. Sylvia
  22. Okay, so after the helpful suggestions I *did* get (many thanks to Wolfie and Fennix!), here is what I have (so far) for a new HUD script. I'm still not sure if Key2Chan is right or even doing anything though, lol. And I have yet to find a way to get the mesh clothing to receive any messages from this HUD. Also, not sure why I can't just say llSay(cmdChannel, button); instead of saying "button_01" twice. But it does not compile. //===== Texture Changing HUD - by Sylvia Wasp === // // installed in the root prim of a linkset // where the other prims are buttons named // "button_01", "button_02", etc. //=============================================== integer cmdChannel; string HUD_Name = "Product HUD"; integer Key2Chan(key ID) { return 0x80000000 | (integer)("0x"+(string)ID); } default { state_entry () { llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_NAME,HUD_Name]); cmdChannel = Key2Chan(llGetOwner()); } touch_start(integer n) { string button = llGetLinkName(llDetectedLinkNumber(0)); if(button == "button_01") { llSay(cmdChannel, "button_01" ); } else if(button == "button_02") { llSay(cmdChannel, "button_02" ); } else if(button == "button_03") { llSay(cmdChannel, "button_03" ); } else if(button == "button_04") { llSay(cmdChannel, "button_04" ); } else if(button == "button_05") { llSay(cmdChannel, "button_05" ); } else if(button == "button_06") { llSay(cmdChannel, "button_06" ); } } }
  23. Hey Thanks for this, I thought of this late last night but I kept getting a script error when I tried it. I have no idea why as it seems like a logical thing to do. I will try it again.
  24. Hey thanks for this. Seriously, a lot of work and it will take me a while to digest. After being up most of the night with this I'm still sitting on my building platform trying to figure this out this morning and this will help a lot. After many hours of goofing around I finally got Key2Chan to work (I think) in the HUD itself, but my main problem now is that I can't see how a randomly generated channel in the HUD can be received by the mesh since using the same method there would presumably create a completely different random channel number. I realise that probably sounds insanely stupid to you scriptures, but it's a very logical hurdle to me, lol. I thought that making the listen in the mesh listen to *any* channel from the same ID would be the way but I can't seem to do that. Thanks for the suggestion about listening to messages from a specific HUD by name. I already do that anyway because sometimes I use two HUDs for one product. I put an automatic re-naming thing in the state entry so if the user renames the HUD then razzing it or resetting it will put the proper name back. Sylvia Edit: by "I got Key2Chan working" I just mean that I took the cryptic junk given me and put it in the HUD script in a way it compiles without errors. I still have no idea whether it's returning anything useful or how to use what it returns.
  25. It may be clear to you but a snippet of code without any context or explanation is of no help to me. I know, I know, you want me to learn all about it for myself. You want me to use the "correct" methods or what you believe is the best methods, but the net result here is I'm going to just use a plain old number if I can't figure this out by midnight. So if people are really concerned about memory usage in the sims, the end result here is actually going to be the complete opposite of that intention. Again, I know I've seen scripts that use llFrand to generate a number that can be used as a unique channel. Your actually responding to my second attempt to ask for information on that, yet you give me a different other method instead, lol. A method that I couldn't understand if I had the rest of the week to figure it out, simply because you think it's a slightly better method.
×
×
  • Create New...