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

GenericEffect.py (13744B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\environment\effects\GenericEffect.py
      2 import blue
      3 import trinity
      4 import audio2
      5 from uthread2 import call_after_simtime_delay
      6 from fsdBuiltData.common.graphicIDs import GetGraphicFile
      7 import eve.client.script.environment.spaceObject.ship as ship
      8 import eve.client.script.environment.effects.effectConsts as effectConst
      9 STOP_REASON_DEFAULT = 'STOP_REASON_DEFAULT'
     10 STOP_REASON_BALL_REMOVED = 'STOP_REASON_BALL_REMOVED'
     11 
     12 class GenericEffect(object):
     13     __guid__ = 'effects.GenericEffect'
     14 
     15     def __init__(self, trigger, effect = None, graphicFile = None):
     16         self.ballIDs = [trigger.shipID, trigger.targetID]
     17         self.gfx = None
     18         self.gfxModel = None
     19         self.graphicFile = graphicFile
     20         self.transformFlags = [0] if effect is None else effect.transformFlags
     21         self.mergeFlags = [0] if effect is None else effect.mergeFlags
     22         if trigger.duration is not None and trigger.duration > 0:
     23             self.duration = trigger.duration
     24         else:
     25             self.duration = getattr(effect, 'duration', 10000)
     26         if effect and effect.secondaryGraphicID is not None:
     27             self.secondaryGraphicFile = GetGraphicFile(effect.secondaryGraphicID)
     28         else:
     29             self.secondaryGraphicFile = None
     30         self.scaleTime = effect.timeScale if effect and effect.timeScale is not None else False
     31         self.sourceOffset = 0 if effect is None else effect.sourceOffset
     32         self.destinationOffset = 0 if effect is None else effect.destinationOffset
     33         self.animationName = None if effect is None else effect.animationName
     34         self.graphicInfo = trigger.graphicInfo
     35         self.graphicRadius = getattr(self.graphicInfo, 'graphicRadius', None)
     36         self.lingerOnDeathTimer = 0
     37         if self.graphicInfo is not None and hasattr(self.graphicInfo, 'get'):
     38             self.lingerOnDeathTimer = self.graphicInfo.get('lingerOnDeathTimer') or 0.0
     39         self.startTime = trigger.startTime
     40         self.timeFromStart = trigger.timeFromStart
     41         self.moduleID = trigger.moduleID
     42         self.fxSequencer = sm.GetService('FxSequencer')
     43         self.observer = None
     44 
     45     def Prepare(self, addToScene = True):
     46         pass
     47 
     48     def Start(self, duration):
     49         pass
     50 
     51     def Stop(self, reason = STOP_REASON_DEFAULT):
     52         pass
     53 
     54     def Repeat(self, duration):
     55         pass
     56 
     57     def UpdateGraphicInfo(self, newGraphicInfo):
     58         pass
     59 
     60     def GetBalls(self):
     61         return self.ballIDs
     62 
     63     def GetBallPositionCurve(self, ball):
     64         if hasattr(ball, 'GetPositionCurve'):
     65             return ball.GetPositionCurve()
     66         return ball
     67 
     68     def GetEffectShipID(self):
     69         try:
     70             return self.ballIDs[0]
     71         except IndexError:
     72             return None
     73 
     74     def GetEffectShipBall(self):
     75         return self.fxSequencer.GetBall(self.GetEffectShipID())
     76 
     77     def GetEffectTargetID(self):
     78         try:
     79             return self.ballIDs[1]
     80         except IndexError:
     81             return None
     82 
     83     def GetEffectTargetBall(self):
     84         return self.fxSequencer.GetBall(self.GetEffectTargetID())
     85 
     86     def PlayNamedAnimations(self, model, animName):
     87         if not model:
     88             return
     89         for each in model.curveSets:
     90             if each.name == animName:
     91                 each.Play()
     92 
     93     def PlayNamedChildAnimations(self, model, animName):
     94         if not model:
     95             return
     96         for each in model.effectChildren:
     97             for curve in getattr(each, 'curveSets', []):
     98                 if curve.name == animName:
     99                     curve.Play()
    100 
    101     def GetEffectRadius(self):
    102         srcRadius = 35
    103         if self.gfx:
    104             effectBall = self.GetEffectShipBall()
    105             if effectBall is not None:
    106                 srcRadius = effectBall.radius
    107         return srcRadius
    108 
    109     def ScaleEffectAudioEmitter(self, entity, scaler = 1.0):
    110         srcRadius = self.GetEffectRadius()
    111         if srcRadius < 0:
    112             return
    113         attenuation = pow(srcRadius, 0.95) * 33 * scaler
    114         if entity is not None:
    115             entity.SetAttenuationScalingFactor(attenuation)
    116 
    117     def AttachObserverToTriEventCurve(self):
    118         if self.gfx is None:
    119             return
    120         for curve in self.gfx.Find('trinity.TriEventCurve'):
    121             if curve.name == 'audioEvents':
    122                 curve.eventListener = self.observer.observer
    123 
    124     def CheckForExistingObserver(self, location, name):
    125         if location is not None:
    126             for observer in location.Find('trinity.TriObserverLocal'):
    127                 if getattr(observer, 'observer', None) is not None:
    128                     if observer.observer.name == name:
    129                         self.observer = observer
    130                         return
    131 
    132         if self.gfx is None:
    133             return
    134         for observer in self.gfx.Find('trinity.TriObserverLocal'):
    135             if getattr(observer, 'observer', None) is not None:
    136                 if 'booster' not in observer.observer.name:
    137                     self.observer = observer
    138                     return
    139 
    140     def AddSoundToEffect(self, scaler = 1.0, model = None, guidOverride = ''):
    141         shipID = self.GetEffectShipID()
    142         emitter_name = 'effect_' + str(shipID) + '_' + (guidOverride or self.__guid__)
    143         self.CheckForExistingObserver(model, emitter_name)
    144         if self.observer is None:
    145             self.CreateNewAudioEmitter(emitter_name)
    146             model = model or self.gfx
    147             self.AttachObserverToModel(model)
    148             self.AttachObserverToTriEventCurve()
    149         if hasattr(self.observer, 'observer') and self.observer.observer is not None:
    150             self.ScaleEffectAudioEmitter(self.observer.observer, scaler)
    151 
    152     def CreateNewAudioEmitter(self, emitter_name):
    153         self.observer = trinity.TriObserverLocal()
    154         entity = audio2.AudEmitter(emitter_name)
    155         self.observer.observer = entity
    156 
    157     def SetupEffectEmitter(self):
    158         if self.observer is None:
    159             self.AddSoundToEffect(scaler=1.0)
    160 
    161     def SendAudioEvent(self, eventName):
    162         triObserver = self.observer
    163         if hasattr(triObserver, 'observer') and triObserver.observer is not None:
    164             triObserver.observer.SendEvent(eventName)
    165 
    166     def AttachObserverToModel(self, model):
    167         model.observers.append(self.observer)
    168 
    169     def AddToScene(self, effect):
    170         scene = self.fxSequencer.GetScene()
    171         if scene is not None:
    172             scene.objects.append(effect)
    173 
    174     def RemoveFromScene(self, effect):
    175         scene = self.fxSequencer.GetScene()
    176         if scene is not None:
    177             scene.objects.fremove(effect)
    178 
    179     def RecycleOrLoad(self, resPath):
    180         return trinity.Load(resPath)
    181 
    182     def _SpawnClientBall(self, position):
    183         bp = self.fxSequencer.GetBallpark()
    184         if bp is None:
    185             return
    186         egopos = bp.GetCurrentEgoPos()
    187         ballPosition = (position[0] + egopos[0], position[1] + egopos[1], position[2] + egopos[2])
    188         return bp.AddClientSideBall(ballPosition)
    189 
    190     def _DestroyClientBall(self, ball):
    191         bp = self.fxSequencer.GetBallpark()
    192         if bp is not None:
    193             bp.RemoveBall(ball.id)
    194 
    195 
    196 class ShipEffect(GenericEffect):
    197     __guid__ = 'effects.ShipEffect'
    198 
    199     def _CleanUp(self, model):
    200         self.RemoveFromScene(model)
    201         self.gfx = None
    202         if model:
    203             model.translationCurve = None
    204             model.rotationCurve = None
    205         self.gfxModel = None
    206         self.observer = None
    207 
    208     def Stop(self, reason = STOP_REASON_DEFAULT):
    209         if self.gfx is None:
    210             raise RuntimeError('ShipEffect: no effect defined:' + self.__guid__)
    211         if self.lingerOnDeathTimer > 0.0 and reason != STOP_REASON_BALL_REMOVED:
    212             if hasattr(self.gfx, 'controllers'):
    213                 self.gfx.SetControllerVariable('isOn', 0.0)
    214             call_after_simtime_delay(self._CleanUp, self.lingerOnDeathTimer, self.gfxModel)
    215         else:
    216             self._CleanUp(self.gfxModel)
    217 
    218     def Prepare(self, addToScene = True):
    219         shipBall = self.GetEffectShipBall()
    220         if shipBall is None:
    221             raise RuntimeError('ShipEffect: no ball found:' + self.__guid__)
    222         self.gfx = self.RecycleOrLoad(self.graphicFile)
    223         if self.gfx is None:
    224             raise RuntimeError('ShipEffect: no effect found:' + self.__guid__)
    225         if type(self.gfx) == trinity.EveTransform:
    226             self.gfxModel = trinity.EveRootTransform()
    227             self.gfxModel.children.append(self.gfx)
    228         elif isinstance(self.gfx, trinity.EveChildContainer):
    229             self.gfxModel = trinity.EveEffectRoot2()
    230             self.gfxModel.effectChildren.append(self.gfx)
    231         else:
    232             self.gfxModel = self.gfx
    233         self.gfxModel.modelRotationCurve = getattr(shipBall.model, 'modelRotationCurve', None)
    234         self.gfxModel.modelTranslationCurve = getattr(shipBall.model, 'modelTranslationCurve', None)
    235         effectBall = shipBall
    236         if effectConst.FX_TF_POSITION_BALL in self.transformFlags:
    237             self.gfxModel.translationCurve = self.GetBallPositionCurve(shipBall)
    238         if effectConst.FX_TF_POSITION_MODEL in self.transformFlags:
    239             behavior = trinity.EveLocalPositionBehavior.centerBounds
    240             self.gfxModel.translationCurve = trinity.EveLocalPositionCurve(behavior)
    241             self.gfxModel.translationCurve.parent = shipBall.model
    242         if effectConst.FX_TF_POSITION_TARGET in self.transformFlags:
    243             effectBall = self.GetEffectTargetBall()
    244             self.gfxModel.translationCurve = self.GetBallPositionCurve(effectBall)
    245         if effectConst.FX_TF_ELLIPSOID in self.transformFlags:
    246             if hasattr(effectBall.model, 'shapeEllipsoidCenter'):
    247                 radius = effectBall.model.shapeEllipsoidRadius
    248                 self.gfxModel.scaling = radius
    249                 position = effectBall.model.shapeEllipsoidCenter
    250                 curve = trinity.Tr2TranslationAdapter()
    251                 curve.value = position
    252                 self.gfxModel.modelTranslationCurve = curve
    253                 self.gfxModel.name = 'THIS ONE'
    254             else:
    255                 self.transformFlags.append(effectConst.FX_TF_SCALE_BOUNDING)
    256         if self.graphicRadius is not None:
    257             self.gfxModel.scaling = (self.graphicRadius, self.graphicRadius, self.graphicRadius)
    258         elif effectConst.FX_TF_SCALE_BOUNDING in self.transformFlags:
    259             shipBBoxMin, shipBBoxMax = effectBall.model.GetLocalBoundingBox()
    260             bBox = (max(-shipBBoxMin[0], shipBBoxMax[0]) * 1.2, max(-shipBBoxMin[1], shipBBoxMax[1]) * 1.2, max(-shipBBoxMin[2], shipBBoxMax[2]) * 1.2)
    261             self.gfxModel.scaling = bBox
    262         elif effectConst.FX_TF_SCALE_SYMMETRIC in self.transformFlags:
    263             if effectBall.model is not None:
    264                 radius = effectBall.model.GetBoundingSphereRadius()
    265                 self.gfxModel.scaling = (radius, radius, radius)
    266                 self.gfx.translation = (0, 0, 0)
    267         elif effectConst.FX_TF_SCALE_RADIUS in self.transformFlags:
    268             if effectBall.model is not None:
    269                 radius = effectBall.model.GetBoundingSphereRadius()
    270                 self.gfxModel.scaling = (radius, radius, radius)
    271         if effectConst.FX_TF_ROTATION_BALL in self.transformFlags:
    272             self.gfxModel.rotationCurve = effectBall
    273         self.gfxModel.name = self.__guid__
    274         self.AddSoundToEffect(2)
    275         if addToScene:
    276             self.AddToScene(self.gfxModel)
    277 
    278     def Start(self, duration):
    279         if self.gfx is None:
    280             raise RuntimeError('ShipEffect: no effect defined:' + self.__guid__)
    281         curveSets = self.gfx.curveSets
    282         if len(curveSets) > 0:
    283             if self.scaleTime:
    284                 length = self.gfx.curveSets[0].GetMaxCurveDuration()
    285                 if length > 0.0:
    286                     scaleValue = length / (duration / 1000.0)
    287                     self.gfx.curveSets[0].scale = scaleValue
    288             curveSets[0].PlayFrom(self.timeFromStart / float(const.SEC))
    289         if hasattr(self.gfx, 'controllers'):
    290             secondsFromStart = self.timeFromStart / float(const.SEC)
    291             self.gfx.SetControllerVariable('elapsedTime', secondsFromStart)
    292             self.gfx.SetControllerVariable('isOn', 1.0)
    293             self.gfx.StartControllers()
    294 
    295     def Repeat(self, duration):
    296         if self.gfx is None:
    297             return
    298         curveSets = []
    299         if self.gfxModel is not None:
    300             if hasattr(self.gfxModel, 'children'):
    301                 gfxModelChildren = self.gfxModel.children
    302                 if len(gfxModelChildren):
    303                     curveSets = gfxModelChildren[0].curveSets
    304             elif isinstance(self.gfxModel, trinity.EveEffectRoot2):
    305                 curveSets = self.gfxModel.curveSets
    306         if len(curveSets):
    307             curveSets[0].Play()
    308 
    309 
    310 def GetBoundingBox(shipBall, scale = 1.0):
    311     if not isinstance(shipBall, ship.Ship):
    312         return (shipBall.radius, shipBall.radius, shipBall.radius)
    313     if hasattr(shipBall, 'GetModel'):
    314         model = shipBall.GetModel()
    315     else:
    316         model = getattr(shipBall, 'model', None)
    317     if model is None:
    318         return (shipBall.radius, shipBall.radius, shipBall.radius)
    319     if hasattr(model, 'GetLocalBoundingBox'):
    320         shipBBoxMin, shipBBoxMax = model.GetLocalBoundingBox()
    321         if shipBBoxMin is None or shipBBoxMax is None:
    322             raise RuntimeError('StretchEffect: invalid LocalBoundingBox')
    323         else:
    324             return (scale * max(-shipBBoxMin[0], shipBBoxMax[0]), scale * max(-shipBBoxMin[1], shipBBoxMax[1]), scale * max(-shipBBoxMin[2], shipBBoxMax[2]))
    325     else:
    326         raise RuntimeError('StretchEffect: needs GetLocalBoundingBox')