Jump to content

Sylvia Wasp

Resident
  • Posts

    269
  • Joined

  • Last visited

Posts posted by Sylvia Wasp

  1. 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");
                }
        }        
    }

     

  2. 8 hours ago, Qie Niangao said:

    I only use Firestorm when absolutely necessary, so you may want to get proper help from their in-world support group chat, but I stopped by Sage and took a look and the only thing I saw that looked like a problem was square brackets around the setting name, which the wiki does warn against:

    So I scampered over to a parcel I control and typed this into the parcel description field:

    and it seemed to work for my alt using the latest Firestorm.

    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.  

     

    Screenshot 2019-08-01 at 10.30.38 AM.png

    Screenshot 2019-08-01 at 10.36.29 AM.png

  3. On 3/9/2018 at 3:23 AM, Chaser Zaks said:

    Firestorm's wiki has a good article explaining how to use parcel windlight: http://wiki.phoenixviewer.com/fs_windlight

    Important: this does not work on all viewers, especially the Linden Lab viewer. Linden Lab is working on parcel windlight that works on all viewers. It isn't available yet but I recommend keeping note of this and switching to it when the time comes as it is more customisable and officially supported.

    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?

  4. 34 minutes ago, Rolig Loon said:

    Yeah, I closed it when mesh came in.  I couldn't compete.  I am a scripter, not much of a mesher.

    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

  5. 4 hours ago, Rolig Loon said:

    I agree, and that's why I put them in my shop (well, that and the fact that it was sort of a novelty). The basic design of a system like that needn't be difficult.  Basically, you have two objects with separable functions: (1) a rezzer that creates the object and (2) the object itself, which has the functions of any normal vendor.  You script the rezzer to create the object on demand and then you script the object as you would script any other vendor (click to Pay the object and have it send you a copy with appropriate perms), plus a timer that kills the object after X seconds or when the buyer pays.  You can load it with other features (sounds, particles, rotating display  .... ) but that's icing and puffery.  The basic design doesn't need to be difficult.

    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

  6. 40 minutes ago, Rolig Loon said:

    I've made a few of those vendors myself, back when I had an in-world shop.  They were fun for things like shoes.  Some builders still use them for displaying houses and other structures.

    I suspect that they are less popular now for a few reasons (some more trivial than others):

    1. Rezzing objects always causes a region's servers to stall briefly, thus adding to lag.  If you have a lot of rezzers in a region, this can make a hefty potential difference.

    2. Whether an object is rezzed "permanently" or is only there for a brief time, it adds to the parcel's land impact.  Again, if a region is at all busy, these vendors can compete with each other and with other objects for precious L.I.

    3. In general, rezzers like this require a bit more customization than simple vendors that display a picture and send a purchase to the buyer.  The average shop owner doesn't have the skill or patience for customization. [This one is trivial, and probably most important for small shops, but still worth thinking about.]

    4. Whether the rezzed items use up valuable L.I. or not, they do use up space.  It's hard to jam many 3-D vendors into a shop without eating up floor space that you need for other things.

    All in all, I think those vendors are fun and certainly have a place.  That's why I used to make them.  They should probably be used sparingly, though.

    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. 

  7. 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! 😄 

  8. 1 minute ago, Mollymews said:

    we have to weigh all these things up. There is absolutely true way to do things.  There are just general guidelines that we adapt too, depending on what we are wanting to achieve and the specifics of each situation

    in the specifc case of a mesh template made by someone else.  If we want to authenticate messages received from a HUD, then the authentication has to go in our own root prim. So yes  we use LINK 1 for efficiency and performance. If we don't then we would need 2 scripts. One in the root for authentication and a second script in the mesh to do the applying. Then we would need a way for the scripts to communicate using linkmessage. This adds an extrs level of complication and work 

    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

    • Like 3
  9. 30 minutes ago, Mollymews said:

    the recommended advice when using a mesh template / mesh parts made by another person in our product,  is to link the mesh to a root prim of our own creation. So that our users will see our name as the creator of our product.

    ...

    and when we do this, our scripts being in the root prim will recognize us as the creator of our product

    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.  

  10. 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) :o 

    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 :) 

     

  11. 14 hours ago, Mollymews said:

    i give some code examples as a FYI  about what key to channel is, why we use it, how it works, what the implications are, and how we might work around any concerns

    the basic reason for using key to channel is so that a sender app and a receiver app can communicate on a known channel. While at the same time spreading app communications across a number of channels on an individual user basis, while also providing some crosstalk protection for two or more users who may be on the same region using our apps.  HUD >> Clothing/Body/Furniture being a typical case where this can happen

    the first script walks thru key to channel, and comments on the what and whys

    the next two scripts show example codes putting it all together, also adding in the protective checks for owner and creator

    another thing to consider.  The example receiver is listening for everything on the channel.  A thing that some creators do is to also filter the listener to a named hud object. An upside is that there is a tiny gain in performance.  The downside with a name filter is that we have to make the HUD No-Modify to prevent the user from renaming the HUD which would break the receiver app

    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 :)  

  12. 45 minutes ago, Fenix Eldritch said:

    That is correct. However, be careful to note that there are two similarly named functions: llRegionSay and llRegionSayTo, which do different things. llRegionSay will act like llSay, but for the whole region. llRegionSayTo will speak across the whole region as well, but is directed only to the target specified by uuid. No one else will hear it, even if they're listening on the same channel. I was advocating for the use of llRegionSayTo which will target a specific avatar or object. [wiki page]

    You listener looks ok, so as you said, the remaining problem is getting the channels set up right. Getting to objects to communicate on a generated private channel can get complicated fast. One approach is to have both objects run the same code to generate the same number based off of a public value (like the owner's key).

    However, the whole point in my suggestion to use llRegionSayTo was to avoid doing that altogether. By using llRegionSayTo, you can safely use the same command channel across all instances of this product. Because of the targeted nature of the communication, only the target will actually hear the message on the channel.

    Try this in your HUD (pick a static cmcChannel number for this test and use the same in your listener) :

    
     llRegionSayTo( llGetOwner(), cmdChannel, button );

    As mentioned previously, if you direct a message to an avatar via llRegionSayTo and use a non-zero channel, then the viewer won't display it in chat - but all of the avatar's worn attachments will be able to hear the message. With this, you can indirectly target your mesh attachments by supplying the uuid of the current owner, That will act as a per-avatar filter.

     

    Edit: I just looked back at my previous post and noticed I typed out "cmdchannel" instead of "cmdChannel". That was a typo on my part and if you copied it from my post, could have been why you got your syntax error. The compiler would see that as some new undefined variable. Sorry!

    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). 

  13. 2 hours ago, Fenix Eldritch said:

    Assuming you're within the same scope as the button variable, I would think you should have no problem doing exactly that. The button variable is a string after all, so the following should work (and alleviate the need for that large if-then-else block entirely) :

    
    string button = llGetLinkName(llDetectedLinkNumber(0));
    llSay(cmdchannel, button);

    If it's not compiling, what error are you seeing?

    Additionally, I would again suggest you consider using llRegionSayTo instead of llSay. This makes the HUD speak directly to the target you specify and no one else. You can potentially avoid all the hassle with generating unique channels and instead rely on llRegionSayTo to target the avatar - which would in turn have all its attachments hear the command as per the description on the wiki page.

    The corresponding listen handler in the attachments should have some filters to be safe, like only accepting messages form the name of the HUD object (as that would most likely remain constant). If you're still having problems with the relay, post a sample of the attachment's listener too.

    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

  14. 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" );
                }
        }                
    }

     

  15. 7 hours ago, Runie Xue said:

    Easy solution:

    on this line:

    llListen(app_channel, "", NULL_KEY, "");

    change to this:

    llListen(app_channel, "", llGetOwner(), "");

     

    After this your script only hear your key and other people on same room not have any problem with that, also you can make more filters inside the event of listen but with this i think works fine.

    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. 

  16. 10 hours ago, Mollymews said:

    i give some code examples as a FYI  about what key to channel is, why we use it, how it works, what the implications are, and how we might work around any concerns

    the basic reason for using key to channel is so that a sender app and a receiver app can communicate on a known channel. While at the same time spreading app communications across a number of channels on an individual user basis, while also providing some crosstalk protection for two or more users who may be on the same region using our apps.  HUD >> Clothing/Body/Furniture being a typical case where this can happen

    the first script walks thru key to channel, and comments on the what and whys

    
    
    default
    {
        state_entry()
        {      
            integer app_channel;
           
            app_channel = (integer)("0x"+(string)llGetOwner()) | 0x80000000;
            // the above code creates a channel number using the 1st 8 hexadecimal numerals
            // of the owner's avatar key: (integer)("0x"+(string)llGetOwner()
            // then uses OR 0x80000000 to convert this into a negative number
            
            // when this is used widely by different script apps then we can get a higher rate of our app
            // receiving understandable messages from other scripts owned by the same person, and scripts
            // owned by others that happen to use the same channel
            // which can result in our app acting on those messages when it shouldn't
            
            // we designate a unique id for our app. Each of our apps has it owns unique id
    
            integer app_id = 73245;      
            
            // we then XOR the channel with our appid, so that at least our apps owned by the same user 
            // will never crosstalk each other
            
            app_channel = (integer)("0x"+(string)llGetOwner()) ^ app_id | 0x80000000;
            
            // an issue with this as wrote is that we need to ensure that the result of this is not
            // equal to 0. 1 XOR 1 == 0;  When so then our app will communicate on the public channel 0.
            // to avoid this remote (but still possible) happening then we check for it      
            
            app_channel = (integer)("0x"+(string)llGetOwner());
            
            if (app_channel == app_id) ++app_id;
            app_channel = app_channel ^ app_id | 0x80000000;
            
            // for this part to be safe then our unique app_ids need to be at least 2 values apart. 1, 3, 5, etc
            
            // this doesn't protect our app from two or more of our app users who might happen to have
            // the same first 8 hexadecimal numerals as each other  
            // for protection against this and from crosstalk from other creators apps then relying on the 
            // channel value all by itself is not a safe method. No matter what channel we choose then the
            // possibility of two or more independent scripts from two or more independent creators using 
            // the same channel remains.
            // the code so far only protects our app from our other apps owned by the same user
            
            // to protect from other creators and other users of our app then see the following example codes
            // in the post
        }
    }

    the next two scripts show example codes putting it all together, also adding in the protective checks for owner and creator

    
    // sender
    
    integer app_id = 73245;
    
    integer app_channel;
    
    
    default
    {
        state_entry()
        {
            app_channel = (integer)("0x"+(string)llGetOwner());
            if (app_channel == app_id) ++app_id;
            app_channel = app_channel ^ app_id | 0x80000000;
        }
        
        touch_start(integer total_number)
        {
            llRegionSay(app_channel, "Hello! how are you?");
        }
    }
    
    // receiver
    
    integer app_id = 73245;
    
    integer app_channel;
    
    
    default
    {
        state_entry()
        {
            app_channel = (integer)("0x"+(string)llGetOwner());
            if (app_channel == app_id) ++app_id;
            app_channel = app_channel ^ app_id | 0x80000000;
           
            llListen(app_channel, "", NULL_KEY, "");
        }
    
        listen(integer channel, string name, key id, string msg)
        {
            // here we get the owner and the creator of the sender (msg received from)
            key msg_owner = llGetOwnerKey(id);
            key msg_creator = llList2Key(llGetObjectDetails(id, [OBJECT_CREATOR]), 0);
            
            // here we compare the owner and creator of the sender to the owner and creator of
            // the receiver 
            if ((msg_owner == llGetOwner()) && (msg_creator == llGetCreator()))
            {
               llSay(0, "Hi! I am good thank you");    
            }         
        }
    }

    another thing to consider.  The example receiver is listening for everything on the channel.  A thing that some creators do is to also filter the listener to a named hud object. An upside is that there is a tiny gain in performance.  The downside with a name filter is that we have to make the HUD No-Modify to prevent the user from renaming the HUD which would break the receiver app

    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.

  17. 7 minutes ago, Wulfie Reanimator said:

    @Fritigern Gothly gave you a link to a wiki page going into detail on how to generate a unique channel based on an UUID/product. (Which is where that Key2Chan came from.) There's no better answer than what she already provided.

    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.  

  18. 29 minutes ago, Ana Stubbs said:

    Memory usage is a bit of a red herring - idle scripts that do nothing have a disproportionate effect on the sim. Obviously it depends how many buttons you have, but if you're relying on the user taking the hud off before going anywhere, unless that is you or your best friend, it's unfortunately not reliable.

    I wouldn't fixate on the word mistake. If you do, you're not going to get very far with scripting. Learn to love your mistakes, bugs, and unexpected behaviours. Any scripter who does not make mistakes is either not learning, or  is making mistakes but can't see them.

    Well, that was kind of my point.  "Mistake" is 100% an insult in this context.  

    It's literally staring off the answer (to a clear, precise and kindly phrased question) with, "your wrong".  

    That's what typically happens on the LSL scripting forum.  You ask a question about a script with an error and you get told that "your entire approach is wrong" and that the person answering it could re-write everything this other way and it would be so much better, yada-yadda ... yet somehow the original question is literally never answered.  

    The only reason I bothered is because I'm on a deadline for a product that I want to roll out tonight.  

    I guess I'm on my own, but I repeat ... there is a way to generate a channel number using random numbers.  If anyone wants to just post that code so I can use it at the top of my script I'd appreciate it.  

    That's what makes it so galling.  I know that almost everyone answering this thread probably knows how to do that but no one wants to say it, lol.  They want to argue about "proper" procedure and who's method is the best.  

  19. 2 minutes ago, Fritigern Gothly said:

    The rudeness is entirely yours, my dear. I went through the trouble of explaining myself, giving you examples, I helped. 
    Your response? "You're rude!"

    So forget it, you have received the last bit of help from nme you will ever get.

    LOL.  I was so very careful not to be rude in my response to your rudeness.  I really tried, honest.  

    I used smiley's and 'perhapses' and every circumlocutory prose I could think of to couch what I was saying in nice terms.  

    I even thanked you profusely for your obscure and inscrutable suggestion that was given to me without any practical explanation or application ... and then *you* post a rude huffy response anyway.   

    I think I know which one of us has trouble communicating with the other monkeys. 😉 

  20. Ok, I guess I got all the scriptures mad at me, lol, BUT ...

    People actually come here for help and none of this is really that helpful.  I have a product ready to go and all I need is a way to generate a channel at the top of one script and nothing said here has actually helped me out.  It's all just theoretical discussions about the details of scripty things among scriptors. 

    I can make the change to reduce my 196k script load for less than one minute of the sims time later, what I need now is what I know is probably a simple snippet of code to fix my problem and no one is coming forward with it.  

    integer Channel = Key2Chan(llGetOwner());

    seems to be a custom function and is not working at all.  

    I know that some people use a random number generator to do the same thing.  Can someone provide a clue as to how I would code that instead? 

  21. 55 minutes ago, Fritigern Gothly said:

    Mistake #1: Using scripted buttons to communicate with the main script. I can guarantee you that you can remove all the scripts from all the buttons and use llGetLinkName(llDetectedLinkNumber(0)) to detect which button was pressed. This will cut down on your script use and therefore your memory usage. Remember that each LSL script reserves 16kb, but when compiled as Mono, it reserves 64kb, so 16 mono scripts reserves 1 MB which often shows up as memory actually used. Plus you will have all your code in a single script instead of all over the place so that if you want to change something like, i don't know, you'd want each button to glow for 2 seconds after being pressed, you can do that in 1 script (and use llSetLinkPrimitiveParamsFast()to set and unset that glow).

    Mistake #2: You appear to be using a single, immutable channel for your system. Try generating a channel based on a user's UUID. this sample in the LSL library will show you how. I personally use the variant with the app key, so that the HUD for product A does not mess with product B when they are used and owned by the same owner. You will have to change the app key for each different product though. To generate the channel number, you would use integer Channel = Key2AppChan(llGetOwner(), 123456); where you would replace 123456 with a predefined integer of your own between -2147483647 and 2147483647.
    If you don't want to mess with app keys, you can use the "simple" routine, which will be used as integer Channel = Key2Chan(llGetOwner()); and works fine as well, but can cause one hud to affect a different product when owned by the same user (like a dress HUD can affect shoes if they both use the simple routine).

    Lol.  This is exactly why I rarely ask questions here.  :) 

    Many genuine thanks for this: 

    integer Channel = Key2Chan(llGetOwner());

    Which is basically (one) answer or one way to do it, but I have to say that I find this response extremely rude.   

    - My first "mistake" isn't a mistake, it's just a choice, and the memory usage on a script in this situation is about as important as which potato chip you pick out of the bag first when eating potato chips.  I don't use mono on the buttons so we are talking about less than 200k even on my most elaborate HUD.  200k which will be in use for less than a minute when a person is changing clothes.  

    It also means I never have to worry about scripting buttons (or anything to do with buttons) which saves me huge amounts of time.  I have pre-made HUDs in inventory with button arrays of two, three, four, six, eight, and twelve buttons.  I drag a HUD out of inventory with the right number of buttons, apply a texture, and change the main HUD code as needed.  Simple!

    The main HUD code is always going to be comprised of a simple list of UUID's (the textures) and an if/else list for the button messages anyway, so I can just plug in the new UUIDs and maybe once in a blue moon have to edit the llSetLinkPrimitiveParamsFast()sections.  

    It's a very simple, clear, practical, reusable system that works very well indeed and is totally not a "mistake".  

    - My second "mistake" also isn't a mistake, it's actually the situation I posed to the forum in the first place.  The very question I asked you. 

  22. Hello, 

    I wrote a texture changing HUD from scratch but I have a question.  

    Basically, the HUD has button prims that when clicked, use llMessageLinked to tell their name to the main HUD prim which then hears them on a link_message

    The main HUD prim then relays the messages to the mesh clothing (things like "button_01", "button_02" etc.) using llSay on a channel. 

    The clothes hear the messages and change textures, and everything seems to work fine except ... if two people are changing clothes in the same room their HUDs affect each other and then change each others clothes.  I'm basically using the same channel and only identifying the HUD to the clothing by the name (of the HUD).  

    I'm sure there must be a better way wherein two people can buy the same clothes and the HUDs they bought don't affect each others clothes?  Perhaps by setting some random channel when the HUD is attached each time?  I'm just not sure how to do this or if it's possible or if customers generally care about it.  The odds of two people buying the same product changing the texture in the same area are pretty small but it does happen.

    Any help would be appreciated. 

    Sylvia 🙂

  23. Aaaannnnd ... on perhaps the 20th or 30th log-in ... everything seems to be mysteriously working again.  

    For absolutely no reason at all.

    Unless some Linden was secretly reading this and switched whatever switch it was that made it work again, lol.  

    Thanks to everyone who commented. 

    Sylvia

    • Like 1
×
×
  • Create New...