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

spawning.py (13082B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\behaviors\utility\spawning.py
      2 from ballpark.entities.spawndataforentities import get_spawn_data_for_entities_with_custom_behavior_overrides
      3 from ballpark.entities.spawndataforentities import get_spawn_data_for_entities
      4 from ballparkCommon.docking import GetUndockVector
      5 from behaviors.const.blackboardchannels import UNDOCK_DIRECTION_CHANNEL_NAME
      6 from behaviors.utility import security
      7 from behaviors.utility.ballparks import get_slim_item
      8 from behaviors.utility.blackboards import get_response_thresholds
      9 from behaviors.utility.context import get_extra_context
     10 from behaviors.utility.entity_groups import entity_group_exists
     11 from behaviors.utility.owner import get_owner_id
     12 from ccpProfile import TimedFunction
     13 from npcs.server.npcspawning.npcgrouping import generate_grouping
     14 from npcs.server.npcspawning.spawn_const import DEFAULT_DEPLOYMENT_OFFSET_METERS
     15 from npcs.server.npcspawning.spawntableloader import SpawnTableLoader
     16 from spawnlists.data import select_probability_items
     17 try:
     18     from ballpark.locationgenerator import GetRandomDeepSpaceLocation
     19 except ImportError:
     20 
     21     def GetRandomDeepSpaceLocation():
     22         return (0, 0, 0)
     23 
     24 
     25 import logging
     26 logger = logging.getLogger(__name__)
     27 
     28 def get_deployment_range(task):
     29     if getattr(task.attributes, 'deploymentRange', None):
     30         return task.attributes.deploymentRange
     31     else:
     32         return DEFAULT_DEPLOYMENT_OFFSET_METERS
     33 
     34 
     35 def get_spawn_table_id(task):
     36     return task.GetLastBlackboardValue(task.attributes.spawnTableIdAddress)
     37 
     38 
     39 class EntityGetter(object):
     40 
     41     def __init__(self, task):
     42         self.task = task
     43 
     44     @TimedFunction('behaviors::utility::spawning::EntityGetter::get_entities')
     45     def get_spawn_data_for_entities(self, max_npc_count = None):
     46         entities = getattr(self.task.attributes, 'entities', {})
     47         behavior_override_id = self.task.get_behavior_override_id()
     48         return self._get_spawn_data_for_entities(entities.iteritems(), behavior_override_id)
     49 
     50     def _get_spawn_data_for_entities(self, entity_types_and_count, behavior_override_id):
     51         return get_spawn_data_for_entities(entity_types_and_count, None, get_deployment_range(self.task), behavior_override_id)
     52 
     53     def on_spawn_entities(self, entity_group_id):
     54         pass
     55 
     56 
     57 class EntityGetterBySpawnlistAndOwner(EntityGetter):
     58 
     59     @TimedFunction('behaviors::utility::spawning::EntityGetterBySpawnlistAndOwner::get_entities')
     60     def get_spawn_data_for_entities(self, max_npc_count = None):
     61         spawn_list_id = security.get_spawnlist_by_group_owner_and_security_level(self.task)
     62         if not spawn_list_id:
     63             return None
     64         entity_group_list = select_probability_items(spawn_list_id)
     65         if not entity_group_list:
     66             return None
     67         entity_group_id = entity_group_list.keys()[0]
     68         entities_iterator = generate_grouping(entity_group_id)
     69         behavior_override_id = self.task.get_behavior_override_id()
     70         return self._get_spawn_data_for_entities(entities_iterator, behavior_override_id)
     71 
     72 
     73 class EntityGetterFromSpawnPointPool(EntityGetter):
     74 
     75     @TimedFunction('behaviors::utility::spawning::EntityGetterFromSpawnPointPool::get_entities')
     76     def get_spawn_data_for_entities(self, max_npc_count = None):
     77         spawn_pool_id = self.task.get_spawn_pool_id()
     78         spawn_point_amount = self._get_spawn_point_amount(spawn_pool_id)
     79         if not spawn_point_amount > 0:
     80             logger.error('Bad authoring for behavior type %s - missing spawn points', self.task.context.mySlimItem.typeID)
     81             return
     82         if spawn_pool_id is not None:
     83             npcs_and_remaining_points = self._get_entities_using_spawn_point_pool(spawn_point_amount, spawn_pool_id, max_npc_count)
     84         else:
     85             npcs_and_remaining_points = self._pick_entities_from_spawn_table(spawn_point_amount, max_npc_count)
     86         if npcs_and_remaining_points is None:
     87             return
     88         npcs, remaining_points = npcs_and_remaining_points
     89         logger.debug('Picked from spawn_pool_id=%s with available points=%s npcs=%s remaining points=%s max_npc_count=%s', spawn_pool_id, spawn_point_amount, npcs, remaining_points, max_npc_count)
     90         return self._get_spawn_data_for_entities(npcs.iteritems(), None)
     91 
     92     def _get_spawn_point_amount(self, spawn_pool_id):
     93         spawn_points = 0
     94         if self.task.HasAttribute('spawnPoints'):
     95             spawn_points = self.task.attributes.spawnPoints
     96         elif spawn_pool_id:
     97             spawn_pool_manager = self._get_spawn_point_pool_manager()
     98             spawn_points = spawn_pool_manager.get_current_spawn_points(spawn_pool_id)
     99         return spawn_points
    100 
    101     def _get_entities_using_spawn_point_pool(self, spawn_point_amount, spawn_pool_id, max_npc_count):
    102         spawn_pool_manager = self._get_spawn_point_pool_manager()
    103         if spawn_pool_id:
    104             available_spawn_points = spawn_pool_manager.get_current_spawn_points(spawn_pool_id)
    105             if spawn_point_amount > available_spawn_points:
    106                 logger.debug('Not enough spawn points in pool for spawning new NPCs')
    107                 return
    108         npc_and_remaining_points = self._pick_entities_from_spawn_table(spawn_point_amount, max_npc_count)
    109         if npc_and_remaining_points is None:
    110             logger.debug('No npcs picked spawn_point_amount=%s, spawn_pool_id=%s, max_npc_count=%s', spawn_point_amount, spawn_pool_id, max_npc_count)
    111             return
    112         npcs, remaining_points = npc_and_remaining_points
    113         if spawn_pool_id:
    114             spawn_pool_manager.consume_spawn_points(spawn_pool_id, spawn_point_amount - remaining_points)
    115         return npc_and_remaining_points
    116 
    117     def _pick_entities_from_spawn_table(self, spawn_point_amount, max_npc_count):
    118         spawn_table_picker = self._get_spawn_table_picker()
    119         required_npc_tags = self.task.get_required_npc_tags()
    120         spawn_table_id = get_spawn_table_id(self.task)
    121         npc_and_remaining_points = spawn_table_picker.pick_npcs_from_table_by_points_and_tags(spawn_table_id, spawn_point_amount, required_npc_tags, max_npc_count=max_npc_count)
    122         return npc_and_remaining_points
    123 
    124     def _get_spawn_point_pool_manager(self):
    125         return self.task.context.entityLocation.spawnPointPoolManager
    126 
    127     def _get_spawn_table_picker(self):
    128         return self.task.context.entityLocation.spawnTablePicker
    129 
    130     def on_spawn_entities(self, entity_group_id):
    131         awareness_manager = self.task.context.entityLocation.GetGroupAwarenessManager()
    132         awareness_manager.on_entity_group_spawn(self.task.get_spawn_pool_id(), entity_group_id)
    133 
    134     def _get_spawn_data_for_entities(self, entities_iterator, _):
    135         return get_spawn_data_for_entities_with_custom_behavior_overrides(entities_iterator, None, get_deployment_range(self.task))
    136 
    137 
    138 class EntitySpawner(object):
    139 
    140     def __init__(self, task):
    141         self.task = task
    142 
    143     @TimedFunction('behaviors::utility::spawning::EntitySpawner::spawn_new_entities')
    144     def spawn_new_entities(self, spawn_data_for_entities):
    145         owner_id = self.get_owner_id()
    146         group_id = self.get_group_id()
    147         self._update_spawn_position(spawn_data_for_entities)
    148         behavior_group_tree_name = self._get_behavior_group_tree_name()
    149         extra_content = get_extra_context(self.task)
    150         group, entity_item_ids = self.task.context.entityLocation.DeployBehaviorEntities(owner_id, spawn_data_for_entities, group_id, groupBehaviorTreeName=behavior_group_tree_name, extraContext=extra_content, spawnTags=self.task.get_required_npc_tags(), standingThresholds=get_response_thresholds(self.task), objectiveTargetGroup=self._get_objective_target_group())
    151         self._register_entity_bounty_multiplier(entity_item_ids)
    152         self.update_entity_group_id(group.GetID())
    153         return (group, entity_item_ids)
    154 
    155     def get_owner_id(self):
    156         return get_owner_id(self.task)
    157 
    158     def _update_spawn_position(self, spawn_data_for_entities):
    159         spawn_position = self.task.get_spawn_position()
    160         for entity_spawn_data in spawn_data_for_entities:
    161             entity_spawn_data.update_spawn_position(spawn_position)
    162 
    163     def _get_spawn_position(self):
    164         if getattr(self.task.attributes, 'spawnPositionAddress', None):
    165             return self.task.GetLastBlackboardValue(self.task.attributes.spawnPositionAddress)
    166         else:
    167             return GetRandomDeepSpaceLocation(self.task.context.ballpark.solarsystemID)
    168 
    169     def get_group_id(self):
    170         if self.task.attributes.spawnNewGroup:
    171             return None
    172         if self.task.HasAttribute('entityGroupIdAddress'):
    173             entity_group_id = self.task.GetLastBlackboardValue(self.task.attributes.entityGroupIdAddress)
    174             if entity_group_exists(self.task, entity_group_id):
    175                 return entity_group_id
    176             return None
    177         return self.task.context.myEntityGroupId
    178 
    179     def _get_behavior_group_tree_name(self):
    180         return getattr(self.task.attributes, 'behaviorTreeGroupName', None)
    181 
    182     def update_entity_group_id(self, entity_group_id):
    183         if self.task.HasAttribute('entityGroupIdAddress'):
    184             self.task.SendBlackboardValue(self.task.attributes.entityGroupIdAddress, entity_group_id)
    185 
    186     def _register_entity_bounty_multiplier(self, entity_item_ids):
    187         bounty_pay_out_multiplier = self.task.get_bounty_pay_out_multiplier()
    188         if bounty_pay_out_multiplier is None:
    189             return
    190         self.task.context.entityLocation.RegisterBountyPayOutMultiplierForEntities(entity_item_ids, bounty_pay_out_multiplier)
    191 
    192     def _get_objective_target_group(self):
    193         if getattr(self.task.attributes, 'objectiveTargetGroupAddress', None):
    194             return self.task.GetLastBlackboardValue(self.task.attributes.objectiveTargetGroupAddress)
    195 
    196 
    197 class EntitySpawnTableSpawner(EntitySpawner):
    198 
    199     def get_owner_id(self):
    200         spawn_table_id = get_spawn_table_id(self.task)
    201         return SpawnTableLoader().get_spawn_table(spawn_table_id).npcowner
    202 
    203 
    204 class EntitySpawnerWithUndock(EntitySpawner):
    205 
    206     @TimedFunction('behaviors::utility::spawning::EntitySpawnerWithUndock::spawn_new_entities')
    207     def spawn_new_entities(self, spawn_data_for_entities):
    208         owner_id = get_owner_id(self.task)
    209         group_id = self.get_group_id()
    210         direction_by_entity_type = self._update_spawn_parameters_and_get_direction(spawn_data_for_entities)
    211         behavior_group_tree_name = self._get_behavior_group_tree_name()
    212         extra_content = get_extra_context(self.task)
    213         group, entity_item_ids = self.task.context.entityLocation.DeployBehaviorEntities(owner_id, spawn_data_for_entities, group_id, groupBehaviorTreeName=behavior_group_tree_name, extraContext=extra_content, spawnTags=self.task.get_required_npc_tags(), standingThresholds=get_response_thresholds(self.task), objectiveTargetGroup=self._get_objective_target_group())
    214         self._register_entity_bounty_multiplier(entity_item_ids)
    215         self.update_entity_group_id(group.GetID())
    216         self._set_undock_direction(entity_item_ids, direction_by_entity_type)
    217         return (group, entity_item_ids)
    218 
    219     def _update_spawn_parameters_and_get_direction(self, spawn_data_for_entities):
    220         structure_id = self._get_structure_id()
    221         direction_by_entity_type = {}
    222         for entity_spawn_data in spawn_data_for_entities:
    223             entity_type_id = entity_spawn_data.entity_type_id
    224             spawn_position, direction = self._get_spawn_position_and_direction(structure_id, entity_type_id)
    225             entity_spawn_data.spawn_position = spawn_position
    226             entity_spawn_data.direction = direction
    227             direction_by_entity_type[entity_type_id] = direction
    228 
    229         return direction_by_entity_type
    230 
    231     def _get_structure_id(self):
    232         return self.task.GetLastBlackboardValue(self.task.attributes.structureIdAddress)
    233 
    234     def _get_spawn_position_and_direction(self, structure_id, entity_type_id):
    235         return GetUndockVector(self.task.context.ballpark, structure_id, entity_type_id)
    236 
    237     def _set_undock_direction(self, entity_ids, direction_by_entity_type):
    238         for entity_id in entity_ids:
    239             entity_type_id = get_slim_item(self.task, entity_id).typeID
    240             direction = direction_by_entity_type[entity_type_id]
    241             self._post_undock_direction_to_entity(entity_id, direction)
    242 
    243     def _post_undock_direction_to_entity(self, entity_id, directional_position):
    244         self.task.GetMessageChannelForItemId(entity_id, UNDOCK_DIRECTION_CHANNEL_NAME).SendMessage(directional_position)
    245 
    246 
    247 def get_spawn_point_pool_manager(task):
    248     return task.context.entityLocation.spawnPointPoolManager
    249 
    250 
    251 def get_current_spawn_points(task, spawn_pool_id):
    252     try:
    253         return get_spawn_point_pool_manager(task).get_current_spawn_points(spawn_pool_id)
    254     except:
    255         logger.exception('failed to get the current spawn pool points')
    256         raise
    257 
    258 
    259 def add_spawn_points(task, spawn_pool_id, amount):
    260     get_spawn_point_pool_manager(task).add_spawn_points(spawn_pool_id, amount)