WalkerList EnemySoldier::_findEnemiesInRange( unsigned int range ) { Tilemap& tmap = _city()->tilemap(); WalkerList walkers; for( unsigned int k=0; k <= range; k ++ ) { TilesArray tiles = tmap.rect( k, pos() ); walker::Type rtype; for( auto tile : tiles ) { const WalkerList& tileWalkers = _city()->walkers( tile->pos() ); for( auto wlk : tileWalkers ) { rtype = wlk->type(); if( rtype == type() || !WalkerHelper::isHuman( wlk ) || isFriendTo( wlk ) ) continue; walkers.push_back( wlk ); } } } return walkers; }
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 Wolf::timeStep(const unsigned long time) { Animal::timeStep( time ); switch( action() ) { case acFight: { WalkerList walkers = _city()->walkers( _d->attackPos ).exclude<Wolf>(); if( !walkers.empty() ) { walkers.front()->updateHealth( defaultAttackValue ); walkers.front()->acceptAction( acFight, pos() ); } else { _findNewWay( pos() ); } } break; default: break; } }
void Wolf::_findNewWay( const TilePos& start ) { WalkerList walkers = _city()->statistic().walkers .find<Walker>( walker::any, config::distance::animalRandrom, start ) .exclude<Wolf>(); Pathway pathway; if( !walkers.empty() ) { WalkerPtr wlk = walkers.random(); pathway = PathwayHelper::create( start, wlk->pos(), PathwayHelper::allTerrain ); } if( !pathway.isValid() ) { pathway = PathwayHelper::randomWay( _city(), start, config::distance::animalRandrom ); } if( pathway.isValid() ) { setPos( start ); setPathway( pathway ); go(); } else { die(); } }
std::string Wharf::troubleDesc() const { if( _d->boat.isValid() ) { WalkerList places = _city()->walkers( walker::fishPlace ); if( places.empty() ) { return "##no_fishplace_in_city##"; } } return CoastalFactory::troubleDesc(); }
void RomeSoldier::timeStep(const unsigned long time) { Soldier::timeStep( time ); if( game::Date::isMonthChanged() ) { unsigned int dst2base = pos().distanceFrom( _d->basePos ); if( dst2base > maxDistanceFromBase ) { updateMorale( dst2base * -10 / maxDistanceFromBase ); if( morale() == 0 ) { _duckout(); } } } switch( _subAction() ) { case fightEnemy: { WalkerList enemies = _findEnemiesInRange( attackDistance() ); if( !enemies.empty() ) { WalkerPtr p = enemies.front(); turn( p->pos() ); p->updateHealth( -3 ); p->acceptAction( Walker::acFight, pos() ); } else { bool haveEnemy = _tryAttack(); if( !haveEnemy ) send2patrol(); } } break; case patrol: if( game::Date::current().day() % 2 == 0 ) { _tryAttack(); } break; default: break; } // end switch( _d->action ) }
void Wolf::_centerTile() { Animal::_centerTile(); WalkerList walkers = _city()->statistic().walkers .neighbors<Walker>( pos() ) .exclude<Wolf>(); if( !walkers.empty() ) { WalkerPtr wlk = walkers.random(); turn( wlk->pos() ); _setAction( acFight ); //setSpeedMultiplier( 0.0 ); _d->attackPos = wlk->pos(); } }
void RomeSoldier::_reachedPathway() { Soldier::_reachedPathway(); switch( (int)_subAction() ) { case expedition: deleteLater(); break; case go2position: { WalkerList walkersOnTile = _city()->statistic().walkers.find<Walker>( type(), pos() ); walkersOnTile.remove( this ); if( walkersOnTile.size() > 0 ) //only me in this tile { _back2base(); } else { _setSubAction( patrol ); } } break; case duckout: { deleteLater(); } break; default: break; } }
inline SmartList<T> Statistic::_Walkers::find( walker::Type type, TilePos start, TilePos stop ) const { WalkerList walkersInArea; TilePos stopPos = stop; if( start == gfx::tilemap::invalidLocation() ) { const WalkerList& all =_parent.rcity.walkers(); walkersInArea.insert( walkersInArea.end(), all.begin(), all.end() ); } else if( stopPos == gfx::tilemap::invalidLocation() ) { const WalkerList& wlkOnTile = _parent.rcity.walkers( start ); walkersInArea.insert( walkersInArea.end(), wlkOnTile.begin(), wlkOnTile.end() ); } else { gfx::TilesArea area( _parent.rcity.tilemap(), start, stop ); for( auto& tile : area) { const WalkerList& wlkOnTile = _parent.rcity.walkers( tile->pos() ); walkersInArea.insert( walkersInArea.end(), wlkOnTile.begin(), wlkOnTile.end() ); } } SmartList< T > result; for( auto& w : walkersInArea ) { if( w->type() == type || type == walker::any ) result.addIfValid( w.as<T>() ); } return result; }
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 ) }