void Disaster::_exec( Game& game, unsigned int ) { Tilemap& tmap = game.city()->tilemap(); Tile& tile = tmap.at( _pos ); TilePos rPos = _pos; bool mayContinue = tile.getFlag( Tile::isDestructible ); if( _type == Disaster::rift ) { mayContinue = tile.getFlag( Tile::isConstructible ); mayContinue |= is_kind_of<Construction>( tile.overlay() ); } if( mayContinue ) { Size size( 1 ); TileOverlayPtr overlay = tile.overlay(); if( overlay.isValid() ) { overlay->deleteLater(); rPos = overlay->pos(); size = overlay->size(); } switch( _type ) { case Disaster::collapse: { GameEventPtr e = PlaySound::create( "explode", rand() % 2, 100 ); e->dispatch(); } break; default: break; } city::PeacePtr peaceSrvc; peaceSrvc << game.city()->findService( city::Peace::defaultName() ); if( peaceSrvc.isValid() ) { peaceSrvc->buildingDestroyed( overlay, _type ); } TilesArray clearedTiles = tmap.getArea( rPos, size ); foreach( tile, clearedTiles ) { bool needBuildRuins = !( _type == Disaster::rift && (*tile)->pos() == _pos ); TileOverlayPtr ov; if( needBuildRuins ) { TileOverlay::Type dstr2constr[] = { objects::burning_ruins, objects::collapsed_ruins, objects::plague_ruins, objects::collapsed_ruins, objects::collapsed_ruins }; ov = TileOverlayFactory::instance().create( dstr2constr[_type] ); if( ov.isValid() ) { SmartPtr< Ruins > ruins = ptr_cast< Ruins >( ov ); if( ruins.isValid() ) { std::string typev = _infoType > 1000 ? utils::format( 0xff, "house%02d", _infoType - 1000 ) : MetaDataHolder::findTypename( _infoType ); ruins->setInfo( utils::format( 0xff, "##ruins_%s_text##", typev.c_str() ) ); ruins->afterBuild(); } } } else { ov = TileOverlayFactory::instance().create( objects::rift ); TilesArray tiles = game.city()->tilemap().getNeighbors(_pos, Tilemap::FourNeighbors); /*foreach( it, tiles ) { ConstructionPtr c = ptr_cast<Construction>( (*it)->overlay() ); if( c.isValid() ) { c->burn(); } }*/ } Dispatcher::instance().append( BuildAny::create( (*tile)->pos(), ov ) ); } std::string dstr2string[] = { "##alarm_fire_in_city##", "##alarm_building_collapsed##", "##alarm_plague_in_city##", "##alarm_earthquake##" }; emit game.city()->onDisasterEvent()( _pos, _( dstr2string[_type] ) ); }
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(); } } }