Jump to content

Vibrating object on sit : script


ainst Composer
 Share

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

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

Recommended Posts

 Hello! I need to make an object that starts to vibrate when an avatar sits on it and it plays animation. I found such a script of vibration and animation, but how should they be combined together?

vibration

integer k;
integer flip = 1;
list params;
vector pos;
integer link = 0;
default {
    state_entry() {
        params = llGetLinkPrimitiveParams(link, [PRIM_POSITION]);
        pos = llList2Vector(params, 0);
    }
    touch_start(integer total_number) {
        if (k = !k) llSetTimerEvent(0.02+llFrand(0.1));
        else llSetTimerEvent(0.0);
    }
    timer() {
        llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_POSITION, pos + ((flip = -flip) * < 0.02, 0.01, 0.01 > )]);
    }
}

animation

string animation; // the first animation in inventory will automatically be used
  // the animation name must be stored globally to be able to stop the animation when standing up
 
default
{
    state_entry()
    {
        // set sit target, otherwise this will not work 
        llSitTarget(<0.0, 0.0, 0.1>, ZERO_ROTATION);
    }
 
    changed(integer change)
    {
        if (change & CHANGED_LINK)
        {
            key av = llAvatarOnSitTarget();
            if (av) //evaluated as true if not NULL_KEY or invalid
                llRequestPermissions(av, PERMISSION_TRIGGER_ANIMATION);
            else // avatar is standing up
            {
                if (animation)
                    llStopAnimation(animation); // stop the started animation
                llResetScript(); // release the avatar animation permissions
            }
        }
    }
 
    run_time_permissions(integer perm)
    {
        if (perm & PERMISSION_TRIGGER_ANIMATION)
        {
            animation = llGetInventoryName(INVENTORY_ANIMATION,0); // get the first animation from inventory
            if (animation)
            {
                llStopAnimation("sit"); // stop the default sit animation
                llStartAnimation(animation);
            }
        }
    }
}

 

Edited by ainst Composer
Link to comment
Share on other sites

The vibrate script does its work mainly in the timer event. So you could simply copy it (and any associated global variables and their assignments in the stat_entry) into your animation script. Starting and stopping the timer could be done in the animation script's changed event: starting the vibration timer when when the script detects the avatar has sat on the object (where you call llRequestPermissions) and stopping the timer when the script detects the avatar has stood up.

As a side note, I should point out that putting calls to llSetLinkPrimitiveParamsFast on a very fast timer will cause a lot of object updates and could be quite laggy. A more efficient solution could be to replace the timer and llSetLinkPrimitiveParamsFast with a call to llSetKeyframedMotion which is considerably more lightweight and easier on the servers.

Edited by Fenix Eldritch
  • Thanks 1
Link to comment
Share on other sites

19 minutes ago, Fenix Eldritch said:

The vibrate script does its work mainly in the timer event. So you could simply copy it (and any associated global variables and their assignments in the stat_entry) into your animation script. Starting and stopping the timer could be done in the animation script's changed event: starting the vibration timer when when the script detects the avatar has sat on the object (where you call llRequestPermissions) and stopping the timer when the script detects the avatar has stood up.

As a side note, I should point out that putting calls to llSetLinkPrimitiveParamsFast on a very fast timer will cause a lot of object updates and could be quite laggy. A more efficient solution could be to replace the timer and llSetLinkPrimitiveParamsFast with a call to llSetKeyframedMotion which is considerably more lightweight and easier on the servers.

Thanks very much! It works perfectly!

Link to comment
Share on other sites

KFM can substantially reduce sim script load by looping through a fixed cycle of motion, but I think you'll find that it's still generating a whole bunch of object updates. If there will only be one of these things in view at any time, it's probably not worth worrying about, but if there will be a flock of them, or if it's important that they appear to continue vibrating even when there are brief network glitches, it may be worth considering building some random vibration into the avatar animation and either making the visible vibrating object an attachment or using texture animation to show different, slightly offset parts of a mesh, thus appearing to vibrate. That way there's only a single update to start the vibration and another when it stops.

  • Thanks 2
Link to comment
Share on other sites

33 minutes ago, Qie Niangao said:

KFM can substantially reduce sim script load by looping through a fixed cycle of motion, but I think you'll find that it's still generating a whole bunch of object updates. If there will only be one of these things in view at any time, it's probably not worth worrying about, but if there will be a flock of them, or if it's important that they appear to continue vibrating even when there are brief network glitches, it may be worth considering building some random vibration into the avatar animation and either making the visible vibrating object an attachment or using texture animation to show different, slightly offset parts of a mesh, thus appearing to vibrate. That way there's only a single update to start the vibration and another when it stops.

 

27 minutes ago, Fenix Eldritch said:

Ah, I was under the impression KFM was closer to a local animation type of thing. Thanks for the object update clarification.

One more thing! When i use it on single prim it works fine but when i link a prim to it it goes crazy! any suggestions? heres what i got. Oh and i need the entire link set to vibrate, besides i link the door with the door script to it.

string animation; // the first animation in inventory will automatically be used
// the animation name must be stored globally to be able to stop the animation when standing up

