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

turrets.py (14805B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\environment\effects\turrets.py
      2 import trinity
      3 from eve.client.script.environment.effects.GenericEffect import GenericEffect, STOP_REASON_DEFAULT
      4 from evetypes import GetGraphicID
      5 from fighters import ABILITY_SLOT_ID_KEY
      6 import evegraphics.settings as gfxsettings
      7 import uthread
      8 import collections
      9 import random
     10 import blue
     11 import geo2
     12 from fsdBuiltData.common.graphicIDs import GetControllerVariableOverrides
     13 from fsdBuiltData.client.effects import GetSourceDamageDelay, GetSourceDamageDuration, GetSourceDamageSize, GetTargetDamageSize, GetTargetDamageDuration, GetTargetDamageDelay
     14 
     15 class StandardWeapon(GenericEffect):
     16     __guid__ = 'effects.StandardWeapon'
     17 
     18     def __init__(self, trigger, *args):
     19         self.ballIDs = [trigger.shipID, trigger.targetID]
     20         self.gfx = None
     21         self.gfxModel = None
     22         self.turrets = []
     23         if trigger.graphicInfo is not None and ABILITY_SLOT_ID_KEY in trigger.graphicInfo:
     24             self.moduleID = trigger.graphicInfo[ABILITY_SLOT_ID_KEY]
     25         else:
     26             self.moduleID = trigger.moduleID
     27         self.otherTypeID = trigger.otherTypeID
     28         self.fxSequencer = sm.GetService('FxSequencer')
     29         self.controllerVariableOverrides = {}
     30         if self.otherTypeID is not None:
     31             ammo_gid = GetGraphicID(self.otherTypeID)
     32             self.controllerVariableOverrides = GetControllerVariableOverrides(ammo_gid) or {}
     33 
     34     def Prepare(self):
     35         pass
     36 
     37     def SetupTurrets(self):
     38         if not gfxsettings.Get(gfxsettings.UI_TURRETS_ENABLED):
     39             return False
     40         shipBall = self.GetEffectShipBall()
     41         targetBall = self.GetEffectTargetBall()
     42         if targetBall is None:
     43             return False
     44         if shipBall is None:
     45             return False
     46         shipID = self.GetEffectShipID()
     47         if not hasattr(shipBall, 'fitted'):
     48             self.fxSequencer.LogError('%s: %s Turrets: Error! can not fit turrets. No fitted attribute ' % (self.__guid__, shipID))
     49             return False
     50         shipBall.FitHardpoints(blocking=True)
     51         if not shipBall.fitted:
     52             return False
     53         if shipBall.modules is None:
     54             return False
     55         self.PopulateTurrets(shipBall)
     56         if len(self.turrets) < 1:
     57             self.fxSequencer.LogError('StandardWeapon: Turret not fitted on shipID will retry', shipID)
     58             return False
     59         return True
     60 
     61     def Shoot(self, shipBall, targetID):
     62         for turret in self.turrets:
     63             turret.StartControllers()
     64             for name, value in self.controllerVariableOverrides.iteritems():
     65                 turret.SetControllerVariable(name, value)
     66 
     67             turret.SetTarget(targetID)
     68             turret.StartShooting()
     69 
     70     def Start(self, duration):
     71         if self.SetupTurrets():
     72             uthread.worker('FxSequencer::ShootTurrets', self.Shoot, self.GetEffectShipBall(), self.GetEffectTargetID())
     73 
     74     def PopulateTurrets(self, shipBall):
     75         if len(self.turrets) != 0 or shipBall is None:
     76             return
     77         shipBall.PrepareForFiring()
     78         self.turrets = shipBall.modules.get(self.moduleID)
     79         if not isinstance(self.turrets, collections.Iterable):
     80             if self.turrets is None:
     81                 self.turrets = []
     82             else:
     83                 self.turrets = [self.turrets]
     84         self.SetAmmoColor()
     85         self.SetDestSpaceObject()
     86         self.SetSourceSpaceObject()
     87 
     88     def SetAmmoColor(self):
     89         if self.otherTypeID is None:
     90             return
     91         for turret in self.turrets:
     92             turret.SetAmmoColorByTypeID(self.otherTypeID)
     93 
     94     def SetDestSpaceObject(self):
     95         targetBall = self.GetEffectTargetBall()
     96         if targetBall is None:
     97             return
     98         for turret in self.turrets:
     99             turret.SetDestSpaceObject(targetBall.model)
    100 
    101     def SetSourceSpaceObject(self):
    102         sourceBall = self.GetEffectShipBall()
    103         if sourceBall is None:
    104             return
    105         for turret in self.turrets:
    106             turret.SetSourceSpaceObject(sourceBall.model)
    107 
    108     def Stop(self, reason = STOP_REASON_DEFAULT):
    109         for turret in self.turrets:
    110             turret.StopShooting()
    111             turret.shooting = 0
    112 
    113         for turret in self.turrets:
    114             turret.SetSourceSpaceObject(None)
    115             turret.SetDestSpaceObject(None)
    116 
    117         self.turrets = []
    118 
    119     def _RestTurrets(self):
    120         for turret in self.turrets:
    121             turret.Rest()
    122             turret.shooting = 0
    123 
    124     def Repeat(self, duration):
    125         if len(self.turrets) < 1:
    126             shipBall = self.GetEffectShipBall()
    127             if shipBall is None:
    128                 return
    129             self.PopulateTurrets(shipBall)
    130         if len(self.turrets) < 1:
    131             return
    132         shipID = self.ballIDs[0]
    133         shipBall = self.fxSequencer.GetBall(shipID)
    134         targetID = self.ballIDs[1]
    135         targetBall = self.fxSequencer.GetBall(targetID)
    136         if targetBall is None or shipBall is None:
    137             self._RestTurrets()
    138             return
    139         shipBall.PrepareForFiring()
    140         uthread.worker('FxSequencer::ShootTurrets', self.Shoot, shipID, targetID)
    141 
    142 
    143 class CloudMining(StandardWeapon):
    144     __guid__ = 'effects.CloudMining'
    145 
    146     def SetAmmoColor(self):
    147         targetBall = self.GetEffectTargetBall()
    148         targetModel = getattr(targetBall, 'model', None)
    149         color = (1.0, 1.0, 1.0, 1.0)
    150         emitters = targetModel.Find('trinity.EveEmitterStatic')
    151         if len(emitters):
    152             if len(emitters[0].particleData):
    153                 color = emitters[0].particleData[0].color
    154         for turret in self.turrets:
    155             if hasattr(turret, 'SetAmmoColor'):
    156                 turret.SetAmmoColor(color)
    157 
    158 
    159 class MissileLaunch(GenericEffect):
    160     __guid__ = 'effects.MissileLaunch'
    161 
    162     def __init__(self, trigger, *args):
    163         self.ballIDs = [trigger.shipID, trigger.targetID]
    164         self.gfx = None
    165         self.gfxModel = None
    166         self.moduleID = trigger.moduleID
    167         self.otherTypeID = trigger.otherTypeID
    168         self.fxSequencer = sm.GetService('FxSequencer')
    169 
    170     def Prepare(self):
    171         pass
    172 
    173     def Shoot(self, targetID):
    174         if getattr(self, 'turret', None) is not None:
    175             self.turret.SetTarget(targetID)
    176 
    177     def Start(self, duration):
    178         if not gfxsettings.Get(gfxsettings.UI_TURRETS_ENABLED):
    179             return
    180         shipID = self.ballIDs[0]
    181         shipBall = self.fxSequencer.GetBall(shipID)
    182         targetID = self.ballIDs[1]
    183         targetBall = self.fxSequencer.GetBall(targetID)
    184         if targetBall is None:
    185             return
    186         if shipBall is None:
    187             return
    188         if not hasattr(shipBall, 'fitted'):
    189             return
    190         shipBall.FitHardpoints(blocking=True)
    191         if not shipBall.fitted:
    192             return
    193         if shipBall.modules is None:
    194             return
    195         self.turret = shipBall.modules.get(self.moduleID)
    196         if self.moduleID == shipID and 0 in shipBall.modules:
    197             self.turret = shipBall.modules.get(0)
    198             if not self.turret:
    199                 self.fxSequencer.LogError('MissileLaunch: Turret not fitted on shipID', shipID, self.moduleID)
    200                 return
    201         uthread.worker('FxSequencer::ShootTurrets', self.Shoot, targetID)
    202 
    203     def SetAmmoColor(self):
    204         pass
    205 
    206     def Stop(self, reason = STOP_REASON_DEFAULT):
    207         if getattr(self, 'turret', None) is None:
    208             return
    209         self.turret.StopShooting()
    210         self.turret.shooting = 0
    211         self.turret = None
    212 
    213     def Repeat(self, duration):
    214         if getattr(self, 'turret', None) is None:
    215             return
    216         shipID = self.ballIDs[0]
    217         shipBall = self.fxSequencer.GetBall(shipID)
    218         targetID = self.ballIDs[1]
    219         targetBall = self.fxSequencer.GetBall(targetID)
    220         if targetBall is None:
    221             self.turret.Rest()
    222             self.turret.shooting = 0
    223             return
    224         if shipBall is None:
    225             self.turret.Rest()
    226             self.turret.shooting = 0
    227             return
    228         if shipBall == targetBall:
    229             return
    230         uthread.worker('FxSequencer::ShootTurrets', self.Shoot, targetID)
    231 
    232 
    233 class ChainWeaponEffect(StandardWeapon):
    234     __guid__ = 'effects.ChainWeaponEffect'
    235 
    236     def __init__(self, trigger, effect = None, graphicFile = None):
    237         super(ChainWeaponEffect, self).__init__(trigger, effect, graphicFile)
    238         self.duration = trigger.duration
    239         self.graphicFile = graphicFile
    240         self.effects = []
    241         self.damageThreads = []
    242         self.startTime = trigger.startTime
    243         self.sourceDamageSize = GetSourceDamageSize(trigger.guid)
    244         self.sourceDamageDuration = GetSourceDamageDuration(trigger.guid)
    245         self.sourceDamageDelay = GetSourceDamageDelay(trigger.guid)
    246         self.targetDamageSize = GetTargetDamageSize(trigger.guid)
    247         self.targetDamageDuration = GetTargetDamageDuration(trigger.guid)
    248         self.targetDamageDelay = GetTargetDamageDelay(trigger.guid)
    249         self.controllerVariableOverrides = {}
    250         if trigger.moduleTypeID is not None:
    251             ammo_gid = GetGraphicID(trigger.moduleTypeID)
    252             self.controllerVariableOverrides = GetControllerVariableOverrides(ammo_gid) or {}
    253         self.targets = []
    254         try:
    255             self.targets = trigger.graphicInfo['targets']
    256         except KeyError:
    257             self.fxSequencer.LogError("ChainWeaponEffect: No 'targets' in graphic info... no additional targets used")
    258 
    259     def _add_effect(self, source_curve, target_curve, jump_index = 0):
    260         if source_curve is None or target_curve is None:
    261             return
    262         gfx = trinity.Load(self.graphicFile)
    263         gfx.source = source_curve
    264         gfx.dest = target_curve
    265         gfx.SetControllerVariable('jumpNumber', jump_index)
    266         self.AddToScene(gfx)
    267         return gfx
    268 
    269     def _get_damage_locator_curve(self, source_id, target_id):
    270         target_ball = self.fxSequencer.GetBall(target_id)
    271         if target_ball is None:
    272             return
    273         target_model = target_ball.model
    274         if target_model is not None:
    275             dest = trinity.EveLocalPositionCurve(trinity.EveLocalPositionBehavior.damageLocator)
    276             dest.parent = target_model
    277             dest.alignPositionCurve = self.fxSequencer.GetBall(source_id)
    278             return dest
    279         return target_ball
    280 
    281     def _add_turret_to_target_effect(self, turret, target_id):
    282         source = trinity.EveLocalPositionCurve(trinity.EveLocalPositionBehavior.activeTurret)
    283         source.turretSetObject = turret.turretSets[0]
    284         source.muzzleIndex = 0
    285         return self._add_effect(source, self._get_damage_locator_curve(self.GetEffectShipID(), target_id))
    286 
    287     def _add_target_to_target_effect(self, source_id, target_id, jump_index):
    288         if source_id == target_id:
    289             self.fxSequencer.LogError('ChainWeaponEffect: Trying to create a stretch between the same object %s' % source_id)
    290             return None
    291         source_curve = self._get_damage_locator_curve(target_id, source_id)
    292         target_curve = self._get_damage_locator_curve(source_id, target_id)
    293         return self._add_effect(source_curve, target_curve, jump_index)
    294 
    295     def setup_firing_effects(self):
    296         self.effects = []
    297         for turret in self.turrets:
    298             e = self._add_turret_to_target_effect(turret, self.GetEffectTargetID())
    299             if e is not None:
    300                 self.effects.append(e)
    301 
    302         last_target = self.GetEffectTargetID()
    303         for index, target in enumerate(self.targets):
    304             e = self._add_target_to_target_effect(last_target, target, index + 1)
    305             if e is not None:
    306                 self.effects.append(e)
    307                 last_target = target
    308 
    309     def remove_stretch_effect(self):
    310         for gfx in self.effects:
    311             self.RemoveFromScene(gfx)
    312 
    313         for t in self.damageThreads:
    314             if t is not None and t.alive:
    315                 t.kill()
    316 
    317         self.damageThreads = []
    318         self.effects = []
    319 
    320     def Start(self, duration):
    321         if not self.SetupTurrets():
    322             return
    323         uthread.worker('FxSequencer::ShootTurrets', self.Shoot, self.GetEffectShipID(), self.GetEffectTargetID())
    324 
    325     def Repeat(self, duration):
    326         super(ChainWeaponEffect, self).Repeat(duration)
    327         self.remove_stretch_effect()
    328 
    329     def Stop(self, reason = STOP_REASON_DEFAULT):
    330         super(ChainWeaponEffect, self).Stop(reason)
    331         self.remove_stretch_effect()
    332 
    333     def Shoot(self, ship_id, target_id):
    334         self.setup_firing_effects()
    335         for turret in self.turrets:
    336             turret.StartControllers()
    337             for name, value in self.controllerVariableOverrides.iteritems():
    338                 turret.SetControllerVariable(name, value)
    339 
    340             turret.SetTarget(target_id)
    341             turret.StartShooting()
    342 
    343         delay = 0
    344         for effect in self.effects:
    345             for name, value in self.controllerVariableOverrides.iteritems():
    346                 effect.SetControllerVariable(name, value)
    347 
    348             effect.StartFiring(delay)
    349             self.damageThreads.append(uthread.new(self._apply_damage, self.sourceDamageDelay + delay, self.sourceDamageSize, self.sourceDamageDuration, effect, False))
    350             self.damageThreads.append(uthread.new(self._apply_damage, self.targetDamageDelay + delay, self.targetDamageSize, self.targetDamageDuration, effect, True))
    351             delay += 0.3 * random.random()
    352 
    353     def _apply_damage(self, delay, size, duration, stretch_effect, applyOnTarget):
    354         blue.synchro.SleepSim(delay * 1000)
    355         source = stretch_effect.source
    356         target = stretch_effect.dest
    357         source_pos = source.GetVectorAt(blue.os.GetSimTime())
    358         source_pos = (source_pos.x, source_pos.y, source_pos.z)
    359         target_pos = target.GetVectorAt(blue.os.GetSimTime())
    360         target_pos = (target_pos.x, target_pos.y, target_pos.z)
    361         if not applyOnTarget:
    362             if not isinstance(source, trinity.EveLocalPositionCurve) or source.parent is None:
    363                 return
    364             if not hasattr(source.parent, 'CreateImpact'):
    365                 return
    366             direction = geo2.Vec3Direction(target_pos, source_pos)
    367             source.parent.CreateImpact(source.damageLocatorIndex, direction, duration, size)
    368         elif target is not None and getattr(target, 'parent', None) is not None:
    369             if not isinstance(target, trinity.EveLocalPositionCurve) or target.parent is None:
    370                 return
    371             if not hasattr(target.parent, 'CreateImpact'):
    372                 return
    373             direction = geo2.Vec3Direction(source_pos, target_pos)
    374             target.parent.CreateImpact(target.damageLocatorIndex, direction, duration, size)