ballparks.py (15705B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\behaviors\monitors\ballparks.py 2 import logging 3 import uthread2 4 from ballpark.messenger.const import MESSAGE_INVULNERABILITY_CANCELED, MESSAGE_ON_BUBBLE_PROXIMITY_ENTERED 5 from ballpark.messenger.const import MESSAGE_ON_BALLPARK_ITEM_DESTROY 6 from ballpark.messenger.const import MESSAGE_ON_ITEM_REMOVED_FROM_PARK, MESSAGE_ON_PROXIMITY 7 from behaviors import status 8 from behaviors.groups.mixin import GroupTaskMixin 9 from behaviors.tasks import Task 10 from behaviors.utility.ballparks import is_ball_cloaked 11 from behaviors.utility.blackboards import update_blackboard_set_if_changed 12 from behaviors.utility.components import get_proximity_sensors, get_proximity_sensor 13 from ccpProfile import TimedFunction 14 from npcs.server.tags import get_behavior_sensor_tags 15 logger = logging.getLogger(__name__) 16 PROXIMITY_EVENT = 'DoBubbleProximity' 17 18 class BubbleChangedMonitor(Task): 19 20 @TimedFunction('behaviors::monitors::ballparks::BubbleChangedMonitor::OnEnter') 21 def OnEnter(self): 22 self.bubbleId = self.GetBubbleId() 23 self.GetServiceManager().RegisterForNotifyEvent(self, PROXIMITY_EVENT) 24 self.context.ballpark.SetBubbleEvents(self.bubbleId, True) 25 self.SetStatusToSuccess() 26 27 def GetBubbleId(self): 28 if getattr(self.attributes, 'bubbleIdAddress', None) is None: 29 return self.context.myBall.newBubbleId 30 else: 31 return self.GetLastBlackboardValue(self.attributes.bubbleIdAddress) 32 33 def CleanUp(self): 34 if not self.IsInvalid(): 35 self.GetServiceManager().UnregisterForNotifyEvent(self, PROXIMITY_EVENT) 36 self.context.ballpark.SetBubbleEvents(self.bubbleId, False) 37 self.bubbleId = None 38 self.SetStatusToInvalid() 39 40 @TimedFunction('behaviors::monitors::ballparks::BubbleChangedMonitor::DoBubbleProximity') 41 def DoBubbleProximity(self, solarSystemId, bubbleId, ballId, isEntering): 42 if self.IsInvalid(): 43 return 44 if bubbleId == self.bubbleId: 45 self.behaviorTree.RequestReset(requestedBy=self) 46 47 def GetServiceManager(self): 48 return sm 49 50 51 class BallEnteredOrLeftBubbleGroupMonitor(Task, GroupTaskMixin): 52 53 @TimedFunction('behaviors::monitors::ballparks::BallEnteredOrLeftBubbleGroupMonitor::OnEnter') 54 def OnEnter(self): 55 self.bubbleIdSet = self.GetMemberBubbleSet() 56 self.GetServiceManager().RegisterForNotifyEvent(self, PROXIMITY_EVENT) 57 for bubbleId in self.bubbleIdSet: 58 self.context.ballpark.SetBubbleEvents(bubbleId, True) 59 60 self.SetStatusToSuccess() 61 62 def CleanUp(self): 63 if not self.IsInvalid(): 64 self.GetServiceManager().UnregisterForNotifyEvent(self, PROXIMITY_EVENT) 65 for bubbleId in self.bubbleIdSet: 66 self.context.ballpark.SetBubbleEvents(bubbleId, False) 67 68 self.SetStatusToInvalid() 69 70 @TimedFunction('behaviors::monitors::ballparks::BallEnteredOrLeftBubbleGroupMonitor::DoBubbleProximity') 71 def DoBubbleProximity(self, solarSystemId, bubbleId, ballId, isEntering): 72 if self.IsInvalid(): 73 return 74 if bubbleId in self.bubbleIdSet: 75 self.behaviorTree.RequestReset(requestedBy=self) 76 77 def GetServiceManager(self): 78 return sm 79 80 81 class TargetChangingBubbleMonitor(BubbleChangedMonitor): 82 83 def DoBubbleProximity(self, solarSystemId, bubbleId, ballId, isEntering): 84 if self.IsInvalid(): 85 return 86 if bubbleId != self.bubbleId: 87 return 88 if isEntering != self.attributes.resetOnEnter: 89 return 90 targetId = self.GetLastBlackboardValue(self.attributes.targetAddress) 91 if ballId != targetId: 92 return 93 logger.debug('Target %s is %s my bubble', ballId, 'entering' if isEntering else 'leaving') 94 self.behaviorTree.RequestReset(requestedBy=self) 95 96 97 class TargetWithOwnerEnteredBubbleMonitor(Task): 98 99 def __init__(self, attributes = None): 100 super(TargetWithOwnerEnteredBubbleMonitor, self).__init__(attributes) 101 self.bubbleIdSet = None 102 103 @TimedFunction('behaviors::monitors::ballparks::TargetWithOwnerEnteredBubbleMonitor::OnEnter') 104 def OnEnter(self): 105 self.bubbleIdSet = None 106 if self.attributes.ownerIds: 107 self.bubbleIdSet = self.GetBubbleIdSet() 108 self.bubbleIdSet.update(self.GetBubbleIdSet()) 109 self.SubscribeToBubbleEnter() 110 self.SetStatusToSuccess() 111 112 def CleanUp(self): 113 if not self.IsInvalid() and self.attributes.ownerIds: 114 self.UnsubscribeFromBubbleEnter() 115 self.SetStatusToInvalid() 116 117 def SubscribeToBubbleEnter(self): 118 for bubbleId in self.bubbleIdSet: 119 self.SubscribeBubbleProximityEntered(bubbleId) 120 self.context.ballpark.SetBubbleEvents(bubbleId, True) 121 122 def SubscribeBubbleProximityEntered(self, bubbleId): 123 messenger = self.GetEventMessenger() 124 messenger.SubscribeBubble(bubbleId, MESSAGE_ON_BUBBLE_PROXIMITY_ENTERED, self.OnBubbleEntered) 125 126 def UnsubscribeFromBubbleEnter(self): 127 if self.bubbleIdSet is None: 128 return 129 for bubbleId in self.bubbleIdSet: 130 self.UnsubscribeBubbleProximityEntered(bubbleId) 131 self.context.ballpark.SetBubbleEvents(bubbleId, False) 132 133 self.bubbleIdSet = None 134 135 def UnsubscribeBubbleProximityEntered(self, bubbleId): 136 messenger = self.GetEventMessenger() 137 messenger.UnsubscribeBubble(bubbleId, MESSAGE_ON_BUBBLE_PROXIMITY_ENTERED, self.OnBubbleEntered) 138 139 @TimedFunction('behaviors::monitors::ballparks::TargetWithOwnerEnteredBubbleMonitor::OnBubbleEntered') 140 def OnBubbleEntered(self, ballId): 141 if self.IsInvalid(): 142 return 143 ballpark = self.context.ballpark 144 slimItem = ballpark.slims.get(ballId) 145 if slimItem and slimItem.ownerID not in self.attributes.ownerIds: 146 return 147 logger.debug('Target %s with owner %s is entering bubble %s', ballId, slimItem.ownerID, ballpark.balls[ballId].newBubbleId) 148 targetSet = self.GetLastBlackboardValue(self.attributes.targetSetAddress) or set() 149 if ballId not in targetSet: 150 targetSet.add(ballId) 151 self.SendBlackboardValue(self.attributes.targetSetAddress, targetSet) 152 153 def GetBubbleIdSet(self): 154 return {self.context.myBall.newBubbleId} 155 156 157 class TargetsWithOwnerEnteredBubbleMonitor(TargetWithOwnerEnteredBubbleMonitor, GroupTaskMixin): 158 159 def GetBubbleIdSet(self): 160 return self.GetMemberBubbleSet() 161 162 163 class TargetLeavingParkMonitor(Task): 164 165 @TimedFunction('behaviors::monitors::ballparks::TargetLeavingParkMonitor::OnEnter') 166 def OnEnter(self): 167 self.targetId = self.GetLastBlackboardValue(self.attributes.targetAddress) 168 self.context.ballpark.eventMessenger.SubscribeItem(self.targetId, MESSAGE_ON_ITEM_REMOVED_FROM_PARK, self._OnItemLeavingPark) 169 self.status = status.TaskSuccessStatus 170 171 def CleanUp(self): 172 if not self.IsInvalid(): 173 self.SetStatusToInvalid() 174 self.context.ballpark.eventMessenger.UnsubscribeItem(self.targetId, MESSAGE_ON_ITEM_REMOVED_FROM_PARK, self._OnItemLeavingPark) 175 176 def _OnItemLeavingPark(self, itemId): 177 targetId = self.GetLastBlackboardValue(self.attributes.targetAddress) 178 if itemId != targetId: 179 return 180 if self.attributes.clearValue: 181 self.SendBlackboardValue(self.attributes.targetAddress, None) 182 self.behaviorTree.RequestReset(requestedBy=self) 183 184 185 class MonitorProximitySensors(Task): 186 187 def __init__(self, attributes = None): 188 super(MonitorProximitySensors, self).__init__(attributes) 189 self.proximitySensorIds = set() 190 self.bubbleIdSet = None 191 self.tags = set() 192 193 @TimedFunction('behaviors::monitors::ballparks::MonitorProximitySensors::OnEnter') 194 def OnEnter(self): 195 self._SetTags() 196 self.proximitySensorIds.clear() 197 super(MonitorProximitySensors, self).OnEnter() 198 self.SetBubbleIdSet(self.GetBubbleIdSet()) 199 proximitySensors = self.FindProximitySensorsForBubbleSet() 200 itemIds = self.FindItemsInSensorRange(proximitySensors) 201 self.ClassifyItems(itemIds) 202 self.SubscribeToProximitySensor(proximitySensors) 203 self.SetStatusToSuccess() 204 205 def _SetTags(self): 206 tags = getattr(self.attributes, 'tags', None) or [] 207 self.tags = get_behavior_sensor_tags(self.context, tags) 208 209 def ClassifyItems(self, itemIds): 210 update_blackboard_set_if_changed(self, itemIds, self.attributes.objectListAddress) 211 212 def CleanUp(self): 213 if not self.IsInvalid(): 214 self.UnsubscribeProximitySensors() 215 super(MonitorProximitySensors, self).CleanUp() 216 217 def UnsubscribeProximitySensors(self): 218 for itemId in self.proximitySensorIds: 219 self.UnsubscribeItem(itemId, MESSAGE_ON_PROXIMITY, self.OnProximityDetected) 220 221 self.proximitySensorIds.clear() 222 223 @TimedFunction('behaviors::monitors::ballparks::MonitorProximitySensors::FindItemsInSensorRange') 224 def FindItemsInSensorRange(self, proximitySensors): 225 itemIds = set() 226 for component in proximitySensors: 227 for itemId in component.GetBallIdsInRange(): 228 if self.IsValidTarget(itemId): 229 itemIds.add(itemId) 230 231 return itemIds 232 233 @TimedFunction('behaviors::monitors::ballparks::MonitorProximitySensors::FindProximitySensorsInBubble') 234 def FindProximitySensorsForBubbleSet(self): 235 proximitySensorComponents = [] 236 for component in self.GetProximitySensors(): 237 if self.InSameBubble(component.GetBubbleId()): 238 proximitySensorComponents.append(component) 239 240 return proximitySensorComponents 241 242 def SubscribeToProximitySensor(self, proximitySensors): 243 for sensor in proximitySensors: 244 self.proximitySensorIds.add(sensor.itemID) 245 self.SubscribeItem(sensor.itemID, MESSAGE_ON_PROXIMITY, self.OnProximityDetected) 246 247 @TimedFunction('behaviors::monitors::ballparks::MonitorProximitySensors::GetProximitySensors') 248 def GetProximitySensors(self): 249 return get_proximity_sensors(self, *self.tags) 250 251 def IsValidTarget(self, itemId): 252 slim = self.context.ballpark.slims.get(itemId) 253 if not slim: 254 return False 255 if self.attributes.includedCategories and slim.categoryID not in self.attributes.includedCategories: 256 return False 257 if self.attributes.excludedGroups and slim.groupID in self.attributes.excludedGroups: 258 return False 259 if self.attributes.validOwnerIds and slim.ownerID not in self.attributes.validOwnerIds: 260 return False 261 if self.attributes.invalidOwnerIds and slim.ownerID in self.attributes.invalidOwnerIds: 262 return False 263 if is_ball_cloaked(self, itemId): 264 return False 265 return True 266 267 def OnProximityDetected(self, ballId, isEntering): 268 uthread2.start_tasklet(self._OnProximityDetected, ballId, isEntering) 269 270 def _OnProximityDetected(self, ballId, isEntering): 271 if self.IsInvalid(): 272 return 273 if isEntering and self.IsValidTarget(ballId): 274 self.ClassifyItems({ballId}) 275 276 def InSameBubble(self, bubbleId): 277 return bubbleId in self.bubbleIdSet 278 279 def SetBubbleIdSet(self, bubbleIdSet): 280 self.bubbleIdSet = bubbleIdSet 281 282 def GetBubbleIdSet(self): 283 return {self.context.myBall.newBubbleId} 284 285 286 class MonitorProximitySensorsForGroupMembers(MonitorProximitySensors, GroupTaskMixin): 287 288 def GetBubbleIdSet(self): 289 return self.GetMemberBubbleSet() 290 291 292 class MonitorSpecificProximitySensor(MonitorProximitySensors): 293 294 @TimedFunction('behaviors::monitors::ballparks::MonitorSpecificProximitySensor::GetProximitySensors') 295 def GetProximitySensors(self): 296 proximitySensorId = self.GetLastBlackboardValue(self.attributes.proximitySensorAddress) 297 if proximitySensorId and self.context.ballpark.HasBall(proximitySensorId): 298 proximitySensor = get_proximity_sensor(self, proximitySensorId) 299 return [proximitySensor] 300 return [] 301 302 303 class MonitorSpecificProximitySensorForGroupMembers(MonitorSpecificProximitySensor, GroupTaskMixin): 304 305 def GetBubbleIdSet(self): 306 return self.GetMemberBubbleSet() 307 308 309 class MonitorInvulnerabilityCanceledInBubble(Task): 310 311 def __init__(self, attributes = None): 312 super(MonitorInvulnerabilityCanceledInBubble, self).__init__(attributes) 313 self.bubbleIdSet = None 314 315 @TimedFunction('behaviors::monitors::ballparks::MonitorInvulnerabilityCanceledInBubble::OnEnter') 316 def OnEnter(self): 317 self.SubscribeToInvulnerabilityCanceledInBubbles() 318 self.SetStatusToSuccess() 319 320 def SubscribeToInvulnerabilityCanceledInBubbles(self): 321 self.bubbleIdSet = self.GetBubbleIds() 322 messenger = self.GetEventMessenger() 323 for bubbleId in self.bubbleIdSet: 324 messenger.SubscribeBubble(bubbleId, MESSAGE_INVULNERABILITY_CANCELED, self.OnInvulnerabilityCanceled) 325 326 def UnsubscribeToInvulnerabilityCanceledInBubbles(self): 327 messenger = self.GetEventMessenger() 328 for bubbleId in self.bubbleIdSet: 329 messenger.UnsubscribeBubble(bubbleId, MESSAGE_INVULNERABILITY_CANCELED, self.OnInvulnerabilityCanceled) 330 331 self.bubbleIdSet = None 332 333 def GetBubbleIds(self): 334 return {self.context.myBall.newBubbleId} 335 336 @TimedFunction('behaviors::monitors::ballparks::MonitorInvulnerabilityCanceledInBubble::OnInvulnerabilityCanceled') 337 def OnInvulnerabilityCanceled(self, itemId, isCompleted, reason): 338 if self.IsInvalid(): 339 return 340 if not self.IsValidTarget(itemId): 341 return 342 logger.debug('Invulnerability canceled isCompleted=%s reason=%s', isCompleted, reason) 343 self.behaviorTree.RequestReset(requestedBy=self) 344 345 def IsValidTarget(self, itemId): 346 if self.attributes.targetIdListAddress is None: 347 return True 348 targetIdList = self.GetLastBlackboardValue(self.attributes.targetIdListAddress) 349 if targetIdList and itemId in targetIdList: 350 return True 351 return False 352 353 def CleanUp(self): 354 if not self.IsInvalid(): 355 self.UnsubscribeToInvulnerabilityCanceledInBubbles() 356 super(MonitorInvulnerabilityCanceledInBubble, self).CleanUp() 357 358 359 class MonitorInvulnerabilityCanceledInGroupBubbles(MonitorInvulnerabilityCanceledInBubble, GroupTaskMixin): 360 361 def GetBubbleIds(self): 362 return self.GetMemberBubbleSet() 363 364 365 class ClearBlackboardChannelOnItemExplosion(Task): 366 367 @TimedFunction('behaviors::monitors::ballparks::MonitorItemExplosion::OnEnter') 368 def OnEnter(self): 369 self.SetStatusToSuccess() 370 item_id = self.GetLastBlackboardValue(self.attributes.itemIdAddress) 371 if self.context.ballpark.HasBall(item_id): 372 self.item_id = item_id 373 self.SubscribeItem(item_id, MESSAGE_ON_BALLPARK_ITEM_DESTROY, self._clear_black_board_channel_on_explosion) 374 else: 375 self.item_id = None 376 377 def _clear_black_board_channel_on_explosion(self, exploding_item_id): 378 if exploding_item_id == self.item_id: 379 self.SendBlackboardValue(self.attributes.blackBoardChannelAddress, None) 380 self.behaviorTree.RequestReset(self) 381 382 def CleanUp(self): 383 if not self.IsInvalid() and self.item_id is not None: 384 self.UnsubscribeItem(self.item_id, MESSAGE_ON_BALLPARK_ITEM_DESTROY, self._clear_black_board_channel_on_explosion) 385 self.SetStatusToInvalid()