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

missile.py (12818B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\environment\spaceObject\missile.py
      2 import math
      3 import random
      4 import blue
      5 import carbon.common.script.util.logUtil as log
      6 import eveSpaceObject.missile as gfxmissile
      7 import evegraphics.settings as gfxsettings
      8 import geo2
      9 import inventorycommon.typeHelpers
     10 import pytelemetry.zoning as telemetry
     11 import uthread
     12 from carbon.client.script.environment.audioService import GetAudioService
     13 from eve.client.script.environment.spaceObject.spaceObject import SpaceObject
     14 from eve.client.script.parklife.sceneManager import GetSceneManager
     15 from eve.client.script.remote.michelle import GetMichelle
     16 from fsdBuiltData.client.groupGraphics import GetGraphicIdsFromTypeID
     17 from fsdBuiltData.common.graphicIDs import GetGraphicFile
     18 from destructionEffect import destructionType as destructionEffectType
     19 SECOND = 10000000
     20 
     21 def _DestroyClientBall(ball):
     22     bp = GetMichelle().GetBallpark()
     23     if bp is not None and ball.ballpark is not None:
     24         bp.RemoveBall(ball.id)
     25 
     26 
     27 def _SpawnClientBall(position):
     28     bp = GetMichelle().GetBallpark()
     29     if bp is None:
     30         return
     31     egopos = bp.GetCurrentEgoPos()
     32     explosionPosition = (position[0] + egopos[0], position[1] + egopos[1], position[2] + egopos[2])
     33     return bp.AddClientSideBall(explosionPosition)
     34 
     35 
     36 def _ShakeCamera(shakeMagnitude, explosionPosition):
     37     camera = GetSceneManager().GetActiveSpaceCamera()
     38     if camera:
     39         camera.ShakeCamera(shakeMagnitude, explosionPosition, 'Missile')
     40 
     41 
     42 def _GetScene():
     43     return GetSceneManager().GetRegisteredScene('default')
     44 
     45 
     46 def _GetMissilesEnabled():
     47     missilesDesired = gfxsettings.Get(gfxsettings.UI_MISSILES_ENABLED)
     48     if missilesDesired:
     49         scene = GetSceneManager().GetRegisteredScene('default', allowBlocking=False)
     50         if scene is None:
     51             return False
     52         updateTime = scene.updateTime
     53         now = blue.os.GetSimTime()
     54         if now < updateTime:
     55             return False
     56         delta = blue.os.TimeDiffInMs(updateTime, now)
     57         return delta < 2000
     58     return missilesDesired
     59 
     60 
     61 class Missile(SpaceObject):
     62     __guid__ = 'spaceObject.Missile'
     63 
     64     def __init__(self):
     65         SpaceObject.__init__(self)
     66         self.exploded = False
     67         self.collided = False
     68         self.targetId = None
     69         self.sourceShipID = None
     70         self.sourceModuleIDList = []
     71         self._delayedBall = None
     72         self._randomizeImpactRotation = True
     73         self.enabled = _GetMissilesEnabled()
     74         self.missileRadius = 100
     75         self._missileModel = None
     76 
     77     @telemetry.ZONE_METHOD
     78     def LoadModel(self, fileName = None, loadedModel = None):
     79         if not self.enabled:
     80             return
     81         slimItem = self.typeData['slimItem']
     82         self.sourceShipID = slimItem.sourceShipID
     83         self.sourceModuleIDList = slimItem.launchModules
     84         impactFileName = inventorycommon.typeHelpers.GetGraphicFile(slimItem.typeID)
     85         if impactFileName == '':
     86             log.LogError('missile::LoadModel failed to get impact red filename for missile typeID ' + str(slimItem.typeID) + ' missileID : ' + str(self.id) + ' sourceShipID: ' + str(self.sourceShipID))
     87             return
     88         missileGraphicID = GetGraphicIdsFromTypeID(slimItem.typeID, [None])[0]
     89         if missileGraphicID is None:
     90             log.LogError('missile::LoadModel failed to get missile graphicID for typeID %s from groupGraphics', slimItem.typeID)
     91             return
     92         missileFileName = GetGraphicFile(missileGraphicID)
     93         if missileFileName is None:
     94             log.LogError('missile::LoadModel failed to get missile red filename for missile typeID ' + str(slimItem.typeID) + ' missileID : ' + str(self.id) + ' sourceShipID: ' + str(self.sourceShipID))
     95             return
     96         self.targetId = self.followId
     97         self._missileModel = gfxmissile.MissileGraphics('Missile in %s' % self.id, missileFileName, impactFileName, self)
     98         self.model = self._missileModel.LoadModel()
     99         if self.model is None:
    100             self.LogError('missile::LoadModel failed to load a model ' + str(missileFileName))
    101             return
    102         self._missileModel.SetMissileCurves(self._GetMissileTranslationCurve(), self._GetMissileRotationCurve())
    103         scene = GetSceneManager().GetRegisteredScene('default')
    104         scene.objects.append(self.model)
    105 
    106     def _GetMissileTranslationCurve(self):
    107         return self
    108 
    109     def _GetMissileRotationCurve(self):
    110         return self
    111 
    112     def _GetModelTurret(self, moduleIdx):
    113         if len(self.sourceModuleIDList) <= moduleIdx:
    114             self.logger.warning('moduleIdx: + %s is too high to index into list!', str(moduleIdx))
    115             return
    116         slimItemID = self.sourceModuleIDList[moduleIdx]
    117         sourceShipBall = GetMichelle().GetBall(self.sourceShipID)
    118         if sourceShipBall is not None:
    119             if not hasattr(sourceShipBall, 'modules'):
    120                 return
    121             if sourceShipBall.modules is None:
    122                 return
    123             if slimItemID in sourceShipBall.modules:
    124                 return sourceShipBall.modules[slimItemID]
    125 
    126     def _EstimateTimeToTarget(self, toCenter = False):
    127         targetBall = GetMichelle().GetBall(self.targetId)
    128         if targetBall is None:
    129             return 5.0
    130         now = blue.os.GetSimTime()
    131         myPos = self.GetVectorAt(now)
    132         targetPos = targetBall.GetVectorAt(now)
    133         if toCenter:
    134             targetRadius = 0
    135         else:
    136             targetRadius = targetBall.radius
    137         return gfxmissile.EstimateTimeToTarget(myPos, targetPos, targetRadius, self.maxVelocity)
    138 
    139     def _GetTimeToTarget(self):
    140         timeToTarget = self._EstimateTimeToTarget()
    141         doSpread = True
    142         if timeToTarget < 1.6:
    143             doSpread = False
    144         timeToTargetCenter = max(0.5, self._EstimateTimeToTarget(toCenter=True))
    145         if timeToTarget > 0:
    146             timeToTarget = (timeToTarget + timeToTargetCenter) * 0.5
    147         else:
    148             timeToTarget = timeToTargetCenter * 0.5
    149         return (doSpread, timeToTarget)
    150 
    151     def _GetAllTurretSets(self, moduleCount):
    152         turretWrappers = []
    153         for moduleIdx in range(0, moduleCount):
    154             turrets = self._GetModelTurret(moduleIdx)
    155             if not isinstance(turrets, list):
    156                 turrets = [turrets]
    157             for turretIndex, turret in enumerate(turrets):
    158                 if turret is not None and len(turret.turretSets) > 0:
    159                     turretWrappers.append(gfxmissile.MissileTurretWrapper(turret.turretSets[0], turret.StartShooting))
    160                     if hasattr(turret.turretSets[0], 'randomizeExplosionRotation'):
    161                         self._randomizeImpactRotation = turret.turretSets[0].randomizeExplosionRotation
    162                 else:
    163                     turretWrappers.append(gfxmissile.MissileTurretWrapper(None))
    164 
    165         return turretWrappers
    166 
    167     @telemetry.ZONE_METHOD
    168     def Prepare(self):
    169         if not self.enabled:
    170             return
    171         if self.collided:
    172             return
    173         SpaceObject.Prepare(self)
    174         if self.model is None:
    175             return
    176         if getattr(self, 'sourceModuleIDList', None) is None:
    177             self.sourceModuleIDList = [0]
    178         moduleCount = max(len(self.sourceModuleIDList), 1)
    179         doSpread, timeToTarget = self._GetTimeToTarget()
    180         if not doSpread:
    181             self.DoCollision(self.targetId, 0, 0, 0)
    182         if len(self.model.warheads) != 1:
    183             log.LogError('There must be one and only one warhead per missile in: ' + str(self.model.name))
    184             return
    185         if self.targetId:
    186             targetBall = GetMichelle().GetBall(self.targetId)
    187             if targetBall is not None:
    188                 self._missileModel.SetTarget(targetBall.model, targetBall.radius)
    189         self._missileModel.SetSourceTranslationCurve(GetMichelle().GetBall(self.sourceShipID))
    190         turretSetInfos = self._GetAllTurretSets(moduleCount)
    191         self._missileModel.Start(turretSetInfos, timeToTarget, doSpread)
    192 
    193     @telemetry.ZONE_METHOD
    194     def RemoveAndClearModel(self, model, scene = None):
    195         if model is not None:
    196             SpaceObject.RemoveAndClearModel(self, model, scene=scene)
    197 
    198     def DoCollision(self, targetId, fx, fy, fz, fake = False):
    199         if self.collided:
    200             return
    201         self.collided = True
    202         if self.model is None:
    203             return
    204         uthread.new(self._DoCollision)
    205 
    206     def _DoCollision(self):
    207         if self.model is None:
    208             return
    209         pos = self.GetVectorAt(blue.os.GetSimTime())
    210         self._delayedBall = _SpawnClientBall((pos.x, pos.y, pos.z))
    211         self._missileModel.SetMissileCurves(self._delayedBall, self)
    212 
    213     def Expire(self):
    214         self.exploded = True
    215 
    216     def ApplyImpactTorqueToTarget(self, targetLocatorID, blastSize):
    217         targetBall = GetMichelle().GetBall(self.targetId)
    218         if hasattr(targetBall, 'ApplyTorqueAtDamageLocator') and targetLocatorID != -1 and not math.isnan(blastSize):
    219             velocity = self.GetVectorDotAt(blue.os.GetSimTime())
    220             targetBall.ApplyTorqueAtDamageLocator(targetLocatorID, (velocity.x, velocity.y, velocity.z), blastSize)
    221 
    222     def Explode(self):
    223         return self.collided
    224 
    225     @telemetry.ZONE_METHOD
    226     def Release(self, origin = None):
    227         if not self.collided and self.enabled and destructionEffectType.isExplosionOrOverride(self.destructionEffectId):
    228             self.Expire()
    229             self.ReleaseAll()
    230 
    231     def DoFinalCleanup(self):
    232         SpaceObject.DoFinalCleanup(self)
    233         self.ReleaseAll()
    234 
    235     def ReleaseAll(self):
    236         if self._missileModel is not None:
    237             self._missileModel.ClearAll()
    238             self._missileModel = None
    239         self.model = None
    240         self._ClearDelayedBall()
    241 
    242     def Display(self, display = 1, canYield = True):
    243         if self.enabled:
    244             SpaceObject.Display(self, display, canYield)
    245 
    246     def _ClearDelayedBall(self):
    247         if self._delayedBall:
    248             _DestroyClientBall(self._delayedBall)
    249             self._delayedBall = None
    250 
    251     def OnAllMissileWarheadsExploded(self):
    252         self._ClearDelayedBall()
    253         self.exploded = True
    254 
    255     def OnMissileModelCleared(self, model):
    256         self.RemoveAndClearModel(model, _GetScene())
    257 
    258     def PlaceMissileImpact(self, impactModel, impactPosition, targetLocatorID):
    259         explosionBall = _SpawnClientBall(impactPosition)
    260         impactModel.translationCurve = explosionBall
    261         useRandomRotation = True
    262         if not self._randomizeImpactRotation:
    263             targetBall = GetMichelle().GetBall(self.targetId)
    264             if targetBall is not None and targetLocatorID != -1:
    265                 if hasattr(targetBall.model, 'GetLocatorRotationFromSet'):
    266                     impactDirection = targetBall.model.GetLocatorRotationFromSet(targetLocatorID, True, 'damage')
    267                     impactRotation = geo2.QuaternionRotationArc((0, 1, 0), impactDirection)
    268                     useRandomRotation = False
    269         if useRandomRotation:
    270             impactRotation = geo2.QuaternionRotationSetYawPitchRoll(random.random() * 2.0 * math.pi, random.random() * 2.0 * math.pi, random.random() * 2.0 * math.pi)
    271         impactModel.rotation = impactRotation
    272         scene = _GetScene()
    273         if scene is not None:
    274             scene.objects.append(impactModel)
    275         shakeMagnitude = min(impactModel.boundingSphereRadius, 250)
    276         shakeMagnitude = max(shakeMagnitude, 50)
    277         _ShakeCamera(shakeMagnitude, impactPosition)
    278         self.ApplyImpactTorqueToTarget(targetLocatorID, self.missileRadius)
    279 
    280     def RemoveMissileImpact(self, impactModel, isFinalExplosion):
    281         if impactModel.translationCurve is not None:
    282             _DestroyClientBall(impactModel.translationCurve)
    283         self.RemoveAndClearModel(impactModel, _GetScene())
    284         if isFinalExplosion:
    285             self.ReleaseAll()
    286 
    287 
    288 class Bomb(Missile):
    289 
    290     def __init__(self):
    291         Missile.__init__(self)
    292         self.impactPosition = None
    293 
    294     def Release(self):
    295         if self.model is not None:
    296             self.impactPosition = self.model.worldPosition
    297         if self._missileModel is not None:
    298             self._missileModel.DetonateWarhead(0)
    299         SpaceObject.Release(self, 'Bomb')
    300 
    301     def _EstimateTimeToTarget(self, toCenter = False):
    302         return 20.0
    303 
    304     def PlaceMissileImpact(self, impactModel, impactPosition, targetLocatorID):
    305         if self.impactPosition is not None:
    306             impactPosition = self.impactPosition
    307         Missile.PlaceMissileImpact(self, impactModel, impactPosition, targetLocatorID)
    308 
    309     def _GetMissileTranslationCurve(self):
    310         return self
    311 
    312     def _GetMissileRotationCurve(self):
    313         sourceShipBall = GetMichelle().GetBall(self.sourceShipID)
    314         return sourceShipBall