effects.py (12421B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\behaviors\actions\effects.py 2 import logging 3 import random 4 from ballpark.messenger.const import MESSAGE_ON_EFFECT_STOPPED 5 from behaviors import status 6 from behaviors.tasks import Task 7 from behaviors.utility.ballparks import get_slim_item, get_ship_balls_in_bubble 8 from behaviors.utility.dogmatic import type_has_effect, try_stop_effect, get_default_effect_id_for_type 9 from ccpProfile import TimedFunction 10 from dogma.const import attributeRateOfFire 11 from eveexceptions import UserError 12 from behaviors.exceptions import BehaviorAuthoringException 13 logger = logging.getLogger(__name__) 14 TARGET_ATTACK_GRAPHIC_EFFECT = 'effects.Laser' 15 16 class PlayOneShotStretchEffectAction(Task): 17 18 @TimedFunction('behaviors::actions::effects::PlayOneShotStretchEffectAction::OnEnter') 19 def OnEnter(self): 20 sourceId = self._GetEffectSourceId() 21 targetId = self.GetLastBlackboardValue(self.attributes.effectTargetAddress) 22 if sourceId is None or targetId is None: 23 self.status = status.TaskFailureStatus 24 else: 25 sfx = self.context.ballpark.specialEffects 26 moduleId = None 27 if getattr(self.attributes, 'useEntityAsModule', False): 28 moduleId = sourceId 29 sfx.StartStretchEffect(sourceId, targetId, self.attributes.effectName, self._GetEffectDuration(), 1, moduleId) 30 self.status = status.TaskSuccessStatus 31 32 def _GetEffectSourceId(self): 33 if self.HasAttribute('effectSourceAddress'): 34 return self.GetLastBlackboardValue(self.attributes.effectSourceAddress) 35 return self.context.myItemId 36 37 def _GetEffectDuration(self): 38 if self.HasAttribute('effectDurationAddress'): 39 return self.GetLastBlackboardValue(self.attributes.effectDurationAddress) 40 return self.attributes.effectDuration 41 42 43 class PlayOneShotTargetedShipEffectAction(Task): 44 45 @TimedFunction('behaviors::actions::effects::PlayOneShotTargetedShipEffectAction::OnEnter') 46 def OnEnter(self): 47 targetId = self.GetLastBlackboardValue(self.attributes.effectTargetAddress) 48 if targetId is None: 49 self.status = status.TaskFailureStatus 50 else: 51 sfx = self.context.ballpark.specialEffects 52 sfx.StartShipEffect(targetId, self.attributes.effectName, self.attributes.effectDuration, 1) 53 self.status = status.TaskSuccessStatus 54 55 56 class PlayOneShotShipEffectAction(Task): 57 58 @TimedFunction('behaviors::actions::effects::PlayOneShotShipEffectAction::OnEnter') 59 def OnEnter(self): 60 ballId = self.context.myItemId 61 if getattr(self.attributes, 'effectTargetAddress', None): 62 ballId = self.GetLastBlackboardValue(self.attributes.effectTargetAddress) 63 sfx = self.context.ballpark.specialEffects 64 sfx.StartShipEffect(ballId, self.attributes.effectName, self.attributes.effectDuration, 1, graphicInfo=getattr(self.attributes, 'graphicInfo', None)) 65 self.status = status.TaskSuccessStatus 66 67 68 class PlayStretchEffectAction(Task): 69 70 def OnEnter(self): 71 self.SetStatusToFailed() 72 targetId = self.GetLastBlackboardValue(self.attributes.effectTargetAddress) 73 graphicInfoAddress = self.attributes.graphicInfoAddress 74 if graphicInfoAddress: 75 graphicInfo = self.GetLastBlackboardValue(graphicInfoAddress) 76 else: 77 graphicInfo = None 78 repeats = self.attributes.effectRepeats 79 if targetId is not None: 80 sfx = self.context.ballpark.specialEffects 81 moduleId = None 82 if getattr(self.attributes, 'useEntityAsModule', False): 83 moduleId = self.context.myItemId 84 sfx.StartStretchEffect(self.context.myItemId, targetId, self.attributes.effectName, self.get_effect_duration(), repeats, moduleId, graphicInfo=graphicInfo) 85 self.SetStatusToSuccess() 86 87 def get_effect_duration(self): 88 if self.HasAttribute('effectDurationRandomVariance'): 89 variance = self.attributes.effectDurationRandomVariance 90 if variance > 0: 91 difference = random.random() * variance - variance * 0.5 92 return self.attributes.effectDuration + difference 93 return self.attributes.effectDuration 94 95 96 class StopStretchEffectAction(Task): 97 98 def OnEnter(self): 99 self.SetStatusToFailed() 100 targetId = self.GetLastBlackboardValue(self.attributes.effectTargetAddress) 101 if targetId is not None: 102 sfx = self.context.ballpark.specialEffects 103 moduleId = None 104 if getattr(self.attributes, 'useEntityAsModule', False): 105 moduleId = self.context.myItemId 106 sfx.StopStretchEffect(self.context.myItemId, targetId, self.attributes.effectName, moduleId) 107 self.SetStatusToSuccess() 108 109 110 class SetDogmaAttributeValue(Task): 111 112 def OnEnter(self): 113 value = self._GetValue() 114 self.context.dogmaLM.SetAttributeValue(self.context.myItemId, self.attributes.attributeId, value) 115 self.SetStatusToSuccess() 116 117 def _GetValue(self): 118 if self.attributes.valueAddress: 119 return self.GetLastBlackboardValue(self.attributes.valueAddress) 120 if self.attributes.value is not None: 121 return self.attributes.value 122 raise BehaviorAuthoringException('BehaviorID: %s has no value defined for task: %s', self.behaviorTree.GetBehaviorId(), type(self).__name__) 123 124 125 class SendDogmaAttributeValueAsMessage(Task): 126 127 def OnEnter(self): 128 attributeValue = self.context.dogmaLM.GetAttributeValue(self.context.myItemId, self.attributes.attributeId) 129 if self.attributes.scalarValueAddress is not None: 130 scalar = self.GetLastBlackboardValue(self.attributes.scalarValueAddress) 131 else: 132 scalar = getattr(self.attributes, 'scalar', None) or 1.0 133 self.SendBlackboardValue(self.attributes.valueAddress, attributeValue * scalar) 134 self.SetStatusToSuccess() 135 136 137 class ResetDogmaAttributeValue(Task): 138 139 @TimedFunction('behaviors::actions::effects::ResetDogmaAttributeValue::OnEnter') 140 def OnEnter(self): 141 typeValue = self.context.dogmaLM.dogmaStaticMgr.GetTypeAttribute2(self.context.mySlimItem.typeID, self.attributes.attributeId) 142 self.context.dogmaLM.SetAttributeValue(self.context.myItemId, self.attributes.attributeId, typeValue) 143 self.status = status.TaskSuccessStatus 144 145 146 class ActivateTargetedEffect(Task): 147 148 @TimedFunction('behaviors::actions::effects::ActivateTargetedEffect::OnEnter') 149 def OnEnter(self): 150 selectedTarget = self.GetLastBlackboardValue(self.attributes.selectedTargetAddress) 151 self.SetStatusToSuccess() 152 item = self.context.ballpark.inventory2.GetItem(self.context.myItemId) 153 if selectedTarget: 154 if self.context.dogmaLM.dogmaStaticMgr.TypeHasEffect(item.typeID, self.attributes.effectId): 155 self.TryActivateEffect(item.ownerID, selectedTarget) 156 157 @TimedFunction('behaviors::actions::effects::ActivateTargetedEffect::TryActivateEffect') 158 def TryActivateEffect(self, ownerID, targetID): 159 try: 160 self.context.dogmaLM.ActivateWithContext(ownerID, self.context.myItemId, self.attributes.effectId, targetid=targetID, repeat=self.attributes.repeats) 161 self.StartMonitoringEffectStoppedIfRequired() 162 logger.debug('ActivateTargetedEffect: %s: start attacking target %s with effect %s', self.context.myItemId, targetID, self.attributes.effectId) 163 except (UserError,) as e: 164 if e.msg == 'EffectAlreadyActive2': 165 self.StartMonitoringEffectStoppedIfRequired() 166 logger.debug('ActivateTargetedEffect: %s: effect already active', self.context.myItemId) 167 else: 168 logger.debug('ActivateTargetedEffect: %s: failed to activate on target %s with effect %s: %s', self.context.myItemId, targetID, self.attributes.effectId, e) 169 170 def CleanUp(self): 171 if self.IsInvalid(): 172 return 173 self.StopMonitoringEffectStopped() 174 self.SetStatusToInvalid() 175 176 def StartMonitoringEffectStopped(self): 177 self.SubscribeItem(self.context.myItemId, MESSAGE_ON_EFFECT_STOPPED, self.OnStopEffect) 178 179 def StopMonitoringEffectStopped(self): 180 self.UnsubscribeItem(self.context.myItemId, MESSAGE_ON_EFFECT_STOPPED, self.OnStopEffect) 181 182 def StartMonitoringEffectStoppedIfRequired(self): 183 if self.attributes.shouldResetBehaviorOnEffectStopped: 184 self.StartMonitoringEffectStopped() 185 186 def OnStopEffect(self, effectId): 187 if self.IsInvalid(): 188 return 189 if effectId == self.attributes.effectId: 190 self.behaviorTree.RequestReset(requestedBy=self) 191 192 193 class ActivateEffect(Task): 194 195 def OnEnter(self): 196 self.SetStatusToSuccess() 197 item = self.context.ballpark.inventory2.GetItem(self.context.myItemId) 198 self.TryActivateEffect(item.ownerID) 199 200 def TryActivateEffect(self, ownerID): 201 effect_id = self.GetEffectId() 202 try: 203 self.context.dogmaLM.ActivateWithContext(ownerID, self.context.myItemId, effectID=effect_id, repeat=self.GetRepeats(), context=self.GetContext()) 204 logger.debug('ActivateEffect: %s: start attacking effect %s', self.context.myItemId, effect_id) 205 except (UserError,) as e: 206 logger.debug('ActivateEffect: %s: failed to activate effect %s: %s', self.context.myItemId, effect_id, e) 207 208 def GetContext(self): 209 return getattr(self.attributes, 'contextDict', None) 210 211 def GetEffectId(self): 212 return self.attributes.effectId 213 214 def GetRepeats(self): 215 return self.attributes.repeats 216 217 218 class ActivateDefaultEffect(ActivateEffect): 219 220 def GetEffectId(self): 221 return get_default_effect_id_for_type(self, self.context.mySlimItem.typeID) 222 223 224 class MockTargetAttack(Task): 225 226 def OnEnter(self): 227 self.SetStatusToFailed() 228 targetId = self.GetLastBlackboardValue(self.attributes.targetIdAddress) 229 if targetId is not None: 230 duration = self.context.dogmaLM.GetAttributeValue(self.context.myItemId, attributeRateOfFire) 231 sfx = self.context.ballpark.specialEffects 232 sfx.StartStretchEffect(self.context.myItemId, targetId, TARGET_ATTACK_GRAPHIC_EFFECT, duration, 99, self.context.myItemId) 233 self.SetStatusToSuccess() 234 235 236 class StopMockTargetAttack(Task): 237 238 def OnEnter(self): 239 self.SetStatusToFailed() 240 targetId = self.GetLastBlackboardValue(self.attributes.targetIdAddress) 241 if targetId is not None: 242 sfx = self.context.ballpark.specialEffects 243 sfx.StopStretchEffect(self.context.myItemId, targetId, TARGET_ATTACK_GRAPHIC_EFFECT, self.context.myItemId) 244 self.SetStatusToSuccess() 245 246 247 class SendDogmaEffectIdAsMessage(Task): 248 249 def OnEnter(self): 250 self.SendBlackboardValue(self.attributes.effectIdAddress, self.attributes.effectId) 251 self.SetStatusToSuccess() 252 253 254 class StopEffect(Task): 255 256 @TimedFunction('behaviors::actions::effects::StopEffect::OnEnter') 257 def OnEnter(self): 258 self.SetStatusToFailed() 259 effect_id = self._get_effect_id() 260 if not effect_id: 261 logger.warn('Behavior=%s does not have effect=%s authored for task=%s', self.behaviorTree.GetBehaviorId(), effect_id) 262 return 263 if not type_has_effect(self, self.context.mySlimItem.typeID, effect_id): 264 logger.warn('Behavior=%s entity=%s is missing effect=%s', self.behaviorTree.GetBehaviorId(), self.context.mySlimItem.typeID, effect_id) 265 return 266 self.SetStatusToSuccess() 267 self._stop_effect(effect_id) 268 269 def _get_effect_id(self): 270 return self.attributes.effectId 271 272 def _stop_effect(self, effect_id): 273 try_stop_effect(self, effect_id, forced=self._is_stop_forced()) 274 275 def _is_stop_forced(self): 276 return self.attributes.forcedStop 277 278 279 class ReplaceNebulaForPlayersInBubble(Task): 280 281 def OnEnter(self): 282 self.SetStatusToSuccess() 283 nebula_path = 'res:/dx9/scene/abyssal/ad01_a_cube.dds' 284 for ball_id in get_ship_balls_in_bubble(self, self.context.myBall.newBubbleId): 285 slim_item = get_slim_item(self, ball_id) 286 sm.GetService('machoNet').SinglecastByCharID(slim_item.charID, 'OnReplaceNebula', nebula_path)