Jump to content

Multiple Sit Targets


Rolig Loon
 Share

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

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

Recommended Posts

I suppose others have made this discovery, but I just realized that the llLinkSitTarget function that was added late last year makes it very easy to seat several avs on the same object, in a way that I hadn't expected.  I have a simple park bench made of two sculpties (the seat is the root prim and the legs are prim 2).  I put this script in it....

default
{
    state_entry()
    {
        llSetMemoryLimit(0x4000);
        llLinkSitTarget(1,<-0.5,0.32,0.1>,llEuler2Rot(<0.0,0.0,PI/2>)); // Sit on the "seat" prim
        llLinkSitTarget(2,<0.2,0.35,0.4>,llEuler2Rot(<0.0,0.0,PI/2>)); //Sit on the "leg" prim
    }
}

and two avs can sit on the seat.  If both avs click on the same prim, the first one to sit down is always assigned to the target on that prim, and the second av is seated on the other prim.  So, if both avs click only on the "seat" prim, the first av always gets link sit target #1 and the second always gets target #2.  If both click only on the "leg" prim, then the first one is assigned to link sit target #2, and the second av gets target #1.  The thing that surprises me is that the second av is always seated on the "other" prim without having clicked that prim to sit, and that the system knows that the second av should default to the prim with the empty sit target.  As I say, others have probably already made this discovery, but I just found it and I think it's cool.  It adds a new dimension to multiple seating, not yet documented in the LSL wiki.  :smileyhappy:

 

  • Like 1
Link to comment
Share on other sites

The LSLWiki touches on this topic

http://lslwiki.net/lslwiki/wakka.php?wakka=llSitTarget    Linked Objects With Multiple Sit Targets

What is especailly nice is we can set all the sit targets from the main script and not have put in, and then take out ,sittarget scritps in all the child prims.  Hmm not sure when it would be useful but we can now even easliy change child sit targets on the fly.

Link to comment
Share on other sites

Interesting.  As I said, I was pretty sure that other people had discovered this behavior before me.  Like most people, I stopped paying any attention to that ancient wiki two or three years ago when it stopped being updated.  It does have some chatty tidbits like that one that never made it into the current wiki, though.  Thanks, Clarke. 

Now, all we need to do is get the note into the current wiki ...........  EDIT:  Done, in both llSitTarget and llLinkSitTarget.

Link to comment
Share on other sites

I didn't take much notice of the llLinkSitTarget() function until your post and then I had an AHA-WOW experience.
So I started to think about how it could be useful
It is useful if you need too sit more avatars in default sits like in a vehicle 
You can do that from a single script

But what if you want to associate different animations to different prims? 
llAvatarOnSitTarget() would require a script in each prim and that is useless if you want just one script in the object.

Luckily we have got llAvatarOnLinkSitTarget() by which we can determine from a single script which avatar is sitting on which prim
So llLinkSitTarget and llAvatarOnLinkSitTarget goes hand in hand 

What I don't know yet is this:
Will the llRequestPermissions(sitter, PERMISSION_TRIGGER_ANIMATION) give the permission implicitly?
Or will it prompt the sitter for permission? 

Link to comment
Share on other sites

To quote the LSL wiki (which is only as infallible as we make it), the catch is that "scripts may hold permissions for only one agent at a time. To hold permissions for multiple agents you must use more than one script."  If that were not so, this nice little discovery would help make some really great couples dance machines.

Link to comment
Share on other sites

I've used llLinkSitTarget() and llAvatarOnLinkSitTarget() to animate avatars on different prims.   I simply put some slave animation scripts in the root prim, along with all the animations, and use the main script there to tell them, by link message, who they should be animating and what anim to play.

The animation permissions are all granted silently, even though the avatar isn't sitting on the same prim as the script that's requesting them.

Link to comment
Share on other sites

Upon further reflection and listening to a voice from beyond, it occurs to me that from the server's perspective, an animation is a triggered event.  Once triggered, the work is being done by the client, which has received its permission in the trigger.  So it really doesn't matter how many people a script can hold permissions for at once.   When an animation like a dance is triggered as you sit, the client takes over.  After that, it assumes that it has permission to continue until you stand up.  You ought to be able to use multiple calls to llAvatarOnLinkSitTarget .

Link to comment
Share on other sites

Thanks, Rolig (and thanks, too, to the voice from beyond!).  I'd been wondering about that, too, and started doing a few tests.

