fittingController.py (25361B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\fitting\fittingController.py 2 import sys 3 import carbonui.const as uiconst 4 import dogma.const as dogmaConst 5 import evetypes 6 import inventorycommon.const as invConst 7 import log 8 import shipmode 9 import signals 10 from collections import defaultdict 11 from cosmetics.client.ships.ship_skin_signals import on_skin_state_set 12 from eve.client.script.ui.inflight.shipstance import ShipStanceButtonController 13 from eve.client.script.ui.shared.fitting.fittingSlotController import FittingSlotController 14 from eve.client.script.ui.shared.fitting.fittingUtil import IsCharge, NUM_SUBSYSTEM_SLOTS, GHOST_FITTABLE_CATEGORIES, GetShipAttributeWithDogmaLocation, GetTypeIDForController 15 from eve.client.script.ui.shared.fittingScreen.controllerGhostFittingExtension import FittingControllerGhostFittingExtension 16 from eve.client.script.ui.shared.fittingScreen.fittingSlotController import ShipFittingSlotController 17 from eve.client.script.ui.shared.fittingScreen.fittingStanceButtons import GhostShipStanceButtonController 18 from eve.client.script.ui.shared.fittingScreen.ghostControllerMixin import GhostControllerMixin 19 from eve.client.script.ui.shared.fittingScreen.structureFittingController import StructureFittingServiceSlotController 20 from eve.client.script.ui.shared.skins.controller import GetSkinnedShipModel, GetMultiHullTypeIDList 21 from eve.common.script.sys.eveCfg import IsControllingStructure 22 from inventorycommon.util import IsShipFittingFlag 23 from player_messaging.client.ui_message import prompt_player_fsd_dialog 24 25 class FittingController(object): 26 __notifyevents__ = ['OnDogmaAttributeChanged', 27 'OnStanceActive', 28 'OnDogmaItemChange', 29 'OnGodmaFlushLocation', 30 'OnAttributes', 31 'OnAttribute', 32 'ProcessActiveShipChanged', 33 'OnPostCfgDataChanged', 34 'OnDogmaDronesChanged', 35 'OnSkillsChanged', 36 'OnFighterTubeTaskStatus', 37 'OnDroneControlLost'] 38 SLOTGROUPS = () 39 SLOTGROUP_LAYOUT_ARCS = {0: (-35.0, 82.0), 40 1: (54.0, 82.0), 41 2: (143.0, 82.0), 42 3: (233.0, 51.0), 43 4: (287.0, 31.0)} 44 SLOT_CLASS = FittingSlotController 45 46 def __init__(self, itemID, typeID = None): 47 self._itemID = itemID 48 self._typeID = typeID or GetTypeIDForController(itemID) 49 self.isShipSimulated = sm.GetService('fittingSvc').IsShipSimulated() 50 self.ghostFittingExtension = FittingControllerGhostFittingExtension() 51 self.SetDogmaLocation() 52 sm.RegisterNotify(self) 53 on_skin_state_set.connect(self._OnSkinStateSet) 54 self.previewFittedItem = None 55 self._skin = None 56 self.on_new_itemID = signals.Signal(signalName='on_new_itemID') 57 self.on_stats_changed = signals.Signal(signalName='on_stats_changed') 58 self.on_hardpoints_fitted = signals.Signal(signalName='on_hardpoints_fitted') 59 self.on_slots_updated = signals.Signal(signalName='on_slots_updated') 60 self.on_subsystem_fitted = signals.Signal(signalName='on_subsystem_fitted') 61 self.on_subsystem_really_changed = signals.Signal(signalName='on_subsystem_really_changed') 62 self.on_module_online_state = signals.Signal(signalName='on_module_online_state') 63 self.on_item_ghost_fitted = signals.Signal(signalName='on_item_ghost_fitted') 64 self.on_name_changed = signals.Signal(signalName='on_name_changed') 65 self.on_skin_material_changed = signals.Signal(signalName='on_skin_material_changed') 66 self.on_stance_activated = signals.Signal(signalName='on_stance_activated') 67 self.on_should_close = signals.Signal(signalName='on_should_close') 68 self.on_slots_with_menu_changed = signals.Signal(signalName='on_slots_with_menu_changed') 69 self.on_controller_changing = signals.Signal(signalName='on_controller_changing') 70 self.on_drones_changed = signals.Signal(signalName='on_drones_changed') 71 self.on_warning_display_changed = signals.Signal(signalName='on_warning_display_changed') 72 self.slotsByFlagID = {} 73 self.slotFlagWithMenu = None 74 self.ConstructSlotControllers() 75 self._UpdateSkin() 76 77 def GetSlotClass(self, flagID): 78 return self.SLOT_CLASS 79 80 def SetDogmaLocation(self): 81 if self.IsSimulated(): 82 dogmaLocation = self.ghostFittingExtension.GetDogmaLocation() 83 else: 84 dogmaLocation = sm.GetService('clientDogmaIM').GetDogmaLocation() 85 self.dogmaLocation = dogmaLocation 86 87 def ConstructSlotControllers(self): 88 for slot in self.slotsByFlagID.values(): 89 slot.Close() 90 91 self.slotsByFlagID = {} 92 self.slotsByGroups = {} 93 for groupIdx, flagIDs in self.SLOTGROUPS: 94 group = [] 95 for i, flagID in enumerate(flagIDs): 96 invItem = self.GetFittedModulesByFlagID().get(flagID, None) 97 slotClass = self.GetSlotClass(flagID) 98 slotController = slotClass(flagID=flagID, parentController=self) 99 self.slotsByFlagID[flagID] = slotController 100 group.append(slotController) 101 102 self.slotsByGroups[groupIdx] = group 103 104 self._UpdateSlots() 105 106 def GetSlotsByGroups(self): 107 return self.slotsByGroups 108 109 def GetTotalNumSlots(self): 110 return sum([ len(group) for group in self.slotsByGroups.itervalues() ]) 111 112 def _UpdateSlots(self): 113 for flagID, slot in self.slotsByFlagID.iteritems(): 114 self.SetSlotModuleAndChargeIDs(slot, flagID) 115 116 for slot in self.slotsByFlagID.itervalues(): 117 slot.on_item_fitted() 118 119 self.on_slots_updated() 120 121 def OnSlotAttributeChanged(self, flagID, shipID, itemID, attributeID, value): 122 slot = self.slotsByFlagID[flagID] 123 self.SetSlotModuleAndChargeIDs(slot, flagID) 124 slot.OnSlotAttributeChanged(shipID, itemID, attributeID, value) 125 126 def SetSlotModuleAndChargeIDs(self, slot, flagID): 127 module, charge = self._GetModuleAndCharge(flagID=flagID) 128 chargeItemID = charge.itemID if charge else None 129 moduleItemID = module.itemID if module else None 130 slot.SetModuleAndChargeIDs(moduleItemID, chargeItemID) 131 if moduleItemID: 132 slot.SetFailedTypeID(None) 133 134 def SetFailedModuleTypeIDs(self, failedTypeIDsByFlags): 135 for flagID, slot in self.slotsByFlagID.iteritems(): 136 typeID = failedTypeIDsByFlags.get(flagID, None) 137 slot.SetFailedTypeID(typeID) 138 139 def UpdateItem(self, itemID, typeID = None): 140 oldItemID = self._itemID 141 oldTypeID = self._typeID 142 self._itemID = itemID 143 if typeID is None: 144 typeID = GetTypeIDForController(itemID) 145 self._typeID = typeID 146 if self.IsControllerChanging(itemID, typeID, oldItemID, oldTypeID): 147 self.on_controller_changing(itemID) 148 self._UpdateSkin() 149 self.on_new_itemID(itemID, oldItemID, typeID, oldTypeID) 150 self._UpdateSlots() 151 152 def _UpdateSkin(self): 153 self._skin = sm.GetService('cosmeticsSvc').GetAppliedSkinStateForCurrentSession(self._itemID) 154 155 def GetDogmaItem(self): 156 return self.dogmaLocation.SafeGetDogmaItem(self._itemID) 157 158 @property 159 def dogmaItem(self): 160 return self.GetDogmaItem() 161 162 def CurrentShipIsLoaded(self): 163 return bool(self.GetDogmaItem()) 164 165 def IsGodmaPrimingInterfering(self): 166 if self.GetItemID() != session.shipid: 167 return False 168 return sm.GetService('godma').IsPriming() 169 170 def GetDogmaLocation(self): 171 return self.dogmaLocation 172 173 def GetItemID(self): 174 return self._itemID 175 176 @property 177 def itemID(self): 178 return self.GetItemID() 179 180 def GetTypeID(self): 181 if self._typeID: 182 return self._typeID 183 return self.GetDogmaItem().typeID 184 185 @property 186 def typeID(self): 187 return self.GetTypeID() 188 189 def IsShip(self): 190 return evetypes.GetCategoryID(self.GetTypeID()) == const.categoryShip 191 192 def GetAttribute(self, attributeID): 193 return GetShipAttributeWithDogmaLocation(self.dogmaLocation, self.GetItemID(), attributeID) 194 195 def GetFittedModules(self): 196 shipDogmaItem = self.GetDogmaItem() 197 if shipDogmaItem: 198 return shipDogmaItem.GetFittedItems().values() 199 return [] 200 201 def SetPreviewFittedItem(self, previewItem = None, force = False): 202 if previewItem and evetypes.GetCategoryID(previewItem.typeID) not in GHOST_FITTABLE_CATEGORIES: 203 return 204 if self.IsSwitchingShips(): 205 return 206 self.previewFittedItem = previewItem 207 self.on_item_ghost_fitted() 208 self.on_stats_changed() 209 210 def GetPreviewFittedItem(self): 211 return self.previewFittedItem 212 213 def GetNumTurretsAndLaunchersFitted(self): 214 turretsFitted = 0 215 launchersFitted = 0 216 modulesByGroupInShip = {} 217 for module in self.GetFittedModules(): 218 if module.groupID not in modulesByGroupInShip: 219 modulesByGroupInShip[module.groupID] = [] 220 modulesByGroupInShip[module.groupID].append(module) 221 if self.dogmaLocation.dogmaStaticMgr.TypeHasEffect(module.typeID, dogmaConst.effectLauncherFitted): 222 launchersFitted += 1 223 if self.dogmaLocation.dogmaStaticMgr.TypeHasEffect(module.typeID, dogmaConst.effectTurretFitted): 224 turretsFitted += 1 225 226 return (launchersFitted, turretsFitted) 227 228 def GetFittedModulesByFlagID(self): 229 modulesByFlag = {} 230 for module in self.GetFittedModules(): 231 modulesByFlag[module.flagID, IsCharge(module.typeID)] = module 232 233 return modulesByFlag 234 235 def GetFittedModulesByGroupID(self): 236 modulesByGroupInShip = defaultdict(list) 237 for module in self.GetFittedModules(): 238 modulesByGroupInShip[module.groupID].append(module) 239 240 return modulesByGroupInShip 241 242 def _GetModuleAndCharge(self, flagID): 243 module = charge = None 244 for item in self.GetFittedModules(): 245 if item.flagID == flagID: 246 if IsCharge(item.typeID): 247 charge = item 248 else: 249 module = item 250 251 return (module, charge) 252 253 def GetSlotAdditionInfo(self, typeAttributesByID): 254 hiSlotAddition = 0 255 medSlotAddition = 0 256 lowSlotAddition = 0 257 if self.GetItemID() and self.IsShip(): 258 subSystemSlot = typeAttributesByID.get(dogmaConst.attributeSubSystemSlot, None) 259 if subSystemSlot is not None: 260 slotOccupant = self.dogmaLocation.GetSubSystemInFlag(self.GetItemID(), int(subSystemSlot)) 261 if slotOccupant is not None: 262 attributesByName = self.dogmaLocation.dogmaStaticMgr.attributesByName 263 GTA = lambda attributeID: self.dogmaLocation.dogmaStaticMgr.GetTypeAttribute2(slotOccupant.typeID, attributeID) 264 hiSlotAddition = -GTA(attributesByName['hiSlotModifier'].attributeID) 265 medSlotAddition = -GTA(attributesByName['medSlotModifier'].attributeID) 266 lowSlotAddition = -GTA(attributesByName['lowSlotModifier'].attributeID) 267 return (lowSlotAddition, medSlotAddition, hiSlotAddition) 268 269 def GetHardpointAdditionInfo(self, typeAttributesByID): 270 turretAddition = 0 271 launcherAddition = 0 272 if self.GetItemID() and self.IsShip(): 273 subSystemSlot = typeAttributesByID.get(dogmaConst.attributeSubSystemSlot, None) 274 if subSystemSlot is not None: 275 slotOccupant = self.dogmaLocation.GetSubSystemInFlag(self.GetItemID(), int(subSystemSlot)) 276 if slotOccupant is not None: 277 attributesByName = self.dogmaLocation.dogmaStaticMgr.attributesByName 278 GTA = lambda attributeID: self.dogmaLocation.dogmaStaticMgr.GetTypeAttribute2(slotOccupant.typeID, attributeID) 279 turretAddition = -GTA(attributesByName['turretHardPointModifier'].attributeID) 280 launcherAddition = -GTA(attributesByName['launcherHardPointModifier'].attributeID) 281 turretAddition += typeAttributesByID.get(dogmaConst.attributeTurretHardpointModifier, 0.0) 282 launcherAddition += typeAttributesByID.get(dogmaConst.attributeLauncherHardPointModifier, 0.0) 283 return (turretAddition, launcherAddition) 284 285 def OnDogmaAttributeChanged(self, shipID, itemID, attributeID, value): 286 if shipID == self.GetItemID(): 287 if attributeID == const.attributeIsOnline: 288 self.on_stats_changed() 289 if itemID in self.dogmaLocation.dogmaItems: 290 dogmaItem = self.dogmaLocation.dogmaItems[itemID] 291 self.on_module_online_state(dogmaItem) 292 if attributeID == const.attributeUpgradeSlotsLeft: 293 self.on_stats_changed() 294 if attributeID in (const.attributeIsOnline, const.attributeQuantity): 295 try: 296 dogmaItem = self.dogmaLocation.GetDogmaItem(itemID) 297 flagID = dogmaItem.flagID 298 except KeyError: 299 if isinstance(itemID, tuple) and itemID[0] == self.GetItemID(): 300 flagID = itemID[1] 301 else: 302 return 303 304 try: 305 self.OnSlotAttributeChanged(flagID, shipID, itemID, attributeID, value) 306 except KeyError: 307 pass 308 309 def OnPostCfgDataChanged(self, cfgname, entry, *args): 310 if cfgname == 'evelocations' and entry[0] == self.GetItemID(): 311 self.on_name_changed() 312 313 def OnDogmaDronesChanged(self): 314 self.on_drones_changed() 315 316 def OnGodmaFlushLocation(self, locationID): 317 pass 318 319 def OnFighterTubeTaskStatus(self, *args): 320 self.on_stats_changed() 321 322 def OnDroneControlLost(self, droneID): 323 self.on_stats_changed() 324 325 def OnDogmaItemChange(self, item, change): 326 locationOrFlagIsInChange = const.ixFlag in change or const.ixLocationID in change 327 didStacksizeFlagOrLocationChange = const.ixStackSize in change or locationOrFlagIsInChange 328 if not didStacksizeFlagOrLocationChange: 329 return 330 oldLocationID = change.get(const.ixLocationID, None) 331 if self.GetItemID() not in (oldLocationID, item.locationID): 332 return 333 if item.groupID in const.turretModuleGroups: 334 self.on_hardpoints_fitted() 335 updateSlotsAndStats = False 336 if IsSubsystemBeingLoaded(change, item, self.itemID): 337 self.on_subsystem_fitted(throttle=True) 338 updateSlotsAndStats = True 339 elif locationOrFlagIsInChange: 340 updateSlotsAndStats = True 341 if updateSlotsAndStats: 342 self._UpdateSlots() 343 self.on_stats_changed() 344 345 def OnAttribute(self, attributeName, item, value, updateStats = 1): 346 self.WaitForShip() 347 try: 348 self.GetService('godma').GetItem(item.itemID) 349 except AttributeError: 350 sys.exc_clear() 351 return 352 353 if updateStats: 354 self.on_stats_changed() 355 356 def OnAttributes(self, changeList): 357 self.WaitForShip() 358 slotsChanged = False 359 for attributeName, item, value in changeList: 360 if attributeName in ('hiSlots', 'medSlots', 'lowSlots'): 361 slotsChanged = True 362 363 self.on_stats_changed() 364 if slotsChanged: 365 self._UpdateSlots() 366 367 def OnSkillsChanged(self, *args): 368 self.on_stats_changed() 369 370 def ProcessActiveShipChanged(self, shipID, oldShipID): 371 if not self.IsSimulated(): 372 self.UpdateItem(shipID) 373 374 def _OnSkinStateSet(self, itemID, skinState): 375 if itemID != self.itemID: 376 return 377 self._skin = skinState 378 self.on_skin_material_changed() 379 380 def Close(self): 381 self.on_stats_changed.clear() 382 self.on_subsystem_fitted.clear() 383 self.on_hardpoints_fitted.clear() 384 self.on_new_itemID.clear() 385 self.on_module_online_state.clear() 386 self.on_item_ghost_fitted.clear() 387 self.on_name_changed.clear() 388 self.on_skin_material_changed.clear() 389 self.on_stance_activated.clear() 390 self.on_should_close.clear() 391 self.on_slots_with_menu_changed.clear() 392 self.on_controller_changing.clear() 393 self.on_drones_changed.clear() 394 for eachController in self.slotsByFlagID.values(): 395 eachController.Close() 396 397 on_skin_state_set.disconnect(self._OnSkinStateSet) 398 sm.UnregisterNotify(self) 399 400 def OnDropData(self, dragObj, nodes): 401 pass 402 403 def OnStanceActive(self, shipID, stanceID): 404 if self._itemID == shipID: 405 self.on_stance_activated(stanceID) 406 407 def WaitForShip(self): 408 self.dogmaLocation.WaitForShip() 409 410 def IsSwitchingShips(self): 411 return self.dogmaLocation.IsSwitchingShips() 412 413 def GetNumTurretsFitted(self): 414 return self._GetNumHardpointsFitted(const.effectTurretFitted) 415 416 def GetNumLaunchersFitted(self): 417 return self._GetNumHardpointsFitted(const.effectLauncherFitted) 418 419 def _GetNumHardpointsFitted(self, effect): 420 hardpointsFitted = 0 421 for module in self.GetFittedModules(): 422 if self.dogmaLocation.dogmaStaticMgr.TypeHasEffect(module.typeID, effect): 423 hardpointsFitted += 1 424 425 return hardpointsFitted 426 427 def GetNumTurretHardpointsLeft(self): 428 return self.GetAttribute(const.attributeTurretSlotsLeft) 429 430 def GetNumLauncherHardpointsLeft(self): 431 return self.GetAttribute(const.attributeLauncherSlotsLeft) 432 433 def GetNumHiSlots(self): 434 return self.GetAttribute(const.attributeHiSlots) 435 436 def GetNumMedSlots(self): 437 return self.GetAttribute(const.attributeMedSlots) 438 439 def GetNumLowSlots(self): 440 return self.GetAttribute(const.attributeLowSlots) 441 442 def GetNumSubsystemSlots(self): 443 if self.HasSubsystems(): 444 return NUM_SUBSYSTEM_SLOTS 445 else: 446 return 0 447 448 def HasSubsystems(self): 449 return bool(evetypes.GetTechLevel(self.GetTypeID()) > 2) 450 451 def HasStance(self): 452 return shipmode.ship_has_stances(self.GetTypeID()) 453 454 def StripFitting(self, prompt = True): 455 if prompt and prompt_player_fsd_dialog('AskStripShip', None, uiconst.YESNO, suppress=uiconst.ID_YES) != uiconst.ID_YES: 456 return 457 if self.IsSimulated(): 458 sm.GetService('ghostFittingSvc').UnfitAllModules() 459 elif not IsControllingStructure(): 460 sm.GetService('invCache').StripFitting(self.GetItemID()) 461 462 def GetCharges(self): 463 return self.dogmaLocation.GetSublocations(self.GetItemID()) 464 465 def GetModel(self): 466 multiHullTypeIDList = GetMultiHullTypeIDList(self.typeID, self.itemID, self.dogmaLocation) 467 return GetSkinnedShipModel(self._skin, self.typeID, multiHullTypeIDList) 468 469 @property 470 def model(self): 471 return self.GetModel() 472 473 @property 474 def scenePath(self): 475 if self.IsSimulated(): 476 return 'res:/dx9/scene/fitting/previewAmmo.red' 477 else: 478 return 'res:/dx9/scene/fitting/fitting.red' 479 480 def GetPreviewFittedTypeID(self): 481 if self.previewFittedItem: 482 return self.previewFittedItem.typeID 483 else: 484 return None 485 486 def GetPowerLoad(self): 487 self.LogUseOfUnsupportedFunction('GetPowerLoad') 488 489 def GetPowerOutput(self): 490 self.LogUseOfUnsupportedFunction('GetPowerLoad') 491 492 def GetCPULoad(self): 493 self.LogUseOfUnsupportedFunction('GetPowerLoad') 494 495 def GetCPUOutput(self): 496 self.LogUseOfUnsupportedFunction('GetPowerLoad') 497 498 def GetCalibrationLoad(self): 499 self.LogUseOfUnsupportedFunction('GetPowerLoad') 500 501 def GetCalibrationOutput(self): 502 self.LogUseOfUnsupportedFunction('GetPowerLoad') 503 504 def LogUseOfUnsupportedFunction(self, what): 505 log.LogException("FittingController: This function (%s)is no longer supported and shouldn't be used" % what) 506 507 def GetSlotController(self, flagID): 508 return self.slotsByFlagID[flagID] 509 510 def UpdateStats(self): 511 self.on_stats_changed() 512 513 def IsSimulated(self): 514 return False 515 516 def GetCurrentAttributeValues(self): 517 return {} 518 519 def IsFittableType(self, typeID): 520 return False 521 522 def SetSlotWithMenu(self, newFlagID): 523 oldFlagID = self.slotFlagWithMenu 524 self.slotFlagWithMenu = newFlagID 525 self.on_slots_with_menu_changed(oldFlagID, newFlagID) 526 527 def HasFighterBay(self): 528 try: 529 return self.dogmaLocation.GetAccurateAttributeValue(self.GetItemID(), const.attributeFighterCapacity) 530 except KeyError as e: 531 log.LogWarn('Failed to find an item when checking fighterbay, itemID = ', e) 532 return False 533 534 def IsControllerChanging(self, newItemID, newTypeID, oldItemID, oldTypeID): 535 oldTypeID = oldTypeID or GetTypeIDForController(oldItemID) 536 newTypeID = newTypeID or GetTypeIDForController(newItemID) 537 if evetypes.GetCategoryID(oldTypeID) != evetypes.GetCategoryID(newTypeID): 538 return True 539 return False 540 541 def UpdateSlotsByFlagID(self, newDict): 542 self.slotsByFlagID.update(newDict) 543 544 def ControllerForCategory(self): 545 pass 546 547 def HasNavigationPanel(self): 548 return True 549 550 def HasFuelPanel(self): 551 return False 552 553 def HasDronePanel(self): 554 return True 555 556 def IsValidItemAndSimulationState(self): 557 if self.isShipSimulated and not isinstance(self._itemID, basestring): 558 return False 559 if not self.isShipSimulated and isinstance(self._itemID, basestring): 560 return False 561 return True 562 563 def ChangeFittingWarningDisplay(self, warningSlotDict): 564 pass 565 566 567 class ShipFittingController(GhostControllerMixin, FittingController): 568 SLOT_CLASS = ShipFittingSlotController 569 __notifyevents__ = GhostControllerMixin.__notifyevents__ + FittingController.__notifyevents__ 570 SLOTGROUPS = ((0, invConst.hiSlotFlags), 571 (1, invConst.medSlotFlags), 572 (2, invConst.loSlotFlags), 573 (3, invConst.subsystemSlotFlags), 574 (4, invConst.rigSlotFlags)) 575 576 def __init__(self, itemID, typeID = None): 577 FittingController.__init__(self, itemID, typeID) 578 GhostControllerMixin.__init__(self, itemID, typeID) 579 580 def IsFittableType(self, typeID): 581 return evetypes.GetCategoryID(typeID) in (const.categoryCharge, const.categorySubSystem, const.categoryModule) 582 583 def ControllerForCategory(self): 584 return const.categoryShip 585 586 def GetStanceBtnControllerClass(self): 587 if not self.IsValidItemAndSimulationState(): 588 return 589 if self.IsSimulated(): 590 return GhostShipStanceButtonController 591 return ShipStanceButtonController 592 593 def SetPreviewFittedItem(self, ghostItem = None, force = False): 594 if not self.IsSimulated(): 595 FittingController.SetPreviewFittedItem(self, ghostItem) 596 else: 597 GhostControllerMixin.SetPreviewFittedItem(self, ghostItem, force) 598 599 def ChangeFittingWarningDisplay(self, warningSlotDict): 600 self.on_warning_display_changed(warningSlotDict) 601 602 603 class StructureFittingController(GhostControllerMixin, FittingController): 604 SLOT_CLASS = ShipFittingSlotController 605 SLOT_CLASS_SERVICES = StructureFittingServiceSlotController 606 __notifyevents__ = GhostControllerMixin.__notifyevents__ + FittingController.__notifyevents__ 607 SLOTGROUPS = ((0, invConst.hiSlotFlags), 608 (1, invConst.medSlotFlags), 609 (2, invConst.loSlotFlags), 610 (4, invConst.rigSlotFlags), 611 (-1, invConst.serviceSlotFlags)) 612 613 def __init__(self, itemID, typeID = None): 614 FittingController.__init__(self, itemID, typeID) 615 GhostControllerMixin.__init__(self, itemID, typeID) 616 617 def IsFittableType(self, typeID): 618 return evetypes.GetCategoryID(typeID) in (const.categoryStructureModule, const.categoryCharge) 619 620 def GetSlotClass(self, flagID): 621 if flagID in invConst.serviceSlotFlags: 622 return self.SLOT_CLASS_SERVICES 623 return self.SLOT_CLASS 624 625 def ControllerForCategory(self): 626 return const.categoryStructure 627 628 def GetStanceBtnControllerClass(self): 629 if not self.IsValidItemAndSimulationState(): 630 return 631 if self.IsSimulated(): 632 return GhostShipStanceButtonController 633 return ShipStanceButtonController 634 635 def HasNavigationPanel(self): 636 return False 637 638 def HasFuelPanel(self): 639 return True 640 641 def HasDronePanel(self): 642 return False 643 644 def SetPreviewFittedItem(self, ghostItem = None, force = False): 645 if not self.IsSimulated(): 646 FittingController.SetPreviewFittedItem(self, ghostItem) 647 else: 648 GhostControllerMixin.SetPreviewFittedItem(self, ghostItem, force) 649 650 651 def IsSubsystemBeingLoaded(change, item, itemID): 652 locationOrFlagIsInChange = const.ixLocationID in change or const.ixFlag in change 653 if not locationOrFlagIsInChange: 654 return False 655 if item.locationID != itemID: 656 return False 657 if not IsShipFittingFlag(item.flagID): 658 return False 659 if item.categoryID != const.categorySubSystem: 660 return False 661 return True