Jump to content

How to use llAvatarOnLinkSitTarget


Kayaker Magic
 Share

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

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

Recommended Posts

I'm trying to use the new llLinkSitTarget and llAvatarOnLinkSitTarget to decrease the number of scripts in a build. I have a row of theater seats that is linked into one build, and currently each child seat prim has its own script. This is because llSitTarget only sets the position and llAvatarOnSitTarget only returns the id of the avatar sitting on the calling prim. The two new functions look like they will allow me to manage all the child prim seats from a single script in the root.

I can call llLinkSitTarget in a loop to set all the seats up.

When changed() happens, I can search through all the child prims and ask llAvatarOnLinkSitTarget which seat has someone sitting on it. I have to keep a list of seated avatars so I know when one of the prims acquires or looses a sitter.

Once I know the key of a newly sat avatar, I can llRequestPermissions to animate that particular avatar.

But then I run into a problem:

run_time_permissions does not tell me WHICH avatar I just got permission to animate and llStartAnimation doesn't give me an option to specify which of them to animate. llRequestPermissions only seems to remember the permissions for one avatar at a time and calling it again releases previous permissions (according to the Wiki) and apparently also releases the previous avatar at the same time. Each script seems to have its own copy and only one copy of the currently granted permissions and avatar, so the only way to do what I want is to have one script per prim, which is how I did it before the new LinkSitTarget functions.

Is my analysis correct? Is there some other way to use the new LinkSitTarget functions?

 

Link to comment
Share on other sites

You can use llGetPermissionsKey to learn who is holding the permissions grant right now.

You can use llDetectedKey on a touch event, or a listen key, to learn who last asked for an animation change, and run llReuqestPermissions against that key to change their poses.

Sometimes it can be easier to skip the llAvatarOnSitTarget stuff and instead loop backwards through the prims, and check something like llGetAgentSize to detect and count the avatars.

Link to comment
Share on other sites

Your analysis looks correct.
The only new thing I see is that you can have all scripts in the root prim.
A script can not hold more than one permission, so you will still need one script per permission.

The advantage of having all scripts in the root is that all scripts can use the animations contained in the root,
you don't need a set of animations in each prim.

Link to comment
Share on other sites

Would something like this work,. on the argument that the link number of whoever last sat down will always equal llGetNumberOfPrims()?

I've not tested this, and I have no idea how you would stop the animations when people get up (if that's necessary), but off the top of my head it might work.

 

list have_permissions;//Gets the link number of a seated avatar// useful snippet from http://wiki.secondlife.com/wiki/LlAvatarOnSitTargetinteger GetAgentLinkNumber(key avatar){	integer link_num = llGetNumberOfPrims();	while (link_num > 1) // Check only child prims.	{		if (llGetLinkKey(link_num) == avatar) // If it is the avatar we want		{			return link_num; // then return the link number		}		--link_num; // else go on with next child.	}	// Avatar wasn't found	return FALSE; // 0 (zero) for easy testing.}default{	state_entry()	{		//llSay(0, "Hello, Avatar!");	}	changed(integer change)	{		if (change & CHANGED_LINK){			key k = llGetLinkKey(llGetNumberOfPrims());			integer max = llGetListLength(have_permissions);			if(max){				while(max--){					if (GetAgentLinkNumber(llList2Key(have_permissions,max))==FALSE){//someone must have got off						have_permissions = llDeleteSubList(max,max);// forget about them					}				}			}			if(llGetAgentSize(k)!=ZERO_VECTOR){// it's an avatar				if(!~llListFindList(have_permissions,[k])){//and not one we have, or have had, permissions for					llRequestPermissions(k,PERMISSION_TRIGGER_ANIMATION);// so rectify that				}			}		}	}	run_time_permissions(integer permissions)	{		if (permissions & PERMISSION_TRIGGER_ANIMATION){			have_permissions+=[llGetPermissionsKey()]; // add them to the list			//do animation stuff		}	}}

 

