bool Officer::Advance( Unit *_unit )
{
    if( !m_onGround ) AdvanceInAir(_unit);
    bool amIDead = Entity::Advance(_unit);
    if( m_inWater != -1.0f ) AdvanceInWater(_unit);

    if( m_onGround && !m_dead ) m_pos.y = g_app->m_location->m_landscape.m_heightMap->GetValue( m_pos.x, m_pos.z );


    //
    // Advance in whatever state we are in

    if( !amIDead && m_onGround && m_inWater == -1.0f )
    {
        switch( m_state )
        {
            case StateIdle :                amIDead = AdvanceIdle();            break;
            case StateToWaypoint :          amIDead = AdvanceToWaypoint();      break;
            case StateGivingOrders :        amIDead = AdvanceGivingOrders();    break;
        }
    }

    if( m_dead )
    {
        m_vel.y -= 20.0f;
        m_pos.y += m_vel.y * SERVER_ADVANCE_PERIOD;
    }


    //
    // If we are giving orders, render them

    if( m_orders == OrderGoto )
    {
        if( syncfrand() < 0.05f )
        {
            OfficerOrders *orders = new OfficerOrders();
            orders->m_pos = m_pos + Vector3(0,2,0);
            orders->m_wayPoint = m_orderPosition;
            int index = g_app->m_location->m_effects.PutData( orders );
            orders->m_id.Set( m_id.GetTeamId(), UNIT_EFFECTS, index, -1 );
            orders->m_id.GenerateUniqueId();
        }
    }

    //
    // If we are absorbing, look around for Darwinians

    if( m_absorb ) Absorb();


    //
    // Attack anything nearby with our "shield"

    if( m_shield > 0 )
    {
        WorldObjectId id = g_app->m_location->m_entityGrid->GetBestEnemy( m_pos.x, m_pos.z, 0.0f, OFFICER_ATTACKRANGE, m_id.GetTeamId() );
        if( id.IsValid() )
        {
            Entity *entity = g_app->m_location->GetEntity( id );
            entity->ChangeHealth( -10 );
            m_shield --;

            Vector3 themToUs = m_pos - entity->m_pos;
            g_app->m_location->SpawnSpirit( m_pos, themToUs, 0, WorldObjectId() );
        }
    }


    //
    // Use teleports.  Remember which teleport we entered,
    // As there may be people following us

    if( m_wayPointTeleportId != -1 )
    {
        int teleportId = EnterTeleports(m_wayPointTeleportId);
        if( teleportId != -1 )
        {
            m_ordersBuildingId = teleportId;
            Teleport *teleport = (Teleport *) g_app->m_location->GetBuilding( teleportId );
            Vector3 exitPos, exitFront;
            bool exitFound = teleport->GetExit( exitPos, exitFront );
            if( exitFound ) m_wayPoint = exitPos + exitFront * 30.0f;
            if( m_orders == OrderGoto ) m_orders = OrderNone;
            m_wayPointTeleportId = -1;
        }
    }

    return amIDead || m_demoted;
}