Snow::Snow()
:   WorldObject()
{    
    m_positionOffset = syncfrand(10.0);
    m_xaxisRate = syncfrand(2.0);
    m_yaxisRate = syncfrand(2.0);
    m_zaxisRate = syncfrand(2.0);

    m_timeSync = GetNetworkTime();
    m_type = EffectSnow;
}
Zombie::Zombie()
:   WorldObject(),
    m_life(0.0)
{
    m_positionOffset = syncfrand(10.0);
    m_xaxisRate = syncfrand(2.0);
    m_yaxisRate = syncfrand(2.0);
    m_zaxisRate = syncfrand(2.0);
    
    m_type = EffectZombie;
}
bool SoulDestroyer::SearchForRandomPosition()
{
    Vector3 toSpawnPoint = ( m_pos - m_spawnPoint );
    toSpawnPoint.y = 0.0;
    double distToSpawnPoint = toSpawnPoint.Mag();
    double chanceOfReturn = ( distToSpawnPoint / m_roamRange );
    if( chanceOfReturn >= 1.0 || syncfrand(1.0) <= chanceOfReturn )
    {
        // We have strayed too far from our spawn point
        // So head back there now       
        Vector3 targetPos = m_spawnPoint;
        targetPos.y = g_app->m_location->m_landscape.m_heightMap->GetValue( targetPos.x, targetPos.z );
        targetPos.y += 100.0 + syncsfrand( 100.0 );
        
        Vector3 returnVector = ( targetPos - m_pos );
        returnVector.SetLength( 160.0 );
        m_targetPos = m_pos + returnVector;
    }
    else
    {
        double distance = 160.0;
        double angle = syncsfrand(2.0 * M_PI);

        m_targetPos = m_pos + Vector3( iv_sin(angle) * distance,
                                       0.0,
                                       iv_cos(angle) * distance );  
        m_targetPos.y = g_app->m_location->m_landscape.m_heightMap->GetValue( m_targetPos.x, m_targetPos.z );
        m_targetPos.y += (100.0 + syncsfrand( 100.0 ));        
    }
    
    return true;
}
bool SoulDestroyer::Advance( Unit *_unit )
{
    if( m_dead ) return AdvanceDead( _unit );
        
    if( m_panic > 0.0 )
    {
        m_targetEntity.SetInvalid();
        if( syncfrand(10.0) < 5.0 )
        {
            SearchForRetreatPosition();
        }
        m_panic -= SERVER_ADVANCE_PERIOD;
    }    
    else if( m_targetEntity.IsValid() )
    {
        WorldObject *target = g_app->m_location->GetEntity( m_targetEntity );
        if( target )
        {
            double distance = (target->m_pos - m_pos).Mag();
            m_targetPos = target->m_pos;            

            if( distance > SOULDESTROYER_MAXSEARCHRANGE )
            {
                m_targetEntity.SetInvalid();
            }
        }
        else
        {
            m_targetEntity.SetInvalid();
        }
    }

    m_retargetTimer -= SERVER_ADVANCE_PERIOD;

    bool arrived = AdvanceToTargetPosition();
    if( arrived || m_targetPos == g_zeroVector || m_retargetTimer < 0.0)
    {
        m_retargetTimer = 5.0;
        bool found = false;
        if( !found && m_panic < 0.1 ) found = SearchForTargetEnemy();
        if( !found ) found = SearchForRandomPosition();
    }

    RecordHistoryPosition();

    if( m_panic < 0.1 ) Attack( m_pos );

#ifdef USE_DIRECT3D
	if(g_deformEffect)
	{
		Vector3* pos1 = m_positionHistory.GetPointer(m_positionHistory.Size()-1);
		Vector3* pos2 = m_positionHistory.GetPointer(m_positionHistory.Size()-2);
		//if(pos1) g_deformEffect->AddTearing(*pos1,0.4);
		//if(pos1 && pos2) g_deformEffect->AddTearing((*pos1+*pos2)*0.5,0.4);
		if(pos1 && pos2) g_deformEffect->AddTearingPath(*pos1,*pos2,0.4);
	}
#endif

	return Entity::Advance(_unit);
}
bool AntHill::SearchForScoutArea ( Vector3 &_pos )
{
    Vector3 scoutPos = m_pos;
	float radius = ANTHILL_SEARCHRANGE/2.0f + syncfrand(ANTHILL_SEARCHRANGE/2.0f);
	float theta = syncfrand(M_PI * 2);
    scoutPos.x += radius * sinf(theta);
	scoutPos.z += radius * cosf(theta);
    scoutPos.y = g_app->m_location->m_landscape.m_heightMap->GetValue( scoutPos.x, scoutPos.z );

    if( scoutPos.y > 0 )
    {
        _pos = scoutPos;
        return true;
    }

    return false;
}
void AntHill::Damage ( float _damage )
{
    Building::Damage( _damage );

    if( m_health > 0 )
    {
        int healthBandBefore = int(m_health / 20.0f);
        m_health += _damage;
        int healthBandAfter = int(m_health / 20.0f);

        if( healthBandAfter != healthBandBefore )
        {
            Matrix34 mat( m_front, g_upVector, m_pos );
            g_explosionManager.AddExplosion( m_shape, mat, 1.0f - (float)m_health/100.0f );
            g_app->m_soundSystem->TriggerBuildingEvent( this, "Damage" );
        }

        if( m_health <= 0 )
        {
            Matrix34 mat( m_front, g_upVector, m_pos );
            g_explosionManager.AddExplosion( m_shape, mat );

            int numSpirits = m_numAntsInside + m_numSpiritsInside;
            for( int i = 0; i < numSpirits; ++i )
            {
                Vector3 pos = m_pos;
	            float radius = syncfrand(20.0f);
	            float theta = syncfrand(M_PI * 2);
    	        pos.x += radius * sinf(theta);
	            pos.z += radius * cosf(theta);

                Vector3 vel = ( pos - m_pos );
                vel.SetLength( syncfrand(50.0f) );

                g_app->m_location->SpawnSpirit( pos, vel, m_id.GetTeamId(), WorldObjectId() );
            }

            g_app->m_soundSystem->TriggerBuildingEvent( this, "Explode" );
            m_health = 0;
        }
    }
}
void Entity::SetType( unsigned char _type )
{
    m_type = _type;

    for( int i = 0; i < NumStats; ++i )
    {
        m_stats[i] = EntityBlueprint::GetStat( m_type, i );		
    }
	

    m_reloading = syncfrand( m_stats[StatRate] );
}
bool SoulDestroyer::ChangeHealth( int _amount, int _damageType )
{
    if( _damageType == DamageTypeLaser ) return false;

    if( !m_dead && _amount < 0 )
    {
        Entity::ChangeHealth(_amount);

        double fractionDead = 1.0 - (double) m_stats[StatHealth] / (double) EntityBlueprint::GetStat( TypeSoulDestroyer, StatHealth );
        fractionDead = max( fractionDead, 0.5 );
        fractionDead = min( fractionDead, 1.0 );
        if( m_dead ) fractionDead = 1.0;

        Panic( 2.0 + syncfrand(2.0) );

        Vector3 predictedRight = m_up ^ m_front;
        Vector3 predictedFront = predictedRight ^ m_up;
        Matrix34 transform(predictedFront, m_up, m_pos);

		g_explosionManager.AddExplosion( m_shape, transform, fractionDead );

        if( fractionDead )
        {
            // We just died
            for( int i = 1; i < m_positionHistory.Size(); i+=1 )
            {
                Vector3 pos1 = *m_positionHistory.GetPointer(i);
                Vector3 pos2 = *m_positionHistory.GetPointer(i-1);

                Vector3 pos = pos1 + (pos2 - pos1);
                Vector3 front = (pos2 - pos1).Normalise();
                Vector3 right = front ^ g_upVector;
                Vector3 up = right ^ front;

                double scale = 1.0 - ( (double) i / (double) m_positionHistory.Size() );
                scale *= 1.5;
                if( i == m_positionHistory.Size()-1 )   scale = 0.8;            
                scale = max( scale, 0.5 );
        
                Matrix34 tailMat( front, up, pos );            
                tailMat.u *= scale;
                tailMat.r *= scale;
                tailMat.f *= scale;

                g_explosionManager.AddExplosion( m_shape, tailMat, 1.0 );
            }            
        }
    }

    return true;
}
AIObjectiveMarker::AIObjectiveMarker()
:   Building(),
    m_scanRange(100.0),
    m_objectiveId(-1),
    m_registered(false),
    m_armourObjective(0),
    m_objectiveBuildingId(-1),
    m_pickupAvailable(false),
    m_pickupOnly(0),
    m_defenseMarker(false),
    m_timer(0.0)
{
    m_type = Building::TypeAIObjectiveMarker;
    m_timer = syncfrand(1.0);
}
bool Snow::Advance()
{
    m_vel *= 0.9;

    //
    // Make me double around slowly

    m_positionOffset += SERVER_ADVANCE_PERIOD;
    m_xaxisRate += syncsfrand(1.0);
    m_yaxisRate += syncsfrand(1.0);
    m_zaxisRate += syncsfrand(1.0);
    if( m_xaxisRate > 2.0 ) m_xaxisRate = 2.0;
    if( m_xaxisRate < 0.0 ) m_xaxisRate = 0.0;
    if( m_yaxisRate > 2.0 ) m_yaxisRate = 2.0;
    if( m_yaxisRate < 0.0 ) m_yaxisRate = 0.0;
    if( m_zaxisRate > 2.0 ) m_zaxisRate = 2.0;
    if( m_zaxisRate < 0.0 ) m_zaxisRate = 0.0;
    m_hover.x = iv_sin( m_positionOffset ) * m_xaxisRate;
    m_hover.y = iv_sin( m_positionOffset ) * m_yaxisRate;
    m_hover.z = iv_sin( m_positionOffset ) * m_zaxisRate;            

    double heightAboveGround = m_pos.y - g_app->m_location->m_landscape.m_heightMap->GetValue( m_pos.x, m_pos.z );
    if( heightAboveGround > -10.0 )
    {
        double fractionAboveGround = heightAboveGround / 100.0;                    
        fractionAboveGround = min( fractionAboveGround, 1.0 );
        fractionAboveGround = max( fractionAboveGround, 0.2 );
        m_hover.y = (-20.0 - syncfrand(20.0)) * fractionAboveGround;
    }
    else
    {
        return true;
    }
    
    Vector3 oldPos = m_pos;

    m_pos += m_vel * SERVER_ADVANCE_PERIOD;
    m_pos += m_hover * SERVER_ADVANCE_PERIOD;
    double worldSizeX = g_app->m_location->m_landscape.GetWorldSizeX();
    double worldSizeZ = g_app->m_location->m_landscape.GetWorldSizeZ();
    if( m_pos.x < 0.0 ) m_pos.x = 0.0;
    if( m_pos.z < 0.0 ) m_pos.z = 0.0;
    if( m_pos.x >= worldSizeX ) m_pos.x = worldSizeX;
    if( m_pos.z >= worldSizeZ ) m_pos.z = worldSizeZ;

    return false;
}
Esempio n. 11
0
unsigned char GenerateSyncValue()
{
    START_PROFILE( "GenerateSyncValue" );

    //
    // Generate a number between 0 and 255 that represents every unit in game
    // So if a single one is different, we will know immediately
    
    unsigned char result = 0;


    //
    // Objects

    hash_context c;
    hash_initial(&c);

#ifdef TRACK_SYNC_RAND
    for( int i = 0; i < g_app->GetWorld()->m_objects.Size(); ++i )
    {
        if( g_app->GetWorld()->m_objects.ValidIndex(i) )
        {
            WorldObject *obj = g_app->GetWorld()->m_objects[i];
			
			Hash( c, obj->m_longitude );
			Hash( c, obj->m_latitude ); 
			Hash( c, obj->m_vel.x ); 
			Hash( c, obj->m_vel.y ); 
			Hash( c, obj->m_currentState );
        }
    }
#endif

    //
    // Random value
    
	Hash( c, syncfrand(255) );
	
	uint32 hashResult[5];
	hash_final(&c, hashResult);
	result = hashResult[0] & 0xFF;
		
    END_PROFILE( "GenerateSyncValue" );

    return result;
}
bool PylonStart::Advance()
{
    //
    // Is the Generator online?

    bool generatorOnline = false;

    int generatorLocationId = g_app->m_globalWorld->GetLocationId("generator");
    GlobalBuilding *globalRefinery = NULL;
    for( int i = 0; i < g_app->m_globalWorld->m_buildings.Size(); ++i )
    {
        if( g_app->m_globalWorld->m_buildings.ValidIndex(i) )
        {
            GlobalBuilding *gb = g_app->m_globalWorld->m_buildings[i];
            if( gb && gb->m_locationId == generatorLocationId &&
                gb->m_type == TypeGenerator && gb->m_online )
            {
                generatorOnline = true;
                break;
            }
        }
    }

    if( generatorOnline )
    {
        //
        // Is our required building online yet?
        GlobalBuilding *globalBuilding = g_app->m_globalWorld->GetBuilding( m_reqBuildingId, g_app->m_locationId );
        if( globalBuilding && globalBuilding->m_online )
        {
            if( syncfrand() > 0.7f )
            {
                TriggerSurge(0.0f);
            }
        }
    }

    return PowerBuilding::Advance();
}
bool SolarPanel::Advance()
{
    float fractionOccupied = (float) GetNumPortsOccupied() / (float) GetNumPorts();

    if( syncfrand(20.0f) <= fractionOccupied )
    {
        TriggerSurge(0.0f);
    }

    if( fractionOccupied > 0.6f )
    {
        if( !m_operating ) g_app->m_soundSystem->TriggerBuildingEvent( this, "Operate" );
        m_operating = true;
    }

    if( fractionOccupied < 0.3f )
    {
        if( m_operating ) g_app->m_soundSystem->StopAllSounds( m_id, "SolarPanel Operate" );
        m_operating = false;
    }

    return PowerBuilding::Advance();
}
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;
}
bool AntHill::Advance()
{
    Building::Advance();

    //
    // Is the world awake yet ?

    if( !g_app->m_location ) return false;
    if( !g_app->m_location->m_teams ) return false;
    if( g_app->m_location->m_teams[ m_id.GetTeamId() ].m_teamType != Team::TeamTypeCPU ) return false;


    bool popLocked = PopulationLocked();

    //
    // Is it time to look for a new objective?

    if( !popLocked && GetHighResTime() > m_objectiveTimer && m_objectives.Size() < 3 )
    {
        Vector3 targetPos;
        WorldObjectId targetId;
        bool targetFound = false;

        if( !targetFound )      targetFound = SearchForDarwinians   ( targetPos, targetId );
        if( !targetFound )      targetFound = SearchForEnemies      ( targetPos, targetId );
        if( !targetFound )      targetFound = SearchForSpirits      ( targetPos );
        if( !targetFound )      targetFound = SearchForScoutArea    ( targetPos );

        if( targetFound )
        {
            AntObjective *objective = new AntObjective();
            objective->m_pos = targetPos;
            objective->m_targetId = targetId;

            objective->m_numToSend = 5 + 5 * (g_app->m_difficultyLevel / 10.0);
            m_objectives.PutData( objective );
        }

        m_objectiveTimer = GetHighResTime() + syncrand() % 5;
    }


    //
    // Send out ants to our existing objectives

    if( !popLocked &&
        m_objectives.Size() > 0 &&
        GetHighResTime() > m_spawnTimer &&
        m_numAntsInside > 0 )
    {

        Unit *unit = g_app->m_location->GetUnit( WorldObjectId( m_id.GetTeamId(), m_unitId, -1, -1 ) );
        if( !unit )
        {
            unit = g_app->m_location->m_teams[m_id.GetTeamId()].NewUnit( Entity::TypeArmyAnt, m_numAntsInside, &m_unitId, m_pos );
        }

        int chosenIndex = syncrand() % m_objectives.Size();
        AntObjective *objective = m_objectives[chosenIndex];
        Vector3 spawnPos = m_pos;
        spawnPos.y = g_app->m_location->m_landscape.m_heightMap->GetValue( spawnPos.x, spawnPos.z );

        WorldObjectId spawnedId = g_app->m_location->SpawnEntities( spawnPos, m_id.GetTeamId(), m_unitId, Entity::TypeArmyAnt, 1, g_zeroVector, 10.0f );
        ArmyAnt *ant = (ArmyAnt *) g_app->m_location->GetEntity( spawnedId );

        ant->m_buildingId = m_id.GetUniqueId();
        ant->m_front = ( ant->m_pos - m_pos ).Normalise();
        ant->m_orders = ArmyAnt::ScoutArea;
        ant->m_wayPoint = objective->m_pos;
        ant->m_targetId = objective->m_targetId;
	    float radius = syncfrand(30.0f);
	    float theta = syncfrand(M_PI * 2);
    	ant->m_wayPoint.x += radius * sinf(theta);
	    ant->m_wayPoint.z += radius * cosf(theta);
        ant->m_wayPoint = ant->PushFromObstructions( ant->m_wayPoint );
        ant->m_wayPoint.y = g_app->m_location->m_landscape.m_heightMap->GetValue( ant->m_wayPoint.x, ant->m_wayPoint.z );

        m_numAntsInside--;

        objective->m_numToSend--;
        if( objective->m_numToSend <= 0 )
        {
            m_objectives.RemoveData( chosenIndex );
        }

        m_spawnTimer = GetHighResTime() + 0.2f - (0.2 * g_app->m_difficultyLevel / 10.0);
    }


    //
    // Convert spirits into ants

    if( m_numSpiritsInside > 0 &&
        GetHighResTime() > m_eggConvertTimer )
    {
        m_numSpiritsInside--;
        m_numAntsInside += 3;

        m_eggConvertTimer = GetHighResTime() + 5.0f;
    }


    //
    // Flicker if we are damaged

    float healthFraction = (float) m_health / 100.0f;
    float timeIndex = g_gameTime + m_id.GetUniqueId() * 10;
    m_renderDamaged = ( frand(0.75f) * (1.0f - fabs(sinf(timeIndex))*1.2f) > healthFraction );


    return ( m_health <= 0 );
}
void SoulDestroyer::Attack( Vector3 const &_pos )
{
    int numFound;
    g_app->m_location->m_entityGrid->GetEnemies( s_neighbours, _pos.x, _pos.z, SOULDESTROYER_DAMAGERANGE, &numFound, m_id.GetTeamId() );

    for( int i = 0; i < numFound; ++i )
    {
        WorldObjectId id = s_neighbours[i];
        Entity *entity = (Entity *) g_app->m_location->GetEntity( id );        
        bool killed = false;

        Vector3 pushVector = ( entity->m_pos - _pos );
        double distance = pushVector.Mag();       
        if( distance < SOULDESTROYER_DAMAGERANGE )
        {
            g_app->m_soundSystem->TriggerEntityEvent( this, "Attack" );

            pushVector.SetLength( SOULDESTROYER_DAMAGERANGE - distance );
                                        
            g_app->m_location->m_entityGrid->RemoveObject( id, entity->m_pos.x, entity->m_pos.z, entity->m_radius );
            entity->m_pos += pushVector;
            g_app->m_location->m_entityGrid->AddObject( id, entity->m_pos.x, entity->m_pos.z, entity->m_radius );
            
            bool dead = entity->m_dead;
            entity->ChangeHealth( (SOULDESTROYER_DAMAGERANGE - distance) * -50.0 );            
            if( !dead && entity->m_dead ) killed = true;
        }

        if( killed )
        {
            // Eat the spirit
            int spiritIndex = g_app->m_location->GetSpirit( id );
            if( spiritIndex != -1 )
            {
                g_app->m_location->m_spirits.RemoveData( spiritIndex );
                if( m_spirits.NumUsed() < SOULDESTROYER_MAXSPIRITS )
                {
                    m_spirits.PutData( (double) GetHighResTime() );
                }
                else
                {
                    // Doesnt need to be sync safe
                    int index = AppRandom() % SOULDESTROYER_MAXSPIRITS;
                    m_spirits.PutData( (double) GetHighResTime(), index );
                }
            }
            
			if(entity->m_type == TypeDarwinian )
            {
				// Create a zombie
				Zombie *zombie = new Zombie();
				zombie->m_pos = entity->m_pos;
				zombie->m_front = entity->m_front;
				zombie->m_up = g_upVector;
				zombie->m_up.RotateAround( zombie->m_front * syncsfrand(1) );
				zombie->m_vel = m_vel * 0.5;
				zombie->m_vel.y = 20.0 + syncfrand(25.0);
				int index = g_app->m_location->m_effects.PutData( zombie );
				zombie->m_id.Set( id.GetTeamId(), UNIT_EFFECTS, index, -1 );
				zombie->m_id.GenerateUniqueId();
			}
        }
    } 
}
bool LaserFence::Advance ()
{
    if( !m_radiusSet )
    {
        Building *building = g_app->m_location->GetBuilding( m_nextLaserFenceId );
        if( building )
        {
            m_centrePos = ( building->m_pos + m_pos ) / 2.0f;
            m_radius = ( building->m_pos - m_pos ).Mag() / 2.0f + m_radius;
        }
        m_radiusSet = true;
    }

    if( m_mode != ModeDisabled )
    {
        m_sparkTimer -= SERVER_ADVANCE_PERIOD;
        if( m_sparkTimer < 0.0f )
        {
            m_sparkTimer = 8.0f + syncfrand(4.0f);
            Spark();
        }
    }

    switch( m_mode )
    {
        case ModeEnabling:
            m_status += LASERFENCE_RAISESPEED * SERVER_ADVANCE_PERIOD;
            if( m_status >= 0.5f && m_nextLaserFenceId != -1 && !m_nextToggled )
            {
                LaserFence *nextFence = (LaserFence *) g_app->m_location->GetBuilding( m_nextLaserFenceId );
                if( nextFence )
				{
					nextFence->Enable();
					m_nextToggled = true;
				}
            }
            if( m_status >= 1.0f )
            {
                m_status = 1.0f;
                m_mode = ModeEnabled;
                if( m_nextLaserFenceId == -1)
                {
                    g_app->m_location->m_obstructionGrid->CalculateAll();
                }
            }
            break;

        case ModeDisabling:
            if( m_status <= 0.5f && m_nextLaserFenceId != -1 && !m_nextToggled)
            {
                LaserFence *nextFence = (LaserFence *) g_app->m_location->GetBuilding( m_nextLaserFenceId );
                if( nextFence )
				{
					nextFence->Disable();
					m_nextToggled = true;
				}
            }
            m_status -= LASERFENCE_RAISESPEED * SERVER_ADVANCE_PERIOD;
            if( m_status <= 0.0f )
            {
                m_status = 0.0f;
                m_mode = ModeDisabled;
                if( m_nextLaserFenceId == -1)
                {
                    g_app->m_location->m_obstructionGrid->CalculateAll();
                }
            }
            break;

        case ModeEnabled:
        {
            if( m_status < 1.0f )
            {
                m_status = 1.0f;
                if( m_nextLaserFenceId == -1)
                {
                    g_app->m_location->m_obstructionGrid->CalculateAll();
                }
            }
            break;
        }
        case ModeDisabled:
            m_status = 0.0f;
            break;
    }

    return Building::Advance();
}