Jump to content
You are about to reply to a thread that has been inactive for 134 days.

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

Recommended Posts

Posted

I've noticed that some objects (for example a six-pack of beer) can directly attach their inventory item (a bottle of beer)  onto the user rather than dropping it into a user's inventory using 'llGiveInventory' and having to have them manually attach the item. I'm guessing(emphasis on guessing) that the function 'llAttachToAvatarTemp' is used, but I'm unsure what the mechanics are for transferring an item from an object's inventory to a user would be. 

In my situation, the object giving an item is using this script to give the user an item with 'llGiveInventory':

default
{
    state_entry()
    {
    }

    link_message(integer l, integer n, string t, key id)
    {   if(n != -2000) return;
        if(llSubStringIndex(t,"giveinv ") == 0)
        {   llGiveInventory(id, llStringTrim(llGetSubString(t,7,-1),STRING_TRIM));
        }
    }
}

 

 

 

Posted

Right, llAttachToAvatarTemp is how it's done most transparently but it still requires permission. One way that permission may already be granted is through an Experience, and one Experience in which many avatars are already participants is AVsitter (the one by Code Violet), which has its own free open source mechanism of managing temp attachments, which are called "PROP1" items in that system documentation.

It's not that hard to roll your own, too, if your recipients will already be enrolled in your Experience, or if they won't mind being asked to grant permissions. I think  The llAttachToAvatarTemp() wiki page has some sample code that may get you started.

  • Like 1
Posted
On 7/24/2024 at 3:38 PM, Qie Niangao said:

Right, llAttachToAvatarTemp is how it's done most transparently but it still requires permission. One way that permission may already be granted is through an Experience, and one Experience in which many avatars are already participants is AVsitter (the one by Code Violet), which has its own free open source mechanism of managing temp attachments, which are called "PROP1" items in that system documentation.

It's not that hard to roll your own, too, if your recipients will already be enrolled in your Experience, or if they won't mind being asked to grant permissions. I think  The llAttachToAvatarTemp() wiki page has some sample code that may get you started.

Following your tip and with the help of chatGPT I re-wrote the script as follows:

default
{
    state_entry()
    {
    }

    link_message(integer sender_num, integer num, string str, key id)
    {   
        if (num != -2000) return;
        
        if (llSubStringIndex(str, "giveinv ") == 0)
        {   
            llSay(0, "One Shot coming up!");
            string item_name = llStringTrim(llGetSubString(str, 7, -1), STRING_TRIM);
            integer item_type = llGetInventoryType(item_name);
            
            if (item_type == INVENTORY_OBJECT)
            {
                // Rez the object near the avatar
                vector rez_pos = llGetPos() + <0, 0, 1>; // Rez 1 meter above the prim
                rotation rez_rot = llGetRot();
                
                // Set the owner key in a global variable in the rezzed object
                string previous_desc = llGetObjectDesc();
                llSetObjectDesc((string)id); // Temporarily set the description to the user key
                
                llRezObject(item_name, rez_pos, ZERO_VECTOR, rez_rot, 0);
                
                llSetObjectDesc(previous_desc); // Restore the original description
            }
            else
            {
                llSay(0, "The item is not an object and cannot be attached.");
            }
        }
    }
}

And then the following script for the inventory item being given:

default
{
    state_entry()
    {
        // Do nothing here initially
    }
    
    on_rez(integer start_param)
    {
        // Retrieve the owner key from the description field
        key owner_id = (key)llGetObjectDesc();
        llRequestPermissions(owner_id, PERMISSION_ATTACH | PERMISSION_TRIGGER_ANIMATION);
    }
    
    run_time_permissions(integer perm)
    {
        if (perm & PERMISSION_ATTACH && perm & PERMISSION_TRIGGER_ANIMATION)
        {
            // Attach to the avatar at the desired attachment point
            llAttachToAvatarTemp(ATTACH_RHAND); // Change ATTACH_CHEST to desired attachment point
            
            // Play the "hold" animation
            llStartAnimation("hold");
        }
    }

    attach(key id)
    {
        if (id == NULL_KEY)
        {
            // Stop the animation when the object is detached
            llStopAnimation("hold");
        }
    }
}

And it seems to work except I get the following error message:

Quote

Script trying to stop animations but PERMISSION_TRIGGER_ANIMATION permission not set

And I'm not sure why or how to fix the script.

Posted (edited)

Presumably it's coming from the detach event (the one llStopAnimation call) which can be addressed by checking

  • llGetPermissions() & PERMISSION_TRIGGER_ANIMATION

If the thing detaches and that condition isn't true, I don't think there's anything more you can do to make sure the animation stops besides hope the viewer does the right thing about anims started by detached objects.

Off the top of my head, I don't think the following would be necessary for a detaching attachment, but for completeness the additional guards on animation permission errors are:

  • llGetPermissionsKey() == <avatar id>
    which in this case would test llGetOwner() as the <avatar id> and I don't see how that would fail in a detaching temp attachment, and
  • ZERO_VECTOR != llGetAgentSize(<avatar id>)
    to make sure the avatar is still in the region to have animations started or stopped, which again seems would be the case for a detaching attachment

