secondlife / jira-archive

2 stars 0 forks source link

[BUG-6962] llApplyImpulse() in attachment does not move hovering avatar who has just been lightly bumped #14735

Open sl-service-account opened 10 years ago

sl-service-account commented 10 years ago

Steps to Reproduce

Using llTakeControls to take action on the movement keys. Not passing through so an alternate method of propulsion (in this case llApplyImpulse) can be used to move the avatar at a rate other than the default movement rate. After being touched by another avatar while hovering, movement no longer functions.

Actual Behavior

An avatar that is following another avatar through a scripted attachment using llMoveToTarget (like a leash) will sometimes get "stuck" and will not continue to follow until bumped or moved. using llAppyImpulse to generate movement while in flight seems to work inconsistently. sometimes you will just "freeze" and are not able to move. rotating seems to "free" you. this behavior seems to be the most reliably reproduced when another avatar collides with you.

Expected Behavior

would expect the impulse to move the avatar. the energy is sufficient and the control event is executing, but no movement occurs.

Other information

Original Jira Fields | Field | Value | | ------------- | ------------- | | Issue | BUG-6962 | | Summary | llApplyImpulse() in attachment does not move hovering avatar who has just been lightly bumped | | Type | Bug | | Priority | Unset | | Status | Accepted | | Resolution | Accepted | | Reporter | Nala Farspire (nala.farspire) | | Created at | 2014-08-13T18:56:47Z | | Updated at | 2014-08-19T19:04:07Z | ``` { 'Business Unit': ['Platform'], 'Date of First Response': '2014-08-13T14:19:58.952-0500', 'System': 'SL Simulator', 'Target Viewer Version': 'viewer-development', 'What just happened?': 'An avatar that is following another avatar through a scripted attachment using llMoveToTarget (like a leash) will sometimes get "stuck" and will not continue to follow until bumped or moved.\r\nusing llAppyImpulse to generate movement while in flight seems to work inconsistently. sometimes you will just "freeze" and are not able to move. rotating seems to "free" you.\r\nthis behavior seems to be the most reliably reproduced when another avatar collides with you.', 'What were you doing when it happened?': 'Using llTakeControls to take action on the movement keys. Not passing through so an alternate method of propulsion (in this case llApplyImpulse) can be used to move the avatar at a rate other than the default movement rate. After being touched by another avatar while hovering, movement no longer functions.', 'What were you expecting to happen instead?': 'would expect the impulse to move the avatar. the energy is sufficient and the control event is executing, but no movement occurs.', } ```
sl-service-account commented 10 years ago

ObviousAltIsObvious commented at 2014-08-13T19:19:59Z

I think this is the same as SVC-2697 - that issue was abandoned, but this kind of bug has been with us for a long, long time.

sl-service-account commented 10 years ago

Maestro Linden commented at 2014-08-13T22:59:49Z, updated at 2014-08-13T23:00:15Z

Hi Nala, thanks for the report.

I made this test script (using the SVC-2697 repro script as a basis), and I'm seeing pretty consistent behavior. When my avatar is standing on a large flat prim, the impulse makes me move at ~0.74m/s. When my avatar is hovering in the air, the script has no effect (my avatar doesn't move at all).

When another avatar bumps into me, the motion due to the script seems unperturbed. While hovering, my avatar moves a bit due to being bumped (as usual), but doesn't exhibit any additional motion from the script. While being 'walked' by the script, another avatar bumping into me appears to have an additive effect on my avatar's velocity.

Can you elaborate on the steps required to trigger the inconsistency, including a complete (but simple) script to reproduce this bug with?

integer step;
integer total_steps = 60;
vector impulse = <1,0,0>;
default
{
    state_entry()
    {
        {
            llSetTimerEvent(0.2);
            llOwnerSay("wear me to get pushed back and forth");
        }
    }

    timer()
    {
        if(llGetAttached())
        {
            integer up = (integer) llFrand(2.0);
            if ((++step % total_steps) >= total_steps/2)
            {
                llSetText("impulse: " + (string)impulse
                    + "\nspeed: " + (string)llVecMag(llGetVel()), <0,1,0>, 1.0);
                llApplyImpulse(impulse, TRUE);
            }
            else
            {
                llSetText("impulse: " + (string)(-impulse)
                    + "\nspeed: " + (string)llVecMag(llGetVel()), <1,0,0>, 1.0);
                llApplyImpulse(-impulse, TRUE);            
            }
        }
        else
        {
            llSetText("wear me to get pushed back and forth", <1,1,1>, 1.0);
        }
    }
}
sl-service-account commented 10 years ago

