Jump to content

Trouble with auto-attaching a HUD for an experience


Patrick Playfair
 Share

You are about to reply to a thread that has been inactive for 2657 days.

Please take a moment to consider if this thread is worth bumping.

Recommended Posts

I am trying to AUTO-ATTCH a HUD upon collision,  I am using the example scripts from the wiki line for line.  I have one object called a HUD Dispenser that REZ's a HUD when someone collides with it.  The HUD that is REZed has a script to RequestExperiencePermissions and if granted, attach to the avatar.

If I place a plain object in the dispenser, it attaches flawlessly everytime.  But when I put a HUD into the dispenser, it works like every 4 or 5 attempts.  The HUD gets REZed, but never attaches.  Eventually one does, but I end up with 100 unattached HUDs lying around.  There is also a section of the script that is supposed to use llDie to get rid of unattached HUDs, but it doesn't appear to work either.  Seems to me to be a timout type issue or something, as the HUD also has scripts that initialize and run on REZ.  Any ideas?

// Example script for LSL Experience Tools attachment
 
// This script runs on an object that is rezzed in-world which gets
// an Experience permissions and then attaches to an AV.
 
integer listener;
integer msg_channel;
 
 
default
{
    on_rez(integer start_parameter)
    {   // Start listening for a message from rezzer
        msg_channel = start_parameter;
        llSay(0, "Alien Abduction HUD has been rezzed");
        listener = llListen(start_parameter, "", NULL_KEY, "");
    }
 
    listen(integer channel, string name, key id, string text)
    {   // Listen for the message from the rezzer with the target agent key
        if (channel == msg_channel)
        {   // Ask for the experience permission
            list msg = llParseString2List(text, ["|"], []);
            llRequestExperiencePermissions((key)llList2String(msg, 1), "");
            llListenRemove(listener);
            llSetTimerEvent(60.0);
        }
    }
 
    experience_permissions(key target_id)
    {   // Permissions granted, so attach to the AV
        llAttachToAvatarTemp(ATTACH_HUD_BOTTOM_LEFT);
        llSetTimerEvent(0.0);
        if (llGetAttached() == 0)
        {   // Attaching failed
            llDie();
        }
    }
 
    experience_permissions_denied( key agent_id, integer reason )
    {   // Permissions denied, so go away
        llDie();
    }
 
    attach( key id )
    {   // Attached or detached from the avatar
        if (id)
        {
            llSetTimerEvent(0.0);
            llSay(0, "Now attached with a key " + (string)id + " and llGetAttached() returning " + (string)llGetAttached());
            // From this point, the object can start doing whatever it needs to do.
            state running;
        }
        else
        {
            llSay(0, "No longer attached");
            llDie();
        }
    }
 
    timer()
    {   // Use a timer to catch no permissions response
        llSay(0, "Permissions timer expired");
        llDie();
    }
}
 
// This state starts when permissions are granted and the object is properly attached
state running
{
    state_entry()
    {
        llSay(0, "off and running!");
    }
 
    attach(key id)
    {
        if (id == NULL_KEY)
        {   // if the object ever un-attaches, make sure it deletes itself
            llSay(0, "No longer attached");
            llDie();
        }
    }
}
Link to comment
Share on other sites

That looks like it ought to work.  There are a few things you might think about that might make a difference, or at least make things run smoother.

First, you didn't show your rezzer, but I assume that you are sending the target avatar's UUID from an object_rez event.  Be sure that you put a short llSleep(0.2) at the start of that event if it's not already there. Rezzing can be delayed slightly, so if you don't delay that message a wee bit too, there's a good chance that the rezzed object won't hear it, especially in a laggy region

Second, you can save yourself some of the fiddly business with the timer event and maybe get rid of it entirely.  Just make your object temp_on_rez.  If it's attached, that won't make any difference.  If it doesn't attach, it will poof in about a minute (which is what your timer is set for now).

Third, I notice that the av UUID is being sent as part of a message that you need to parse when it arrives.  You don't seem to be using whatever the first element in that message is, though. If you really don't need it, you can simplify both scripts by sending just the UUID.

Finally, again since I can't see your rezzer I can't check .... but you should verify that the UUID that it's sending is really the av's UUID.  If it sends NULL_KEY, your rezzed object obviously won't have any idea who to attach to.  I screw up on this point often enough that I have gotten in the habit of checking explicitly for

if (llGetAgentSize(av) != ZERO_VECTOR) { // do stuff }

just in case.

Link to comment
Share on other sites

I will check those things out, and I like the idea about making it TEMP REZZ.  Below is the script that is in the dispenser.  Keep in mind that it works perfectly (and fast) if I REZZ and attach a plain object with no OTHER scripts in it.  But the HUD I am rezzing has a bunch of scripts in it.  (it is actually a stripped down RLV relay).

 

Thanks

 

default{    state_entry()    {        llVolumeDetect(TRUE);    }     collision_start(integer NumberOfCollisions)    {        integer i = 0;        for(; i < NumberOfCollisions; i++)        {            integer channel = llRound(llFrand(-1000));            key give_to = llDetectedKey(i);            llSay(0, "Rezzing HUD for " + (string)give_to + " using channel " + (string)channel);            llRezObject(llGetInventoryName(INVENTORY_OBJECT, 0), llGetPos(), ZERO_VECTOR, ZERO_ROTATION, channel);            llRegionSay(channel, "ATTACH|" + (string)give_to);        }    }}
Link to comment
Share on other sites

Yeah, this is where I would typically start to have trouble:

           llRezObject(llGetInventoryName(INVENTORY_OBJECT, 0), llGetPos(), ZERO_VECTOR, ZERO_ROTATION, channel);            llRegionSay(channel, "ATTACH|" + (string)give_to);

llRezObject and llRezAtRoot each have a 0.1 second forced delay that can easily turn into 0.2 seconds on a busy region, so if you send that message by llRegionSay too soon, the new object might not be ready to hear it.  I prefer to write

 

object_rez(key id){    llSleep(0.2);    llRegionSayTo(id, channel, (string)give_to);}

 Congrats on getting it to work.  :)

Link to comment
Share on other sites

It certainly  sounds as if there may be a race condition in which the rezzer sends the HUD the target's UUID before the HUD is ready to receive it.

When I'm attaching stuff using experience perms I usually have the object tell the rezzer that it's successfully rezzed, and only then does the rezzer send the target's UUID.

Alteratively, you might try using the Key2Number routine in the wiki and send the HUD that as its start parameter.   Then the HUD fires a sensor (or llGetAgentList()) and loops through the results until it finds a uuid that generates that number.    That way you don't need to rely on communications between the HUD and the rezzer.

Why there should be a problem attaching the HUD and not a plain object I don't know (maybe the HUD is taking longer properly to rez than is the plain attachment).   But try my suggestion to see if helps -- it certainly looks, on the face of it, as it there's a race condition causing the problem. 

You might also try simply adding a 0.25 second in the rezzer script after its rezzed the HUD and before it sends the UUID.   That would be worth a try before doing anything more complex.

Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 2657 days.

Please take a moment to consider if this thread is worth bumping.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...