(I haven't looked in detail at the rest, so please come back if there are other questions. To be honest, I was a little surprised you didn't take the AVsitter approach, but I can sure appreciate that Experiences aren't universally appreciated by visitors.)

Edited by Qie Niangao
Posted
12 hours ago, Qie Niangao said:

To be honest, I was a little surprised you didn't take the AVsitter approach, but I can sure appreciate that Experiences aren't universally appreciated by visitors

To your point about using Experiences to handle permissions, count me an advocate, yes - but, I followed your link to the AVsitter page explaining how to use AVsitter in that capacity and to be honest, I'm just not that capable a scripter of being able to follow their instructions and examples and to implement the approach for myself. 

Whole parts of LL scripting really cause me confusion, even basic stuff like llMessageLinked() and link_message() can make my head spin when you've got scripts on multiple channels funneling data from various inputs being conditionally filtered and then re-outputted. So, I do a lot of perusing on this forum - and thank you guys/gals who take the time to clarify some of this stuff.

In any case, the error actually arises when the item is rezzed or attached (TBH, I don't understand exactly what goes on in the process of transferring an item from an object's inventory to an avatar - it seems it's a much more complex series of events than merely depositing an item in an avatar's inventory - it's first rezzed by the script in the object sending the item then made to attach to the avatar by a script in that item?) And while the item does get attached the animation doesn't play and that error message appears. 

If i just attach the item to myself from my own inventory (with my UID manullay entered into the item's description) it works great. As does the de-attach script when the item is touched ( I did not include that script in this posting, would it help to see that?).

And, lastly, I'm unsure of how your two proposals should be implemented or exactly where.

Posted

Just to add confusion, I forgot that the attach() event does not get called when a temp-attached object is detached, unlike normal non-temp attachments, so if that's the only place llStopAnimation is called, something else is going on. I can make up a story that the script is processing an event from when it was previously non-temp attached and detached, but I do wonder if the "touch to detach" script might have that llStopAnimation in it somewhere it can trigger without permissions in the temp-attach scenario, so yeah, maybe good to see that script.

Meanwhile, just to clarify what I was saying before, I was proposing to augment the attach() handler something like:

    attach(key id)
    {
        if ((id == NULL_KEY) && (llGetPermissions() & PERMISSION_TRIGGER_ANIMATION))
        {
            // Stop the animation when the object is detached
            llStopAnimation("hold");
        }
    }

… but that no longer even seems likely to be the llStopAnimation causing this permissions error.

You're absolutely correct that it's more complicated for a script to attach stuff to an avatar than to just give that stuff to their inventory. I still haven't tested this code or looked at it in detail, but I think it's got a bug with the attachment knowing to whom it should attach. It appears to be looking at its own description, not that of the object that rezzed it which is where you recorded the intended recipient's UUID—but that's not going to work as-is anyway because it immediately switches that back to the previous description, before the rezzed attachment would have time to fetch it. So we'll need to fix that, too. (There's a new function, llRezObjectWithParams() with an argument REZ_PARAM_STRING that makes this much easier than before—if it works. I haven't tested it on the main grid yet and I recall there were delays in rolling it out, so… not 100% sure it's ready yet.)

Posted

Here's the de-attach on touch script:

key owner;

default
{
    state_entry()
    {
        owner = llGetOwner();
    }
    touch_start(integer total_number)
    {
        key toucher = llDetectedKey(0);
        if(llGetAttached() && toucher == owner)
        {
            llRequestPermissions(toucher,PERMISSION_ATTACH);
        }
    }
    attach(key id)
    {
        if(id)
        {
            llResetScript();
        }
    }
    run_time_permissions(integer perm)
    {
        if(perm & PERMISSION_ATTACH)
        {
            llDetachFromAvatar();
        }
    }
}

Now, it's absolutely not imperitive that the Item description be switched back to some previous description - in fact I htought about removing that aspect as unnecessarily complicating the script. It was, actually, chatGPT which added the switch. So, I'll remove that bit and see what impact that has and report back. Thanks for the tip.

Posted
2 hours ago, Qie Niangao said:

It appears to be looking at its own description, not that of the object that rezzed it which is where you recorded the intended recipient's UUID—but that's not going to work as-is anyway because it immediately switches that back to the previous description, before the rezzed attachment would have time to fetch it. So we'll need to fix that, too

I removed the lines injecting the switch action and still receive the error message:

Script trying to trigger animations but PERMISSION_TRIGGER_ANIMATION permission not set

To clarify, the error is reporting a problem with trying to 'trigger' the animation and not as a result of llStopAnimation() function correct? I did add your augmentation to tghe attach() script but receive the same damn error: Script trying to trigger animations but PERMISSION_TRIGGER_ANIMATION permission not set

Posted

Just because, I separated the two permission requests into two attach() scripts and, of course, get two dialogues requesting permissions to either animate pose or attach the item and NO error message. Yay! Except the animation does not play. The animation is full perm. So now I'm utterly confused and wonder how anyone gets anything scripted in SL without getting high blood pressure.

Posted

Okay, I finally got in-world to check out some stuff. First, unfortunately, that new REZ_PARAM_STRING parameter doesn't work yet (nor does the function to access it, llGetStartString), so we'll need to stick with one of the old ways of communicating the target avatar key from the rezzer to the object being attached. So we can stick with using the rezzer's object description and just not changing it back right away. (That works fine as long as a new request doesn't come so quickly that an earlier target gets replaced by a new one before the first rezzed object reads its target; if that happens, the first avatar will miss their attachment and the next will get two.)

We do, however, need to get it to attach to the right target, and the rezzer can only change its own description but the above attachment code uses its description so that doesn't get communicated. So instead of:

21 hours ago, Hawthorne Gray said:
        // Retrieve the owner key from the description field
        key owner_id = (key)llGetObjectDesc();

we need something like:

        // Find out which object rezzed us:
        key rezzer = llList2Key(llGetObjectDetails(llGetKey(), [OBJECT_REZZER_KEY]), 0);
        // Retrieve the target avatar key from the rezzer's description field:
        key owner_id = (key)llList2Key(llGetObjectDetails(rezzer, [OBJECT_DESC]), 0);

I'm not sure why this should fix the permissions error, but you're certainly correct that the message about "trying to trigger animations" isn't coming from calling llStopAnimation(), which would have triggered the previously reported message about "trying to stop animations". I think I'll just plow ahead and see what errors you get after the above change, and after we address:

3 hours ago, Hawthorne Gray said:

get two dialogues requesting permissions to either animate pose or attach

which is too annoying, so let's roll in that touch-to-detach functionality into the attachment script which already gets the right permissions. For now, let's keep it simple and just add a touch_start handler:

    touch_start(integer total_number)
    {
        key toucher = llDetectedKey(0);
        if ((llGetPermissionsKey() == toucher)
            && (llGetPermissions() & PERMISSION_ATTACH))
        {
            llDetachFromAvatar();
        }
        // else we'll just ignore the touch
    }

and remove the de-attach script completely.

Now… let's see how it behaves with these changes. (It's working on my testbench.) I'd just mention that you probably want to eventually make the attachment object temporary so they don't accumulate around the rezzer for those who reject the permissions—and those who accept the permissions but have no remaining attachment slots. That latter condition is special because at that point the unattached object belongs to the intended wearer so they can Take it into inventory, something they can't do with temp-attached objects.