Nala Farspire commented at 2014-08-15T13:36:24Z, updated at 2014-08-15T16:58:18Z

Okay. well first of all the problem does not seem to occur when you are on the ground. the bug is related to flying. there actually may be 2 parts to this. They seem like they might be related but then again they may not. I'm seeing similar behavior between llApplyImpulse and llMoveToTarget when flying. for the llMoveToTarget take any collar that is out there, an opencollar for example. have someone activate the leash. Fly and let them try to drag you around on the leash. (a simple MoveToTarget follower) you will eventually get stuck and won't follow until you move or are bumped. doesn't do this with you on the ground.

for the ApplyImpulse situation try this script

attach an object with this script in it. then fly. have someone wearing an attachment that protrudes (like a pair of wings) come near you and let their attachment touch you. (this can also be accomplished by having them touch you in any way but in the case of direct contact they will "push" you which can cancel the effect. we want contact but no (or very little) push.

after they make contact with you you will be unable to move forward, back, up or down. turning seems to free you and you can move again.


string Gs_bird_stand_anim = "stand_anim_of_your_choice";
string Gs_bird_walk_anim = "walk_anim_of_your_choice";
string Gs_bird_hover_anim = "hover_anim_of_your_choice";
string Gs_bird_fly_anim = "fly_anim_of_your_choice";

key Gk_owner;                                       //owner (wearer) of the AO

integer Gi_override_permission;                     //flag to indicate we got override permission

float Gf_linearforce;                               //forward/back force
float Gf_upforce;                                   //upward/downward force
float Gf_mass;                                      //mass of the avatar

SendOverrides()
{
    llSetAnimationOverride( "Crouching", Gs_bird_stand_anim);
    llSetAnimationOverride( "CrouchWalking", Gs_bird_walk_anim);
    llSetAnimationOverride( "Falling Down", Gs_bird_stand_anim);
    llSetAnimationOverride( "Flying", Gs_bird_fly_anim);
    llSetAnimationOverride( "FlyingSlow", Gs_bird_fly_anim);
    llSetAnimationOverride( "Hovering", Gs_bird_hover_anim);
    llSetAnimationOverride( "Hovering Down", Gs_bird_hover_anim);
    llSetAnimationOverride( "Hovering Up", Gs_bird_hover_anim);
    llSetAnimationOverride( "Jumping", Gs_bird_stand_anim);
    llSetAnimationOverride( "Landing", Gs_bird_stand_anim);
    llSetAnimationOverride( "PreJumping", Gs_bird_stand_anim);
    llSetAnimationOverride( "Running", Gs_bird_walk_anim);
    llSetAnimationOverride( "Sitting", Gs_bird_stand_anim);
    llSetAnimationOverride( "Sitting on Ground", Gs_bird_stand_anim);
    llSetAnimationOverride( "Standing", Gs_bird_stand_anim);
    llSetAnimationOverride( "Standing Up", Gs_bird_stand_anim);
    llSetAnimationOverride( "Striding", Gs_bird_stand_anim);
    llSetAnimationOverride( "Soft Landing", Gs_bird_stand_anim);
    llSetAnimationOverride( "Taking Off", Gs_bird_stand_anim);
    llSetAnimationOverride( "Turning Left", Gs_bird_stand_anim);
    llSetAnimationOverride( "Turning Right", Gs_bird_stand_anim);
    llSetAnimationOverride( "Walking", Gs_bird_walk_anim);
}

init()
{
        Gk_owner = llGetOwner();                        //set owner (wearer)
        Gi_override_permission = 0;                     //we don't have override permission yet
        Gf_mass = llGetObjectMass(llGetOwner());        //get the mass of the person
        if (llGetAttached())                            //if attached get permissions
            llRequestPermissions(Gk_owner, PERMISSION_OVERRIDE_ANIMATIONS | PERMISSION_TRIGGER_ANIMATION | PERMISSION_TAKE_CONTROLS);
}

default
{ 
    state_entry()
    {
        init();
    }

    on_rez(integer start)
    {
        init();
    }

    changed(integer change)
    {
        if (change & CHANGED_OWNER)                 //owner changed
        {
            llResetScript();                                //reset the script
        }
    }

    attach(key on)
    {
        if (Gi_override_permission & on == NULL_KEY)         //AO detached and we have permissions
        {
            llResetAnimationOverride("ALL");                        //reset overrides
            Gi_override_permission = 0;                             //permission dropped
        }
    }

    run_time_permissions(integer perm)
    {
        if (perm & PERMISSION_TAKE_CONTROLS)        //take controls permission
        {
            llTakeControls(CONTROL_FWD | CONTROL_BACK | CONTROL_UP | CONTROL_DOWN , TRUE, FALSE);
            //take controls for page up, page down, forward and back - do NOT pass through
        }

        if (perm & PERMISSION_OVERRIDE_ANIMATIONS)  //override permission
        {
            Gi_override_permission = 1;                     //got override permission
            SendOverrides();                                //load up the anim list
        }
    }

    control(key name, integer level, integer edge)
    {
        integer flying = llGetAgentInfo(Gk_owner) & AGENT_FLYING; //get flying ststus
        vector up;
        vector down;
        vector fwd;

        if (level & CONTROL_UP && flying)           //up (flying)
        {
            Gf_upforce = 1.000 * Gf_mass;               //calculate upward force based on mass
            up = llRot2Up(llGetRot());                  //get the upward vector
            up = llVecNorm(up);                         //normalize the vector
            up *= Gf_upforce;                           //multiply the force into the vector
            llApplyImpulse(up, FALSE);                  //apply an impulse to move the avatar
        }

        if (level & CONTROL_DOWN && flying)         //down (flying)
        {
            Gf_upforce = 1.000 * Gf_mass;               //calculate upward force based on mass
            up = llRot2Up(llGetRot());                  //get the upward vector
            up = llVecNorm(up);                         //normalize the vector
            up *= -Gf_upforce;                          //multiply the force into the vector
            llApplyImpulse(up, FALSE);                  //apply an impulse to move the avatar
        }

        if (level & CONTROL_FWD)                    //forward
        {
            if (!flying) Gf_linearforce = .1133 * Gf_mass;  //calculate linear force based on mass for walking
            else Gf_linearforce = 1.000 * Gf_mass;          //calculate linear force based on mass for flying
            fwd = llRot2Fwd(llGetRot());                    //get the forward vector
            fwd = llVecNorm(fwd);                           //normalize the vector
            fwd *= Gf_linearforce;                          //multiply the force into the vector
            llApplyImpulse(fwd, FALSE);                     //apply an impulse to move the avatar
        }

        if (level & CONTROL_BACK)                   //back
        {
            if (!flying) Gf_linearforce = .1133 * Gf_mass;  //calculate linear force based on mass for walking
            else Gf_linearforce = 1.000 * Gf_mass;          //calculate linear force based on mass for flying
            fwd = llRot2Fwd(llGetRot());                    //get the forward vector
            fwd = llVecNorm(fwd);                           //normalize the vector
            fwd *= -Gf_linearforce;                         //multiply the force into the vector
            llApplyImpulse(fwd, FALSE);                     //apply an impulse to move the avatar
        }

        if (~level & edge)                          //any key released
        {
             llApplyImpulse(<0,0,0>, FALSE);                //cancel out any impulse to stop moving
        }
    }
}
sl-service-account commented 10 years ago

Nala Farspire commented at 2014-08-15T13:50:29Z, updated at 2014-08-15T16:54:15Z

sorry for the formatting glitches. I wasn't quite sure how to get the script to come out like yours did. fixed.

sl-service-account commented 10 years ago

Nala Farspire commented at 2014-08-15T13:59:37Z, updated at 2014-08-15T14:01:18Z

I would also like to add that I have gotten frozen when there was no collision with anything (other than the ground) but contact with another avatar seems to be the most reliable way of getting this to occur. when I get shot out of an avatar cannon when I land on the ground it will sometimes not let me move. in that situation a rotation does not free me but a forward jump or flying does.

sl-service-account commented 10 years ago

Maestro Linden commented at 2014-08-15T18:44:19Z

Hm, I can't seem to reproduce the loss of controls when I use your script. I used some of the looping internal animations for the animation overrides, so that the script would work without any additional inventory items:

string Gs_bird_stand_anim = "aim_r_handgun";
string Gs_bird_walk_anim = "female_walk";
string Gs_bird_hover_anim = "aim_r_rifle";
string Gs_bird_fly_anim = "flyslow";

key Gk_owner;                                       //owner (wearer) of the AO

integer Gi_override_permission;                     //flag to indicate we got override permission

float Gf_linearforce;                               //forward/back force
float Gf_upforce;                                   //upward/downward force
float Gf_mass;                                      //mass of the avatar

SendOverrides()
{
    llSetAnimationOverride( "Crouching", Gs_bird_stand_anim);
    llSetAnimationOverride( "CrouchWalking", Gs_bird_walk_anim);
    llSetAnimationOverride( "Falling Down", Gs_bird_stand_anim);
    llSetAnimationOverride( "Flying", Gs_bird_fly_anim);
    llSetAnimationOverride( "FlyingSlow", Gs_bird_fly_anim);
    llSetAnimationOverride( "Hovering", Gs_bird_hover_anim);
    llSetAnimationOverride( "Hovering Down", Gs_bird_hover_anim);
    llSetAnimationOverride( "Hovering Up", Gs_bird_hover_anim);
    llSetAnimationOverride( "Jumping", Gs_bird_stand_anim);
    llSetAnimationOverride( "Landing", Gs_bird_stand_anim);
    llSetAnimationOverride( "PreJumping", Gs_bird_stand_anim);
    llSetAnimationOverride( "Running", Gs_bird_walk_anim);
    llSetAnimationOverride( "Sitting", Gs_bird_stand_anim);
    llSetAnimationOverride( "Sitting on Ground", Gs_bird_stand_anim);
    llSetAnimationOverride( "Standing", Gs_bird_stand_anim);
    llSetAnimationOverride( "Standing Up", Gs_bird_stand_anim);
    llSetAnimationOverride( "Striding", Gs_bird_stand_anim);
    llSetAnimationOverride( "Soft Landing", Gs_bird_stand_anim);
    llSetAnimationOverride( "Taking Off", Gs_bird_stand_anim);
    llSetAnimationOverride( "Turning Left", Gs_bird_stand_anim);
    llSetAnimationOverride( "Turning Right", Gs_bird_stand_anim);
    llSetAnimationOverride( "Walking", Gs_bird_walk_anim);
}

init()
{
        Gk_owner = llGetOwner();                        //set owner (wearer)
        Gi_override_permission = 0;                     //we don't have override permission yet
        Gf_mass = llGetObjectMass(llGetOwner());        //get the mass of the person
        if (llGetAttached())                            //if attached get permissions
            llRequestPermissions(Gk_owner, PERMISSION_OVERRIDE_ANIMATIONS | PERMISSION_TRIGGER_ANIMATION | PERMISSION_TAKE_CONTROLS);
}

default
{ 
    state_entry()
    {
        init();
    }

    on_rez(integer start)
    {
        init();
    }

    changed(integer change)
    {
        if (change & CHANGED_OWNER)                 //owner changed
        {
            llResetScript();                                //reset the script
        }
    }

    attach(key on)
    {
        if (Gi_override_permission & on == NULL_KEY)         //AO detached and we have permissions
        {
            llResetAnimationOverride("ALL");                        //reset overrides
            Gi_override_permission = 0;                             //permission dropped
        }
    }

    run_time_permissions(integer perm)
    {
        if (perm & PERMISSION_TAKE_CONTROLS)        //take controls permission
        {
            llTakeControls(CONTROL_FWD | CONTROL_BACK | CONTROL_UP | CONTROL_DOWN , TRUE, FALSE);
            //take controls for page up, page down, forward and back - do NOT pass through
        }

        if (perm & PERMISSION_OVERRIDE_ANIMATIONS)  //override permission
        {
            Gi_override_permission = 1;                     //got override permission
            SendOverrides();                                //load up the anim list
        }
    }

    control(key name, integer level, integer edge)
    {
        integer flying = llGetAgentInfo(Gk_owner) & AGENT_FLYING; //get flying ststus
        vector up;
        vector down;
        vector fwd;

        if (level & CONTROL_UP && flying)           //up (flying)
        {
            Gf_upforce = 1.000 * Gf_mass;               //calculate upward force based on mass
            up = llRot2Up(llGetRot());                  //get the upward vector
            up = llVecNorm(up);                         //normalize the vector
            up *= Gf_upforce;                           //multiply the force into the vector
            llApplyImpulse(up, FALSE);                  //apply an impulse to move the avatar
        }

        if (level & CONTROL_DOWN && flying)         //down (flying)
        {
            Gf_upforce = 1.000 * Gf_mass;               //calculate upward force based on mass
            up = llRot2Up(llGetRot());                  //get the upward vector
            up = llVecNorm(up);                         //normalize the vector
            up *= -Gf_upforce;                          //multiply the force into the vector
            llApplyImpulse(up, FALSE);                  //apply an impulse to move the avatar
        }

        if (level & CONTROL_FWD)                    //forward
        {
            if (!flying) Gf_linearforce = .1133 * Gf_mass;  //calculate linear force based on mass for walking
            else Gf_linearforce = 1.000 * Gf_mass;          //calculate linear force based on mass for flying
            fwd = llRot2Fwd(llGetRot());                    //get the forward vector
            fwd = llVecNorm(fwd);                           //normalize the vector
            fwd *= Gf_linearforce;                          //multiply the force into the vector
            llApplyImpulse(fwd, FALSE);                     //apply an impulse to move the avatar
        }

        if (level & CONTROL_BACK)                   //back
        {
            if (!flying) Gf_linearforce = .1133 * Gf_mass;  //calculate linear force based on mass for walking
            else Gf_linearforce = 1.000 * Gf_mass;          //calculate linear force based on mass for flying
            fwd = llRot2Fwd(llGetRot());                    //get the forward vector
            fwd = llVecNorm(fwd);                           //normalize the vector
            fwd *= -Gf_linearforce;                         //multiply the force into the vector
            llApplyImpulse(fwd, FALSE);                     //apply an impulse to move the avatar
        }

        if (~level & edge)                          //any key released
        {
             llApplyImpulse(<0,0,0>, FALSE);                //cancel out any impulse to stop moving
        }
    }
}

When my avatar wearing your script is hovering or flying forward, and another avatar wearing a 20m box gets near him, he is still able to move in any direction, afterwards. I also tried direct avatar collisions (which makes more sense as a repro - attachments aren't physically simulated at all, so there is no 'collision' when an avatar with a big attachment approaches another), but this didn't do the trick.

Could it be that some of your override animations are looping, preventing execution of further animations?

Some states are transitional and have undefined behavior if set to continuously looping animations. These states are "PreJumping", "Landing", "Soft Landing" and "Standing Up".

sl-service-account commented 10 years ago

Nala Farspire commented at 2014-08-15T22:59:10Z

well it is likely some of them loop. but correct me if I'm wrong but you said at the top of your last comment " I used some of the looping internal animations" so a looping animation should be fine yes? and why only when flying? I'm going to try your script as you posted it and see if I can repro.

sl-service-account commented 10 years ago

Nala Farspire commented at 2014-08-15T23:01:46Z, updated at 2014-08-15T23:37:55Z

Yeah I get the same thing with your version of the script. It took me less than a minute to reproduce it. Don't be moving when you get "bumped" just hover, and I had another flying av just gently bump into me. At one point I did put in some diagnostic messages. I verified that the control events were in fact executing by putting in an ownersay telling me the value of my force just before applying it (also to see if somehow my numbers were getting distorted). And yes I know attachments don't receive collisions and the wings in my case pass right through me, I did find that odd that should have any kind of effect on me. Maybe it's the other av being close enough to me to hit my physics shape or bounding box, I don't know. But this last test (with your script) it was just me and another av - no attachments other than the object I have the script in. Pretty sure it's not firestorm, another person who was helping me diagnose this is using singularity. As I did say I have experienced this loss of movement under other circumstances but this method is almost sure fire. I can make it do it reliably every time. Before I started this I did look around to see if anyone else had experienced such an issue and like the first person said it was a lot like SVC-2697 but I saw that one got killed off during a JIRA upgrade so I thought I would try again. I invite anyone else reading this to give it a try!

sl-service-account commented 10 years ago

Whirly Fizzle commented at 2014-08-15T23:54:09Z, updated at 2014-08-15T23:55:14Z

I can reproduce this on Second Life 3.7.13 (292225) Jul 22 2014 00:31:11 (Second Life Release) using Maestro's script.

sl-service-account commented 10 years ago

Maestro Linden commented at 2014-08-16T00:28:39Z

Well, I actually probably shouldn't have picked those internal looping animations for those certain animation states, but I don't think I usually hit them do to how I was testing. On the other hand, there's no good choice of animation for Gs_bird_stand_anim as it is in the current script - some of the animation states which use it require a looping animation, and others (from that caveat in the wiki) are incompatible with a looping animations. I think you'd ideally want 2 versions of that animation asset, one with looping (which "Standing Up" and other looping states use) and one without looping (which transitional states like "Standing Up" use).

When you hit the ground hard, which is probably happening when you land from a cannon fall, it would play the "Standing Up" animation state. Is your "Standing Up" animation looped? If so, you could get into the state where the avatar never finishes 'standing up', and you'd be unable to move the controls (normally you can't move while 'standing up', but the animation only lasts 2 seconds or so before completing). I'm not sure that these animation states would ever trigger when simply being bumped while hovering, though.

sl-service-account commented 10 years ago

Nala Farspire commented at 2014-08-16T01:34:26Z

well you're probably right about the standing up anim now that I think about it. but we do have another confirmed reproduction of the flying issue.

sl-service-account commented 10 years ago

Maestro Linden commented at 2014-08-18T18:18:46Z

Alt 1 rezzed a box containing Maestro's script, removed all attachments, took box into inventory and wore the box. Which of my scripts did you use, Whirly? Were you referring to the first script, which just does llApplyImpulse() in a loop, or the second one with all the animation overrides (which I later realized was problematic due to the looping animation issue)?

sl-service-account commented 10 years ago

Whirly Fizzle commented at 2014-08-18T18:39:36Z

The second script: https://jira.secondlife.com/browse/BUG-6962?focusedCommentId=440744&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-440744

sl-service-account commented 10 years ago

Nala Farspire commented at 2014-08-18T20:03:38Z

and you were correct about the looping standup animation. I replaced the standup and landing animations with non looping ones and you no longer get stuck after a hard landing. the flying situation however is unaffected (which is not surprising).

sl-service-account commented 10 years ago

Maestro Linden commented at 2014-08-19T19:02:32Z

Okay, I can finally reproduce this issue after being gently bumped in the air. Perhaps before I was hitting the turn buttons first, earlier.

I cleaned up the test script a bit, removing the extraneous AO feature and adding a bunch of debug statements:

float Gf_linearforce;                               //forward/back force
float Gf_upforce;                                   //upward/downward force
float Gf_mass;                                      //mass of the avatar

init()
{
        Gf_mass = llGetObjectMass(llGetOwner());        //get the mass of the person
        if (llGetAttached())                            //if attached get permissions
            llRequestPermissions(llGetOwner(), PERMISSION_TAKE_CONTROLS);
}

default
{ 
    state_entry()
    {
        init();
    }

    on_rez(integer start)
    {
        init();
    }

    changed(integer change)
    {
        if (change & CHANGED_OWNER)                 //owner changed
        {
            llResetScript();                                //reset the script
        }
    }

    run_time_permissions(integer perm)
    {
        if (perm & PERMISSION_TAKE_CONTROLS)        //take controls permission
        {
            llTakeControls(CONTROL_FWD | CONTROL_BACK | CONTROL_UP | CONTROL_DOWN , TRUE, FALSE);
            //take controls for page up, page down, forward and back - do NOT pass through
        }
    }

    control(key name, integer level, integer edge)
    {
        llOwnerSay("Control: lvl=" + (string)level + " edge=" + (string)edge);
        integer flying = llGetAgentInfo(llGetOwner()) & AGENT_FLYING; //get flying ststus
        vector up;
        vector down;
        vector fwd;

        if (level & CONTROL_UP && flying)           //up (flying)
        {
            Gf_upforce = 1.000 * Gf_mass;               //calculate upward force based on mass
            up = llRot2Up(llGetRot());                  //get the upward vector
            up = llVecNorm(up);                         //normalize the vector
            up *= Gf_upforce;                           //multiply the force into the vector
            llApplyImpulse(up, FALSE);                  //apply an impulse to move the avatar
            llOwnerSay("up");
        }

        if (level & CONTROL_DOWN && flying)         //down (flying)
        {
            Gf_upforce = 1.000 * Gf_mass;               //calculate upward force based on mass
            up = llRot2Up(llGetRot());                  //get the upward vector
            up = llVecNorm(up);                         //normalize the vector
            up *= -Gf_upforce;                          //multiply the force into the vector
            llApplyImpulse(up, FALSE);                  //apply an impulse to move the avatar
            llOwnerSay("down");
        }

        if (level & CONTROL_FWD)                    //forward
        {
            if (!flying) Gf_linearforce = .1133 * Gf_mass;  //calculate linear force based on mass for walking
            else Gf_linearforce = 1.000 * Gf_mass;          //calculate linear force based on mass for flying
            fwd = llRot2Fwd(llGetRot());                    //get the forward vector
            fwd = llVecNorm(fwd);                           //normalize the vector
            fwd *= Gf_linearforce;                          //multiply the force into the vector
            llApplyImpulse(fwd, FALSE);                     //apply an impulse to move the avatar
            llOwnerSay("forward");
        }

        if (level & CONTROL_BACK)                   //back
        {
            if (!flying) Gf_linearforce = .1133 * Gf_mass;  //calculate linear force based on mass for walking
            else Gf_linearforce = 1.000 * Gf_mass;          //calculate linear force based on mass for flying
            fwd = llRot2Fwd(llGetRot());                    //get the forward vector
            fwd = llVecNorm(fwd);                           //normalize the vector
            fwd *= -Gf_linearforce;                         //multiply the force into the vector
            llApplyImpulse(fwd, FALSE);                     //apply an impulse to move the avatar
            llOwnerSay("backward");
        }

        if (~level & edge)                          //any key released
        {
             llApplyImpulse(<0,0,0>, FALSE);                //cancel out any impulse to stop moving
             llOwnerSay("zero impulse");
        }
    }
}

When I see the bug, the control() event is correctly firing (rapidly), and the script is applying a series of forward impulses, like so:

.
.

[11:56] BUG-6962 new test: Control: lvl=1 edge=0
[11:56] BUG-6962 new test: forward
[11:56] BUG-6962 new test: Control: lvl=1 edge=0
[11:56] BUG-6962 new test: forward
[11:56] BUG-6962 new test: Control: lvl=1 edge=0
[11:56] BUG-6962 new test: forward
[11:56] BUG-6962 new test: Control: lvl=1 edge=0
[11:56] BUG-6962 new test: forward
[11:56] BUG-6962 new test: Control: lvl=1 edge=0
[11:56] BUG-6962 new test: forward
.
.

But my avatar doesn't move, for some reason. Perhaps some sort of anti-pushing code is preventing the avatar from moving (my test parcel was set to no-push)? In any case, this is a solid enough repro that I'll import this issue.