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

moondefencebutton.py (31591B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\inflight\moondefencebutton.py
      2 import random
      3 import dogma.data as dogma_data
      4 from carbon.common.script.util import timerstuff
      5 from carbon.common.script.util.format import FmtAmt, FmtDist
      6 from carbonui.primitives.container import Container
      7 from carbonui.primitives.fill import Fill
      8 from carbonui.primitives.frame import Frame
      9 from carbonui.primitives.line import Line
     10 from carbonui.primitives.sprite import Sprite
     11 from carbonui.util.various_unsorted import ParanoidDecoMethod
     12 from eve.client.script.ui.control import eveIcon, eveLabel
     13 from inventorycommon.util import GetItemVolume
     14 import uthread
     15 from eve.client.script.ui.util import uix
     16 import blue
     17 from eve.client.script.parklife import states as state
     18 import carbonui.const as uiconst
     19 import log
     20 import localization
     21 from carbonui.uicore import uicore
     22 from eveservices.menu import GetMenuService
     23 from menu import MenuLabel
     24 from player_messaging.client.ui_message import prompt_player_fsd_dialog
     25 
     26 class DefenceStructureButton(Container):
     27     __guid__ = 'xtriui.DefenceStructureButton'
     28     __notifyevents__ = ['OnStateChange',
     29      'ProcessGodmaLocationPrimed',
     30      'OnGodmaItemChange',
     31      'OnTargetOBO',
     32      'OnAttribute',
     33      'OnStructureTargetAdded',
     34      'OnStructureTargetRemoved',
     35      'OnSlimItemChange',
     36      'UpdateItem']
     37     __update_on_reload__ = 1
     38     __cgattrs__ = []
     39     __chargesizecache__ = {}
     40     isDragObject = True
     41     moduleinfo = None
     42 
     43     def _OnClose(self):
     44         if self.invCookie:
     45             sm.GetService('inv').Unregister(self.invCookie)
     46         Container._OnClose(self)
     47 
     48     def ApplyAttributes(self, attributes):
     49         Container.ApplyAttributes(self, attributes)
     50         self.Reset()
     51         sm.RegisterNotify(self)
     52 
     53     def Reset(self):
     54         self.def_effect = None
     55         self.charge = None
     56         self.target = None
     57         self.waitingForActiveTarget = 0
     58         self.blockOntarget = 0
     59         self.online = False
     60         self.goingOnline = 0
     61         self.sr.accuracyTimer = None
     62         self.quantity = None
     63         self.invReady = 1
     64         self.invCookie = None
     65         self.isInvItem = 1
     66         self.blinking = 0
     67         self.effect_activating = 0
     68         self.dogmaLM = None
     69         self.sr.sourceIcon = None
     70         self.sr.sourceGaugeParent = None
     71         self.sr.sourceGauge_shield = None
     72         self.sr.sourceGauge_armor = None
     73         self.sr.sourceGauge_structure = None
     74         self.sr.sourceUpdateTimer = None
     75         self.sr.sourceID = None
     76         self.sr.sourceGlow = None
     77         self.sr.sourceBusy = None
     78         self.sr.sourceQtyParent = None
     79         self.sourceGaugesInited = 0
     80         self.sourceGaugesVisible = 0
     81         self.id = None
     82         self.sr.targetIcon = None
     83         self.sr.targetGaugeParent = None
     84         self.sr.targetGauge_shield = None
     85         self.sr.targetGauge_armor = None
     86         self.sr.targetGauge_structure = None
     87         self.sr.targetUpdateTimer = None
     88         self.sr.targetID = None
     89         self.targetGaugesInited = 0
     90         self.targetGaugesVisible = 0
     91         self.sr.distanceUpdateTimer = None
     92 
     93     def Setup(self, moduleinfo):
     94         targetContainer = Container(name='targetCont', align=uiconst.TOPLEFT, parent=self, top=0, height=64, width=64)
     95         slot = DefenceModuleButton(parent=targetContainer, idx=0)
     96         self.sr.targetIcon = targetContainer.GetChild('iconSprite')
     97         self.sr.targetContainer = targetContainer
     98         self.sr.targetContainer.state = uiconst.UI_DISABLED
     99         sourceContainer = Container(name='sourceCont', align=uiconst.TOPLEFT, parent=self, top=targetContainer.height + 22, height=64, width=64)
    100         slot = DefenceModuleButton(parent=sourceContainer, idx=0)
    101         self.sr.sourceIcon = sourceContainer.GetChild('iconSprite')
    102         self.sr.sourceIcon.state = uiconst.UI_DISABLED
    103         self.sr.glow = sourceContainer.GetChild('glow')
    104         self.sr.busy = sourceContainer.GetChild('busy')
    105         self.sr.quantityParent = sourceContainer.GetChild('quantityParent')
    106         self.sr.quantityParent.left = 8
    107         self.sr.quantityParent.width = 28
    108         idx = self.parent.children.index(self)
    109         fill = Fill(parent=self, color=(1.0, 1.0, 1.0, 0.125), state=uiconst.UI_HIDDEN, idx=idx)
    110         self.sr.hilite = fill
    111         self.sr.sourceContainer = sourceContainer
    112         self.sr.sourceContainer.state = uiconst.UI_DISABLED
    113         chargeIcon = eveIcon.Icon(parent=sourceContainer, align=uiconst.RELATIVE, top=32, left=6, size=24, idx=0, state=uiconst.UI_HIDDEN, ignoreSize=True)
    114         self.sr.chargeIcon = chargeIcon
    115         if not len(self.__cgattrs__):
    116             self.__cgattrs__.extend([dogma_data.get_charge_group_attribute_ids()])
    117         self.sr.typeID = moduleinfo.typeID
    118         self.moduleinfo = moduleinfo
    119         self.locationFlag = moduleinfo.flagID
    120         self.sr.sourceID = moduleinfo.itemID
    121         self.id = moduleinfo.itemID
    122         self.sr.glow.z = 0
    123         self.sr.qtylabel = eveLabel.Label(text='', parent=self.sr.quantityParent, width=30, state=uiconst.UI_DISABLED, idx=0, fontsize=9)
    124         self.sr.distancelabel = eveLabel.EveHeaderSmall(text='', parent=self.sr.targetContainer, left=12, top=-16, width=70, state=uiconst.UI_DISABLED, idx=0)
    125         if cfg.IsChargeCompatible(moduleinfo):
    126             self.invCookie = sm.GetService('inv').Register(self)
    127         self.SetCharge(None)
    128         for key in moduleinfo.effects.iterkeys():
    129             effect = moduleinfo.effects[key]
    130             if self.IsEffectActivatible(effect):
    131                 self.def_effect = effect
    132                 if effect.isActive:
    133                     self.SetActive()
    134             if effect.effectName == 'online':
    135                 if effect.isActive:
    136                     self.ShowOnline()
    137                 else:
    138                     self.ShowOffline()
    139 
    140         self.state = uiconst.UI_NORMAL
    141         currentTarget = self.GetCurrentTarget()
    142         if currentTarget is not None:
    143             uthread.pool('DefenceMobuleButton::OnTargetAdded::', self.OnTargetAdded, currentTarget)
    144         self.sr.sourceUpdateTimer = timerstuff.AutoTimer(random.randint(750, 1000), self.UpdateData, 'source')
    145         self.UpdateData('source')
    146         self.sr.targetUpdateTimer = timerstuff.AutoTimer(random.randint(750, 1000), self.UpdateData, 'target')
    147         self.UpdateData('target')
    148         self.UpdateDistance()
    149         self.sr.distanceUpdateTimer = timerstuff.AutoTimer(random.randint(5000, 6000), self.UpdateDistance)
    150         self.EnableDrag()
    151         uthread.new(self.BlinkIcon)
    152 
    153     def HideGauge(self, loc):
    154         gaugeParent = None
    155         if getattr(self, '%sGaugesInited' % loc, None):
    156             gaugeParent = self.sr.Get('%sGaugeParent' % loc)
    157             gaugeParent.state = uiconst.UI_HIDDEN
    158             self.sr.distancelabel.state = uiconst.UI_HIDDEN
    159 
    160     def ShowGauge(self, loc):
    161         gaugeParent = None
    162         if getattr(self, '%sGaugesInited' % loc, None):
    163             gaugeParent = self.sr.Get('%sGaugeParent' % loc)
    164             gaugeParent.state = uiconst.UI_DISABLED
    165             self.sr.distancelabel.state = uiconst.UI_DISABLED
    166 
    167     def InitGauges(self, loc):
    168         if getattr(self, '%sGaugesInited' % loc, None):
    169             gaugeParent = self.sr.Get('%sGaugeParent' % loc)
    170             gaugeParent.state = uiconst.UI_NORMAL
    171             return
    172         container = self.sr.Get('%sContainer' % loc)
    173         par = Container(name='gauges', parent=container, align=uiconst.TOPLEFT, width=52, height=32, top=59, left=6)
    174         for each in ('SHIELD', 'ARMOR', 'STRUCTURE'):
    175             g = Container(name=each, align=uiconst.TOTOP, width=52, height=8, left=-2)
    176             Container(name='push', parent=g, align=uiconst.TOBOTTOM, height=1)
    177             g.name = '%sGauge_%s' % (loc, each.lower())
    178             g.height = 9
    179             Line(parent=g, align=uiconst.TOTOP, color=(1.0, 1.0, 1.0, 0.5))
    180             Line(parent=g, align=uiconst.TOBOTTOM, color=(1.0, 1.0, 1.0, 0.5))
    181             Line(parent=g, align=uiconst.TOLEFT, color=(1.0, 1.0, 1.0, 0.5))
    182             Line(parent=g, align=uiconst.TORIGHT, color=(1.0, 1.0, 1.0, 0.5))
    183             g.sr.bar = Fill(parent=g, align=uiconst.TOLEFT)
    184             Fill(parent=g, color=(158 / 256.0,
    185              11 / 256.0,
    186              14 / 256.0,
    187              1.0))
    188             par.children.append(g)
    189             setattr(self.sr, '%sGauge_%s' % (loc, each.lower()), g)
    190 
    191         Container(name='push', parent=par, align=uiconst.TOTOP, height=2)
    192         self.sr.gaugeParent = par
    193         setattr(self.sr, '%sGaugeParent' % loc, par)
    194         setattr(self, '%sGaugesInited' % loc, 1)
    195 
    196     def UpdateDistance(self):
    197         sourceID = self.sr.Get('sourceID', None)
    198         targetID = self.sr.Get('targetID', None)
    199         if not sourceID and not targetID:
    200             return
    201         sourceBall = sm.GetService('michelle').GetBall(sourceID)
    202         if not sourceBall:
    203             return
    204         targetBall = sm.GetService('michelle').GetBall(targetID)
    205         if not targetBall:
    206             return
    207         bp = sm.GetService('michelle').GetBallpark()
    208         dist = bp.DistanceBetween(sourceID, targetID)
    209         self.sr.distancelabel.text = FmtDist(dist)
    210         self.sr.distancelabel.left = self.width / 2 - self.sr.distancelabel.textwidth / 2
    211 
    212     def UpdateData(self, loc):
    213         itemID = self.sr.Get('%sID' % loc, None)
    214         if not itemID:
    215             return
    216         ball = sm.GetService('michelle').GetBall(itemID)
    217         if not ball:
    218             return
    219         self.UpdateDamage(loc)
    220 
    221     def UpdateDamage(self, loc):
    222         itemID = self.sr.Get('%sID' % loc, None)
    223         if not itemID:
    224             return
    225         bp = sm.GetService('michelle').GetBallpark()
    226         if bp is None:
    227             setattr(self.sr, '%sUpdateTimer' % loc, None)
    228             return
    229         dmg = bp.GetDamageState(itemID)
    230         if dmg is not None:
    231             self.SetDamageState(dmg, loc)
    232 
    233     def OnSlimItemChange(self, oldSlim, newSlim):
    234         if self.destroyed or self.sr.targetID != oldSlim.itemID and self.sr.sourceID != oldSlim.itemID:
    235             return
    236         if self.sr.sourceID != oldSlim.itemID:
    237             self.UpdateData('source')
    238         elif self.sr.targetID != oldSlim.itemID:
    239             self.UpdateData('target')
    240 
    241     def SetDamageState(self, state, loc):
    242         self.InitGauges(loc)
    243         visible = 0
    244         ref = [self.sr.Get('%sGauge_shield' % loc, None), self.sr.Get('%sGauge_armor' % loc, None), self.sr.Get('%sGauge_structure' % loc, None)]
    245         for i, gauge in enumerate(ref):
    246             if gauge is None:
    247                 continue
    248             if state[i] is None:
    249                 gauge.state = uiconst.UI_HIDDEN
    250             else:
    251                 gauge.sr.bar.width = int((gauge.width - 2) * state[i])
    252                 gauge.state = uiconst.UI_DISABLED
    253                 visible += 1
    254 
    255         setattr(self, '%sGaugesVisible' % loc, visible)
    256 
    257     def SetCharge(self, charge):
    258         self.sr.sourceIcon.LoadIconByTypeID(self.moduleinfo.typeID, ignoreSize=True)
    259         self.sr.sourceIcon.SetSize(48, 48)
    260         self.sr.sourceIcon.state = uiconst.UI_DISABLED
    261         if charge and charge.stacksize > 0:
    262             if self.charge is None or charge.typeID != self.charge.typeID:
    263                 self.sr.chargeIcon.LoadIconByTypeID(charge.typeID, ignoreSize=True)
    264                 self.sr.chargeIcon.SetSize(24, 24)
    265                 self.sr.chargeIcon.state = uiconst.UI_DISABLED
    266             self.charge = charge
    267             self.UpdateChargeQuantity(charge)
    268             self.sr.qtylabel.parent.state = uiconst.UI_DISABLED
    269         else:
    270             self.sr.chargeIcon.state = uiconst.UI_HIDDEN
    271             self.sr.qtylabel.parent.state = uiconst.UI_HIDDEN
    272             self.quantity = 0
    273             self.sr.sourceID = self.moduleinfo.itemID
    274             self.charge = None
    275         self.CheckOnline()
    276 
    277     def UpdateChargeQuantity(self, charge):
    278         if charge is self.charge:
    279             self.quantity = charge.stacksize
    280             self.sr.qtylabel.text = FmtAmt(self.quantity, 'ss')
    281 
    282     def SetDamage(self, damage):
    283         pass
    284 
    285     def GetVolume(self):
    286         if self.charge:
    287             return GetItemVolume(self.charge, 1)
    288 
    289     def GetShell(self):
    290         return sm.GetService('invCache').GetInventoryFromId(session.shipid)
    291 
    292     def BlinkIcon(self):
    293         if self.destroyed or self.blinking:
    294             return
    295         self.blinking = 1
    296         while self.waitingForActiveTarget or self.goingOnline:
    297             blue.pyos.synchro.SleepWallclock(250)
    298             if self.destroyed:
    299                 return
    300             self.sr.sourceIcon.opacity = 0.25
    301             blue.pyos.synchro.SleepWallclock(250)
    302             if self.destroyed:
    303                 return
    304             self.sr.sourceIcon.opacity = 1.0
    305 
    306         if self.destroyed:
    307             return
    308         self.blinking = 0
    309         self.CheckOnline()
    310 
    311     def CopyItemIDToClipboard(self, itemID):
    312         blue.pyos.SetClipboardData(str(itemID))
    313 
    314     def GetMenu(self):
    315         if self.destroyed:
    316             return
    317         m = []
    318         if self.sr.Get('sourceID', None):
    319             sourceLabel = MenuLabel('UI/Inflight/Source')
    320             m += [(sourceLabel, GetMenuService().CelestialMenu(self.sr.sourceID))]
    321             m += [None]
    322         if self.sr.Get('targetID', None):
    323             targetLabel = MenuLabel('UI/Inflight/Target')
    324             m += [(targetLabel, GetMenuService().CelestialMenu(self.sr.targetID))]
    325         return m
    326 
    327     def ProcessGodmaLocationPrimed(self, structureID):
    328         structs = sm.GetService('pwn').GetCurrentControl()
    329         if structureID in structs:
    330             item = sm.services['godma'].GetItem(structureID)
    331             if item.groupID == const.groupMobileLaserSentry:
    332                 if len(item.modules) == 0:
    333                     self.SetCharge(None)
    334                 else:
    335                     self.SetCharge(item.modules[0])
    336 
    337     def CheckPending(self):
    338         if not uicore.layer.shipui:
    339             return
    340         blue.pyos.synchro.SleepWallclock(1000)
    341         uicore.layer.shipui.CheckPendingReloads()
    342 
    343     def CheckOnline(self, sound = 0):
    344         if not self or self.destroyed:
    345             return
    346         self.ShowOnline()
    347 
    348     def ChangeOnline(self, on = 1):
    349         uthread.new(self._ChangeOnline, on)
    350 
    351     def _ChangeOnline(self, on):
    352         if not on and prompt_player_fsd_dialog('PutOffline', {}, uiconst.YESNO, suppress=uiconst.ID_YES) != uiconst.ID_YES:
    353             return
    354         for key in self.moduleinfo.effects.keys():
    355             effect = self.moduleinfo.effects[key]
    356             if effect.effectName == 'online':
    357                 if on:
    358                     effect.Activate()
    359                     self.goingOnline = 1
    360                     uthread.new(self.BlinkIcon)
    361                     blue.pyos.synchro.SleepWallclock(5000)
    362                     self.goingOnline = 0
    363                 else:
    364                     self.ShowOffline(1)
    365                     effect.Deactivate()
    366                 return
    367 
    368     def ShowOnline(self):
    369         self.online = True
    370         if not self.goingOnline:
    371             self.sr.sourceIcon.opacity = 1.0
    372 
    373     def ShowOffline(self, ping = 0):
    374         self.online = False
    375         self.goingOnline = 0
    376         self.sr.sourceIcon.opacity = 0.25
    377         if ping:
    378             prompt_player_fsd_dialog('OnLogin')
    379         self.state = uiconst.UI_NORMAL
    380 
    381     def IsEffectRepeatable(self, effect, activatibleKnown = 0):
    382         if activatibleKnown or self.IsEffectActivatible(effect):
    383             if not effect.item.disallowRepeatingActivation:
    384                 return effect.durationAttributeID is not None
    385         return 0
    386 
    387     def IsEffectActivatible(self, effect):
    388         return effect.isDefault and effect.effectName != 'online' and effect.effectCategory in (const.dgmEffActivation, const.dgmEffTarget)
    389 
    390     def GetDefaultEffect(self):
    391         if self.moduleinfo is None or sm.GetService('godma').GetItem(self.sr.sourceID) is None:
    392             return
    393         for key in self.moduleinfo.effects.iterkeys():
    394             effect = self.moduleinfo.effects[key]
    395             if self.IsEffectActivatible(effect):
    396                 return effect
    397 
    398     GetDefaultEffect = ParanoidDecoMethod(GetDefaultEffect, ('sr', 'moduleInfo', 'effects'))
    399 
    400     def OnClick(self, *args):
    401         if self.goingOnline or self.IsBeingDragged():
    402             return
    403         ctrlRepeat = 0
    404         if uicore.uilib.Key(uiconst.VK_CONTROL):
    405             ctrlRepeat = 1000
    406         self.Click(ctrlRepeat)
    407 
    408     def Click(self, ctrlRepeat = 0):
    409         if self.waitingForActiveTarget:
    410             sm.GetService('pwntarget').CancelTargetOrder(self)
    411             self.HideGauge('target')
    412             self.waitingForActiveTarget = 0
    413         elif self.def_effect is None:
    414             log.LogWarn('No default Effect available for this moduletypeID:', self.moduleinfo.typeID)
    415         elif not self.online:
    416             prompt_player_fsd_dialog('ClickOffllineModule')
    417         elif self.def_effect.isActive:
    418             self.DeactivateEffect(self.def_effect)
    419         elif not self.effect_activating:
    420             self.activationTimer = timerstuff.AutoTimer(500, self.ActivateEffectTimer)
    421             self.effect_activating = 1
    422             self.ActivateEffect(self.def_effect, ctrlRepeat=ctrlRepeat)
    423 
    424     def ActivateEffectTimer(self, *args):
    425         self.effect_activating = 0
    426         self.activationTimer = None
    427 
    428     def OnEndDrag(self, *args):
    429         uthread.new(uicore.layer.shipui.ResetSwapMode)
    430 
    431     def GetDragData(self, *args):
    432         return
    433         if settings.user.ui.Get('lockModules', 0):
    434             return []
    435         if self.charge:
    436             fakeNode = uix.GetItemData(self.charge, 'icons')
    437             fakeNode.isCharge = 1
    438         else:
    439             fakeNode = uix.GetItemData(self.moduleinfo, 'icons')
    440             fakeNode.isCharge = 0
    441         fakeNode.__guid__ = 'xtriui.ShipUIModule'
    442         fakeNode.slotFlag = self.moduleinfo.flagID
    443         uicore.layer.shipui.StartSwapMode()
    444         return [fakeNode]
    445 
    446     def OnDropData(self, dragObj, nodes):
    447         return
    448         log.LogInfo('Module.OnDropData', self.sr.sourceID)
    449         flag1 = self.moduleinfo.flagID
    450         flag2 = None
    451         for node in nodes:
    452             if node.Get('__guid__', None) == 'xtriui.ShipUIModule':
    453                 flag2 = node.slotFlag
    454                 break
    455 
    456         if flag1 == flag2:
    457             return
    458         if flag2 is not None:
    459             uicore.layer.shipui.SwapSlots(flag1, flag2)
    460             return
    461         for node in nodes:
    462             self.Add(node.rec)
    463 
    464     def OnMouseDown(self, *args):
    465         log.LogInfo('Module.OnMouseDown', self.sr.sourceID)
    466         if getattr(self, 'downTop', None) is not None:
    467             return
    468         self.downTop = self.parent.top
    469         self.parent.top += 2
    470 
    471     def OnMouseUp(self, *args):
    472         log.LogInfo('Module.OnMouseUp', self.sr.sourceID)
    473         if getattr(self, 'downTop', None) is not None:
    474             self.parent.top = self.downTop
    475             self.downTop = None
    476 
    477     def OnMouseEnter(self, *args):
    478         self.HiliteOn()
    479         uthread.pool('ShipMobuleButton::MouseEnter', self.MouseEnter)
    480 
    481     def MouseEnter(self, *args):
    482         if self.destroyed or sm.GetService('godma').GetItem(self.moduleinfo.itemID) is None:
    483             return
    484         log.LogInfo('Module.OnMouseEnter', self.sr.sourceID)
    485         prompt_player_fsd_dialog('NeocomButtonEnter')
    486         self.ShowAccuracy()
    487         self.sr.accuracyTimer = timerstuff.AutoTimer(1000, self.ShowAccuracy)
    488         uthread.new(sm.GetService('tactical').ShowModuleRange, self.moduleinfo)
    489 
    490     def OnMouseExit(self, *args):
    491         log.LogInfo('Module.OnMouseExit', self.sr.sourceID)
    492         self.HiliteOff()
    493         self.sr.accuracyTimer = None
    494         uthread.new(sm.GetService('tactical').ClearModuleRange)
    495         self.OnMouseUp(None)
    496 
    497     def OnMouseMove(self, *args):
    498         uthread.pool('ShipModuleButton::MouseMove', self.UpdateInfo)
    499 
    500     def ShowAccuracy(self):
    501         self.UpdateInfo()
    502 
    503     def UpdateInfo(self):
    504         if self.destroyed:
    505             return
    506         self.sr.hint = ''
    507         if uicore.uilib.mouseOver != self:
    508             self.sr.accuracyTimer = None
    509             return
    510         infoList = [localization.GetByLabel('UI/Common/TypeLabel', typeID=self.sr.typeID)]
    511         statusList = []
    512         defEff = self.GetDefaultEffect()
    513         if defEff:
    514             if defEff.isActive:
    515                 statusList.append(localization.GetByLabel('UI/Inflight/StatusActive'))
    516             else:
    517                 statusList.append(localization.GetByLabel('UI/Inflight/StatusInactive'))
    518         if self.goingOnline:
    519             statusList.append(localization.GetByLabel('UI/Inflight/GoingOnline'))
    520         if self.waitingForActiveTarget:
    521             statusList.append(localization.GetByLabel('UI/Inflight/WaitingForActiveTarget'))
    522         if statusList:
    523             infoList.append(localization.GetByLabel('UI/Inflight/StatusLabel', statusList=localization.formatters.FormatGenericList(statusList)))
    524         if cfg.IsChargeCompatible(self.moduleinfo):
    525             if self.charge and self.charge.typeID:
    526                 infoList.append(localization.GetByLabel('UI/Inflight/ChargeQuantity', quantity=self.quantity, typeID=self.charge.typeID))
    527             else:
    528                 infoList.append(localization.GetByLabel('UI/Inflight/ChargeNoCharge'))
    529         accuracy = self.GetAccuracy()
    530         acc = ''
    531         if accuracy is not None:
    532             infoList.append(localization.GetByLabel('UI/Inflight/AccuracyLabel', accuracy=accuracy[0]))
    533         if self.charge:
    534             godmaInfo = sm.GetService('godma').GetItem(self.charge.itemID)
    535             if godmaInfo and godmaInfo.crystalsGetDamaged:
    536                 infoList.append(localization.GetByLabel('UI/Inflight/DamageLabel', damage=godmaInfo.damage))
    537         t = self.sr.Get('targetID', None)
    538         if t:
    539             slimItem = sm.GetService('michelle').GetBallpark().GetInvItem(t)
    540             infoList.append(localization.GetByLabel('UI/Inflight/TargetLabel', itemName=uix.GetSlimItemName(slimItem)))
    541         pos = uicore.layer.shipui.GetPosFromFlag(self.moduleinfo.itemID)
    542         if pos:
    543             slotno = pos[1] + 1
    544             cmd = uicore.cmd
    545             combo = cmd.GetShortcutByFuncName('CmdActivateHighPowerSlot%i' % slotno, True)
    546             if not combo:
    547                 combo = localization.GetByLabel('UI/Common/None')
    548             infoList.append(localization.GetByLabel('UI/Inflight/ShortcutLabel', keyCombo=combo))
    549         if self and getattr(self, 'sr', None):
    550             self.sr.hint = '<br>'.join(infoList)
    551 
    552     def GetAccuracy(self, targetID = None):
    553         if self is None or self.destroyed:
    554             return
    555 
    556     def SetActive(self):
    557         self.sr.glow.state = uiconst.UI_DISABLED
    558         sm.GetService('ui').BlinkSpriteA(self.sr.glow, 0.75, 1000, None, passColor=0)
    559         self.state = uiconst.UI_NORMAL
    560         self.effect_activating = 0
    561         self.activationTimer = None
    562 
    563     def SetIdle(self):
    564         self.sr.glow.state = uiconst.UI_HIDDEN
    565         self.sr.busy.state = uiconst.UI_HIDDEN
    566         sm.GetService('ui').StopBlink(self.sr.busy)
    567         sm.GetService('ui').StopBlink(self.sr.glow)
    568         self.state = uiconst.UI_NORMAL
    569 
    570     def HiliteOn(self):
    571         self.sr.hilite.state = uiconst.UI_DISABLED
    572 
    573     def HiliteOff(self):
    574         self.sr.hilite.state = uiconst.UI_HIDDEN
    575 
    576     def Update(self, effectState):
    577         if self.def_effect and effectState.effectName == self.def_effect.effectName:
    578             if effectState.start:
    579                 self.SetActive()
    580             else:
    581                 self.SetIdle()
    582         if effectState.effectName == 'online':
    583             if effectState.active:
    584                 self.ShowOnline()
    585             else:
    586                 self.ShowOffline()
    587         self.UpdateInfo()
    588 
    589     def ActivateEffect(self, effect, targetID = None, ctrlRepeat = 0):
    590         if effect and effect.effectName == 'useMissiles':
    591             if self.charge is None:
    592                 return
    593             RELEVANTEFFECT = sm.GetService('godma').GetStateManager().GetDefaultEffect(self.charge.typeID)
    594         else:
    595             RELEVANTEFFECT = effect
    596         if RELEVANTEFFECT and not targetID and RELEVANTEFFECT.effectCategory == 2:
    597             targetID = self.GetCurrentTarget()
    598             if not targetID:
    599                 sm.GetService('pwntarget').OrderTarget(self)
    600                 uthread.new(self.BlinkIcon)
    601                 self.waitingForActiveTarget = 1
    602                 return
    603         if self.sr.Get('moduleinfo'):
    604             for key in self.moduleinfo.effects.iterkeys():
    605                 checkeffect = self.moduleinfo.effects[key]
    606                 if checkeffect.effectName == 'online':
    607                     if not checkeffect.isActive:
    608                         self._ChangeOnline(1)
    609                     break
    610 
    611         if effect:
    612             effect.Activate(targetID, 9999999)
    613 
    614     def DeactivateEffect(self, effect):
    615         self.sr.glow.state = uiconst.UI_HIDDEN
    616         self.sr.busy.state = uiconst.UI_DISABLED
    617         sm.GetService('ui').BlinkSpriteA(self.sr.busy, 0.75, 1000, None, passColor=0)
    618         self.state = uiconst.UI_DISABLED
    619         effect.Deactivate()
    620 
    621     def OnStateChange(self, itemID, flag, true, *args):
    622         if true and flag == state.activeTarget and self.waitingForActiveTarget:
    623             self.ActivateEffect(self.def_effect, itemID)
    624             sm.GetService('pwntarget').CancelTargetOrder(self)
    625             self.waitingForActiveTarget = 0
    626 
    627     def OnAttribute(self, attributeName, item, newValue):
    628         if item.locationID == self.sr.sourceID:
    629             structs = sm.GetService('pwn').GetCurrentControl()
    630             if self.sr.sourceID in structs:
    631                 itemStr = sm.services['godma'].GetItem(self.sr.sourceID)
    632                 if itemStr.groupID == const.groupMobileLaserSentry:
    633                     self.SetCharge(itemStr.modules[0])
    634                 else:
    635                     self.SetCharge(itemStr.sublocations[0])
    636         self.scanAttributeChangeFlag = True
    637 
    638     def GetCurrentTarget(self):
    639         return sm.GetService('pwn').GetCurrentTarget(self.sr.sourceID)
    640 
    641     def CountDown(self, tid):
    642         if self.destroyed:
    643             return
    644         self.countDown = 1
    645         self.scanAttributeChangeFlag = False
    646         slimItem = sm.GetService('michelle').GetBallpark().GetInvItem(tid)
    647         source = self.sr.sourceID
    648         time = sm.GetService('bracket').GetScanSpeed(source, slimItem)
    649         if hasattr(self, 'sr') and self.sr.Get('targetContainer'):
    650             par = Container(parent=self.sr.targetContainer, width=52, height=13, left=6, top=62, align=uiconst.TOPLEFT, state=uiconst.UI_DISABLED)
    651             t = eveLabel.EveHeaderSmall(text='', parent=par, width=200, left=6, top=1, state=uiconst.UI_NORMAL)
    652             p = Fill(parent=par, align=uiconst.RELATIVE, width=48, height=11, left=1, top=1, color=(1.0, 1.0, 1.0, 0.25))
    653             Frame(parent=par, color=(1.0, 1.0, 1.0, 0.5))
    654             startTime = blue.os.GetSimTime()
    655             while not self.destroyed and self.countDown:
    656                 now = blue.os.GetSimTime()
    657                 dt = blue.os.TimeDiffInMs(startTime, now)
    658                 if self.scanAttributeChangeFlag:
    659                     waitRatio = dt / float(time)
    660                     self.scanAttributeChangeFlag = False
    661                     time = sm.GetService('bracket').GetScanSpeed(source, slimItem)
    662                     startTime = now - long(time * waitRatio * 10000)
    663                     dt = blue.os.TimeDiffInMs(startTime, now)
    664                 if t.destroyed:
    665                     return
    666                 t.text = localization.formatters.FormatNumeric((time - dt) / 1000.0, decimalPlaces=3)
    667                 if dt > time:
    668                     t.text = localization.GetByLabel('UI/Inflight/Brackets/TargetLocked')
    669                     break
    670                 p.width = int(48 * ((time - dt) / time))
    671                 blue.pyos.synchro.Sleep(51)
    672 
    673             if self.destroyed:
    674                 return
    675             if not self.countDown:
    676                 par.Close()
    677             p.width = 0
    678             blue.pyos.synchro.SleepWallclock(250)
    679             if t.destroyed:
    680                 return
    681             t.text = ''
    682             blue.pyos.synchro.SleepWallclock(250)
    683             if t.destroyed:
    684                 return
    685             t.text = localization.GetByLabel('UI/Inflight/Brackets/TargetLocked')
    686             blue.pyos.synchro.SleepWallclock(250)
    687             if t.destroyed:
    688                 return
    689             t.text = ''
    690             blue.pyos.synchro.SleepWallclock(250)
    691             if t.destroyed:
    692                 return
    693             t.text = localization.GetByLabel('UI/Inflight/Brackets/TargetLocked')
    694             blue.pyos.synchro.SleepWallclock(250)
    695             par.Close()
    696 
    697     def OnTargetOBO(self, what, sid = None, tid = None, reason = None):
    698         uthread.new(self._OnTargetOBO, what, sid, tid, reason)
    699 
    700     def _OnTargetOBO(self, what, sid, tid, reason):
    701         if sid != self.sr.sourceID:
    702             return
    703         if self.blockOntarget:
    704             return
    705         self.blockOntarget = 1
    706         if what == 'add':
    707             self.OnTargetAdded(tid)
    708         elif what == 'clear':
    709             self.OnTargetClear()
    710         elif what == 'lost':
    711             self.OnTargetLost(tid, reason)
    712         self.blockOntarget = 0
    713 
    714     def OnTargetAdded(self, tid):
    715         if self.destroyed:
    716             return
    717         self.countDown = 0
    718         self.ShowGauge('target')
    719         currentTarget = sm.GetService('pwn').GetCurrentTarget(self.sr.sourceID)
    720         if currentTarget != tid:
    721             return
    722         slimItem = sm.GetService('michelle').GetBallpark().GetInvItem(tid)
    723         self.waitingForActiveTarget = 0
    724         self.sr.targetID = tid
    725         self.sr.targetIcon.LoadIconByTypeID(slimItem.typeID, ignoreSize=True)
    726         self.sr.targetIcon.SetSize(48, 48)
    727         self.sr.targetIcon.state = uiconst.UI_DISABLED
    728 
    729     def OnStructureTargetAdded(self, sid, tid):
    730         self.OnTargetAdded(tid)
    731 
    732     def OnStructureTargetRemoved(self, sid, tid):
    733         self.OnTargetLost(tid)
    734 
    735     def OnTargetLost(self, tid, reason):
    736         self.sr.targetIcon.state = uiconst.UI_HIDDEN
    737         self.sr.targetID = None
    738         self.HideGauge('target')
    739         self.waitingForActiveTarget = 0
    740 
    741     def OnTargetClear(self):
    742         self.OnTargetLost(None, None)
    743 
    744 
    745 class DefenceModuleButton(Container):
    746     default_name = 'slot'
    747     default_width = 64
    748     default_height = 64
    749     default_align = uiconst.TOPLEFT
    750     default_state = uiconst.UI_DISABLED
    751 
    752     def ApplyAttributes(self, attributes):
    753         Container.ApplyAttributes(self, attributes)
    754         quantityParent = Container(parent=self, name='quantityParent', pos=(8, 10, 22, 10), align=uiconst.BOTTOMRIGHT, state=uiconst.UI_HIDDEN)
    755         fill = Fill(parent=quantityParent, color=(0.0, 0.0, 0.0, 1.0))
    756         iconSprite = eveIcon.Icon(parent=self, name='iconSprite', pos=(8, 6, 48, 48), state=uiconst.UI_HIDDEN)
    757         mainshape = Sprite(parent=self, name='mainshape', align=uiconst.TOALL, state=uiconst.UI_PICKCHILDREN, texturePath='res:/UI/Texture/classes/DefenceModuleButton/mainShape.png', color=(1.0, 1.0, 1.0, 0.7))
    758         glow = Sprite(parent=self, name='glow', pos=(-1, -1, -1, -1), align=uiconst.TOALL, state=uiconst.UI_HIDDEN, texturePath='res:/UI/Texture/classes/DefenceModuleButton/mainGlow.png', color=(0.24, 0.67, 0.16, 0.74))
    759         busy = Sprite(parent=self, name='busy', pos=(-2, -2, -2, -2), align=uiconst.TOALL, state=uiconst.UI_HIDDEN, texturePath='res:/UI/Texture/classes/DefenceModuleButton/mainGlow.png', color=(1.0, 0.13, 0.0, 0.73))