Link to comment
Share on other sites

The newly-seated avatar is always the highest-numbered link in the linkset, so you can always get its UUID from

llGetLinkKey(llGetNumberOfPrims())

Unless each sit target is meant to have a unique animation associated with it, it really doesn't matter which prim the new arrival sat on. Just use that newly-acquired UUID to llRequestPermissions and trigger the animation.  A script can only handle one avatar's permissions at a time, but you only need the permission to trigger the animation.   Once it's going, it doesn't make any difference that the script may have turned its attention to a different seated av.  The only time it gets a little tricky is if one of the seated avs needs permission to change animations or do something else.  If that happens, you use a touch_start event to trigger a new permission request for that av.

BTW, there's a note in the wiki entry for llLinkSitTarget that you might find helpful ...

If an object has multiple seats (each seat has a script that sets a sit target with llSitTarget, or the linkset has a script that assigns several llLinkSitTargets), the following method determines which sit target an avatar ends up at:

  • If the prim that is clicked on has a sit target and that sit target is not full, that sit target is used.
  • If the prim that is clicked on has no sit target, and one or more other linked prims have sit targets that are not full, the sit target of the prim with the lowest link number will be used.
Link to comment
Share on other sites

... and if there are sit targets set in the linkset and all of them are full, the avatar may or may not be seated at all, in no pattern I've been able to detect.

Another old-time mystery, related to this: "A script can only handle one avatar's permissions at a time, but you only need the permission to trigger the animation.   Once it's going, it doesn't make any difference that the script may have turned its attention to a different seated av. " In the past, it's been common practice for poseball and other animation scripts to try to llStopAnimation() when an avatar stands from the object that animated them, and for that the script would still need permission. I think this is superstitious (or obsolete?), and that simply standing from the object removes all animations triggered by scripts in the object, but I'd be very interested to learn circumstances where it's actually useful in helping to prevent stuck animations.

We know animations can be stuck even with llStopAnimation() -- it's not as if it's reliably transmitted or anything. If the avatar has left the sim already, e.g., teleported out while still seated, the script would err if it tried to stop the animation, and this seems to be to most common way of getting stuck. But maybe there are others that are somehow helped by llStopAnimation().

Link to comment
Share on other sites

As I recall, llStopAnimation is, or can be,  useful if the script has been playing a looping animation of priority 4 and the avatar's AO wants to play a stand or walk animation of a lower priority.   

There's an oddity with this, though, that I would need to test.   From memory, you need not just to call llStopAnimation but also actually explicitly to start another animation (e.g. the default stand), otherwise it tends not to work.    We explored this ages ago, in the old, old Scripting Forum when I found I couldn't stop an animation; I'd have to look out the details or look at one of my scripts when I get in world (it's not something I come across very often because my business partner makes all our animations and she very rarely finds a need to use priority 4 for anything).

Link to comment
Share on other sites

I think things have changed subtlely in recent times, because it has been a while since I had to issue a llStopAnimation as an avatar left a sit target.  The permission seems to be released automatically, although I know this was not always the case in the past.  It certainly makes life easier if we don't need to keep track of which avatar is sitting where, and it keeps users from getting those annoying messages about PERMISSION_TRIGGER_ANIMATION not being granted. 

Link to comment
Share on other sites

The problem comes, I think, if you're playing a looping animation when you stand up.   Something needs to stop it.   That something might be your AO, of course, but -- at least as far as I understand it -- if you've got a high priority looping animation playing when you stand up, it's likely to cause problems unless something with animation permissions stops it for you and starts to play something else.

Link to comment
Share on other sites

Yes, I can see that.  In fact, I have used a trivial looping animation that keeps the avatar's right arm angled and at waist level -- for holding a teacup, for example -- and it typically does not cancel immediately when the avatar stands.  I had forgotten that because my own AO overrides it shortly anyway, but that might not happen with all AOs.  Good point.  I wonder how serious a problem this is, though? Like your partner, I rarely have high-priority looping animations to deal with, other than the teacup one.

 

