entityspawning.py (11928B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\behaviors\actions\entityspawning.py 2 from ballpark.entities.spawndataforentities import get_spawn_data_for_entities 3 from ballpark.locationgenerator import GetRandomDeepSpaceLocation 4 from behaviors.const.blackboardchannels import GUARD_OBJECT_ITEM_ID 5 from behaviors.groups.mixin import GroupTaskMixin 6 from behaviors.tasks import Task 7 from behaviors.utility.awareness import get_spawn_pool_id, get_awareness_config 8 from behaviors.utility.context import get_extra_context 9 from behaviors.utility.groups import get_entity_group_member_count 10 from behaviors.utility.owner import get_owner_id 11 from behaviors.utility.spawning import EntityGetter, EntityGetterBySpawnlistAndOwner, EntityGetterFromSpawnPointPool 12 from behaviors.utility.spawning import get_spawn_point_pool_manager 13 from behaviors.utility.spawning import EntitySpawner, EntitySpawnerWithUndock 14 from behaviors.utility.spawning import EntitySpawnTableSpawner 15 from ccpProfile import TimedFunction 16 from npcs.server.npcspawning.reactivespawn_counters import get_npc_fleet_type 17 from npcs.server.npcspawning.reactivespawning import ReactiveSpawnConfig 18 import logging 19 logger = logging.getLogger(__name__) 20 21 class RegisterSpawnPool(Task): 22 23 @TimedFunction('behaviors::actions::entityspawning::RegisterSpawnPool::OnEnter') 24 def OnEnter(self): 25 max_spawn_points = self.attributes.maxSpawnPoints 26 if not max_spawn_points: 27 self.SetStatusToFailed() 28 return 29 initial_spawn_points = self._get_initial_spawn_points() 30 spawn_point_pool_id = self._assign_spawn_pool(max_spawn_points, initial_spawn_points) 31 logger.debug('Registering spawn pool %s', spawn_point_pool_id) 32 self._post_spawn_point_pool(spawn_point_pool_id) 33 self.SetStatusToSuccess() 34 35 def _get_initial_spawn_points(self): 36 return getattr(self.attributes, 'initialSpawnPoints', None) 37 38 def _assign_spawn_pool(self, max_spawn_points, initial_spawn_points): 39 spawn_point_pool_manager = self._get_spawn_point_pool_manager() 40 spawn_point_pool_id = spawn_point_pool_manager.register_new_spawn_point_pool(max_spawn_points, initial_spawn_points) 41 return spawn_point_pool_id 42 43 def _get_spawn_point_pool_manager(self): 44 return self.context.entityLocation.GetSpawnPoolManager() 45 46 def _post_spawn_point_pool(self, spawn_point_pool_id): 47 self.SendBlackboardValue(self.attributes.spawnPoolIdAddress, spawn_point_pool_id) 48 49 50 class SpawnNewEntities(Task, GroupTaskMixin): 51 52 @TimedFunction('behaviors::actions::entityspawning::SpawnNewEntities::OnEnter') 53 def OnEnter(self): 54 self.SetStatusToFailed() 55 entity_getter = self._get_entity_getter() 56 entity_spawner = self._get_entity_spawner() 57 existing_entity_group_id = entity_spawner.get_group_id() 58 max_npc_count = self._get_max_npc_count_for_group(existing_entity_group_id) 59 spawn_data_for_entities = entity_getter.get_spawn_data_for_entities(max_npc_count=max_npc_count) 60 if spawn_data_for_entities: 61 group, entity_item_ids = entity_spawner.spawn_new_entities(spawn_data_for_entities) 62 self._update_group(group.GetID(), len(entity_item_ids), existing_entity_group_id) 63 entity_getter.on_spawn_entities(group.GetID()) 64 self.SetStatusToSuccess() 65 else: 66 logger.debug('No entities to spawn. group_id=%s max_npc_count=%s', existing_entity_group_id, max_npc_count) 67 68 def _get_entity_getter(self): 69 return EntityGetter(self) 70 71 def _get_entity_spawner(self): 72 return EntitySpawner(self) 73 74 def _update_group(self, entity_group_id, entity_count, existing_entity_group_id): 75 self._update_reinforcements_for_group(entity_count, existing_entity_group_id) 76 self._register_entity_group_with_blackboard(entity_group_id) 77 self._update_group_blackboard_channels(entity_group_id) 78 79 def _update_reinforcements_for_group(self, entity_count, existing_entity_group_id): 80 if existing_entity_group_id is None: 81 return 82 reinforcement_manager = self._get_reinforcement_manager() 83 reinforced_group = reinforcement_manager.GetReinforcedGroup(existing_entity_group_id) 84 if not reinforced_group: 85 return 86 old_count = reinforced_group.GetFullStrengthCount() 87 reinforced_group.SetEntityUnitCount(old_count + entity_count) 88 89 def _get_reinforcement_manager(self): 90 return self.context.entityLocation.reinforcementManager 91 92 def _register_entity_group_with_blackboard(self, entity_group_id): 93 if not hasattr(self.attributes, 'entityGroupSetAddress') or not self.attributes.spawnNewGroup: 94 return 95 entity_groups_set = self.GetLastBlackboardValue(self.attributes.entityGroupSetAddress) or set() 96 entity_groups_set.add(entity_group_id) 97 self.SendBlackboardValue(self.attributes.entityGroupSetAddress, entity_groups_set) 98 99 def _update_group_blackboard_channels(self, entity_group_id): 100 if self.HasAttribute('guardObjectAddress'): 101 guard_object_item_id = self.GetLastBlackboardValue(self.attributes.guardObjectAddress) 102 self.GetMessageChannelForGroupId(entity_group_id, GUARD_OBJECT_ITEM_ID[1]).SendMessage(guard_object_item_id) 103 104 def get_spawn_pool_id(self): 105 if self.HasAttribute('spawnPoolIdAddress'): 106 return self.GetLastBlackboardValue(self.attributes.spawnPoolIdAddress) 107 108 def get_spawn_table_id(self): 109 if self.HasAttribute('spawnTableIdAddress'): 110 return self.GetLastBlackboardValue(self.attributes.spawnTableIdAddress) 111 112 def _get_max_npc_count_for_group(self, group_id): 113 if not self.HasAttribute('maxNpcCount'): 114 return 115 max_npc_count = self.attributes.maxNpcCount 116 if group_id is not None: 117 group_count = get_entity_group_member_count(self, group_id) 118 max_npc_count -= group_count 119 if max_npc_count < 0: 120 max_npc_count = 0 121 return max_npc_count 122 123 def get_bounty_pay_out_multiplier(self): 124 return getattr(self.attributes, 'bountyPayOutMultiplier', None) 125 126 def get_behavior_override_id(self): 127 return getattr(self.attributes, 'behaviorTreeName', None) 128 129 def get_spawn_position(self): 130 if getattr(self.attributes, 'spawnPositionAddress', None): 131 return self.GetLastBlackboardValue(self.attributes.spawnPositionAddress) 132 else: 133 return GetRandomDeepSpaceLocation(self.context.ballpark.solarsystemID) 134 135 def get_required_npc_tags(self): 136 return getattr(self.attributes, 'npcTagList', set()) 137 138 139 class SpawnNewEntitiesBySpawnlistAndOwnerId(SpawnNewEntities): 140 141 def _get_entity_getter(self): 142 return EntityGetterBySpawnlistAndOwner(self) 143 144 145 class SpawnEntitiesFromSpawnTable(SpawnNewEntities): 146 147 def _get_entity_getter(self): 148 return EntityGetterFromSpawnPointPool(self) 149 150 def _get_entity_spawner(self): 151 return EntitySpawnTableSpawner(self) 152 153 154 class SpawnNewEntitiesAtStructure(SpawnNewEntities): 155 156 def _get_entity_spawner(self): 157 return EntitySpawnerWithUndock(self) 158 159 160 class SpawnNewEntitiesAtStructureBySpawnlistAndOwnerId(SpawnNewEntitiesAtStructure): 161 162 def _get_entity_getter(self): 163 return EntityGetterBySpawnlistAndOwner(self) 164 165 166 class SpawnNewEntitiesAtStructureFromSpawnTable(SpawnNewEntitiesAtStructure): 167 168 def _get_entity_getter(self): 169 return EntityGetterFromSpawnPointPool(self) 170 171 172 class SendSpawnTableIdToBlackboard(Task): 173 174 def OnEnter(self): 175 self.SendBlackboardValue(self.attributes.npcSpawnTableIdAddress, self.attributes.npcSpawnTableId) 176 self.SetStatusToSuccess() 177 178 179 class SetSpawnPoolAmount(Task): 180 181 def OnEnter(self): 182 spawn_pool_id = get_spawn_pool_id(self) 183 spawn_point_pool_manager = get_spawn_point_pool_manager(self) 184 spawn_point_pool_manager.set_spawn_points(spawn_pool_id, self.attributes.spawnPointAmount) 185 self.SetStatusToSuccess() 186 187 188 class SetSelfEntityRespawn(Task, GroupTaskMixin): 189 190 def OnEnter(self): 191 entity_types_and_count = [(self.context.mySlimItem.typeID, 1)] 192 spawn_data_for_entities = get_spawn_data_for_entities(entity_types_and_count, self.context.myBall.GetPosition(), self.attributes.deploymentRangeMeters, self.behaviorTree.GetBehaviorId()) 193 self.context.entityLocation.spawnManager.SetRealItemRespawn(self.context.myEntityGroupId, self.context.mySlimItem.ownerID, spawn_data_for_entities, self.attributes.minRespawnDelaySeconds, self.attributes.maxRespawnDelaySeconds) 194 self.SetStatusToSuccess() 195 196 197 class DisableRespawnGroup(Task, GroupTaskMixin): 198 199 def OnEnter(self): 200 self.context.entityLocation.behaviorRespawnManager.remove_respawn_group(self.context.myEntityGroupId) 201 self.SetStatusToSuccess() 202 203 204 class SetSpawnTableOnBlackboardByOwner(Task): 205 206 def OnEnter(self): 207 spawn_table_id = self._get_spawn_table_id() 208 self.SendBlackboardValue(self.attributes.spawnTableIdAddress, spawn_table_id) 209 self.SetStatusToSuccess() 210 211 def _get_spawn_table_id(self): 212 owner_id = get_owner_id(self) 213 spawn_table_id = self.attributes.ownerToSpawnTableMapping.get(owner_id) 214 if spawn_table_id is None: 215 raise ValueError('Unable to find a spawn table id for owner %s' % owner_id) 216 return spawn_table_id 217 218 219 class ReactiveSpawning(Task): 220 221 def OnEnter(self): 222 self.SetStatusToSuccess() 223 owner_id = get_owner_id(self) 224 spawn_config = self._get_spawn_config(owner_id) 225 reactive_spawn_manager = self.context.entityLocation.reactiveSpawnManager 226 reactive_spawn_manager.start_spawner(spawn_config) 227 self._post_spawn_pool_id(spawn_config.spawn_point_pool_id) 228 reactive_spawn_manager.deregister_when_spawner_is_destroyed(spawn_config, self.context.entityLocation.event_handler_registry) 229 logger.debug('behavior::entity_spawning::Behavior=%s initialized reactive spawn task with config=%s', self.behaviorTree.GetBehaviorId(), spawn_config) 230 231 def get_member_collection_id(self): 232 return self.context.myEntityGroupId 233 234 def _get_spawn_config(self, owner_id): 235 spawn_config = ReactiveSpawnConfig(owner_id, self.get_spawn_table_id(), self.attributes.npcFleetCounterTableId, get_awareness_config(self), initial_point_amount=self.attributes.initialPointAmount, min_point_amount=self.attributes.minPointAmount, max_point_amount=self.attributes.maxPointAmount, extra_context=get_extra_context(self), capped_spawn_points=self.attributes.cappedSpawnPoints, should_spawn_without_threats=self.attributes.spawnWithoutThreats, should_reset_without_threats=self.attributes.resetWithoutThreats, spawn_point_multiplier=self.attributes.spawnPointMultiplier, initial_spawn_npc_fleet_type_id=getattr(self.attributes, 'initialSpawnNpcFleetTypeID', None), min_spawn_interval_seconds=self.attributes.minSpawnIntervalSeconds, max_spawn_interval_seconds=self.attributes.maxSpawnIntervalSeconds, spawner_item_id=self.context.mySlimItem.itemID, bounty_payout_multiplier=self.attributes.bountyPayoutMultiplier, should_match_player_points=self.attributes.shouldMatchPlayerPoints, spawn_point_threshold=self.attributes.spawnPointThreshold) 236 return spawn_config 237 238 def get_spawn_table_id(self): 239 return self.GetLastBlackboardValue(self.attributes.spawnTableIdAddress) 240 241 def _post_spawn_pool_id(self, spawn_pool_id): 242 self.SendBlackboardValue(self.attributes.spawnPoolIdAddress, spawn_pool_id) 243 244 def _has_initial_spawn_npc_fleet_type_id(self): 245 return hasattr(self.attributes, 'initialSpawnNpcFleetTypeID') and self.attributes.initialSpawnNpcFleetTypeID is not None 246 247 def _get_initial_spawn_npc_fleet_type(self): 248 return get_npc_fleet_type(self.attributes.initialSpawnNpcFleetTypeID)