Jump to content

llPush, gravity, and moving/holding/trapping avatars.


Wulfie Reanimator
 Share

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

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

Recommended Posts

So I'm working on a little something. It's game inspired and for use in combat sims or my own amusement.

Essentially, this: (7 second video)

The goal is to wait for an avatar to walk within a certain range, then use llPushObject to pull them in and up into the air.

Problem is that llPushObject seems very weak, especially the further the avatar is from the point I want them to "gravitate" towards.

My current code looks something like this:

key target;
vector gravity_center;

float force = 3.2;
float grab_range = 3;
float escape_range = 6;
float exponent = 0.0002;

// snipped

sensor(integer n)
{
    target = llDetectedKey(0);
    gravity_center = llGetPos() + <0,0,2>;

    llOwnerSay((string)["target ", target]);
    llSetColor(<1,1,0>, -1);

    while (TRUE)
    {
        vector avatar = llList2Vector(llGetObjectDetails(target, [OBJECT_POS]), 0);
        vector direction = gravity_center - avatar; // Vector TOWARD the center.

        if (llVecMag(direction) > escape_range) jump exit; // Exit condition!

        float mass = llGetObjectMass(target);
        llPushObject(target, llVecNorm(direction) * force * mass, ZERO_VECTOR, FALSE);
        llSleep(0.044);

        if (exponent < 2) // Slow curve to force-growth, chance to escape.
        {
            exponent *= 2;
            llOwnerSay((string)["increment ", exponent]);
        }

        if (force < 1000) // 1000 is still very weak.
        {
            force += exponent;
            llOwnerSay((string)["force ", force]);
        }
    }

    @exit;
    llSetColor(<1,0,0>, ALL_SIDES);
}

Yeah; repeating sensors, infinite loops, AND jumps! What a time to be alive.
One event is faster than one every fraction of a second, we don't have break to terminate a loop, and the object does not need to respond to anything during the loop.

Adding the avatar's mass to the equation didn't seem to do anything. So my question is, how do I account for the distance so avatars would be more strongly affected? Are there other pushing functions I'm forgetting?

Edit: Update!

The wiki page for llPushObject says "The push impact is diminished with distance by a factor of distance cubed."

So... llPow(llVecMag(distance), 3) does a good job at counteracting the distance falloff. It's a great start, but when the avatar is near the target, it tends to "overshoot" and bounce and can't hold the avatar in place while in the air, so I'm still looking for help/input.

Edited by Wulfie Reanimator
  • Like 1
Link to comment
Share on other sites

7 hours ago, Wulfie Reanimator said:

The goal is to wait for an avatar to walk within a certain range, then use llPushObject to pull them in and up into the air.
...

So... llPow(llVecMag(distance), 3) does a good job at counteracting the distance falloff. It's a great start, but when the avatar is near the target, it tends to "overshoot" and bounce and can't hold the avatar in place while in the air, so I'm still looking for help/input.

Have you checked the page LlPushObject/Havok4Implementation,  it is pseudo code, but looks quite clever "attenuate the impulse by distances that are beyond some threshold".

And the @exit...  I would avoid jumps, but script with a boolean:

    integer bDoIt= TRUE;

    while (bDoIt)
    {
        vector avatar = llList2Vector(llGetObjectDetails(target, [OBJECT_POS]), 0);
        vector direction = gravity_center - avatar; // Vector TOWARD the center.

        if (llVecMag(direction) > escape_range) bDoIt= FALSE; // Exit condition!

        if (bDoIt)
        {
        }
    }

 

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

10 hours ago, Fenix Eldritch said:

What if you were to cage them from a distance, and the cage would use a much lower powered push to keep the avatar suspended within itself? Since the target would be inside the object doing the push, you wouldn't have to deal with the distance falloff.

This has a couple problems -- I want the target to be able to escape within the first few seconds of being grabbed, and they would most likely be shot by enemy combatants while they are trapped mid-air, so the cage shouldn't block the avatar's movement or physical objects flying at it. The second part is relatively easy to build around, but the first part is the hard one.

6 hours ago, Lucia Nightfire said:

Have an invisible phantom prim move to a target agent and push them to the target location instead of using a stationary object do the pushing.

I can do the initial pulling part just fine now, but the problems happen when I'm supposed to be holding the avatar in place in the air. I don't know what kind of counter-forces I can use to cancel out the "bounciness" that gets more extreme over time.

Edited by Wulfie Reanimator
Link to comment
Share on other sites

If you have access to an Experience, you can force seat the person on a prim and then move the prim with llMoveToTarget or just shove it with llPush. As long as you don't block the person's ability to stand, he can still escape quickly if he's alert.

Link to comment
Share on other sites

1 hour ago, Wulfie Reanimator said:

I can do the initial pulling part just fine now, but the problems happen when I'm supposed to be holding the avatar in place in the air. I don't know what kind of counter-forces I can use to cancel out the "bounciness" that gets more extreme over time.

"Holding" someone in air by push alone is not possible. I recommend what Rolig suggests in some form, whether it be forced sitting on a movetotarget object or temp attaching a movetotarget object.

Link to comment
Share on other sites

6 minutes ago, Rolig Loon said:

If you have access to an Experience, you can force seat the person on a prim and then move the prim with llMoveToTarget or just shove it with llPush. As long as you don't block the person's ability to stand, he can still escape quickly if he's alert.

Unfortunately no, the sim(s) I might use this on don't have Experiences.

2 minutes ago, Lucia Nightfire said:

"Holding" someone in air by push alone is not possible. I recommend what Rolig suggests in some form, whether it be forced sitting on a movetotarget object or temp attaching a movetotarget object.

