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

base_repairshop.py (15180B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\station\repairshop\base_repairshop.py
      2 import math
      3 import evetypes
      4 import inventorycommon.const as invConst
      5 import localization
      6 import uthread
      7 from carbon.common.script.net.moniker import Moniker
      8 from carbon.common.script.sys.service import Service
      9 from carbonui import uiconst
     10 from carbonui.primitives.container import Container
     11 from carbonui.primitives.containerAutoSize import ContainerAutoSize
     12 from eve.client.script.ui.control import eveLabel, eveScroll
     13 from carbonui.button.group import ButtonGroup
     14 from eve.client.script.ui.control.entries.item import Item
     15 from eve.client.script.ui.control.entries.util import GetFromClass
     16 from carbonui.control.window import Window
     17 from eve.client.script.ui.control.themeColored import SpriteThemeColored
     18 from eve.client.script.ui.util import uix
     19 from eve.common.lib import appConst
     20 from eve.common.script.sys import eveCfg
     21 from eve.common.script.util.eveFormat import FmtISK
     22 from eveexceptions import UserError
     23 from eveservices.menu import GetMenuService
     24 from inventorycommon.util import IsFittingModule
     25 from menu import MenuLabel
     26 from player_messaging.client.ui_message import prompt_player_fsd_dialog
     27 from repair import IsRepairable
     28 
     29 class RepairSvc(Service):
     30     __guid__ = 'svc.repair'
     31     __notifyevents__ = ['OnSessionChanged']
     32     __servicename__ = 'repair'
     33     __displayname__ = 'Repair Service'
     34 
     35     def __init__(self):
     36         Service.__init__(self)
     37         self.repairMgr = None
     38 
     39     def OnSessionChanged(self, isRemote, sess, change):
     40         if 'stationid' in change or 'structureid' in change:
     41             self.repairMgr = None
     42 
     43     def GetRemoteRepairMgr(self):
     44         if session.stationid:
     45             dockableLocation = session.stationid
     46             locationID = session.stationid
     47             locationGroup = invConst.groupStation
     48             sessionCheckDict = {'stationid': session.stationid}
     49         elif session.structureid:
     50             dockableLocation = session.structureid
     51             locationID = session.solarsystemid2
     52             locationGroup = invConst.groupSolarSystem
     53             sessionCheckDict = {'structureid': session.structureid}
     54         else:
     55             raise RuntimeError('Trying to access repair manager when neither in station nor structure, that is not allowed!')
     56         self.repairMgr = Moniker('repairSvc', (dockableLocation, locationID, locationGroup))
     57         self.repairMgr.SetSessionCheck(sessionCheckDict)
     58         return self.repairMgr
     59 
     60     def GetRepairQuotes(self, itemIDs):
     61         return self.GetRemoteRepairMgr().GetRepairQuotes(itemIDs)
     62 
     63     def RepairItems(self, itemIDs, payment):
     64         if session.stationid:
     65             self.GetRemoteRepairMgr().RepairItemsInStation(itemIDs, payment)
     66         elif session.structureid:
     67             self.GetRemoteRepairMgr().RepairItemsInStructure(itemIDs)
     68         else:
     69             raise RuntimeError('Must be in station or structure to use repair service')
     70 
     71 
     72 class RepairShopWindow(Window):
     73     __guid__ = 'form.RepairShopWindow'
     74     default_width = 400
     75     default_height = 300
     76     default_minSize = (350, 270)
     77     default_windowID = 'repairshop'
     78     default_captionLabelPath = 'UI/Station/Repair/RepairShopHeader'
     79     default_descriptionLabelPath = 'Tooltips/StationServices/Repairshop_description'
     80     default_iconNum = 'res:/ui/Texture/WindowIcons/repairshop.png'
     81     default_scope = uiconst.SCOPE_DOCKED
     82 
     83     def ApplyAttributes(self, attributes):
     84         Window.ApplyAttributes(self, attributes)
     85         self.invCookie = None
     86         self.invReady = 0
     87         self.optionsByItemType = {}
     88         self.itemToRepairDescription = ''
     89         self.invCache = sm.GetService('invCache')
     90         self.ConstructTopParent()
     91         buttonGroup = ButtonGroup(parent=self.sr.main)
     92         self.pickBtn = buttonGroup.AddButton(localization.GetByLabel('UI/Commands/PickNewItem'), self.DisplayItems)
     93         self.repairItemBtn = buttonGroup.AddButton(localization.GetByLabel('UI/Commands/RepairItem'), self.QuoteItems)
     94         self.repairAllBtn = buttonGroup.AddButton(localization.GetByLabel('UI/Commands/RepairAll'), self.DoNothing)
     95         self.scroll = eveScroll.Scroll(parent=self.sr.main, padding=(0, 16, 0, 0))
     96         self.scroll.sr.minColumnWidth = {localization.GetByLabel('UI/Common/Type'): 30}
     97         uthread.new(self.DisplayItems)
     98 
     99     def ConstructTopParent(self):
    100         topParent = ContainerAutoSize(name='topParent', parent=self.GetMainArea(), align=uiconst.TOTOP, clipChildren=True)
    101         self.avgDamageLabel = eveLabel.EveLabelLarge(parent=topParent, name='avgDamage', state=uiconst.UI_NORMAL, align=uiconst.TOTOP)
    102         self.totalCostLabel = eveLabel.EveLabelLarge(parent=topParent, name='totalCost', state=uiconst.UI_NORMAL, align=uiconst.TOTOP, padTop=4)
    103 
    104     def DisplayItems(self, *args):
    105         self.itemToRepairDescription = ''
    106         self.HideButtons()
    107         btnSetup = {self.pickBtn: uiconst.UI_HIDDEN,
    108          self.repairItemBtn: uiconst.UI_NORMAL,
    109          self.repairAllBtn: uiconst.UI_HIDDEN}
    110         self.SetHint()
    111         self.avgDamageLabel.Hide()
    112         self.totalCostLabel.Hide()
    113         try:
    114             hangarInv = sm.GetService('invCache').GetInventory(appConst.containerHangar)
    115             items = hangarInv.List(invConst.flagHangar)
    116             ships = []
    117             tmplst = []
    118             for item in items:
    119                 if IsRepairable(item):
    120                     if item.categoryID == invConst.categoryShip:
    121                         ships.append(item)
    122                     else:
    123                         tmplst.append((evetypes.GetName(item.typeID), item))
    124 
    125             shipIDs = [ s.itemID for s in ships ]
    126             cfg.evelocations.Prime(shipIDs)
    127             for item in ships:
    128                 tmplst.append((cfg.evelocations.Get(item.itemID).name, item))
    129 
    130             if len(tmplst) == 0:
    131                 self.SetHint(localization.GetByLabel('UI/Station/Repair/NothingToRepair', repairShop=localization.GetByLabel('UI/Station/Repair/RepairFacilities')))
    132             else:
    133                 scrolllist = []
    134                 currIndex = 1
    135                 for label, item in tmplst:
    136                     scrolllist.append(GetFromClass(Item, {'info': item,
    137                      'itemID': item.itemID,
    138                      'typeID': item.typeID,
    139                      'label': label,
    140                      'getIcon': 1,
    141                      'GetMenu': self.GetItemInHangarMenu,
    142                      'OnDblClick': self.OnDblClick,
    143                      'name': 'repairEntry%s' % currIndex,
    144                      'GetSortValue': self.GetNodeSortValue}))
    145 
    146                 self.scroll.sr.id = None
    147                 self.scroll.sr.ignoreTabTrimming = 1
    148                 self.state = uiconst.UI_NORMAL
    149                 self.scroll.Load(contentList=scrolllist, headers=[localization.GetByLabel('UI/Common/Type')])
    150         finally:
    151             self.state = uiconst.UI_NORMAL
    152 
    153         self.DisplayButtons(btnSetup)
    154 
    155     def GetNodeSortValue(self, node, by, sortDirection, idx):
    156         ret = self.scroll._GetSortValue(by, node, idx)
    157         if node.itemID == session.shipid:
    158             return (sortDirection, ret)
    159         return (not sortDirection, ret)
    160 
    161     def GetSelected(self):
    162         return [ node.info for node in self.scroll.GetSelected() ]
    163 
    164     def GetAll(self):
    165         return [ node.info for node in self.scroll.GetNodes() ]
    166 
    167     def QuoteItems(self, *args):
    168         self.DisplayRepairQuote(self.GetSelected())
    169 
    170     def SetHint(self, hintstr = None):
    171         if self.scroll:
    172             self.scroll.ShowHint(hintstr)
    173 
    174     def DoNothing(self, *args):
    175         pass
    176 
    177     def GetItemInHangarMenu(self, entry):
    178         item = entry.sr.node.info
    179         items = self.GetSelected()
    180         if item not in items:
    181             items.append(item)
    182         m = GetMenuService().GetMenuFromItemIDTypeID(item.itemID, item.typeID)
    183         m += [(MenuLabel('UI/Inventory/ItemActions/GetRepairQuote'), self.DisplayRepairQuote, (items,))]
    184         return m
    185 
    186     def OnDblClick(self, *args):
    187         self.DisplayRepairQuote(self.GetSelected())
    188 
    189     def GetItemMenu(self, entry):
    190         info = entry.sr.node.info
    191         m = GetMenuService().GetMenuFromItemIDTypeID(info.itemID, info.typeID)
    192         items = self.GetSelected()
    193         if info not in items:
    194             items.append(info)
    195         if info.damage > 0.0:
    196             m += [(MenuLabel('UI/Commands/Repair'), self.Repair, (items,))]
    197         return m
    198 
    199     def OnItemDblClick(self, entry):
    200         info = entry.sr.node.info
    201         items = self.GetSelected()
    202         if info not in items:
    203             items.append(info)
    204         if info.damage > 0.0:
    205             uthread.new(self.Repair, items)
    206 
    207     def DisplayRepairQuote(self, items, *args):
    208         if not len(items):
    209             return
    210         self.itemToRepairDescription = ''
    211         self.HideButtons()
    212         btnSetup = {self.pickBtn: uiconst.UI_HIDDEN,
    213          self.repairItemBtn: uiconst.UI_HIDDEN}
    214         self.SetHint()
    215         totalitems = 0
    216         totaldamage = 0.0
    217         totalcost = 0
    218         self.itemToRepairDescription = ''
    219         scrolllist = []
    220         listEntryData = []
    221         repairQuotes = {}
    222         itemIDs = []
    223         for item in items:
    224             itemIDs.append(item.itemID)
    225 
    226         if len(itemIDs):
    227             repairQuotes = sm.GetService('repair').GetRepairQuotes(itemIDs)
    228         currIndex = 1
    229         for item in items:
    230             for quote in repairQuotes[item.itemID]:
    231                 if quote.itemID in [ entryData['itemID'] for entryData in listEntryData ]:
    232                     continue
    233                 damage = math.ceil(quote.damage)
    234                 if damage == 0:
    235                     continue
    236                 dmg = localization.GetByLabel('UI/Station/Repair/CurrentDamage', curHealth=max(0, int(quote.maxHealth - damage)), maxHealth=quote.maxHealth, percentHealth=damage / float(quote.maxHealth or 1) * 100.0)
    237                 cst = localization.GetByLabel('UI/Station/Repair/RepairCostNumberOnly', isk=int(math.ceil(damage * quote.costToRepairOneUnitOfDamage)))
    238                 totalitems += 1
    239                 totaldamage += damage / float(quote.maxHealth or 1) * 100.0
    240                 totalcost += damage * quote.costToRepairOneUnitOfDamage
    241                 label = evetypes.GetName(quote.typeID) + '<t>' + dmg + '<t>' + cst
    242                 listEntryData.append({'info': quote,
    243                  'itemID': quote.itemID,
    244                  'typeID': quote.typeID,
    245                  'label': label,
    246                  'getIcon': 1,
    247                  'GetMenu': self.GetItemMenu,
    248                  'OnDblClick': self.OnItemDblClick,
    249                  'name': 'subRepairEntry%s' % currIndex})
    250                 currIndex += 1
    251 
    252         listEntryData.sort(lambda a, b: -(a['label'].upper() < b['label'].upper()))
    253         for entryData in listEntryData:
    254             scrolllist.append(GetFromClass(Item, entryData))
    255 
    256         if not totaldamage:
    257             activeShip = eveCfg.GetActiveShip()
    258             if activeShip is not None and activeShip in [ item.itemID for item in items ]:
    259                 btnSetup[self.repairAllBtn] = uiconst.UI_HIDDEN
    260         else:
    261             self.repairAllBtn.OnClick = self.RepairAll
    262             self.repairAllBtn.SetLabel(localization.GetByLabel('UI/Commands/RepairAll'))
    263             btnSetup[self.repairAllBtn] = uiconst.UI_NORMAL
    264         self.scroll.sr.id = 'repair3'
    265         self.scroll.sr.ignoreTabTrimming = 0
    266         hint = localization.GetByLabel('UI/Station/Repair/NothingToRepair', repairShop=localization.GetByLabel('UI/Station/Repair/RepairFacilities'))
    267         headers = [localization.GetByLabel('UI/Common/Type'), localization.GetByLabel('UI/Common/Damage'), localization.GetByLabel('UI/Common/Cost')]
    268         self.scroll.Load(fixedEntryHeight=35, contentList=scrolllist, headers=headers, noContentHint=hint)
    269         self.avgDamageLabel.Show()
    270         self.avgDamageLabel.text = localization.GetByLabel('UI/Station/Repair/AverageDamage', damage=totaldamage / (totalitems or 1))
    271         self.totalCostLabel.Show()
    272         self.totalCostLabel.text = localization.GetByLabel('UI/Station/Repair/RepairCost', isk=int(math.ceil(totalcost)))
    273         self.state = uiconst.UI_NORMAL
    274         btnSetup[self.pickBtn] = uiconst.UI_NORMAL
    275         self.DisplayButtons(btnSetup)
    276 
    277     def Repair(self, items, *args):
    278         self.RepairItems(items)
    279 
    280     def RepairAll(self, *args):
    281         self.RepairItems(self.GetAll())
    282 
    283     def RepairItems(self, items):
    284         totalCost = 0
    285         hasModule = False
    286         for item in items:
    287             totalCost += math.ceil(item.damage) * item.costToRepairOneUnitOfDamage
    288             categoryID = evetypes.GetCategoryIDByGroup(item.groupID)
    289             if IsFittingModule(categoryID):
    290                 hasModule = True
    291 
    292         btnSetup = {self.repairItemBtn: uiconst.UI_HIDDEN,
    293          self.pickBtn: uiconst.UI_NORMAL}
    294         amount = None
    295         if totalCost > 0.0:
    296             if hasModule:
    297                 if prompt_player_fsd_dialog('RepairNonPartialConfirmation', {'isk': FmtISK(totalCost)}, uiconst.YESNO) == uiconst.ID_YES:
    298                     amount = totalCost
    299             else:
    300                 dialogResult = uix.QtyPopup(totalCost, 0, totalCost, hint=localization.GetByLabel('UI/Station/Repair/FullRepair', isk=totalCost), label=localization.GetByLabel('UI/Station/Repair/RepairCostLabel'), digits=2)
    301                 if dialogResult is not None:
    302                     amount = dialogResult['qty']
    303         else:
    304             amount = 0.0
    305         if amount is not None:
    306             itemIDs = []
    307             try:
    308                 for item in items:
    309                     if self.invCache.IsItemLocked(item.itemID):
    310                         raise UserError('ItemLocked', {'item': evetypes.GetName(item.typeID)})
    311                     if not self.invCache.TryLockItem(item.itemID, 'lockUnassemblingItem', {}, 1):
    312                         raise UserError('ItemLocked', {'item': evetypes.GetName(item.typeID)})
    313                     itemIDs.append(item.itemID)
    314 
    315                 if len(itemIDs):
    316                     sm.GetService('repair').RepairItems(itemIDs, amount)
    317             finally:
    318                 for itemID in itemIDs:
    319                     self.invCache.UnlockItem(itemID)
    320 
    321                 sm.ScatterEvent('OnRepairDone', itemIDs)
    322                 uthread.new(self.DisplayRepairQuote, self.GetAll())
    323 
    324         else:
    325             btnSetup[self.repairAllBtn] = uiconst.UI_NORMAL
    326         self.DisplayButtons(btnSetup)
    327 
    328     def HideButtons(self):
    329         btnParent = self.pickBtn.parent
    330         for btn in btnParent.children:
    331             btn.state = uiconst.UI_HIDDEN
    332 
    333     def DisplayButtons(self, btnSetup):
    334         for btn, state in btnSetup.iteritems():
    335             btn.state = state
    336 
    337         totalWidth = 0
    338         btnParent = self.pickBtn.parent
    339         for btn in btnParent.children:
    340             if btn.state != uiconst.UI_HIDDEN:
    341                 totalWidth = totalWidth + btn.width
    342 
    343         left = self.pickBtn.parent.width / 2 - totalWidth / 2
    344         for btn in btnParent.children:
    345             if btn.state != uiconst.UI_HIDDEN:
    346                 btn.left = left
    347                 left = left + btn.width + 4