Pathway Emigrant::_findSomeWay( TilePos startPoint ) { HousePtr house = _findBlankHouse(); _d->failedWayCount++; Pathway pathway; if( house.isValid() ) { pathway = PathwayHelper::create( startPoint, house->pos(), PathwayHelper::roadFirst ); if( !pathway.isValid() ) { pathway = PathwayHelper::create( startPoint, ptr_cast<Construction>(house), PathwayHelper::roadFirst ); } if( pathway.isValid() ) { _lockHouse( house ); } } if( !pathway.isValid() || _d->failedWayCount > 10 ) { pathway = PathwayHelper::create( startPoint, _city()->borderInfo().roadExit, PathwayHelper::allTerrain ); } return pathway; }
void Religion::handleEvent(NEvent& event) { if( event.EventType == sEventMouse ) { switch( event.mouse.type ) { case mouseMoved: { Tile* tile = _camera()->at( event.mouse.pos(), false ); // tile under the cursor (or NULL) std::string text = ""; if( tile != 0 ) { HousePtr house = ptr_cast<House>( tile->overlay() ); if( house.isValid() ) { int templeAccess = house->spec().computeReligionLevel( house ); bool oracleAccess = house->hasServiceAccess( Service::oracle ); text = (templeAccess == 5 && oracleAccess ) ? "##religion_access_full##" : utils::format( 0xff, "##religion_access_%d_temple##", templeAccess ); } } _setTooltipText( _(text) ); } break; default: break; } } Layer::handleEvent( event ); }
void Immigrant::onDestination() { bool gooutCity = true; if( _d->destination.getI() > 0 && _d->destination.getJ() > 0 ) //have destination { const Tile& tile = _getCity()->getTilemap().at( _d->destination ); HousePtr house = tile.getOverlay().as<House>(); if( house.isValid() ) { int freeRoom = house->getMaxHabitants() - house->getHabitants().count(); if( freeRoom > 0 ) { house->addHabitants( _d->peoples ); Walker::onDestination(); gooutCity = (_d->peoples.count() > 0); } } } if( gooutCity ) { _findPath2blankHouse( _getCity()->getTilemap().at( getIJ() ) ); } else { deleteLater(); } }
HousePtr Immigrant::_findBlankHouse() { CityHelper hlp( _getCity() ); HouseList houses = hlp.find< House >( building::house ); HousePtr blankHouse; _d->destination = TilePos( -1, -1 ); HouseList::iterator itHouse = houses.begin(); while( itHouse != houses.end() ) { if( (*itHouse)->getAccessRoads().size() > 0 && ( (*itHouse)->getHabitants().count() < (*itHouse)->getMaxHabitants() ) ) { itHouse++; } else { itHouse = houses.erase( itHouse ); } } if( houses.size() > 0 ) { itHouse = houses.begin(); std::advance(itHouse, rand() % houses.size() ); blankHouse = *itHouse; _d->destination = blankHouse->getTilePos(); } return blankHouse; }
void MarketAccess::handleEvent(NEvent& event) { if( event.EventType == sEventMouse ) { switch( event.mouse.type ) { case mouseMoved: { Tile* tile = _camera()->at( event.mouse.pos(), false ); // tile under the cursor (or NULL) std::string text = ""; if( tile != 0 ) { HousePtr house = tile->overlay<House>(); if( house.isValid() ) { int accessLevel = house->getServiceValue( Service::market ); accessLevel = math::clamp<int>( accessLevel / maxAccessLevel, 0, maxAccessLevel-1 ); text = marketLevelName[ accessLevel ]; } } _setTooltipText( text ); } break; default: break; } } Layer::handleEvent( event ); }
void Sentiment::handleEvent(NEvent& event) { if( event.EventType == sEventMouse ) { switch( event.mouse.type ) { case mouseMoved: { Tile* tile = _camera()->at( event.mouse.pos(), false ); // tile under the cursor (or NULL) std::string text = ""; if( tile != 0 ) { HousePtr house = tile->overlay().as<House>(); if( house.isValid() ) { int happiness = math::clamp<int>( house->state( pr::happiness ) / maxSentimentLevel, 0, maxSentimentLevel-1 ); text = sentimentLevelName[ happiness ]; } } _setTooltipText( text ); } break; default: break; } } Layer::handleEvent( event ); }
void HouseManager::load(const std::string& fileName) { try { TiXmlDocument doc; doc.Parse(g_resources.readFileContents(fileName).c_str()); if(doc.Error()) stdext::throw_exception(stdext::format("failed to load '%s': %s (House XML)", fileName, doc.ErrorDesc())); TiXmlElement *root = doc.FirstChildElement(); if(!root || root->ValueTStr() != "houses") stdext::throw_exception("invalid root tag name"); for(TiXmlElement *elem = root->FirstChildElement(); elem; elem = elem->NextSiblingElement()) { if(elem->ValueTStr() != "house") stdext::throw_exception("invalid house tag."); uint32 houseId = elem->readType<uint32>("houseid"); HousePtr house = getHouse(houseId); if(!house) house = HousePtr(new House(houseId)), addHouse(house); house->load(elem); } } catch(std::exception& e) { g_logger.error(stdext::format("Failed to load '%s': %s", fileName, e.what())); } }
void Health::drawTile(Engine& engine, Tile& tile, const Point& offset) { Point screenPos = tile.mappos() + offset; if( tile.overlay().isNull() ) { //draw background //engine.draw( tile.picture(), screenPos ); drawPass( engine, tile, offset, Renderer::ground ); drawPass( engine, tile, offset, Renderer::groundAnimation ); } else { bool needDrawAnimations = false; OverlayPtr overlay = tile.overlay(); int healthLevel = -1; if( _isVisibleObject( overlay->type() ) ) { // Base set of visible objects needDrawAnimations = true; } else if( _flags.count( overlay->type() ) ) { needDrawAnimations = true; //city::Helper helper( _city() ); //drawArea( engine, helper.getArea( overlay ), offset, ResourceGroup::foodOverlay, OverlayPic::base ); } else if( overlay->type() == object::house ) { HousePtr house = ptr_cast<House>( overlay ); healthLevel = _getLevelValue( house ); needDrawAnimations = (house->spec().level() == 1) && (house->habitants().empty()); if( !needDrawAnimations ) { drawArea( engine, overlay->area(), offset, ResourceGroup::foodOverlay, OverlayPic::inHouseBase ); } } else //other buildings { drawArea( engine, overlay->area(), offset, ResourceGroup::foodOverlay, OverlayPic::base ); } if( needDrawAnimations ) { Layer::drawTile( engine, tile, offset ); registerTileForRendering( tile ); } else if( healthLevel > 0 ) { drawColumn( engine, screenPos, healthLevel ); } } tile.setWasDrawn(); }
void Tax::drawTile(Engine& engine, Tile& tile, const Point& offset) { Point screenPos = tile.mappos() + offset; if( tile.overlay().isNull() ) { //draw background engine.draw( tile.picture(), screenPos ); } else { bool needDrawAnimations = false; TileOverlayPtr overlay = tile.overlay(); int taxLevel = -1; if( _isVisibleObject( overlay->type() ) ) { // Base set of visible objects needDrawAnimations = true; } else if( overlay->type() == objects::house ) { HousePtr house = ptr_cast<House>( overlay ); //taxLevel = house->getServiceValue( Service::forum ); taxLevel = math::clamp<int>( house->taxesThisYear(), 0, 100 ); needDrawAnimations = (house->spec().level() == 1) && (house->habitants().empty()); if( needDrawAnimations ) { int taxAccess = house->hasServiceAccess( Service::forum ); needDrawAnimations = (taxAccess < 25); } if( !needDrawAnimations ) { city::Helper helper( _city() ); drawArea( engine, helper.getArea( overlay ), offset, ResourceGroup::foodOverlay, OverlayPic::inHouseBase ); } } else { city::Helper helper( _city() ); drawArea( engine, helper.getArea( overlay ), offset, ResourceGroup::foodOverlay, OverlayPic::base ); } if( needDrawAnimations ) { Layer::drawTile( engine, tile, offset ); registerTileForRendering( tile ); } else if( taxLevel > 0 ) { _addColumn( screenPos, taxLevel ); //drawColumn( engine, screenPos, taxLevel ); } } tile.setWasDrawn(); }
void Unemployed::drawTile(Engine& engine, Tile& tile, const Point& offset) { Point screenPos = tile.mappos() + offset; if( tile.overlay().isNull() ) { //draw background //engine.draw( tile.picture(), screenPos ); drawPass( engine, tile, offset, Renderer::ground ); drawPass( engine, tile, offset, Renderer::groundAnimation ); } else { bool needDrawAnimations = false; OverlayPtr overlay = tile.overlay(); WorkingBuildingPtr workBuilding = overlay.as<WorkingBuilding>(); int worklessPercent = 0; if( _isVisibleObject( overlay->type() ) ) { needDrawAnimations = true; } else if( overlay->type() == object::house ) { HousePtr house = overlay.as<House>(); int worklessNumber = (int)house->getServiceValue( Service::recruter ); int matureNumber = (int)house->habitants().mature_n(); worklessPercent = math::percentage( worklessNumber, matureNumber ); needDrawAnimations = (house->spec().level() == 1) && house->habitants().empty(); if( !needDrawAnimations ) { drawArea( engine, overlay->area(), offset, ResourceGroup::foodOverlay, OverlayPic::inHouseBase ); } } else if( workBuilding.isValid() ) { worklessPercent = math::percentage( workBuilding->needWorkers(), workBuilding->maximumWorkers() ); needDrawAnimations = workBuilding->needWorkers() > 0; if( !needDrawAnimations ) drawArea( engine, overlay->area(), offset, ResourceGroup::foodOverlay, OverlayPic::base ); } if( needDrawAnimations ) { Layer::drawTile( engine, tile, offset ); registerTileForRendering( tile ); } else if( worklessPercent > 0 ) { drawColumn( engine, screenPos, worklessPercent ); } } tile.setWasDrawn(); }
void Emigrant::_append2house( HousePtr house ) { int freeRoom = house->maxHabitants() - house->habitants().count(); if( freeRoom > 0 ) { house->addHabitants( _d->peoples ); _lockHouse( HousePtr() ); } }
foreach( it, buildings ) { if( (*it)->type() == object::house ) { HousePtr house = it->as<House>(); TilePos pos = house->pos(); int hash = (pos.i() << 8) | pos.i(); _d->servedHouses[ hash ] = house->habitants().count(); } }
GuiInfoBox* create( Widget* parent, const Tile& tile ) { HousePtr house = tile.getTerrain().getOverlay().as<House>(); if( house->getNbHabitants() > 0 ) { return new InfoBoxHouse( parent, tile ); } else { return new InfoBoxFreeHouse( parent, tile ); } }
void Peace::buildingDestroyed(gfx::TileOverlayPtr overlay) { HousePtr house = ptr_cast<House>( overlay ); if( house.isValid() && house->spec().level() > HouseLevel::tent ) { _d->significantBuildingsDestroyed = true; } else { _d->significantBuildingsDestroyed |= !_d->unsignificantBuildings.count( overlay->type() ); } }
int LayerHealth::_getLevelValue( HousePtr house ) { switch(_type) { case citylayer::health: return (int) house->state( House::health ); case citylayer::hospital: return (int) house->getServiceValue( Service::hospital ); case citylayer::barber: return (int) house->getServiceValue( Service::barber ); case citylayer::baths: return (int) house->getServiceValue( Service::baths ); } return 0; }
void Fire::drawTile(Engine& engine, Tile& tile, const Point& offset) { Point screenPos = tile.mappos() + offset; if( tile.overlay().isNull() ) { //draw background //engine.draw( tile.picture(), screenPos ); drawPass( engine, tile, offset, Renderer::ground ); drawPass( engine, tile, offset, Renderer::groundAnimation ); } else { bool needDrawAnimations = false; OverlayPtr overlay = tile.overlay(); int fireLevel = 0; if( _isVisibleObject( overlay->type() ) ) { // Base set of visible objects needDrawAnimations = true; } else if( overlay->type() == object::house ) { HousePtr house = ptr_cast<House>( overlay ); fireLevel = (int)house->state( pr::fire ); needDrawAnimations = (house->spec().level() == 1) && house->habitants().empty(); drawArea( engine, overlay->area(), offset, ResourceGroup::foodOverlay, OverlayPic::inHouseBase ); } else //other buildings { ConstructionPtr constr = ptr_cast<Construction>( overlay ); if( constr != 0 ) { fireLevel = (int)constr->state( pr::fire ); } drawArea( engine, overlay->area(), offset, ResourceGroup::foodOverlay, OverlayPic::base ); } if( needDrawAnimations ) { Layer::drawTile( engine, tile, offset ); registerTileForRendering( tile ); } else if( fireLevel >= 0) { _addColumn( screenPos, fireLevel ); } } tile.setWasDrawn(); }
void Sentiment::drawTile(Engine& engine, Tile& tile, const Point& offset) { Point screenPos = tile.mappos() + offset; if( tile.overlay().isNull() ) { //draw background //engine.draw( tile.picture(), screenPos ); drawPass( engine, tile, offset, Renderer::ground ); drawPass( engine, tile, offset, Renderer::groundAnimation ); } else { bool needDrawAnimations = false; OverlayPtr overlay = tile.overlay(); int sentimentLevel = 0; if( _isVisibleObject( overlay->type() ) ) { needDrawAnimations = true; } else if( overlay->type() == object::house ) { HousePtr house = overlay.as<House>(); sentimentLevel = (int)house->state( pr::happiness ); needDrawAnimations = (house->spec().level() == 1) && house->habitants().empty(); if( !needDrawAnimations ) { drawArea( engine, overlay->area(), offset, ResourceGroup::foodOverlay, OverlayPic::inHouseBase ); } } else { drawArea( engine, overlay->area(), offset, ResourceGroup::foodOverlay, OverlayPic::base ); } if( needDrawAnimations ) { Layer::drawTile( engine, tile, offset ); registerTileForRendering( tile ); } else if( sentimentLevel > 0 ) { drawColumn( engine, screenPos, 100 - sentimentLevel ); } } tile.setWasDrawn(); }
void Emigrant::_reachedPathway() { bool gooutCity = true; Walker::_reachedPathway(); if( pos() == _city()->borderInfo().roadExit ) { city::MigrationPtr migration; migration << _city()->findService( city::Migration::defaultName() ); if( migration.isValid() ) { migration->citizenLeaveCity( this ); } deleteLater(); return; } HousePtr house = ptr_cast<House>( _city()->getOverlay( pos() ) ); if( house.isValid() ) { _append2house( house ); gooutCity = (_d->peoples.count() > 0); } else { if( _checkNearestHouse() ) { return; } } if( gooutCity ) { Pathway way = _findSomeWay( pos() ); if( way.isValid() ) { _updatePathway( way ); go(); } else { die(); } } else { deleteLater(); } }
void Religion::drawTile(Engine& engine, Tile& tile, const Point& offset) { Point screenPos = tile.mappos() + offset; if( tile.overlay().isNull() ) { //draw background //engine.draw( tile.picture(), screenPos ); drawPass( engine, tile, offset, Renderer::ground ); drawPass( engine, tile, offset, Renderer::groundAnimation ); } else { bool needDrawAnimations = false; OverlayPtr overlay = tile.overlay(); int religionLevel = -1; if( _isVisibleObject( overlay->type() ) ) { // Base set of visible objects needDrawAnimations = true; } else if( overlay->type() == object::house ) { HousePtr house = ptr_cast<House>( overlay ); religionLevel = (int) house->getServiceValue(Service::religionMercury); religionLevel += house->getServiceValue(Service::religionVenus); religionLevel += house->getServiceValue(Service::religionMars); religionLevel += house->getServiceValue(Service::religionNeptune); religionLevel += house->getServiceValue(Service::religionCeres); religionLevel = math::clamp( religionLevel / (house->spec().minReligionLevel()+1), 0, 100 ); needDrawAnimations = (house->spec().level() == 1) && house->habitants().empty(); if( !needDrawAnimations ) { drawArea( engine, overlay->area(), offset, ResourceGroup::foodOverlay, OverlayPic::inHouseBase ); } } else { drawArea( engine, overlay->area(), offset, ResourceGroup::foodOverlay, OverlayPic::base ); } if( needDrawAnimations ) { Layer::drawTile( engine, tile, offset ); registerTileForRendering( tile ); } else if( religionLevel > 0 ) { drawColumn( engine, screenPos, religionLevel ); } } tile.setWasDrawn(); }
void TaxCollector::onMidTile() { ServiceWalker::onMidTile(); ReachedBuildings buildings = getReachedBuildings( getIJ() ); for( ReachedBuildings::iterator it=buildings.begin(); it != buildings.end(); it++ ) { HousePtr house = (*it).as<House>(); if( house.isValid() ) { int money = house->collectTaxes(); _d->money += money; _d->peoplesReached += money > 0 ? house->getNbHabitants() : 0; } } }
void Unemployed::handleEvent(NEvent& event) { if( event.EventType == sEventMouse ) { switch( event.mouse.type ) { case mouseMoved: { Tile* tile = _camera()->at( event.mouse.pos(), false ); // tile under the cursor (or NULL) std::string text = ""; if( tile != 0 ) { HousePtr house = tile->overlay().as<House>(); WorkingBuildingPtr workBuilding = tile->overlay().as<WorkingBuilding>(); if( house.isValid() ) { int workless = house->getServiceValue( Service::recruter ); if( workless > 0 ) text = utils::format( 0xff, "%s %d %s", _("##this_house_have##"), workless, _("##unemployers##") ); else text = "##this_house_haveno_unemployers##"; } else if( workBuilding.isValid() ) { int need = workBuilding->needWorkers(); if( need > 0 ) text = utils::format( 0xff, "%s %d %s", _("##this_building_need##"), need, _("##workers##") ); else text = "##this_building_have_all_workers##"; } } _setTooltipText( text ); } break; default: break; } } Layer::handleEvent( event ); }
int Education::_getLevelValue( HousePtr house ) const { switch(_type) { case citylayer::education: { float acc = 0; int level = house->spec().minEducationLevel(); switch(level) { case 3: acc += house->getServiceValue( Service::academy ); case 2: acc += house->getServiceValue( Service::library ); case 1: acc += house->getServiceValue( Service::school ); return static_cast<int>(acc / level); default: return 0; } } case citylayer::school: return (int) house->getServiceValue( Service::school ); case citylayer::library: return (int) house->getServiceValue( Service::library ); case citylayer::academy: return (int) house->getServiceValue( Service::academy ); } return 0; }
bool Emigrant::_checkNearestHouse() { city::Helper helper( _city() ); for( int k=1; k < 3; k++ ) { TilePos offset( k, k ); HouseList houses = helper.find<House>( building::house, pos()-offset, pos() + offset ); std::map< int, HousePtr > vacantRoomPriority; foreach( it, houses ) { HousePtr house = *it; unsigned int freeRoom = house->maxHabitants() - house->habitants().count(); vacantRoomPriority[ 1000 - freeRoom ] = house; } foreach( it, vacantRoomPriority ) //have destination { HousePtr house = it->second; int freeRoom = house->maxHabitants() - house->habitants().count(); if( freeRoom > 0 ) { Pathway pathway = PathwayHelper::create( pos(), house->pos(), makeDelegate( _d.data(), &Impl::mayWalk ) ); _updatePathway( pathway ); go(); return true; } }
void RandomPlague::_exec( Game& game, unsigned int time) { int population = game.city()->states().population; if( _d->popRange.contain( population ) ) { Logger::info( "Execute random plague event" ); _d->isDeleted = true; HouseList houses = game.city()->statistic().houses.habitable(); unsigned int number4burn = math::clamp<unsigned int>( (houses.size() * _d->strong / 100), 1u, 100u ); for( unsigned int k=0; k < number4burn; k++ ) { HousePtr house = houses.random(); house->setState( pr::health, 0.f ); } } }
void Tax::handleEvent(NEvent& event) { if( event.EventType == sEventMouse ) { switch( event.mouse.type ) { case mouseMoved: { Tile* tile = _camera()->at( event.mouse.pos(), false ); // tile under the cursor (or NULL) std::string text = ""; if( tile != 0 ) { BuildingPtr bld = ptr_cast<Building>( tile->overlay() ); if( bld.isNull() ) { text = "##no_people_in_this_locality##"; } else { HousePtr house = ptr_cast<House>( tile->overlay() ); if( house.isValid() ) { int taxAccess = house->hasServiceAccess( Service::forum ); if( taxAccess < 25 ) text = "##house_not_registered_for_taxes##"; } } } _setTooltipText( _(text) ); } break; default: break; } } Layer::handleEvent( event ); }
void TaxCollector::_centerTile() { Walker::_centerTile(); int difficulty = SETTINGS_VALUE(difficulty); float multiply = 1.0f; switch (difficulty) { case 0: multiply = 3.0f; break; case 1: multiply = 2.0f; break; case 2: multiply = 1.5f; break; case 3: multiply = 1.0f; break; case 4: multiply = 0.75f; break; } ReachedBuildings buildings = getReachedBuildings( pos() ); foreach( it, buildings ) { HousePtr house = ptr_cast<House>( *it ); if( house.isValid() ) { float tax = house->collectTaxes() * multiply; _d->money += tax; house->applyService( this ); std::string posStr = utils::format( 0xff, "%02dx%02d", house->pos().i(), house->pos().j() ); _d->history[ posStr ] += tax; } }
void CityServiceEmigrant::update( const unsigned int time ) { if( time % 44 != 1 ) return; unsigned int vacantPop=0; LandOverlays houses = _d->city->getBuildingList(B_HOUSE); for( LandOverlays::iterator itHouse = houses.begin(); itHouse != houses.end(); ++itHouse ) { HousePtr house = (*itHouse).as<House>(); if( house.isValid() && house->getAccessRoads().size() > 0 ) { vacantPop += math::clamp( house->getMaxHabitants() - house->getNbHabitants(), 0, 0xff ); } } if( vacantPop == 0 ) { return; } Walkers walkers = _d->city->getWalkerList( WT_EMIGRANT ); if( vacantPop <= walkers.size() * 5 ) { return; } Tile& roadTile = _d->city->getTilemap().at( _d->city->getRoadEntry() ); EmigrantPtr emigrant = Emigrant::create( _d->city ); if( emigrant.isValid() ) { emigrant->send2City( roadTile ); } }
void Immigrant::_findPath2blankHouse( Tile& startPoint ) { HousePtr house = _findBlankHouse(); Pathway pathWay; Tilemap& citymap = _getCity()->getTilemap(); Tile& destTile = house.isValid() ? house->getTile() : citymap.at( _getCity()->getBorderInfo().roadExit ); Size arrivedArea( house.isValid() ? house->getSize() : 1 ); bool pathFound = Pathfinder::getInstance().getPath( startPoint.getIJ(), destTile.getIJ(), pathWay, false, arrivedArea ); if( pathFound ) { setPathway( pathWay ); setIJ( startPoint.getIJ() ); go(); } if( !pathFound ) { deleteLater(); } }
void Emigrant::_lockHouse( HousePtr house ) { if( _d->housePosLock.i() >= 0 ) { HousePtr oldHouse = ptr_cast<House>( _city()->tilemap().at( _d->housePosLock ).overlay() ); if( oldHouse.isValid() ) { _d->housePosLock = TilePos( -1, -1 ); oldHouse->setState( House::settleLock, 0 ); } } if( house.isValid() ) { _d->housePosLock = house->pos(); house->setState( House::settleLock, TileHelper::hash( _d->housePosLock ) ); } }
int Entertainment::_getLevelValue( HousePtr house ) { switch( _type ) { case citylayer::entertainment: { int entLevel = house->spec().computeEntertainmentLevel( house ); int minLevel = house->spec().minEntertainmentLevel(); return math::percentage( entLevel, minLevel ); } case citylayer::theater: return (int) house->getServiceValue( Service::theater ); case citylayer::amphitheater: return (int) house->getServiceValue( Service::amphitheater ); case citylayer::colloseum: return (int) house->getServiceValue( Service::colloseum ); case citylayer::hippodrome: return (int) house->getServiceValue( Service::hippodrome ); } return 0; }