| 783 | } |
| 784 | |
| 785 | bool Monster::SelectTarget( const Map& map ) |
| 786 | { |
| 787 | { |
| 788 | // Clear current target, if needed. |
| 789 | const MonsterBasePtr target= target_.monster.lock(); |
| 790 | if( target != nullptr && target->Health() <= 0 ) |
| 791 | { |
| 792 | target_.monster_id= 0u; |
| 793 | target_.monster= MonsterBaseWeakPtr(); |
| 794 | target_.have_position= false; |
| 795 | } |
| 796 | |
| 797 | // Already have target - do not select. |
| 798 | if( target != nullptr && target->Health() > 0 && target_.have_position ) |
| 799 | return true; |
| 800 | } |
| 801 | |
| 802 | const float c_half_view_angle= Constants::half_pi * 0.75f; |
| 803 | const float c_half_view_angle_cos= std::cos( c_half_view_angle ); |
| 804 | const m_Vec2 view_dir( std::cos(angle_), std::sin(angle_) ); |
| 805 | |
| 806 | float nearest_player_distance= Constants::max_float; |
| 807 | const Map::PlayersContainer::value_type* nearest_player= nullptr; |
| 808 | |
| 809 | const Map::PlayersContainer& players= map.GetPlayers(); |
| 810 | for( const Map::PlayersContainer::value_type& player_value : players ) |
| 811 | { |
| 812 | PC_ASSERT( player_value.second != nullptr ); |
| 813 | const Player& player= *player_value.second; |
| 814 | |
| 815 | if( player.Health() <= 0 ) |
| 816 | continue; |
| 817 | |
| 818 | const m_Vec2 dir_to_player= player.Position().xy() - Position().xy(); |
| 819 | const float distance_to_player= dir_to_player.Length(); |
| 820 | if( distance_to_player == 0.0f ) |
| 821 | continue; |
| 822 | |
| 823 | if( distance_to_player >= nearest_player_distance ) |
| 824 | continue; |
| 825 | |
| 826 | if( state_ == State::Idle ) |
| 827 | { |
| 828 | // Monsters in Idle state have no back eyes. |
| 829 | const float angle_cos= ( dir_to_player * view_dir ) / distance_to_player; |
| 830 | if( angle_cos < c_half_view_angle_cos ) |
| 831 | continue; |
| 832 | |
| 833 | // Monsters in Idle state didn`t see invisible players. |
| 834 | if( player.IsInvisible() ) |
| 835 | continue; |
| 836 | } |
| 837 | |
| 838 | if( CanSee( map, player.Position() ) ) |
| 839 | { |
| 840 | nearest_player_distance= distance_to_player; |
| 841 | nearest_player= &player_value; |
| 842 | } |
nothing calls this directly
no test coverage detected