bool EnemySoldier::_tryAttack() { WalkerList enemies = _findEnemiesInRange( attackDistance() ); if( !enemies.empty() ) { _setSubAction( Soldier::fightEnemy ); setTarget( enemies.front()->pos() ); fight(); } else { ConstructionList constructions = _findContructionsInRange( attackDistance() ); if( !constructions.empty() ) { _setSubAction( Soldier::destroyBuilding ); setTarget( constructions.front()->pos() ); fight(); } } if( action() == acFight ) { bool needMeMove = false; _city()->statistic().map.isTileBusy<EnemySoldier>( pos(), this, needMeMove ); if( needMeMove ) { _move2freePos( target() ); } } return action() == acFight; }
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 ) }
ConstructionList EnemySoldier::_findContructionsInRange( unsigned int range ) { ConstructionList ret; Tilemap& tmap = _map(); for( unsigned int k=0; k <= range; k++ ) { ConstructionList blds = tmap.rect( k, pos() ) .overlays() .select<Construction>(); for( auto b : blds ) { if( !_atExclude.count( b->group() ) ) { ret.push_back( b ); } } } if( ret.empty() ) return ret; switch( _atPriority ) { case attackFood: case attackCitizen: case attackIndustry: { ConstructionList tmpRet; object::Group needGroup; switch( _atPriority ) { case attackIndustry: needGroup = object::group::industry; break; case attackFood: needGroup = object::group::food; break; case attackCitizen: needGroup = object::group::house; break; case attackSenate: needGroup = object::group::administration; break; default: needGroup = object::group::unknown; break; } for( auto bld : ret ) { if( bld->group() == needGroup ) { tmpRet << bld; } } if( !tmpRet.empty() ) return tmpRet; } break; case attackBestBuilding: { ConstructionPtr maxBuilding = ret.front(); unsigned int maxCost = __getCost( maxBuilding ); foreach( it, ret ) { unsigned int cost = __getCost( *it ); if( cost > maxCost ) { maxCost = cost; maxBuilding = *it; } } if( maxBuilding.isValid() ) { ret.clear(); ret << maxBuilding; return ret; } } break; default: break; }
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; }