Jump to content

stop animations after standing


Steffan Mielziner
 Share

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

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

Recommended Posts

I have an object that I put some dance animations into.  The files are named like so:   <dance_name>;<length_in_seconds>

I want the avie to be able to sit/dance, continually play each animation to its length, move on to the next dance, then continually loops back to whatever the first animation is.

So, THAT part seems to work OK.  What doesn't work is getting the animations to stop once the avie stands.  Even after telling the Avater Health to Stop Animations in the client, the next dance will kick in after the sleep timeout.

What am I doing wrong here?

Thanks,

Steff

string danceFileName;
integer dancing;

start_dancing() {

    integer totalDances = llGetInventoryNumber(INVENTORY_ANIMATION);
    integer currentDanceNum = 0;
    dancing = 1;
    
    while( dancing ) {
    
        danceFileName = llGetInventoryName(INVENTORY_ANIMATION, currentDanceNum);
        list danceFileNameTokens = llParseString2List(danceFileName, [";"], []);
        string danceLength = llList2String( danceFileNameTokens, 1 );
        llStartAnimation(danceFileName);
        llSleep( (float) danceLength );
        llStopAnimation(danceFileName);
    
        currentDanceNum = currentDanceNum + 1;
        if (currentDanceNum == totalDances) {
            currentDanceNum = 0;
        }
    }

}


default {

    state_entry() {
        llSetSitText("Dance");
        llSitTarget(<0.0, 0.0, 1>, ZERO_ROTATION);
    }
 
    changed(integer change) {
        if (change & CHANGED_LINK) {
            key av = llAvatarOnSitTarget();
            if (av) {
                llRequestPermissions(av, PERMISSION_TRIGGER_ANIMATION);
            } else {
                if (danceFileName) {
                    llStopAnimation(danceFileName);
                }
                dancing = 0;
                llResetScript();
            }
        }
    }
 
    run_time_permissions(integer perm) {
        if (perm & PERMISSION_TRIGGER_ANIMATION) {
            llStopAnimation("sit");
            start_dancing();
        }
    }
}


 

Link to comment
Share on other sites

The big problem  is that you never do anything to stop the animations.    Your user function start_dancing sets dancing to TRUE and then enters an infinite loop, while (dancing), which is always going to evaluate as TRUE because nothing can make it FALSE.

There's an additional potential problem, in that since you cause the script to sleep for the length of each animation, even when you fix the main problem, the script isn't going to be able to do anything until the clip that it's playing has finished.