Link to comment
Share on other sites

    My Momma done raised me right! She taught me to close doors behind me! And free memory that I malloc'ed, and fclose files that I fopen'ed, and to llStopAnimation the animations that I llStartAnimation'ed! I just ASSUMED that I needed to hold onto that permission to stop the animation later! If I don't have to do that, then I can use llAvatarOnLinkSitTarget (to answer my own question) to sit all the avatars on all the seats in a build with one script and one set of animations in the inventory of one prim! Below is the script that I was able to get working after reading all the suggestions above! Each avatar is seated with an animation selected at random out of inventory. I'd like to expand this to allow touching on the seat to select one of the animations from a dialog, or randomly fidgeting by switching between the animations on a timer. I'm not sure if I can re-aquire the permission to do this, but I'll go try that next! Thanks everyone!

 

//multiple seater. One script and a set of animations in one prim//    will sit all the avatars on all the seats in a build.////  Name each of the seats in the build "Xseat"//  Put several animations in the root prim with this script//      Each time anyone sits on one of the seat prims, this script will//  sit that avatar with one of the animations at random.list IDseated;    //list of seated avatarslist LNseated;    //list of prims they are seated onvector sitpos=<-0.1,0,0.1>; //offset to make the animation look rightrotation sitrot=ZERO_ROTATION;  //rotation to put the avatar uprightstring sitname="Xseat";     //each child prim with this name becomes a seatdefault{    state_entry()    {        llOwnerSay("Set up seats");        integer i;        for (i=1;i<=llGetNumberOfPrims();i++)    //look at all the prims        {            if (llGetLinkName(i)==sitname)    //each seat prim must be named "xseat"                llLinkSitTarget(i,sitpos,sitrot);        }    }    changed(integer flags)    {        if (flags&CHANGED_LINK)    //if the link changed it must be a sit/unsit        {            integer i;            for (i=1;i<=llGetNumberOfPrims();i++)            {                if (llGetLinkName(i)==sitname)    //each seat prim must be named this                {                    key sav=llAvatarOnLinkSitTarget(i);                    if (sav!=NULL_KEY)        //is someone seated there ?                    {                        if (llListFindList(IDseated,[sav])<0)        //they are new                        {                            IDseated += [sav];        //add them to the list                            LNseated += [i];                            llRequestPermissions(sav,PERMISSION_TRIGGER_ANIMATION);    //request animations                            return;                        }                    }                    else            //no one seated here, see if they just left                    {                        integer j=llListFindList(LNseated,[i]);    //check to see if the are in the list                        if (j>=0)            //if they were in the list but unsat,                        {                   //then remove them                            IDseated = llListReplaceList(IDseated,[],j,j);                            LNseated = llListReplaceList(LNseated,[],j,j);                            return;                        }                    }                } //all the child prims named sitname            } //for all the child prims        	llOwnerSay("oops, didn't catch one!");        } //if this is a CHANGED_LINK    } //changed        run_time_permissions(integer perms)    {        if (perms&PERMISSION_TRIGGER_ANIMATION)        {           //pick an animation at random out of inventory            string anim=llGetInventoryName(INVENTORY_ANIMATION,(integer)llFrand(llGetInventoryNumber(INVENTORY_ANIMATION)));            llStartAnimation(anim);        //start the new one            llStopAnimation("sit");    //stop the default sit        }    }}

 

 

Link to comment
Share on other sites

Wow, that's a very neat piece of code:smileysurprised::):smileyvery-happy:

I can't help comparing with a job I made where I sat multiple persons on one prim
In that case neither llAvatarOnLinkSitTarget nor llAvatarOnSitTarget is of any use.
Also you can set only one llSitTarget per prim so all seated persons have to be moved and placed like child prims.

Anyway you surely have shown how to use llAvatarOnLinkSitTarget in a classy way:)

Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 4132 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...