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

fittingSearchUtil.py (18200B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\fittingScreen\fittingSearchUtil.py
      2 import itertools
      3 from eve.client.script.ui.shared.fittingScreen.browsers.browserUtil import AUTO_FITTED_SERVICES_BY_STRUCTURE_TYPE
      4 from eve.common.lib.appConst import GROUP_CAPITALSHIPS
      5 import evetypes
      6 from dynamicitemattributes import IsMutator
      7 from shipfitting.fittingStuff import IsModuleTooBigForShip, GetSlotTypeForType, GetCanFitModuleTypeToShipType, IsRigSizeRestricted, IsCategoryOK_StructureVsShipRestrictions
      8 MODULE_CATEGORIES = (const.marketCategoryShipEquipment,
      9  const.marketCategoryShipModifications,
     10  const.marketCategoryDrones,
     11  const.marketCategoryStructureEquipment,
     12  const.marketCategoryStructureModifications)
     13 FAKE_FLAGID = -1
     14 MAX_CPU_POWERGRID = 999999999999L
     15 
     16 class SearchFittingHelper(object):
     17     __notifyevents__ = ['OnSkillsChanged']
     18 
     19     def __init__(self, cfg, *args):
     20         self.cfg = cfg
     21         self.dogmaStaticMgr = sm.GetService('clientDogmaIM').GetDogmaLocation().dogmaStaticMgr
     22         self.ResetAllVariables()
     23         sm.RegisterNotify(self)
     24 
     25     def ResetAllVariables(self):
     26         self.typeNames_lower = {}
     27         self.canFitModuleToShip = {}
     28         self.rigRestricted = {}
     29         self.tooBigModule = {}
     30         self.restrictedByDroneOrFighter = {}
     31         self.slotTypeByTypeID = {}
     32         self.shipRigSizeByTypeID = {}
     33         self.isCapitalShipByTypeID = {}
     34         self.marketCategoryByTypeID = {}
     35         self.numSlotsForModule = {}
     36         self.isHiSlot = {}
     37         self.isMedSlot = {}
     38         self.isLoSlot = {}
     39         self.isRigSlot = {}
     40         self.isSubSystemSlot = {}
     41         self.isServiceSlot = {}
     42         self.isDrone = {}
     43         self.isFighter = {}
     44         self.isDroneOrFighter = {}
     45         self.isDynamicType = {}
     46         self.missingSkills = {}
     47         self.cpuRequirementsByModuleTypeID = {}
     48         self.powergridRequirementsByModuleTypeID = {}
     49         self.calibrationRequirementByModuleTypeID = {}
     50         self.searchableTypeIDs = None
     51         self.searchableChargeTypeIDs = None
     52         self.isModule = {}
     53         self.isCharge = {}
     54         self.mutaplasmids = {}
     55 
     56     def GetTypeName(self, typeID):
     57         try:
     58             return self.typeNames_lower[typeID]
     59         except KeyError:
     60             t = evetypes.GetName(typeID)
     61             lower = t.lower()
     62             self.typeNames_lower[typeID] = lower
     63             return lower
     64 
     65     def ResetCpuAndPowergridDicts(self):
     66         self.cpuRequirementsByModuleTypeID = {}
     67         self.powergridRequirementsByModuleTypeID = {}
     68 
     69     def CanFitModuleToShipTypeOrGroup(self, shipTypeID, dogmaLocation, moduleTypeID):
     70         dictKey = (shipTypeID, moduleTypeID)
     71         try:
     72             return self.canFitModuleToShip[dictKey]
     73         except KeyError:
     74             canFit = GetCanFitModuleTypeToShipType(dogmaLocation, shipTypeID, moduleTypeID)
     75             if canFit:
     76                 canFit = IsCategoryOK_StructureVsShipRestrictions(shipTypeID, moduleTypeID)
     77             self.canFitModuleToShip[dictKey] = canFit
     78             return canFit
     79 
     80     def IsMutaplasmid(self, typeID):
     81         try:
     82             return self.mutaplasmids[typeID]
     83         except KeyError:
     84             isMutaplasmid = IsMutator(typeID)
     85             self.mutaplasmids[typeID] = isMutaplasmid
     86             return isMutaplasmid
     87 
     88     def IsDynamicType(self, typeID):
     89         try:
     90             return self.isDynamicType[typeID]
     91         except KeyError:
     92             isDynamicType = evetypes.IsDynamicType(typeID)
     93             self.isDynamicType[typeID] = isDynamicType
     94             return isDynamicType
     95 
     96     def IsRigSizeRestricted(self, moduleTypeID, shipRigSize):
     97         dictKey = (moduleTypeID, shipRigSize)
     98         try:
     99             return self.rigRestricted[dictKey]
    100         except KeyError:
    101             isRestricted = IsRigSizeRestricted(self.dogmaStaticMgr, moduleTypeID, shipRigSize)
    102             self.rigRestricted[dictKey] = isRestricted
    103             return isRestricted
    104 
    105     def IsModuleTooBig(self, shipTypeID, moduleTypeID, isCapitalShip):
    106         dictKey = (shipTypeID, moduleTypeID)
    107         try:
    108             return self.tooBigModule[dictKey]
    109         except KeyError:
    110             tooBig = IsModuleTooBigForShip(moduleTypeID, shipTypeID, isCapitalShip)
    111             self.tooBigModule[dictKey] = tooBig
    112             return tooBig
    113 
    114     def RestrictedByDroneOrFighter(self, shipTypeID, typeID, isModularShip):
    115         dictKey = (shipTypeID, typeID)
    116         try:
    117             return self.restrictedByDroneOrFighter[dictKey]
    118         except KeyError:
    119             restricted = False
    120             if self.IsDroneOrFighter(typeID):
    121                 isDrone = self.IsDrone(typeID)
    122                 if isDrone:
    123                     droneBayCapacity = self.dogmaStaticMgr.GetTypeAttribute2(shipTypeID, const.attributeDroneCapacity)
    124                     if droneBayCapacity == 0 and not isModularShip:
    125                         restricted = True
    126                 else:
    127                     fighterBayCapacity = self.dogmaStaticMgr.GetTypeAttribute2(shipTypeID, const.attributeFighterCapacity)
    128                     if fighterBayCapacity == 0:
    129                         restricted = True
    130                     elif not self._IsFighterAvailableForShipTypeID(shipTypeID, typeID):
    131                         restricted = True
    132             self.restrictedByDroneOrFighter[dictKey] = restricted
    133             return restricted
    134 
    135     def _IsFighterAvailableForShipTypeID(self, shipTypeID, fighterTypeID):
    136         fighterAttributes = [(const.attributeFighterSquadronIsHeavy, const.attributeFighterHeavySlots),
    137          (const.attributeFighterSquadronIsSupport, const.attributeFighterSupportSlots),
    138          (const.attributeFighterSquadronIsLight, const.attributeFighterLightSlots),
    139          (const.attributeFighterSquadronIsStandupHeavy, const.attributeFighterStandupHeavySlots),
    140          (const.attributeFighterSquadronIsStandupSupport, const.attributeFighterStandupSupportSlots),
    141          (const.attributeFighterSquadronIsStandupLight, const.attributeFighterStandupLightSlots)]
    142         for squadronAttributeID, slotAttributeID in fighterAttributes:
    143             if self.dogmaStaticMgr.GetTypeAttribute2(fighterTypeID, squadronAttributeID):
    144                 if self.dogmaStaticMgr.GetTypeAttribute2(shipTypeID, slotAttributeID):
    145                     return True
    146 
    147         return False
    148 
    149     def GetNumSlotForModuleForModularShip(self, dogmaLocation, shipID, moduleTypeD, numTurretsFitted, numLaunchersFitted):
    150         attribute = self._GetAttributeForNumSlotsCheck(moduleTypeD)
    151         if attribute is None:
    152             return
    153         attrValue = dogmaLocation.GetAttributeValue(shipID, attribute)
    154         if attribute == const.attributeTurretSlotsLeft:
    155             return attrValue + numTurretsFitted
    156         if attribute == const.attributeLauncherSlotsLeft:
    157             return attrValue + numLaunchersFitted
    158         return attrValue
    159 
    160     def GetNumSlotForModule(self, shipTypeID, moduleTypeD):
    161         dictKey = (shipTypeID, moduleTypeD)
    162         try:
    163             return self.numSlotsForModule[dictKey]
    164         except KeyError:
    165             numSlots = self._GetNumForSlotModule(moduleTypeD, shipTypeID)
    166             self.numSlotsForModule[dictKey] = numSlots
    167             return numSlots
    168 
    169     def _GetNumForSlotModule(self, moduleTypeD, shipTypeID):
    170         attribute = self._GetAttributeForNumSlotsCheck(moduleTypeD)
    171         if attribute is None:
    172             return
    173         return self.dogmaStaticMgr.GetTypeAttribute(shipTypeID, attribute)
    174 
    175     def _GetAttributeForNumSlotsCheck(self, moduleTypeD):
    176         if self.IsHislotModule(moduleTypeD):
    177             typeEffects = self.dogmaStaticMgr.TypeGetEffects(moduleTypeD)
    178             if const.effectTurretFitted in typeEffects:
    179                 attribute = const.attributeTurretSlotsLeft
    180             elif const.effectLauncherFitted in typeEffects:
    181                 attribute = const.attributeLauncherSlotsLeft
    182             else:
    183                 attribute = const.attributeHiSlots
    184         elif self.IsMedslotModule(moduleTypeD):
    185             attribute = const.attributeMedSlots
    186         elif self.IsLoSlot(moduleTypeD):
    187             attribute = const.attributeLowSlots
    188         elif self.IsRigSlot(moduleTypeD):
    189             attribute = const.attributeRigSlots
    190         elif self.IsServiceSlot(moduleTypeD):
    191             attribute = const.attributeServiceSlots
    192         else:
    193             return None
    194         return attribute
    195 
    196     def IsHislotModule(self, moduleTypeID):
    197         return self.IsSpecificSlotType(moduleTypeID, const.effectHiPower, self.isHiSlot)
    198 
    199     def IsMedslotModule(self, moduleTypeID):
    200         return self.IsSpecificSlotType(moduleTypeID, const.effectMedPower, self.isMedSlot)
    201 
    202     def IsLoSlot(self, moduleTypeID):
    203         return self.IsSpecificSlotType(moduleTypeID, const.effectLoPower, self.isLoSlot)
    204 
    205     def IsRigSlot(self, moduleTypeID):
    206         return self.IsSpecificSlotType(moduleTypeID, const.effectRigSlot, self.isRigSlot)
    207 
    208     def IsSubSystemSlot(self, moduleTypeID):
    209         return self.IsSpecificSlotType(moduleTypeID, const.effectSubSystem, self.isSubSystemSlot)
    210 
    211     def IsServiceSlot(self, moduleTypeID):
    212         return self.IsSpecificSlotType(moduleTypeID, const.effectServiceSlot, self.isServiceSlot)
    213 
    214     def IsDroneOrFighter(self, typeID):
    215         try:
    216             return self.isDroneOrFighter[typeID]
    217         except KeyError:
    218             isDroneOrFighter = self.IsDrone(typeID) or self.IsFighter(typeID)
    219             self.isDroneOrFighter[typeID] = isDroneOrFighter
    220             return isDroneOrFighter
    221 
    222     def IsDrone(self, typeID):
    223         try:
    224             return self.isDrone[typeID]
    225         except KeyError:
    226             categoryID = evetypes.GetCategoryID(typeID)
    227             isDrone = categoryID == const.categoryDrone
    228             self.isDrone[typeID] = isDrone
    229             return isDrone
    230 
    231     def IsFighter(self, typeID):
    232         try:
    233             return self.isFighter[typeID]
    234         except KeyError:
    235             categoryID = evetypes.GetCategoryID(typeID)
    236             isFighter = categoryID == const.categoryFighter
    237             self.isFighter[typeID] = isFighter
    238             return isFighter
    239 
    240     def IsModule(self, typeID):
    241         try:
    242             return self.isModule[typeID]
    243         except KeyError:
    244             isModule = evetypes.GetCategoryID(typeID) in (const.categoryModule, const.categoryStructureModule)
    245             self.isModule[typeID] = isModule
    246             return isModule
    247 
    248     def IsCharge(self, typeID):
    249         try:
    250             return self.isCharge[typeID]
    251         except KeyError:
    252             isCharge = evetypes.GetCategoryID(typeID) == const.categoryCharge
    253             self.isCharge[typeID] = isCharge
    254             return isCharge
    255 
    256     def IsSpecificSlotType(self, moduleTypeID, slotTypeWanted, cacheDict):
    257         try:
    258             return cacheDict[moduleTypeID]
    259         except KeyError:
    260             slotType = self.GetSlotTypeForModuleType(moduleTypeID)
    261             if slotType == slotTypeWanted:
    262                 isRightType = True
    263             else:
    264                 isRightType = False
    265             cacheDict[moduleTypeID] = isRightType
    266             return isRightType
    267 
    268     def GetSlotTypeForModuleType(self, moduleTypeID):
    269         try:
    270             return self.slotTypeByTypeID[moduleTypeID]
    271         except KeyError:
    272             slotType = GetSlotTypeForType(moduleTypeID)
    273             self.slotTypeByTypeID[moduleTypeID] = slotType
    274             return slotType
    275 
    276     def GetShipRigSize(self, shipTypeID):
    277         try:
    278             return self.shipRigSizeByTypeID[shipTypeID]
    279         except KeyError:
    280             rigSize = self.dogmaStaticMgr.GetTypeAttribute2(shipTypeID, const.attributeRigSize)
    281             self.shipRigSizeByTypeID[shipTypeID] = rigSize
    282             return rigSize
    283 
    284     def IsCapitalSize(self, groupID):
    285         try:
    286             return self.isCapitalShipByTypeID[groupID]
    287         except KeyError:
    288             isCapitalSize = groupID in self.cfg.GetShipGroupByClassType()[GROUP_CAPITALSHIPS]
    289             self.isCapitalShipByTypeID[groupID] = isCapitalSize
    290             return isCapitalSize
    291 
    292     def GetCalibrationForModuleType(self, moduleTypeID):
    293         try:
    294             return self.calibrationRequirementByModuleTypeID[moduleTypeID]
    295         except KeyError:
    296             calibrationValue = self.dogmaStaticMgr.GetTypeAttribute2(moduleTypeID, const.attributeUpgradeCost)
    297             self.calibrationRequirementByModuleTypeID[moduleTypeID] = calibrationValue
    298             return calibrationValue
    299 
    300     def GetCPUForModuleType(self, ghostFittingSvc, shipID, moduleTypeID, shipTypeID, resourceRigsFitted):
    301         dictKey = (shipTypeID, resourceRigsFitted, moduleTypeID)
    302         try:
    303             return self.cpuRequirementsByModuleTypeID[dictKey]
    304         except KeyError:
    305             cpuValue = self.dogmaStaticMgr.GetTypeAttribute2(moduleTypeID, const.attributeCpu)
    306             if cpuValue != 0:
    307                 cpuValue, powerValue = self.GetCpuAndPower(ghostFittingSvc, shipID, moduleTypeID, dictKey)
    308             else:
    309                 self.cpuRequirementsByModuleTypeID[dictKey] = cpuValue
    310             return cpuValue
    311 
    312     def GetPowergridForModuleType(self, ghostFittingSvc, shipID, moduleTypeID, shipTypeID, resourceRigsFitted):
    313         dictKey = (shipTypeID, resourceRigsFitted, moduleTypeID)
    314         try:
    315             return self.powergridRequirementsByModuleTypeID[dictKey]
    316         except KeyError:
    317             powerValue = self.dogmaStaticMgr.GetTypeAttribute2(moduleTypeID, const.attributePower)
    318             if powerValue != 0:
    319                 cpuValue, powerValue = self.GetCpuAndPower(ghostFittingSvc, shipID, moduleTypeID, dictKey)
    320             else:
    321                 self.powergridRequirementsByModuleTypeID[dictKey] = powerValue
    322             return powerValue
    323 
    324     def GetSearcableTypeIDs(self, marketGroups):
    325         if not self.searchableTypeIDs:
    326             myGroups = []
    327             for x in MODULE_CATEGORIES:
    328                 myGroups += marketGroups[x]
    329 
    330             typeIDs = {i for i in itertools.chain.from_iterable([ x.types for x in myGroups ])}
    331             typeIDs.update(self._GetSpecialAssetModules(marketGroups))
    332             typeIDs.update(AUTO_FITTED_SERVICES_BY_STRUCTURE_TYPE.values())
    333             self.searchableTypeIDs = typeIDs
    334         return self.searchableTypeIDs
    335 
    336     def _GetSpecialAssetModules(self, marketGroups):
    337         myGroups = marketGroups[const.marketCategorySpecialEditionAssets]
    338         typeIDs = {i for i in itertools.chain.from_iterable([ x.types for x in myGroups ]) if self.IsModule(i)}
    339         return typeIDs
    340 
    341     def GetSearcableChargeTypeIDs(self, marketGroups):
    342         if not self.searchableChargeTypeIDs:
    343             myGroups = marketGroups[const.marketCategoryAmmunitionAndCharges]
    344             typeIDs = {i for i in itertools.chain.from_iterable([ x.types for x in myGroups ])}
    345             typeIDs.update(self._GetSpecialAssetCharges(marketGroups))
    346             self.searchableChargeTypeIDs = typeIDs
    347         return self.searchableChargeTypeIDs
    348 
    349     def _GetSpecialAssetCharges(self, marketGroups):
    350         myGroups = marketGroups[const.marketCategorySpecialEditionAssets]
    351         typeIDs = {i for i in itertools.chain.from_iterable([ x.types for x in myGroups ]) if self.IsCharge(i)}
    352         return typeIDs
    353 
    354     def GetMarketCategoryForType(self, typeID, allMarketGroups):
    355         try:
    356             return self.marketCategoryByTypeID[typeID]
    357         except KeyError:
    358             for mg in allMarketGroups:
    359                 if typeID in mg.types:
    360                     topMarketCategory = mg
    361                     break
    362             else:
    363                 topMarketCategory = None
    364 
    365             self.marketCategoryByTypeID[typeID] = topMarketCategory
    366             return topMarketCategory
    367 
    368     def GetCpuAndPower(self, ghostFittingSvc, shipID, moduleTypeID, dictKey):
    369         info = ghostFittingSvc.LoadFakeItem(shipID, moduleTypeID)
    370         if info is None:
    371             cpuValue = powerValue = MAX_CPU_POWERGRID
    372         else:
    373             cpuValue = info.cpuValue
    374             powerValue = info.powerValue
    375         self.cpuRequirementsByModuleTypeID[dictKey] = cpuValue
    376         self.powergridRequirementsByModuleTypeID[dictKey] = powerValue
    377         return (cpuValue, powerValue)
    378 
    379     def GetMissingSkills(self, typeID, dogmaLocation, skillSvc):
    380         try:
    381             return self.missingSkills[typeID]
    382         except KeyError:
    383             missingSkillsForType = dogmaLocation.GetMissingSkills(typeID, skillSvc)
    384             self.missingSkills[typeID] = missingSkillsForType
    385             return missingSkillsForType
    386 
    387     def OnSkillsChanged(self, skillInfos):
    388         toRemove = []
    389         for changedSkillTypeID, skillInfo in skillInfos.iteritems():
    390             newSkillLevel = skillInfo.effectiveSkillLevel
    391             for eachTypeID, missingSkillInfo in self.missingSkills.iteritems():
    392                 missingLevel = missingSkillInfo.get(changedSkillTypeID, None)
    393                 if missingLevel is not None and missingLevel <= newSkillLevel:
    394                     toRemove.append((eachTypeID, changedSkillTypeID))
    395 
    396         for typeID, skillTypeID in toRemove:
    397             self.missingSkills[typeID].pop(skillTypeID)
    398 
    399         if toRemove:
    400             sm.ScatterEvent('OnSkillFilteringUpdated')
    401 
    402     def BuildNameDict(self):
    403         marketGroups = sm.GetService('marketutils').GetMarketGroups()
    404         typeIDs = set(self.GetSearcableTypeIDs(marketGroups))
    405         typeIDs.update(self.GetSearcableChargeTypeIDs(marketGroups))
    406         for typeID in typeIDs:
    407             text = evetypes.GetName(typeID).lower()
    408             self.typeNames_lower[typeID] = text
    409 
    410     def GetFittedLauncherAndTurrets(self, dogmaLocation, shipItem):
    411         currentModuleList = shipItem.GetFittedItems().values()
    412         numTurrets = 0
    413         numLaunchers = 0
    414         for module in currentModuleList:
    415             if module.flagID not in const.hiSlotFlags:
    416                 continue
    417             if dogmaLocation.dogmaStaticMgr.TypeHasEffect(module.typeID, const.effectTurretFitted):
    418                 numTurrets += 1
    419             elif dogmaLocation.dogmaStaticMgr.TypeHasEffect(module.typeID, const.effectLauncherFitted):
    420                 numLaunchers += 1
    421 
    422         return (numTurrets, numLaunchers)