void Build::drawTile( const RenderInfo& rinfo, Tile& tile ) { __D_IMPL(_d,Build); ConstructionPtr cntr = tile.overlay<Construction>(); city::AreaInfo info( _city(), tile.epos(), &_d->buildTiles ); const Picture* picBasic = 0; const Picture* picOver = 0; if( cntr.isValid() && info.tiles().size() > 0 ) { picBasic = &cntr->picture(); picOver = &cntr->picture( info ); } if( picOver && picBasic != picOver ) { Point screenPos = tile.mappos() + rinfo.offset; drawLandTile( rinfo, tile ); rinfo.engine.draw( *picOver, screenPos ); drawPass( rinfo, tile, Renderer::overlayAnimation ); } else if( _d->lastLayer.isValid() ) { _d->lastLayer->drawTile( rinfo, tile ); } else { Layer::drawTile( rinfo, tile ); } if( !_d->overdrawBuilding ) _tryDrawBuildTile( rinfo, tile ); }
void ShowTileInfo::_exec(Game& game, unsigned int time) { switch( _mode ) { case current: break; case next: case prew: { city::Helper helper( game.city() ); ConstructionPtr c = ptr_cast<Construction>( game.city()->getOverlay( _pos ) ); c = (_mode == next ? helper.next( c ) : helper.prew( c )); if( c.isValid() ) { _pos = c->pos(); GameEventPtr e = MoveCamera::create( _pos ); e->dispatch(); } } break; default: break; } gui::infobox::Manager::getInstance().showHelp( game.city(), game.gui(), _pos ); }
void Fire::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 ) { ConstructionPtr constr = ptr_cast<Construction>( tile->overlay() ); if( constr != 0 ) { int fireLevel = math::clamp<int>( constr->state( pr::fire ), 0, 100 ); text = fireLevelName[ math::clamp<int>( fireLevel / 10, 0, 9 ) ]; } } _setTooltipText( _(text) ); } break; default: break; } } Layer::handleEvent( event ); }
void Game::load(std::string filename) { StringHelper::debug( 0xff, "Load game begin" ); _d->empire->initialize( GameSettings::rcpath( GameSettings::citiesModel ) ); GameLoader loader; _d->loadOk = loader.load( filename, *this); if( !_d->loadOk ) { StringHelper::debug( 0xff, "LOADING ERROR: can't load game from %s", filename.c_str() ); return; } _d->empire->initPlayerCity( _d->city.as<EmpireCity>() ); LandOverlayList& llo = _d->city->getOverlayList(); foreach( LandOverlayPtr overlay, llo ) { ConstructionPtr construction = overlay.as<Construction>(); if( construction.isValid() ) { construction->computeAccessRoads(); } }
void RandomFire::_exec( Game& game, unsigned int time) { int population = game.city()->population(); if( population > _d->minPopulation && population < _d->maxPopulation ) { Logger::warning( "Execute random fire event" ); _d->isDeleted = true; Priorities<int> exclude; exclude << objects::waterGroup << objects::roadGroup << objects::disasterGroup; ConstructionList ctrs; ctrs << game.city()->overlays(); for( ConstructionList::iterator it=ctrs.begin(); it != ctrs.end(); ) { if( exclude.count( (*it)->group() ) ) { it = ctrs.erase( it ); } else { ++it; } } unsigned int number4burn = math::clamp<unsigned int>( (ctrs.size() * _d->strong / 100), 1u, 100u ); for( unsigned int k=0; k < number4burn; k++ ) { ConstructionPtr building = ctrs.random(); building->burn(); } } }
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 Build::_drawBuildTile( const RenderInfo& rinfo, Tile* tile) { if( tile == nullptr ) return; __D_IMPL(_d,Build); city::AreaInfo areaInfo( _city(), TilePos(), &_d->buildTiles ); Tile* postTile = tile; postTile->resetRendered(); if( postTile->master() ) postTile = postTile->master(); ConstructionPtr construction = postTile->overlay<Construction>(); rinfo.engine.resetColorMask(); areaInfo.pos = postTile->epos(); bool maskSet = false; Size size(1,1); if( construction.isValid() && construction->canBuild( areaInfo ) ) { rinfo.engine.setColorMask( 0x00000000, 0x0000ff00, 0, 0xff000000 ); maskSet = true; size = construction->size(); } if( postTile == tile && maskSet ) { TilesArray area = _city()->tilemap().area( areaInfo.pos, size ); for( auto gtile : area ) drawLandTile( rinfo, *gtile ); } drawLandTile( rinfo, *postTile ); if( maskSet ) { const Picture& picOver = construction->picture( areaInfo ); rinfo.engine.draw( picOver, postTile->mappos() + rinfo.offset ); drawPass( rinfo, *postTile, Renderer::overlayAnimation ); rinfo.engine.resetColorMask(); } }
Pathway ChastenerElephant::_findPathway2NearestConstruction( unsigned int range ) { Pathway ret; for( unsigned int tmpRange=1; tmpRange <= range; tmpRange++ ) { ConstructionList constructions = _findContructionsInRange( tmpRange ); foreach( it, constructions ) { ConstructionPtr c = ptr_cast<Construction>( *it ); ret = PathwayHelper::create( pos(), c->pos(), makeDelegate( _d.data(), &Impl::mayMove ) ); if( ret.isValid() ) { return ret; } } }
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 RandomFire::_exec( Game& game, unsigned int time) { int population = game.city()->states().population; if( _d->popRange.contain( population ) ) { Logger::warning( "Execute random fire event" ); _d->isDeleted = true; std::set<object::Group> exclude; exclude << object::group::water << object::group::road << object::group::disaster; ConstructionList ctrs = statistic::getObjectsNotIs<Construction>( game.city(), exclude ); unsigned int number4burn = math::clamp<unsigned int>( (ctrs.size() * _d->strong / 100), 1u, 100u ); for( unsigned int k=0; k < number4burn; k++ ) { ConstructionPtr building = ctrs.random(); building->burn(); } } }
void RomeArcher::timeStep(const unsigned long time) { Soldier::timeStep( time ); switch( _subAction() ) { case Soldier::fightEnemy: { WalkerList enemies = _findEnemiesInRange( attackDistance() ); if( !enemies.empty() ) { WalkerPtr p = enemies.front(); turn( p->pos() ); if( _animationRef().index() == (int)(_animationRef().frameCount()-1) ) { _fire( p->pos() ); _updateAnimation( time+1 ); } } else { //_check4attack(); send2patrol(); } } break; case Soldier::destroyBuilding: { ConstructionList constructions = _findContructionsInRange( attackDistance() ); if( !constructions.empty() ) { ConstructionPtr b = constructions.front(); turn( b->pos() ); if( _animationRef().index() == (int)(_animationRef().frameCount()-1) ) { _fire( b->pos() ); _updateAnimation( time+1 ); } } else { //_check4attack(); send2patrol(); } } case Soldier::patrol: if( game::Date::current().day() % 2 == 0 ) { _tryAttack(); } break; default: break; } // end switch( _d->action ) }
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(); } } }
bool Game::load(std::string filename) { Logger::warning( "Game: try load from " + filename ); Logger::warning( "Game: reseting variables" ); reset(); scene::SplashScreen screen; screen.initialize(); bool usingOldgfx = SETTINGS_VALUE( oldgfx ) || !SETTINGS_VALUE( c3gfx ).toString().empty(); screen.setImage( usingOldgfx ? "load4" : "freska", 1 ); screen.update( *_d->engine ); vfs::Path fPath( filename ); if( !fPath.exist() ) { Logger::warning( "Game: Cannot find file " + fPath.toString() ); fPath = game::Settings::rpath( filename ); if( !fPath.exist() ) { Logger::warning( "Game: Cannot find file " + fPath.toString() ); Logger::warning( "Game: Try find file in resource's folder " ); fPath = game::Settings::rcpath( filename ).absolutePath(); if( !fPath.exist() ) { Logger::warning( "Game: Cannot find file " + fPath.toString() ); return false; } } } Logger::warning( "Game: init empire start options" ); events::Dispatcher::instance().reset(); _d->empire->initialize( SETTINGS_RC_PATH( citiesModel ), SETTINGS_RC_PATH( empireObjectsModel ), SETTINGS_RC_PATH( worldModel ) ); Logger::warning( "Game: try find loader" ); game::Loader loader; loader.onUpdate().connect( &screen, &scene::SplashScreen::setText ); bool loadOk = loader.load( fPath, *this ); if( !loadOk ) { Logger::warning( "LOADING ERROR: can't load game from " + filename ); return false; } _d->restartFile = loader.restartFile(); Logger::warning( "Game: init player city" ); world::CityPtr city = _d->empire->initPlayerCity( ptr_cast<world::City>( _d->city ) ); if( city.isNull() ) { Logger::warning( "INIT ERROR: can't initalize city %s in empire" + _d->city->name() ); return false; } _d->empire->emperor().checkCities(); Logger::warning( "Game: calculate road access for buildings" ); const OverlayList& llo = _d->city->overlays(); for( auto overlay : llo ) { ConstructionPtr construction = overlay.as<Construction>(); if( construction.isValid() ) { construction->computeRoadside(); } } Logger::warning( "Game: initialize local pathfinder" ); Pathfinder::instance().update( _d->city->tilemap() ); Logger::warning( "Game: load finished" ); screen.exitScene( scene::SplashScreen::hideDevText ); return true; }
void Rioter::timeStep(const unsigned long time) { Walker::timeStep( time ); switch( _d->state ) { case Impl::searchHouse: { city::Helper helper( _city() ); ConstructionList constructions = helper.find<Construction>( objects::house ); for( ConstructionList::iterator it=constructions.begin(); it != constructions.end(); ) { HousePtr h = ptr_cast<House>( *it ); if( h->spec().level() <= _d->houseLevel ) { it=constructions.erase( it ); } else { ++it; } } Pathway pathway = _d->findTarget( _city(), constructions, pos() ); //find more expensive house, fire this!!! if( pathway.isValid() ) { setPos( pathway.startPos() ); setPathway( pathway ); go(); _d->state = Impl::go2destination; } else //not find house, try find any, that rioter can destroy { _d->state = Impl::searchAnyBuilding; } } break; case Impl::searchAnyBuilding: { city::Helper helper( _city() ); ConstructionList constructions = helper.find<Construction>( objects::house ); for( ConstructionList::iterator it=constructions.begin(); it != constructions.end(); ) { TileOverlay::Type type = (*it)->type(); TileOverlay::Group group = (*it)->group(); if( type == objects::house || type == objects::road || _d->excludeGroups.count( group ) > 0 ) { it=constructions.erase( it ); } else { it++; } } Pathway pathway = _d->findTarget( _city(), constructions, pos() ); if( pathway.isValid() ) { setPos( pathway.startPos() ); setPathway( pathway ); go(); _d->state = Impl::go2destination; } else { _d->state = Impl::go2anyplace; } } break; case Impl::go2anyplace: { Pathway pathway = PathwayHelper::randomWay( _city(), pos(), 10 ); if( pathway.isValid() ) { setPathway( pathway ); go(); _d->state = Impl::go2destination; } else { die(); _d->state = Impl::wait; } } break; case Impl::go2destination: case Impl::wait: break; case Impl::destroyConstruction: { if( game::Date::isDayChanged() ) { city::Helper helper( _city() ); ConstructionList constructions = helper.find<Construction>( objects::any, pos() - TilePos( 1, 1), pos() + TilePos( 1, 1) ); for( ConstructionList::iterator it=constructions.begin(); it != constructions.end(); ) { if( (*it)->type() == objects::road || _d->excludeGroups.count( (*it)->group() ) > 0 ) { it=constructions.erase( it ); } else { ++it; } } if( constructions.empty() ) { _animationRef().clear(); _setAction( acMove ); _d->state = Impl::searchHouse; } else { foreach( it, constructions ) { ConstructionPtr c = *it; c->updateState( Construction::fire, 1 ); c->updateState( Construction::damage, 1 ); if( c->state( Construction::damage ) < 10 || c->state( Construction::fire ) < 10 ) { events::GameEventPtr e = events::Disaster::create( c->tile(), events::Disaster::riots ); e->dispatch(); } break; } } } } break; default: break; }