It's quite possible. llPushObject-based avatar grabbers can and have been done.

I can even show you the one I have. Even if you try to move while you're being held in the air, you won't be able to move much.

But this is what mine does. I'm not touching any inputs and I get thrown about to the point where I escape without trying.

Link to comment
Share on other sites

1 hour ago, Wulfie Reanimator said:

It's quite possible.

Ok, bad choice of words, heh. I mean it only has one "impulse" meaning it's applied on one frame. You have to keep making pushes and because of many variables, results can vary.

With movetotarget with an attachment you cut out a lot of unpredictability and overhead.

Link to comment
Share on other sites

40 minutes ago, Lucia Nightfire said:

Ok, bad choice of words, heh. I mean it only has one "impulse" meaning it's applied on one frame. You have to keep making pushes and because of many variables, results can vary.

With movetotarget with an attachment you cut out a lot of unpredictability and overhead.

That's why I'm using a loop to apply many pushes while accounting for different variables.

And due to the "must be forced" nature of the effect, temporary attachments aren't viable since I need to request permission to do it, and the enemy team is definitely not going to wear an attachment I tell them to. RLV isn't an option either since combat sims don't mandate it, and force-sitting an avatar is very different from the "feeling" I want to create.

This needs to be done with llPushObject, and the knowledge I'm going to get from this can easily carry over to lots of other things.

Back on topic a bit though, right now I'm accounting for:

  • Distance: llPow(VecMag(direction), 3)
  • Avatar velocity: llGetObjectDetails
  • Avatar mass: llGetObjectMass

My final calculation is along the lines of "(impulse - velocity) * strength" where:

  • impulse = direction * force
  • strength = llGetObjectMass * llPow(distance, 3)

(direction = gravity center - target position, force = float)

So in theory whatever my impulse is, I want to remove the avatar's current velocity from it. Meaning if my impulse is low (avatar is close to where it should be), it should start only counter-acting the avatar's velocity to prevent it from falling or moving. In practice it's not really doing that and it doesn't even sound right the more I think about it. Thoughts?

Edited by Wulfie Reanimator
Link to comment
Share on other sites

i tend to approach arena type avatar movement control by putting a impulse engine in the player HUD, rather than have the arena game objects try to move the avatar

a impulse engine where the player can also move themselves with WASD, interacting with the task. Sometimes the player wins the task, sometimes not depending on player character powers and/or game assets they possess

in the tractor beam case, the impulse engine applies llMoveToTarget. Incrementally adjusting the target to form lines and curves thru space. And allowing the player to manipulate WASD to try and break free

 

Link to comment
Share on other sites

10 minutes ago, Mollymews said:

i tend to approach arena type avatar movement control by putting a impulse engine in the player HUD, rather than have the arena game objects try to move the avatar

a impulse engine where the player can also move themselves with WASD, interacting with the task. Sometimes the player wins the task, sometimes not depending on player character powers and/or game assets they possess

in the tractor beam case, the impulse engine applies llMoveToTarget. Incrementally adjusting the target to form lines and curves thru space. And allowing the player to manipulate WASD to try and break free

I have no control over any attachments the avatars can or won't wear. Zero control besides what my own objects do. It's just the LL combat system, any HUDs people tend to wear are proprietary to their own group with few shared standards and zero cross-compatibility.

I have made MoveToTarget-based things before, they're fun and easy, but don't apply to this case.

Edited by Wulfie Reanimator
  • Thanks 1
Link to comment
Share on other sites

Another update.

After tweaking the numbers and writing myself some sensible debug messages, I found that using a much lower force had much better results. I originally started with 100, then 25, and here's the result with 5.

Video: https://puu.sh/FBO57/7ee82e2903.mp4

It seems to remain stable and even regular movement isn't enough to destabilize it. There are a few quirks that allow you to still get launched (for example, if you free-fall into it). 

Partial source code:

sensor(integer n)
{
    target = llDetectedKey(0);
    gravity_center = llGetPos() + GRAVITY_CENTER;

    llOwnerSay((string)["target ", target]);
    llSetColor(<1,1,0>, -1);

    while (TRUE)
    {
        list data = llGetObjectDetails(target, [OBJECT_POS, OBJECT_VELOCITY]);
        vector avatar = llList2Vector(data, 0);
        vector velocity = llList2Vector(data, 1);
        vector direction = gravity_center - avatar;
        float distance = llVecMag(direction);

        if (distance > escape_range)
        {
            llOwnerSay((string)["exit"]);
            jump exit; // Exit condition!
        }

        float modifier = (1 / distance);
        if (modifier > 1) modifier = 1;
        vector impulse = direction * force * modifier;
        float strength = llGetObjectMass(target) * llPow(distance, 3);

        llPushObject(target, (impulse - velocity * 0.55) * strength, ZERO_VECTOR, FALSE);
        llSleep(0.044);

        if ((growth *= 1.5) > MAX_GROWTH)
        {
            growth = MAX_GROWTH;
            // llOwnerSay((string)["growth ", growth]);
        }
        if ((force += growth) > MAX_FORCE)
        {
            force = MAX_FORCE;
            // llOwnerSay((string)["force ", force]);
        }
    }

    @exit;
    init();
}

The biggest change I made was add a little "force modifier" which is just (1 / distance) with a maximum value of 1.0, making the primary force slightly weaker over distance so the target won't get multiple full-strength pushes back towards the center, making them overshoot more and more.

I also had to remove about 55% (arbitrary) of the avatar's velocity from the impulse because 100% would cause them to shake pretty violently during the first second of the grab and 0% would just fling the avatar right out of the trap.

Edited by Wulfie Reanimator
  • Like 2
Link to comment
Share on other sites

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