Also, another caution here: while the object is attached, the wearer can copy stuff out of the object into their inventory, so a full-perm animation could leak unless its next-owner permissions have been set appropriately. (This is a whole hairy problem for embedding animated attachments in products for sale because the buyer wants to be able to transfer those animated attachments to users of the product they bought—the next next owner from the attachment's creator. I'm hoping this project either isn't for product distribution or this animation has no end-user license restrictions; otherwise the spooky "slam bit" awaits.)

Posted

wow ok you have handed me a whole lot to work with and also noted a problem about rezzing and changing the description correctly - which you are right, doesn't work correctly presently . I will play aorund with this and get back to you @Qie Niangao - thank you.

  • Like 1
Posted (edited)

So, this is the attach()  script I came up with and it only will razz object but will not attach it.

default
{
    state_entry()
    {
      
    }
    
    on_rez(integer start_param)
    {      
        // Retrieve the owner key from the description field
        // Find out which object rezzed us:
        key rezzer = llList2Key(llGetObjectDetails(llGetKey(), [OBJECT_REZZER_KEY]), 0);
        // Retrieve the target avatar key from the rezzer's description field:
        key owner_id = (key)llList2Key(llGetObjectDetails(rezzer, [OBJECT_DESC]), 0);
        llRequestPermissions(owner_id, PERMISSION_TRIGGER_ANIMATION);
       
    }
    
    run_time_permissions(integer perm)
    {
        if (perm & PERMISSION_TRIGGER_ANIMATION && perm & PERMISSION_ATTACH)
        {
            // Play the "hold" animation
            llStartAnimation("hold");
             // Attach to the avatar at the desired attachment point
            llAttachToAvatarTemp(ATTACH_RHAND);
        }
    }

   attach(key id)
    {
        if ((id == NULL_KEY) && (llGetPermissions() & PERMISSION_TRIGGER_ANIMATION))
        {
            // Stop the animation when the object is detached
            llStopAnimation("hold");
        }
    }
    touch_start(integer total_number) 
    {
        key toucher = llDetectedKey(0);
        if ((llGetPermissionsKey() == toucher)
            && (llGetPermissions() & PERMISSION_ATTACH))
        {
            llDetachFromAvatar();
        }
        else { llSay(0, "nope");}
        // else we'll just ignore the touch
    }
}

I also inserted the llDetachFromAvatar() action into the script.

 

I will note: the key of the avatar to whom the inventory is suppposed to be transfered to,  does get filled properly with that avatar's key. 

Edited by Hawthorne Gray
You are about to reply to a thread that has been inactive for 134 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
×
×
  • Create New...