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

shipAlert.py (12792B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\inflight\shipAlert.py
      2 import math
      3 import blue
      4 from carbonui.fontconst import EVE_SMALL_FONTSIZE
      5 from carbonui.primitives.container import Container
      6 from carbonui.primitives.sprite import Sprite
      7 from carbonui.util.color import Color
      8 from eve.client.script.ui.control import eveLabel
      9 from eve.client.script.util.settings import IsShipHudTopAligned
     10 from eve.common.lib import appConst as const
     11 from eveaudio.shiphealthnotification import SoundNotification
     12 import uthread
     13 import carbonui.const as uiconst
     14 import localization
     15 from carbonui.uicore import uicore
     16 SHIELD_INDEX = 0
     17 ARMOR_INDEX = 1
     18 HULL_INDEX = 2
     19 CAPACITOR_INDEX = 3
     20 CARGOHOLD_INDEX = 4
     21 NAMES_TO_LEVEL = {'shield': SHIELD_INDEX,
     22  'armour': ARMOR_INDEX,
     23  'hull': HULL_INDEX,
     24  'capacitor': CAPACITOR_INDEX,
     25  'cargoHold': CARGOHOLD_INDEX}
     26 
     27 class ShipAlertContainer(Container):
     28     __notifyevents__ = ['OnSessionChanged', 'OnDamageStateChange', 'OnCapacitorChange']
     29     messages = ['UI/Inflight/ShieldLevelAlert', 'UI/Inflight/ArmorLevelAlert', 'UI/Inflight/HullLevelAlert']
     30     rtpcNames = ['shield_level',
     31      'armor_level',
     32      'hull_level',
     33      'capacitor_level',
     34      'cargo_hold_level']
     35     hudGlowColor = (1.0, 0.4, 0.4, 0.2)
     36 
     37     def ApplyAttributes(self, attributes):
     38         Container.ApplyAttributes(self, attributes)
     39         self.alertText = None
     40         self.fullScreen = Container(name='shipAlerts', parent=uicore.layer.inflight, align=uiconst.TOALL, state=uiconst.UI_DISABLED)
     41         self.labelCont = Container(name='fakeTextCont', parent=self, align=uiconst.CENTER, state=uiconst.UI_DISABLED, width=400)
     42         self.warningLabelCont = Container(name='warningLabelCont', parent=self.labelCont, align=uiconst.TOBOTTOM, height=40, top=100)
     43         self.warningLabel = eveLabel.EveCaptionLarge(name='warningLabel', parent=self.warningLabelCont, align=uiconst.CENTER, bold=True, color=(1, 1, 1, 1.0), idx=0)
     44         self.warningLabel.uppercase = True
     45         self.warningLabel.opacity = 0.0
     46         self.exceptionLabel = eveLabel.Label(name='fakeException', parent=self.labelCont, align=uiconst.TOBOTTOM, fontsize=EVE_SMALL_FONTSIZE, color=(1, 0, 0, 0.4))
     47         self.damageElements = self.AddSideElements()
     48         self.oldDamageState = [1,
     49          1,
     50          1,
     51          1,
     52          1]
     53         self.alertStartTimes = [None,
     54          None,
     55          None,
     56          None,
     57          None]
     58         self.isActuallyDamaged = [False,
     59          False,
     60          False,
     61          False,
     62          False]
     63         self.lastRTPCLevels = [None,
     64          None,
     65          None,
     66          None,
     67          None]
     68         self.animMethods = [self.DoShieldAnimation, self.DoArmorAnimation, self.DoHullAnimation]
     69         self.animDuration = 2.0
     70         self.UpdatePosition()
     71         sm.RegisterNotify(self)
     72         self.enteringCapsule = False
     73 
     74     def AddSideElements(self):
     75         name = 'red bars'
     76         texture = 'res:/UI/Texture/classes/ShipAlert/warped2.png'
     77         cont = Container(name=name, parent=self.fullScreen, align=uiconst.TOALL)
     78         width = 1024
     79         height = 256
     80         Sprite(parent=cont, texturePath=texture, align=uiconst.CENTERTOP, height=height, width=width, color=(1, 0, 0, 1), rotation=math.pi, useSizeFromTexture=True)
     81         Sprite(parent=cont, texturePath=texture, align=uiconst.CENTERBOTTOM, height=height, width=width, color=(1, 0, 0, 1), rotation=0, useSizeFromTexture=True)
     82         cont.opacity = 0
     83         return cont
     84 
     85     def _OnClose(self, *args):
     86         Container._OnClose(self, *args)
     87         self.fullScreen.Close()
     88 
     89     def SetNotificationEnabled(self, levelName, enabled):
     90         level = NAMES_TO_LEVEL[levelName]
     91         if enabled:
     92             isActive = self.IsLevelActive(level, self.oldDamageState[level])
     93             if isActive:
     94                 self.LevelTakenDamage(level, True)
     95         else:
     96             self.alertStartTimes[level] = None
     97 
     98     def AlertThresholdChanged(self, levelName):
     99         level = NAMES_TO_LEVEL[levelName]
    100         isActive = self.IsLevelActive(level, self.oldDamageState[level])
    101         if isActive:
    102             self.LevelTakenDamage(level, True)
    103         else:
    104             self.alertStartTimes[level] = None
    105 
    106     def UpdatePosition(self):
    107         if self.parent is None:
    108             return
    109         self.height = uicore.desktop.height - self.parent.height
    110         self.width = self.parent.width
    111         self.top = self.parent.height
    112         self.labelCont.height = self.height
    113         self.alignedTop = IsShipHudTopAligned()
    114         if not self.alignedTop:
    115             self.align = uiconst.CENTERBOTTOM
    116             self.warningLabelCont.align = uiconst.TOBOTTOM
    117             self.exceptionLabel.align = uiconst.TOBOTTOM
    118         else:
    119             self.align = uiconst.CENTERTOP
    120             self.warningLabelCont.align = uiconst.TOTOP
    121             self.exceptionLabel.align = uiconst.TOTOP
    122 
    123     def OnSessionChanged(self, isRemote, sess, change):
    124         if 'shipid' not in change:
    125             return
    126         if sess.sessionChangeReason in ('eject', 'storeVessel'):
    127             return
    128         self.alertStartTimes[2] = None
    129         ship = sm.GetService('godma').GetItem(change['shipid'][1])
    130         if ship is not None and ship.groupID == const.groupCapsule and not session.structureid:
    131             self.DoEnteringCapsuleAnimation()
    132 
    133     def OnCapacitorChange(self, load, maxCap, level):
    134         isActive, changeDirection = self.SetDamageAmountAndCheckIfActive(3, level)
    135         if isActive and changeDirection < 0:
    136             self.LevelTakenDamage(3)
    137 
    138     def OnDamageStateChange(self, shipID, damageState):
    139         if shipID != session.shipid:
    140             return
    141         self.NewDamageState(damageState)
    142 
    143     def NewDamageState(self, damageState):
    144         activateHigher = False
    145         for level in [HULL_INDEX, ARMOR_INDEX, SHIELD_INDEX]:
    146             damageAmount = damageState[level]
    147             isActive, changeDirection = self.SetDamageAmountAndCheckIfActive(level, damageAmount)
    148             if changeDirection < 0:
    149                 activateHigher = True
    150             if isActive and (changeDirection < 0 or activateHigher):
    151                 self.LevelTakenDamage(level, changeDirection < 0)
    152             elif changeDirection > 0:
    153                 if level == HULL_INDEX:
    154                     self.alertStartTimes[HULL_INDEX] = None
    155                     self.exceptionLabel.text = ''
    156 
    157     def IsLevelActive(self, level, damageAmount):
    158         info = SoundNotification(level)
    159         enabled = settings.user.notifications.Get(info.activeFlagSettingsName, 1)
    160         alertLevel = settings.user.notifications.Get(info.healthThresholdSettingsName, info.defaultThreshold)
    161         if enabled and damageAmount < alertLevel:
    162             return True
    163         return False
    164 
    165     def SetDamageAmountAndCheckIfActive(self, level, damageAmount):
    166         isActive = self.IsLevelActive(level, damageAmount)
    167         changeDirection = 0
    168         if self.oldDamageState is not None and damageAmount != self.oldDamageState[level]:
    169             if damageAmount < self.oldDamageState[level]:
    170                 changeDirection = -1
    171             elif damageAmount > self.oldDamageState[level]:
    172                 changeDirection = 1
    173         rtpcLevel = min(int((1.0 - damageAmount) * 100), 99)
    174         if self.lastRTPCLevels[level] is None or self.lastRTPCLevels[level] != rtpcLevel:
    175             sm.GetService('audio').SetGlobalRTPC(self.rtpcNames[level], rtpcLevel)
    176             self.lastRTPCLevels[level] = rtpcLevel
    177         self.oldDamageState[level] = damageAmount
    178         return (isActive, changeDirection)
    179 
    180     def LevelTakenDamage(self, level, isDamaged = True):
    181         self.isActuallyDamaged[level] = isDamaged
    182         self.alertStartTimes[level] = blue.os.GetSimTime()
    183         if level != CAPACITOR_INDEX:
    184             if getattr(self, 'alertAnimation_Thread', None) is None:
    185                 self.alertAnimation_Thread = uthread.new(self.DoAlertAnimation_Thread)
    186         elif getattr(self, 'capacitorAnimation_Thread', None) is None:
    187             self.capacitorAnimation_Thread = uthread.new(self.DoCapacitorAnimation_Thread)
    188 
    189     def SetWarningText(self, text):
    190         if not self.enteringCapsule:
    191             self.warningLabel.text = text
    192 
    193     def GetAlertLevelAndStartTime(self):
    194         alertLevel = self.GetActiveAlertLevel()
    195         if alertLevel is None:
    196             return (None, None)
    197         alertStartTime = self.alertStartTimes[alertLevel]
    198         return (alertLevel, alertStartTime)
    199 
    200     def DoAlertAnimation_Thread(self):
    201         alertLevel, alertStartTime = self.GetAlertLevelAndStartTime()
    202         if alertLevel is None or alertStartTime is None:
    203             return
    204         alertActive = True
    205         while alertActive and not self.destroyed:
    206             self.SetWarningText(localization.GetByLabel(self.messages[alertLevel]))
    207             if not self.enteringCapsule:
    208                 animationMethod = self.animMethods[alertLevel]
    209                 animationMethod()
    210             else:
    211                 blue.synchro.SleepSim(self.animDuration * 1000)
    212             alertLevel, alertStartTime = self.GetAlertLevelAndStartTime()
    213             if alertLevel is None or alertStartTime is None:
    214                 alertActive = False
    215             else:
    216                 alertActive = alertStartTime < 0 or blue.os.TimeDiffInMs(alertStartTime, blue.os.GetSimTime()) < self.animDuration * 1000
    217 
    218         self.alertAnimation_Thread = None
    219 
    220     def GetActiveAlertLevel(self):
    221         highestAlertLevel = None
    222         for level, startTime in enumerate(self.alertStartTimes[:3]):
    223             if startTime is None:
    224                 continue
    225             if not self.IsLevelActive(level, self.oldDamageState[level]):
    226                 continue
    227             valid = startTime < 0 or blue.os.TimeDiffInMs(startTime, blue.os.GetSimTime()) < self.animDuration * 1000
    228             if valid:
    229                 highestAlertLevel = level
    230 
    231         return highestAlertLevel
    232 
    233     def DoCapacitorAnimation_Thread(self):
    234         alertActive = True
    235         while alertActive:
    236             self.DoCapacitorAnimation(self.animDuration)
    237             blue.synchro.SleepSim(self.animDuration * 1000)
    238             capacitorAlertStartTime = self.alertStartTimes[CAPACITOR_INDEX]
    239             if capacitorAlertStartTime is None:
    240                 alertActive = False
    241             else:
    242                 alertActive = blue.os.TimeDiffInMs(capacitorAlertStartTime, blue.os.GetSimTime()) < self.animDuration * 1000
    243 
    244         self.capacitorAnimation_Thread = None
    245 
    246     def DoCapacitorAnimation(self, totalDuration):
    247         loops = 1.0
    248         duration = totalDuration / loops
    249         sm.GetService('audio').SendUIEvent('ui_warning_capacitor')
    250         uicore.animations.MorphScalar(uicore.layer.shipui.capacitorContainer, 'opacity', 1.0, 0.5, duration=duration, loops=loops, curveType=uiconst.ANIM_WAVE)
    251 
    252     def DoShieldAnimation(self, duration = 2.0, fromHigher = False):
    253         uicore.animations.MorphScalar(self.damageElements, 'opacity', 0, 0.7, duration=duration, curveType=uiconst.ANIM_WAVE)
    254         uicore.animations.SpGlowFadeIn(uicore.layer.shipui.hpGauges.shieldGauge, duration=duration, glowColor=self.hudGlowColor, glowExpand=3.0, curveType=uiconst.ANIM_WAVE)
    255         if not fromHigher:
    256             sm.GetService('audio').SendUIEvent('ui_warning_shield')
    257             blue.synchro.SleepSim(duration * 1000)
    258 
    259     def DoArmorAnimation(self, duration = 1.0, fromHigher = False):
    260         uicore.animations.MorphScalar(self.damageElements, 'opacity', 0, 0.7, duration=duration, curveType=uiconst.ANIM_WAVE)
    261         uicore.animations.SpGlowFadeIn(uicore.layer.shipui.hpGauges.armorGauge, duration=duration, glowColor=self.hudGlowColor, glowExpand=3.0, curveType=uiconst.ANIM_WAVE)
    262         self.DoShieldAnimation(duration, True)
    263         if not fromHigher:
    264             sm.GetService('audio').SendUIEvent('ui_warning_armor')
    265             blue.synchro.SleepSim(duration * 1000)
    266 
    267     def DoHullAnimation(self, duration = 0.6):
    268         uicore.animations.MorphScalar(self.damageElements, 'opacity', 0, 1, duration=duration, curveType=uiconst.ANIM_WAVE)
    269         uicore.animations.SpGlowFadeIn(uicore.layer.shipui.hpGauges.structureGauge, duration=duration, glowColor=self.hudGlowColor, glowExpand=3.0, curveType=uiconst.ANIM_WAVE)
    270         self.DoArmorAnimation(duration, True)
    271         sm.GetService('audio').SendUIEvent('ui_warning_hull')
    272         blue.synchro.SleepSim(duration * 1000)
    273 
    274     def DoEnteringCapsuleAnimation(self):
    275         loops = 1.0
    276         duration = 2.0 / loops
    277         self.SetWarningText(localization.GetByLabel('UI/Inflight/CapsuleEjected'))
    278         self.enteringCapsule = True
    279         self.warningLabel.color = Color.RED
    280         uicore.animations.MorphScalar(self.warningLabel, 'opacity', 1, 0, duration=duration, loops=loops)