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)