NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

awareness.py (9975B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\behaviors\actions\awareness.py
      2 from ballpark.entities.awareness.enemy_cluster_generator import THREAT_TIME_WINDOW_SECONDS
      3 from behaviors.blackboards.scopes import GetBlackboardIdFromScopeAndContext, GetBlackboardScopeFromAddress
      4 from behaviors.const.combat import THREAT_MAX_DISTANCE_FROM_GUARD_OBJECT, FW_ATTACK_NONE
      5 from behaviors.tasks import Task
      6 from behaviors.utility.awareness import get_fleet_awareness, get_awareness_config
      7 from behaviors.utility.ballparks import get_ball_positions, is_coordinate_in_range_of_ball, is_ball_in_park, is_ball_cloaked, get_ball_position
      8 from behaviors.utility.dogmatic import get_dogma_lm
      9 from behaviors.utility.owner import get_owner_id
     10 from behaviors.utility.threat import get_damage_tracker, evaluate_target
     11 from ccpProfile import TimedFunction
     12 from evemath import weighted_choice, get_center_point, get_farthest_distance_from_point
     13 import logging
     14 logger = logging.getLogger(__name__)
     15 MIN_CLUSTER_QUALITY = 0.1
     16 
     17 class ClusterData(object):
     18 
     19     def __init__(self, item_ids, centroid, radius, threat):
     20         self.item_ids = item_ids
     21         self.centroid = centroid
     22         self.radius = radius
     23         self.quality = threat * self._calculate_cluster_quality()
     24 
     25     def _calculate_cluster_quality(self):
     26         cluster_radius_over_max_distance = self.radius / THREAT_MAX_DISTANCE_FROM_GUARD_OBJECT
     27         cluster_proportion = min(cluster_radius_over_max_distance, 1.0) / len(self.item_ids)
     28         return max(1.0 - cluster_proportion, MIN_CLUSTER_QUALITY)
     29 
     30 
     31 class SendCentroidOfBallIds(Task):
     32 
     33     @TimedFunction('behaviors::actions::awareness::SendCentroidOfBallIds::OnEnter')
     34     def OnEnter(self):
     35         centroid = None
     36         ball_ids = self.GetLastBlackboardValue(self.attributes.ballIdListAddress)
     37         if ball_ids:
     38             position_list = get_ball_positions(self, ball_ids)
     39             try:
     40                 centroid = get_center_point(position_list)
     41             except ValueError:
     42                 logger.debug('No valid positions left in list with id %s', ball_ids)
     43 
     44         self.SendBlackboardValue(self.attributes.centroidPositionAddress, centroid)
     45         self.SetStatusToSuccess()
     46 
     47 
     48 class ComputeCentroidAndRadiusOfItemIds(Task):
     49 
     50     @TimedFunction('behaviors::actions::awareness::ComputeCentroidAndRadiusOfItemIds::OnEnter')
     51     def OnEnter(self):
     52         centroid = None
     53         radius = None
     54         ball_ids = self.GetLastBlackboardValue(self.attributes.itemIdsAddress)
     55         if ball_ids:
     56             position_list = get_ball_positions(self, ball_ids)
     57             if position_list:
     58                 centroid = get_center_point(position_list)
     59                 radius = get_farthest_distance_from_point(centroid, position_list)
     60         self.SendBlackboardValue(self.attributes.centroidPositionAddress, centroid)
     61         self.SendBlackboardValue(self.attributes.radiusPositionAddress, radius)
     62         self.SetStatusToSuccess()
     63 
     64 
     65 class InitializeGroupAwareness(Task):
     66 
     67     @TimedFunction('behaviors::actions::awareness::InitializeGroupAwareness::OnEnter')
     68     def OnEnter(self):
     69         manager = self.context.entityLocation.GetGroupAwarenessManager()
     70         member_collection_id = self.get_member_collection_id()
     71         if manager.is_registered(member_collection_id):
     72             logger.debug('Group %s already registered, ignoring.', member_collection_id)
     73             self.SetStatusToFailed()
     74         else:
     75             manager.register_group_awareness(member_collection_id, self.get_awareness_config())
     76             self.SetStatusToSuccess()
     77 
     78     def get_member_collection_id(self):
     79         return self.context.myEntityGroupId
     80 
     81     def get_awareness_config(self):
     82         config = get_awareness_config(self)
     83         config.standings_enabled = self.attributes.standingsEnabled
     84         config.react_to_disapproval = self.attributes.reactToDisapproval or False
     85         fwAttackMethod = self.attributes.fwAttackMethod
     86         if fwAttackMethod == FW_ATTACK_NONE:
     87             fwAttackMethod = None
     88         config.fw_attack_method = fwAttackMethod
     89         return config
     90 
     91 
     92 class InitializeSpawnPoolFleetAwareness(InitializeGroupAwareness):
     93 
     94     def __init__(self, attributes = None):
     95         super(InitializeSpawnPoolFleetAwareness, self).__init__(attributes=attributes)
     96         self.spawn_pool_id = None
     97 
     98     @TimedFunction('behaviors::actions::awareness::InitializeSpawnPoolFleetAwareness::OnEnter')
     99     def OnEnter(self):
    100         self.spawn_pool_id = self.GetLastBlackboardValue(self.attributes.spawnPoolIdAddress)
    101         get_owner_id(self)
    102         manager = self._get_awareness_manager()
    103         blackboard_scope = GetBlackboardScopeFromAddress(self.attributes.combatTargetsSetAddress)
    104         blackboard_id = GetBlackboardIdFromScopeAndContext(blackboard_scope, self.context)
    105         manager.register_spawn_pool_fleet_awareness(self.spawn_pool_id, get_owner_id(self), blackboard_id, self.behaviorTree.GetBehaviorId(), self.get_awareness_config())
    106         self.SetStatusToSuccess()
    107 
    108     def get_member_collection_id(self):
    109         return self.spawn_pool_id
    110 
    111     def _get_awareness_manager(self):
    112         return self.context.entityLocation.GetGroupAwarenessManager()
    113 
    114     def get_awareness_config(self):
    115         config = get_awareness_config(self)
    116         config.standings_enabled = False
    117         config.fw_attack_method = None
    118         return config
    119 
    120 
    121 class AddMyItemIdToSpawnPoolFleetAwareness(Task):
    122 
    123     @TimedFunction('behaviors::actions::awareness::AddMyItemIdToSpawnPoolFleetAwareness::OnEnter')
    124     def OnEnter(self):
    125         spawn_pool_id = self.GetLastBlackboardValue(self.attributes.spawnPoolIdAddress)
    126         manager = self._get_awareness_manager()
    127         awareness = manager.get_spawn_pool_fleet_awareness(spawn_pool_id)
    128         if awareness is None:
    129             logger.error('Unable to find a spawn pool fleet awareness instance for spawn pool %s', spawn_pool_id, self.attributes.spawnPoolIdAddress)
    130             self.SetStatusToFailed()
    131         else:
    132             member_collection = awareness.get_member_collection()
    133             member_collection.add_item_id(self.context.myItemId)
    134             self.SetStatusToSuccess()
    135 
    136     def _get_awareness_manager(self):
    137         return self.context.entityLocation.GetGroupAwarenessManager()
    138 
    139 
    140 class InitializeEnemyClusterGeneration(Task):
    141 
    142     @TimedFunction('behaviors::actions::awareness::InitializeEnemyClusterGeneration::OnEnter')
    143     def OnEnter(self):
    144         spawn_pool_id = self.get_spawn_pool_id()
    145         group_awareness = get_fleet_awareness(self, spawn_pool_id)
    146         if group_awareness.get_enemy_cluster_generator() is None:
    147             group_awareness.enable_enemy_cluster_generator(get_dogma_lm(self), get_damage_tracker(self), self.attributes.updateIntervalSeconds, self.GetChannelFromAddress(self.attributes.enemyClustersAddress))
    148         self.SetStatusToSuccess()
    149 
    150     def get_awareness_manager(self):
    151         return self.context.entityLocation.GetGroupAwarenessManager()
    152 
    153     def get_spawn_pool_id(self):
    154         return self.GetLastBlackboardValue(self.attributes.spawnPoolIdAddress)
    155 
    156 
    157 class SelectClusterWeightedByThreat(Task):
    158 
    159     @TimedFunction('behaviors::actions::awareness::SelectClusterWeightedByThreat::OnEnter')
    160     def OnEnter(self):
    161         enemy_clusters = self.get_updated_enemy_clusters(self.get_enemy_clusters())
    162         cluster = None
    163         if enemy_clusters:
    164             cluster = self.select_cluster_weighted_by_threat(enemy_clusters)
    165         if cluster:
    166             self.SendBlackboardValue(self.attributes.clusterCentroidAddress, cluster.centroid)
    167             self.SendBlackboardValue(self.attributes.clusterRadiusAddress, cluster.radius)
    168             self.SendBlackboardValue(self.attributes.clusterItemIdsAddress, cluster.item_ids)
    169             self.SetStatusToSuccess()
    170         else:
    171             self.SetStatusToFailed()
    172 
    173     def select_cluster_weighted_by_threat(self, enemy_clusters):
    174         return weighted_choice([ (cluster, cluster.quality) for cluster in enemy_clusters ])
    175 
    176     def get_updated_enemy_clusters(self, enemy_clusters):
    177         updated_enemy_clusters = []
    178         for cluster in enemy_clusters:
    179             item_ids = {item_id for item_id in cluster['item_ids'] if is_ball_in_park(self, item_id) and not is_ball_cloaked(self, item_id)}
    180             if not item_ids:
    181                 continue
    182             points = [ get_ball_position(self, ball_id) for ball_id in item_ids ]
    183             centroid = get_center_point(points)
    184             if not self._is_in_range(centroid):
    185                 continue
    186             updated_cluster = ClusterData(item_ids, centroid, get_farthest_distance_from_point(centroid, points), self._get_cluster_threat(item_ids))
    187             updated_enemy_clusters.append(updated_cluster)
    188 
    189         return updated_enemy_clusters
    190 
    191     def get_enemy_clusters(self):
    192         return self.GetLastBlackboardValue(self.attributes.enemyClustersAddress)
    193 
    194     def _is_in_range(self, cluster_coordinates):
    195         guard_object_id = self._get_guard_object_id()
    196         if guard_object_id is None:
    197             return True
    198         return is_coordinate_in_range_of_ball(self, guard_object_id, cluster_coordinates, THREAT_MAX_DISTANCE_FROM_GUARD_OBJECT)
    199 
    200     def _get_guard_object_id(self):
    201         if not self.HasAttribute('guardObjectIdAddress'):
    202             return
    203         guard_object_id = self.GetLastBlackboardValue(self.attributes.guardObjectIdAddress)
    204         if guard_object_id is None:
    205             return
    206         if not is_ball_in_park(self, guard_object_id):
    207             return
    208         return guard_object_id
    209 
    210     @TimedFunction('behaviors::actions::awareness::SelectClusterWeightedByThreat::_update_cluster_threat')
    211     def _get_cluster_threat(self, item_ids):
    212         return sum((self._get_item_threat(item_id) for item_id in item_ids))
    213 
    214     def _get_item_threat(self, item_id):
    215         return evaluate_target(self.context.damageTracker, self.context.dogmaLM, item_id, THREAT_TIME_WINDOW_SECONDS)