void plSwimStrategy::Apply(float delSecs)
{
    hsVector3 velocity = fController->GetLinearVelocity();
    hsVector3 achievedVelocity = fController->GetAchievedLinearVelocity();

    IAdjustBuoyancy();

    //trying to dampen the oscillations
    float retardent = 0.0f;
    static float finalBobSpeed = 0.5f;
    if ((achievedVelocity.fZ > finalBobSpeed) || (achievedVelocity.fZ < -finalBobSpeed))
        retardent = achievedVelocity.fZ * -0.90f;

    float zacc = (1.0f - fBuoyancy) * kGravity + retardent;
    velocity.fZ += (zacc * delSecs);

    velocity.fZ += achievedVelocity.fZ;

    // Water Current
    if (fCurrentRegion != nil)
    {
        float angCurrent = 0.0f;
        hsVector3 linCurrent(0.0f, 0.0f, 0.0f);
        fCurrentRegion->GetCurrent(fController, linCurrent, angCurrent, delSecs);

        if (hsABS(angCurrent) > 0.0001f)
            fController->IncrementAngle(angCurrent * delSecs);

        velocity += linCurrent;

        if (velocity.fZ > fCurrentRegion->fMaxUpwardVel)
            velocity.fZ = fCurrentRegion->fMaxUpwardVel;
    }

    if (velocity.fZ < kTerminalVelocity)
        velocity.fZ = kTerminalVelocity;

    // Convert to displacement vector
    hsVector3 displacement = velocity * delSecs;

    // Reset vars and move controller //
    fController->SetPushingPhysical(nil);
    fController->SetFacingPushingPhysical(false);
    fHadContacts = fOnGround = false;

    unsigned int collideResults = 0;
    unsigned int collideFlags = 1<<plSimDefs::kGroupStatic | 1<<plSimDefs::kGroupAvatarBlocker | 1<<plSimDefs::kGroupDynamic;
    if (!fController->IsSeeking())
        collideFlags |= (1<<plSimDefs::kGroupExcludeRegion);

    fController->Move(displacement, collideFlags, collideResults);

    if ((collideResults & kBottom) || (collideResults & kSides))
        fHadContacts = true;
}
void plSwimStrategy::Apply(float delSecs)
{
    hsAssert(fCore,"PlSwimStrategy::Apply No Core shouldn't be Applying");
    uint32_t collideFlags =
        1<<plSimDefs::kGroupStatic |
        1<<plSimDefs::kGroupAvatarBlocker |
        1<<plSimDefs::kGroupDynamic;
    if(!fCore->IsSeeking())
    {
        collideFlags|=(1<<plSimDefs::kGroupExcludeRegion);
    }

    hsVector3 LinearVelocity=fCore->GetLinearVelocity();
    hsVector3 AchievedLinearVelocity=fCore->GetAchievedLinearVelocity();
    if (fCore->IsKinematic())
    {
        plSceneObject* so = plSceneObject::ConvertNoRef(fOwner->ObjectIsLoaded());
        if (so)
        {
            // If we've been moved since the last physics update (somebody warped us),
            // update the physics before we apply velocity.
            const hsMatrix44& l2w = so->GetCoordinateInterface()->GetLocalToWorld();
            if (!CompareMatrices(l2w, fCore->GetLastGlobalLoc(), .0001f))
            {
                fCore->SetKinematicLoc(l2w);
                fCore->SetGlobalLoc(l2w);
            }
        }
        return;
        
    }
    if (!fCore->IsEnabled())
        return;
    
    fCore->SetPushingPhysical(nil);
    fCore->SetFacingPushingPhysical( false);
    fHadContacts=false;
    fOnGround=false;
    plSceneObject* so = plSceneObject::ConvertNoRef(fOwner->ObjectIsLoaded());
    if (so)
    {
        // If we've been moved since the last physics update (somebody warped us),
        // update the physics before we apply velocity.
        const hsMatrix44& l2w = so->GetCoordinateInterface()->GetLocalToWorld();
        if (!CompareMatrices(l2w, fCore->GetLastGlobalLoc(), .0001f))
            fCore->SetGlobalLoc(l2w);

        // Convert our avatar relative velocity to subworld relative
        if (!LinearVelocity.IsEmpty())
        {
            LinearVelocity = l2w * LinearVelocity;
            const plCoordinateInterface* subworldCI = fCore->GetSubworldCI();
            if (subworldCI)
                LinearVelocity = subworldCI->GetWorldToLocal() * LinearVelocity;
        }
        IAdjustBuoyancy();
        float zacc;
        float retardent=0.0f;
        static float FinalBobSpeed=0.5f;
        //trying to dampen the oscillations
        if((AchievedLinearVelocity.fZ>FinalBobSpeed)||(AchievedLinearVelocity.fZ<-FinalBobSpeed))
            retardent=AchievedLinearVelocity.fZ *-.90f;
        zacc=(1-fBuoyancy)*-32.f + retardent;
        
        hsVector3 linCurrent(0.0f,0.0f,0.0f);
        float angCurrent = 0.f;
        if (fCurrentRegion != nil)
        {
        
            fCurrentRegion->GetCurrent(fCore, linCurrent, angCurrent, delSecs);
            //fAngularVelocity+= angCurrent;
        }
        hsVector3 vel(LinearVelocity.fX , LinearVelocity.fY , AchievedLinearVelocity.fZ+ LinearVelocity.fZ );
        vel.fZ= vel.fZ + zacc*delSecs;
        if(fCurrentRegion!=nil){
            if (vel.fZ > fCurrentRegion->fMaxUpwardVel)
            {
                vel.fZ = fCurrentRegion->fMaxUpwardVel;
            }
            vel+= linCurrent;
        }
        static const float kGravity = -32.f;
        if(vel.fZ<kGravity)
        {//applying this terminal velocity just to avoid shooting 100 feet below the surface
            // and losing our surface ray cast
            vel.fZ =kGravity;
        }
        hsVector3 displacement= vel*delSecs;
        unsigned int colFlags = 0;
        fContactNormals.SetCount(0);
        fCore->Move(displacement,collideFlags,colFlags);
        if((colFlags&kBottom)||(colFlags&kSides))fHadContacts=true;
        float angvel=fCore->GetAngularVelocity();
        fCore->SetAngularVelocity(angvel +angCurrent);
    }
}