To my great pleasure, I discover that, by checking who's the permission key and who I'm trying to animate, I can animate two avatars independently, and change the animations, all from the one script.

It's not thoroughly tested yet, but here's what I'm using:

 

integer handle;integer chan;integer objectPrimCount;list anims;key av1;key av2;key what_av;key toucher;string av1Old;string av2Old;string what_anim;string oldAnim;string av1Name;string av2Name;string caption;list build_anim_list(){    anims=[];    integer max=llGetInventoryNumber(INVENTORY_ANIMATION);    integer i;    while(i<max){        anims+=[llGetSubString(llGetInventoryName(INVENTORY_ANIMATION,i),0,23)];        ++i;    }    return anims;}stop_anims(key who){    if(llGetPermissions()&PERMISSION_TRIGGER_ANIMATION){        if(who==llGetPermissionsKey()){            list l = llGetAnimationList(who);            integer max=llGetListLength(l);            integer i;            while(i<max){                llStopAnimation(llList2Key(l,i));                ++i;            }        }    }}list order_buttons(list buttons){    return llList2List(buttons, -3, -1) + llList2List(buttons, -6, -4)        + llList2List(buttons, -9, -7) + llList2List(buttons, -12, -10);}default{    state_entry()    {        llLinkSitTarget(1,<0.0,0.0,0.5>,ZERO_ROTATION);        llLinkSitTarget(2,<0.0,0.0,0.5>,ZERO_ROTATION);        anims = build_anim_list();        objectPrimCount=llGetObjectPrimCount(llGetKey());        chan = (integer)(llFrand(-1000000000.0) - 1000000000.0);    }    changed(integer change){        if(change & CHANGED_INVENTORY){            anims = build_anim_list();        }        if(change & CHANGED_LINK){            objectPrimCount=llGetObjectPrimCount(llGetKey());            if(objectPrimCount==llGetNumberOfPrims()){                toucher = "";            }            if(anims!=[]){//sanity check -- make sure there's actually something to play                llListenRemove(handle);//in case someone sits down or stands up while I'm in the middle of choosing an animation                llSetTimerEvent(0.0);                if(change & CHANGED_LINK){                    key k = llAvatarOnLinkSitTarget(1);                    if(k!=av1){                        if(k){                            av1=k;                            av1Old="";                            av1Name=llGetSubString(llGetDisplayName(av1),0,23);                            what_av=av1;                            what_anim=llGetInventoryName(INVENTORY_ANIMATION,0);                            llRequestPermissions(what_av,PERMISSION_TRIGGER_ANIMATION);                        }                        else{//looks like av1 has got up                            if(av1==llGetPermissionsKey()){                                llStopAnimation(av1Old);                                av1Old="";                            }                            av1=k;                            av1Name="";                        }                    }                    k = llAvatarOnLinkSitTarget(2);                    if(k!=av2){                        if(k){                            av2=k;                            av2Old="";                            what_av=av2;                            av2Name=llGetSubString(llGetDisplayName(av2),0,23);                            what_anim=llGetInventoryName(INVENTORY_ANIMATION,0);                            llRequestPermissions(what_av,PERMISSION_TRIGGER_ANIMATION);                        }                        else{//looks like av2 has got up                            if(av2==llGetPermissionsKey()){                                llStopAnimation(av2Old);                                av2Old="";                            }                            av2=k;                            av2Name="";                        }                    }                }            }        }    }    run_time_permissions(integer permissions){        if(permissions & PERMISSION_TRIGGER_ANIMATION){            if((what_av==av1 && av1Old=="")||(what_av==av2 && av2Old=="")){                stop_anims(what_av);                llStartAnimation(what_anim);            }            else{                if(what_anim!=oldAnim){                    llStartAnimation(what_anim);                    llStopAnimation(oldAnim);                }            }            if(what_av==av1){                av1Old=what_anim;            }            else{                av2Old=what_anim;            }            if(toucher){                llSetTimerEvent(20.0);                if(llGetNumberOfPrims()==(objectPrimCount+1)){                    what_av = llGetLinkKey(llGetNumberOfPrims());                    llDialog(toucher,"Please choose an animation",order_buttons(["Finished"]+anims),chan);                }                else{                    llDialog(toucher,"Whom do you want to animate?",[av1Name]+[av2Name],chan);                }            }        }    }    touch_start(integer total_number)    {        if(llGetNumberOfPrims()>objectPrimCount){            llListenRemove(handle);            toucher = llDetectedKey(0);            handle = llListen(chan,"",toucher,"");            llSetTimerEvent(20.0);            if(llGetNumberOfPrims()==(objectPrimCount+1)){                what_av = llGetLinkKey(llGetNumberOfPrims());                llDialog(toucher,"Please choose an animation",order_buttons(["Finished"]+anims),chan);            }            else{                llDialog(toucher,"Whom do you want to animate?",[av1Name]+[av2Name],chan);            }        }    }    timer(){        llListenRemove(handle);        llSetTimerEvent(0.0);        toucher="";    }    listen(integer channel, string name, key id, string msg){        if("Finished"==msg){            llListenRemove(handle);            llSetTimerEvent(0.0);            toucher="";            return;        }        llSetTimerEvent(20.0);        if(~llListFindList([av1Name,av2Name],[msg])){            if(av1Name==msg){                what_av=av1;                oldAnim=av1Old;            }            else{                what_av=av2;                oldAnim=av2Old;            }            llDialog(toucher,"Please choose an animation",["Finished"]+anims,chan);        }        else if(~llListFindList(anims,[msg])){            string s = llGetInventoryName(INVENTORY_ANIMATION,llListFindList(anims,[msg]));            if(s!=oldAnim){//don't try to restart stuff                what_anim=s;                if(what_av==llGetPermissionsKey()){                    llStartAnimation(what_anim);                    llStopAnimation(oldAnim);                    if(what_av==av1){                        av1Old=what_anim;                    }                    else{                        av2Old=what_anim;                    }                    if(llGetNumberOfPrims()==(objectPrimCount+1)){                        what_av = llGetLinkKey(llGetNumberOfPrims());                        llDialog(toucher,"Please choose an animation",["Finished"]+anims,chan);                    }                    else{                        llDialog(toucher,"Whom do you want to animate?",[av1Name]+[av2Name],chan);                    }                }                else{                    llRequestPermissions(what_av,PERMISSION_TRIGGER_ANIMATION);                }            }        }    }}

 

  • Like 1
Link to comment
Share on other sites

  • 7 years later...

Hi!
I have been trying to get two avatars to sit on a single prim (if that's possible?) or at least a single object for longer than I care to remember but it's one feat that continues to elude me. Based on Rolig's remarks and my ability to misunderstand them, I ventured to adapt a sit script I have used for years, hoping to crack this puzzle at last. I also added two different sit animations to the object. Whether it was a single prim or two linked prims, I'm getting nowhere. The first avatar sits successfully using the first pose in the inventory, but the second avatar to try to sit actually does the basic sit, ignoring the second animation in the object.

Can anyone diagnose where I'm going wrong please? Script I have evolved so far is below: (thank you!)

 

//*************************************

key agent;
key sitter;
string pietext="Enter";

//*************************************

default
{
    state_entry()
    {

         llLinkSitTarget(1,<-0.5,0.32, 0.65>,llEuler2Rot(<0.0,0.0,PI/2>));
         llLinkSitTarget(0,<0.2,0.35,0.4>,llEuler2Rot(<0.0,0.0,PI/2>));
    }

    changed(integer n)
    {
        if(n & CHANGED_LINK)
        {
            agent=llAvatarOnSitTarget();
            if(agent!=NULL_KEY)
            {
                llRequestPermissions(agent,PERMISSION_TRIGGER_ANIMATION);
            }

        }
        if(n & CHANGED_INVENTORY)
        {
            agent=llAvatarOnSitTarget();
            if(agent!=NULL_KEY)
            {
                llUnSit(agent);
            }
        }
    }
    run_time_permissions(integer n)
    {
        llStopAnimation("sit");
        llStartAnimation(llGetInventoryName(INVENTORY_ANIMATION,0));
        llStartAnimation(llGetInventoryName(INVENTORY_ANIMATION,1));
    }
}

 

Edited by Frankie Rockett
Typos.
Link to comment
Share on other sites

It is my understanding that it is impossible to get two agents to sit on one prim/object. You must have an equal or greater number of prim/objects in a linkset to the number of sitters because the agent is being added to the linkset. You cannot add two agents to one prim because the agent is a temporary link in the linkset, the second agent cannot be linked to the first and the first is already linked to the prim.

I may be wrong here, I am not a professional scripter, though I do know some of the "rules" of the system and remember this being one of those rules: simplified paraphrasing is "all agents must have their own prim to sit on."

Link to comment
Share on other sites

1 hour ago, Alyona Su said:

It is my understanding that it is impossible to get two agents to sit on one prim/object. You must have an equal or greater number of prim/objects in a linkset to the number of sitters because the agent is being added to the linkset. You cannot add two agents to one prim because the agent is a temporary link in the linkset, the second agent cannot be linked to the first and the first is already linked to the prim.

I may be wrong here, I am not a professional scripter, though I do know some of the "rules" of the system and remember this being one of those rules: simplified paraphrasing is "all agents must have their own prim to sit on."

It's more of a "yes and no." You can have multiple avatars sit on a single prim (try stretching a cube), but you can't have multiple sit-targets for a single prim.

That said, you don't need a sit-target to move/rotate an avatar, you can treat the avatar as a regular link in that aspect. The problems arise when the object is a weird shape (or inside another solid object where you'll get the "no room to sit here" error) and you won't be able to sit on the object at all without a sit-target.

Link to comment
Share on other sites

31 minutes ago, Wulfie Reanimator said:

It's more of a "yes and no." You can have multiple avatars sit on a single prim (try stretching a cube), but you can't have multiple sit-targets for a single prim.

That said, you don't need a sit-target to move/rotate an avatar, you can treat the avatar as a regular link in that aspect. The problems arise when the object is a weird shape (or inside another solid object where you'll get the "no room to sit here" error) and you won't be able to sit on the object at all without a sit-target.

Ahah! Thank you for this description. I always knew that "it couldn't be done" - I've never known about the "except in the case of..."  :) Thank you.

Link to comment
Share on other sites

43 minutes ago, Frankie Rockett said:

So, assuming I have 2 linked prims and not one, what's wrong with my code example such that I can't get the 2nd avatar to sit AND have the 2nd pose/animation asigned to him like the 1st one has?

Thanks!

I've not studied your code in detail, so this may not be the only issue, but try changing your lines in state_entry() to 

       llLinkSitTarget(2,<-0.5,0.32, 0.65>,llEuler2Rot(<0.0,0.0,PI/2>));
       llLinkSitTarget(1,<0.2,0.35,0.4>,llEuler2Rot(<0.0,0.0,PI/2>));

or vice-versa.   At the moment you're trying to set a sit target for prim 0, which doesn't exist -- link numbers start at 1 (the root prim) in multi-prim objects.  A link number of 0 refers to an unlinked prim.

Link to comment
Share on other sites

1 hour ago, Frankie Rockett said:

So, assuming I have 2 linked prims and not one, what's wrong with my code example such that I can't get the 2nd avatar to sit AND have the 2nd pose/animation asigned to him like the 1st one has?

Thanks!

Sorry, I should've addressed you too.

Firstly, in the run_time_permissions event, right now you're just starting one animation and then the next. A single script can only hold animation permissions for one avatar at a time, so you'd have to either request permission to animate each avatar on llAvatarOnLinkSitTarget before playing their respective animations, or you'd need a second script to control the other sitter.

Secondly, like Innula pointed out, you need to set the sit targets for links 1 and 2, not 0 and 1 as they are technically the same prim.

Thirdly, in the changed event, the script is only checking for one avatar to unseat. If there are two avatars sitting on the object, only one of them (the last to sit, I believe) will be detected and unseated.

Link to comment
Share on other sites

3 hours ago, Wulfie Reanimator said:

It's more of a "yes and no." You can have multiple avatars sit on a single prim (try stretching a cube), but you can't have multiple sit-targets for a single prim.

Yes. And FWIW, when I was experimenting years ago, I found that a single prim that would seat multiple avatars would not do so once it had a sit target set.

Also, as you rightly point out, the sit target is optional anyway for "normal" seats as long as there's a path for the avatar to get to the seat. As I recall, camming-in to sit on some remote prim in a closed room really only works with sit target-equipped seats. I also recall the probability of success for non-sit target seats was a function of camera position and angle as well as which surface of the prim was clicked to initiate the sitting, so some folks would sit effortlessly while others would try and try without success. (This all was attributed to some Havok woo I never tried to understand.)

Link to comment
Share on other sites

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

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

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...