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; }
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(); } } }