integer k;
integer flip = 1;
list params;
vector pos;
integer link = 0;


default {
    state_entry() {
        // set sit target, otherwise this will not work 
        llSitTarget( < 0.0, 0.0, 0.1 > , ZERO_ROTATION);

        params = llGetLinkPrimitiveParams(link, [PRIM_POSITION]);
        pos = llList2Vector(params, 0);
    }

    changed(integer change) {
        if (change & CHANGED_LINK) {
            key av = llAvatarOnSitTarget();
            if (av) //evaluated as true if not NULL_KEY or invalid
                llRequestPermissions(av, PERMISSION_TRIGGER_ANIMATION);
            if (k = !k) llSetTimerEvent(0.02 + llFrand(0.1));

            else // avatar is standing up
            {
                if (animation)
                    llStopAnimation(animation); // stop the started animation
                llResetScript(); // release the avatar animation permissions
                llSetTimerEvent(0.0);
            }
        }
    }

    run_time_permissions(integer perm) {
        if (perm & PERMISSION_TRIGGER_ANIMATION) {
            animation = llGetInventoryName(INVENTORY_ANIMATION, 0); // get the first animation from inventory
            if (animation) {
                llStopAnimation("sit"); // stop the default sit animation
                llStartAnimation(animation);
            }
        }
    }

    timer() {
        llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_POSITION, pos + ((flip = -flip) * < 0.02, 0.01, 0.01 > )]);
    }



}

 

Edited by ainst Composer
Link to comment
Share on other sites

The first parameter of llSetLinkPrimitiveParamsFast uses a constant to denote what prim in the linkset to target. LINK_THIS signifies you want to target the specific prim in which the script resides. If you want llSetLinkPrimitiveParamsFast to affect the entire linkset, use the constant LINK_SET instead.

Also you can streamline the code a little by removing "if (k = !k)" test. Since you only ever want to start the timer when the avatar is seated, that test is already covered by the one used to call llRequestPermissions. You could do this and save yourself an extra step:

if (av) //evaluated as true if not NULL_KEY or invalid
{
	llRequestPermissions(av, PERMISSION_TRIGGER_ANIMATION);
	llSetTimerEvent(0.02 + llFrand(0.1));
}
else ...

Edited to add:
Turns out using LINK_ROOT is preferable when setting the position of the entire object as per the discussion below.

Edited by Fenix Eldritch
  • Thanks 1
Link to comment
Share on other sites

9 minutes ago, Fenix Eldritch said:

The first parameter of llSetLinkPrimitiveParamsFast uses a constant to denote what prim in the linkset to target. LINK_THIS signifies you want to target the specific prim in which the script resides. If you want llSetLinkPrimitiveParamsFast to affect the entire linkset, use the constant LINK_SET instead.

Also you can streamline the code a little by removing "if (k = !k)" test. Since you only ever want to start the timer when the avatar is seated, that test is already covered by the one used to call llRequestPermissions. You could do this and save yourself an extra step:


if (av) //evaluated as true if not NULL_KEY or invalid
{
	llRequestPermissions(av, PERMISSION_TRIGGER_ANIMATION);
	llSetTimerEvent(0.02 + llFrand(0.1));
}
else ...

 

Thanks a lot! i did everything like you advised!

Maybe its not the script? Or is it because of my door? See whats going on >>>

ezgif.com-video-to-gif.gif

Link to comment
Share on other sites

1 minute ago, Fenix Eldritch said:

Does the door have its own script? If so, it could be interfering with your vibrate script. As a test, try temporarily disabling the door script (uncheck the "running" box in the script's window) and see if the same problem happens when you sit on the object.

Yes it happens even without door script...

Link to comment
Share on other sites

Ah, I think I see the issue. In your state_entry event, your method of getting the position still assumes you're targeting an unlinked prim. Since this is now a linkset, you want to get the position of the root. Try using

params = llGetLinkPrimitiveParams(LINK_ROOT, [PRIM_POSITION]);

 

Edited by Fenix Eldritch
LINK_ROOT not LINK_SET
  • Thanks 1
Link to comment
Share on other sites

11 minutes ago, Fenix Eldritch said:

Ah, I think I see the issue. In your state_entry event, your method of getting the position still assumes you're targeting an unlinked prim. Since this is now a linkset, you want to get the position of the root. Try using


params = llGetLinkPrimitiveParams(LINK_ROOT, [PRIM_POSITION]);

 

Oh thanks very much! its perfect! Works everything now! Thank you!

  • Like 1
Link to comment
Share on other sites

Followup: I re-read the wiki page for http://wiki.secondlife.com/wiki/PRIM_POSITION and this caveat jumped out at me:

Quote

It is usually not a good idea to combine PRIM_POSITION with LINK_SET. The root will treat the coordinates as world or attachment, while the children will treat them as local, yielding inconsistent results or failure. If you want to move the object as a unit, use LINK_ROOT instead.

So for completeness sake, it would be advisable to use LINK_ROOT when setting the position in your code.

  • Thanks 1
Link to comment
Share on other sites

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