If I were writing this, I would get rid the llSleep call and using a timer, instead.  (always a good idea, to my mind, if you find you're putting the script to sleep for any longer than 0.5 seconds or so).

So, in the changed event, if there's an avatar sitting on the object, I would ask for animation permissions and then, in the run_time_permissions event, I would start the first animation and set a timer for the length of that animation.

Then in the timer event, I would step through my animation list, starting a new timer for each clip, and then go back to the start, as you do in the user function.

To stop the dancing when the avatar gets up, simply call llStopAnimation in the changed event if there isn't anyone sitting on the prim any more, and then stop the timer.

 

Edited by Innula Zenovka
Link to comment
Share on other sites

11 minutes ago, Love Zhaoying said:

Once an avatar stands, (since you said it is a poseball) the animations are no longer controlled by the script.  However, the animation keeps running because you did not tell it to stop.

Non-poseball dance (whether a "sign", big ball in the sky, or a hud to click) machines handle this by having a menu option the user clicks to "STOP".  (The user had already given permission to animate, so "stop" doesn't ask for permission again but stops all animations that the script had run.)

I fear that your users have no option but to select "stop all animations/stop animating me" from the viewer menu.  If they have an AO, the next AO cycle should stop the animation also. You can also consider an option to "click the ball" to stop dancing once they got off of it (similar to STOP menu item for a non-sitting/non-poseball dance machine).

 

I think it's worse than that.   The script keeps its animation permissions unless it's told to release them (or the script is reset).

Normally that wouldn't be a problem since, as you say, the avatar's AO is going to start playing a stand or walk animation as soon as the dancer gets up, and most animation scripts won't try to do anything to the former sitter after she's stood, even if they don't explicitly stop the animation.

However, since the start_dancing() user function never gets told to stop, I think what's likely to happen is that the script is going to keep on animating the avatar for as long as she's on the same region, or until someone else sits on the prim.   Even then, though, because of the llSleep(), the script isn't going to know about the next sitter until the end of the current animation, so I suspect the second sitter is probably going to get up again before anything starts and then be surprised to find herself animated some 10 seconds or so later.

 

 

  • Like 3
Link to comment
Share on other sites

 

The wiki suggests a little trick too...

Quote

if you must stop a looped animation, playing a single frame non-looped one immediately after stopping it, at low priority, will clear the list.

 

so something like...

  llStopAnimation(danceFileName);
  llStartAnimation("b43c9176-112c-944f-33fa-da2d275a9ac");
  llStopAnimation("b43c9176-112c-944f-33fa-da2d275a9ac");

 the UUID is one i have for a blank anim,  from MP

Blank Animation-Zero priority

 

Edited by Xiija
Link to comment
Share on other sites

While you can stop animations by using either the name of the animation or its uuid, you can call them only by name.   I think llStartAnimation("b43c9176-112c-944f-33fa-da2d275a9ac"); is going to trigger a script error message complaining it can't find an animation called "b43c9176-112c-944f-33fa-da2d275a9ac".

When I want to stop a looped animation like that, I use the built-in system animations, which you can call by name without having them in the objects's inventory.    So I call llStartAnimation("stand"); when the avatar stands up.    If the avatar is using an AO, then the AO will kick in almost immediately and cancel "stand" (which is priority 0, so it's as low as it gets).   If not, at least the avatar is standing rather than stuck in the looped animation.

  • Like 2
Link to comment
Share on other sites

Thank you Innula and Love for the detailed reply.  With your help, I finally got it working.  I think in my brain I'm mixing up procedural code with event driven scripting.

For completeness, here is what I ended up with:

string danceFileName;
integer currentDanceNum;
integer totalDances;

default {

    state_entry() {
        currentDanceNum = 0;
        totalDances = llGetInventoryNumber(INVENTORY_ANIMATION);
        llSetSitText("Dance");
        llSitTarget(<0.0, 0.0, 1>, ZERO_ROTATION);
    }
    
    timer() {
        llStopAnimation(danceFileName);
        llSetTimerEvent(0.0);
        currentDanceNum = currentDanceNum + 1;
        if (currentDanceNum == totalDances) {
            currentDanceNum = 0;
        }
        danceFileName = llGetInventoryName(INVENTORY_ANIMATION, currentDanceNum);
        list danceFileNameTokens = llParseString2List(danceFileName, [";"], []);
        string danceLength = llList2String( danceFileNameTokens, 1 );
        llStartAnimation(danceFileName);
        llSetTimerEvent((float)danceLength);
    }
 
    changed(integer change) {
        if (change & CHANGED_LINK) {
            key av = llAvatarOnSitTarget();
            if (av) {
                llRequestPermissions(av, PERMISSION_TRIGGER_ANIMATION);
            } else {
                if (danceFileName) {
                    llStopAnimation(danceFileName);
                }
                llSetTimerEvent(0.0);
                llResetScript();
            }
        }
    }
 
    run_time_permissions(integer perm) {
        if (perm & PERMISSION_TRIGGER_ANIMATION) {
            llStopAnimation("sit");
            danceFileName = llGetInventoryName(INVENTORY_ANIMATION, currentDanceNum);
            list danceFileNameTokens = llParseString2List(danceFileName, [";"], []);
            string danceLength = llList2String( danceFileNameTokens, 1 );
            llStartAnimation(danceFileName);
            llSetTimerEvent((float)danceLength);
        }
    }
}

 

  • Like 1
Link to comment
Share on other sites

There seems to be one minor bug left in this, if an avie doesn't stand before logging off, I get:  llStopAnimation: Script trying to stop animations but agent not found

Is there a good way to ask if anyone is still dancing on the animation or if the user is still online before trying to stop?

I was thinking about trying to use llRequestAgentData with DATA_ONLINE, but then I noticed that this seems to be unresolved https://jira.secondlife.com/browse/SVC-6831?

suggestions?

Thanks,  -Steff

Link to comment
Share on other sites

One of the easiest things to do is to ask
 

if (llGetAgentSize(agent_UUID) != ZERO_VECTOR)

{

    llStopAnimation(my_animation);

}

If the avatar is anywhere in the region, the script will stop the animation.  Otherwise, it won't even try.

  • Like 2
Link to comment
Share on other sites

Awesome.  Thank you Rolig!

this seems to work flawlessly:

string danceFileName;
integer currentDanceNum;
integer totalDances;
key currentAvatarKey;

default {

    state_entry() {
        currentDanceNum = 0;
        totalDances = llGetInventoryNumber(INVENTORY_ANIMATION);
        llSetSitText("Dance");
        llSitTarget(<0.0, 0.0, 1>, ZERO_ROTATION);
    }
    
    timer() {
        llStopAnimation(danceFileName);
        llSetTimerEvent(0.0);
        currentDanceNum = currentDanceNum + 1;
        if (currentDanceNum == totalDances) {
            currentDanceNum = 0;
        }
        danceFileName = llGetInventoryName(INVENTORY_ANIMATION, currentDanceNum);
        list danceFileNameTokens = llParseString2List(danceFileName, [";"], []);
        string danceLength = llList2String( danceFileNameTokens, 1 );
        llStartAnimation(danceFileName);
        llSetTimerEvent((float)danceLength);
    }
 
    changed(integer change) {
        if (change & CHANGED_LINK) {
            key requestingAvatarKey = llAvatarOnSitTarget();
            if (requestingAvatarKey) {
                llRequestPermissions(requestingAvatarKey, PERMISSION_TRIGGER_ANIMATION);
                currentAvatarKey = requestingAvatarKey;
            } else {
                if (llGetAgentSize(currentAvatarKey) != ZERO_VECTOR) {
                    llStopAnimation(danceFileName);
                }
                llSetTimerEvent(0.0);
                llResetScript();
            }
        }
    }
 
    run_time_permissions(integer perm) {
        if (perm & PERMISSION_TRIGGER_ANIMATION) {
            llStopAnimation("sit");
            danceFileName = llGetInventoryName(INVENTORY_ANIMATION, currentDanceNum);
            list danceFileNameTokens = llParseString2List(danceFileName, [";"], []);
            string danceLength = llList2String( danceFileNameTokens, 1 );
            llStartAnimation(danceFileName);
            llSetTimerEvent((float)danceLength);
        }
    }
}

 

Edited by Steffan Mielziner
  • Like 1
Link to comment
Share on other sites

1 hour ago, stepfordbride said:

Go to Avatar on the top of the Screen go to Avatar health and then  sop avatar animation.

 

That's fine, except when you are looking for a scripted solution that will keep the next owner from having to do that.  ;)

  • Like 1
Link to comment
Share on other sites

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