예제 #1
0
void Build::_buildAll()
{
  __D_REF(d,Build);
  auto command = d.renderer->mode().as<BuildMode>();
  if( command.isNull() )
    return;

  ConstructionPtr construction = command->contruction();

  if( !construction.isValid() )
  {
    Logger::warning( "LayerBuild: No construction for build" );
    return;
  }

  if( !_city()->treasury().haveMoneyForAction( 1 ) )
  {
    events::dispatch<WarningMessage>( "##out_of_credit##", 2 );
    return;
  }

  bool buildOk = false;
  bool tileBusyBuilding = false;
  city::AreaInfo areaInfo( _city(), TilePos() );
  for( auto tile : d.buildTiles )
  {
    areaInfo.pos = tile->epos();
    tileBusyBuilding |= tile->overlay().is<Building>();

    if( construction->canBuild( areaInfo ) && tile->isMaster())
    {
      events::dispatch<BuildAny>( tile->epos(), construction->type() );
      buildOk = true;

      events::dispatch<UndoAction>( UndoAction::built, construction->type(),
                                    tile->epos(), construction->info().cost() );
    }
  }

  d.startTilePos = d.lastTilePos;

  if( !buildOk )
  {
    std::string errorStr = construction->errorDesc();
    std::string busyText = tileBusyBuilding
                              ? "##need_build_on_free_area##"
                              : "##need_build_on_cleared_area##";
    events::dispatch<WarningMessage>( errorStr.empty() ? busyText : errorStr,
                                         WarningMessage::neitral );
  }

  d.needUpdateTiles = true;
}
예제 #2
0
void BuildAny::_exec( Game& game, unsigned int )
{  
  if( _overlay.isNull() )
    return;

  TileOverlayPtr ctOv = game.city()->getOverlay( _pos );

  bool mayBuild = true;
  if( ctOv.isValid() )
  {
    mayBuild = ctOv->isDestructible();
  }

  city::Helper helper( game.city() );
  TilePos offset(10, 10);
  EnemySoldierList enemies = helper.find<EnemySoldier>( walker::any, _pos - offset, _pos + offset );
  if( !enemies.empty() && _overlay->group() != objects::disasterGroup )
  {
    GameEventPtr e = WarningMessage::create( "##too_close_to_enemy_troops##" );
    e->dispatch();
    return;
  }

  if( !_overlay->isDeleted() && mayBuild )
  {
    CityAreaInfo info = { game.city(), _pos, TilesArray() };
    bool buildOk = _overlay->build( info );

    if( !buildOk )
      return;

    helper.updateDesirability( _overlay, city::Helper::onDesirability );
    game.city()->addOverlay( _overlay );

    ConstructionPtr construction = ptr_cast<Construction>( _overlay );
    if( construction.isValid() )
    {
      const MetaData& buildingData = MetaDataHolder::getData( _overlay->type() );
      game.city()->funds().resolveIssue( FundIssue( city::Funds::buildConstruction,
                                                    -(int)buildingData.getOption( MetaDataOptions::cost ) ) );

      if( construction->group() != objects::disasterGroup )
      {
        GameEventPtr e = PlaySound::create( "buildok", 1, 100 );
        e->dispatch();
      }

      if( construction->isNeedRoadAccess() && construction->getAccessRoads().empty() )
      {
        GameEventPtr e = WarningMessage::create( "##building_need_road_access##" );
        e->dispatch();
      }

      std::string error = construction->errorDesc();
      if( !error.empty() )
      {
        GameEventPtr e = WarningMessage::create( error );
        e->dispatch();
      }

      WorkingBuildingPtr wb = ptr_cast<WorkingBuilding>( construction );
      if( wb.isValid() && wb->maximumWorkers() > 0 )
      {
        unsigned int worklessCount = statistic::getWorklessNumber( game.city() );
        if( worklessCount < wb->maximumWorkers() )
        {
          GameEventPtr e = WarningMessage::create( "##city_need_more_workers##" );
          e->dispatch();
        }
      }
    }
  }
  else
  {
    ConstructionPtr construction = ptr_cast<Construction>( _overlay );
    if( construction.isValid() )
    {
      GameEventPtr e = WarningMessage::create( construction->errorDesc() );
      e->dispatch();
    }
  }
}