From a74cdc59bd61652265fb0793c7585073f16d0d3f Mon Sep 17 00:00:00 2001 From: Ryan Holmes Date: Sun, 17 Mar 2019 21:44:28 -0400 Subject: [PATCH] Implement fixes for #1870 - undo the Module.toDummy that happens when replacing a module, but the new module doesn't fit. And shuffle around the logic that dictates if a module / item fits onto a particular ship to allow us to ask a fit if a base item can fit based on low-level attributes that don't change --- eos/saveddata/fit.py | 26 ++++++++++++++++++++++ eos/saveddata/module.py | 28 +----------------------- gui/builtinContextMenus/metaSwap.py | 4 ++++ gui/fitCommands/calc/fitReplaceModule.py | 28 +++++++++++++----------- 4 files changed, 46 insertions(+), 40 deletions(-) diff --git a/eos/saveddata/fit.py b/eos/saveddata/fit.py index ff1ee24e2..c31c17696 100644 --- a/eos/saveddata/fit.py +++ b/eos/saveddata/fit.py @@ -384,6 +384,32 @@ class Fit(object): else: return val + def canFit(self, item): + # Whereas Module.fits() deals with current state of the fit in order to determine if somethign fits (for example maxGroupFitted which can be modified by effects), + # this function should be used against Items to see if the item is even allowed on the fit with rules that don't change + + fitsOnType = set() + fitsOnGroup = set() + + shipType = item.attributes.get("fitsToShipType", None) + if shipType is not None: + fitsOnType.add(shipType.value) + + fitsOnType.update([item.attributes[attr].value for attr in item.attributes if attr.startswith("canFitShipType")]) + fitsOnGroup.update([item.attributes[attr].value for attr in item.attributes if attr.startswith("canFitShipGroup")]) + + if (len(fitsOnGroup) > 0 or len(fitsOnType) > 0) \ + and self.ship.item.group.ID not in fitsOnGroup \ + and self.ship.item.ID not in fitsOnType: + return False + + # Citadel modules are now under a new category, so we can check this to ensure only structure modules can fit on a citadel + if isinstance(self.ship, Citadel) and item.category.name != "Structure Module" or \ + not isinstance(self.ship, Citadel) and item.category.name == "Structure Module": + return False + + return True + def clear(self, projected=False, command=False): self.__effectiveTank = None self.__weaponDpsMap = {} diff --git a/eos/saveddata/module.py b/eos/saveddata/module.py index 8fd3117fc..db215bcdf 100644 --- a/eos/saveddata/module.py +++ b/eos/saveddata/module.py @@ -539,34 +539,8 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): return fits def __fitRestrictions(self, fit, hardpointLimit=True): - # Check ship type restrictions - fitsOnType = set() - fitsOnGroup = set() - shipType = self.getModifiedItemAttr("fitsToShipType", None) - if shipType is not None: - fitsOnType.add(shipType) - - for attr in list(self.itemModifiedAttributes.keys()): - if attr.startswith("canFitShipType"): - shipType = self.getModifiedItemAttr(attr, None) - if shipType is not None: - fitsOnType.add(shipType) - - for attr in list(self.itemModifiedAttributes.keys()): - if attr.startswith("canFitShipGroup"): - shipGroup = self.getModifiedItemAttr(attr, None) - if shipGroup is not None: - fitsOnGroup.add(shipGroup) - - if (len(fitsOnGroup) > 0 or len(fitsOnType) > 0) \ - and fit.ship.item.group.ID not in fitsOnGroup \ - and fit.ship.item.ID not in fitsOnType: - return False - - # Citadel modules are now under a new category, so we can check this to ensure only structure modules can fit on a citadel - if isinstance(fit.ship, Citadel) and self.item.category.name != "Structure Module" or \ - not isinstance(fit.ship, Citadel) and self.item.category.name == "Structure Module": + if not fit.canFit(self.item): return False # EVE doesn't let capital modules be fit onto subcapital hulls. Confirmed by CCP Larrikin that this is dictated diff --git a/gui/builtinContextMenus/metaSwap.py b/gui/builtinContextMenus/metaSwap.py index 2cbbb2221..d9a34599e 100644 --- a/gui/builtinContextMenus/metaSwap.py +++ b/gui/builtinContextMenus/metaSwap.py @@ -8,6 +8,7 @@ import gui.mainFrame from gui.contextMenu import ContextMenu from service.market import Market from service.settings import ContextMenuSettings +from service.fit import Fit class MetaSwap(ContextMenu): @@ -53,6 +54,8 @@ class MetaSwap(ContextMenu): def getSubMenu(self, context, selection, rootMenu, i, pitem): self.moduleLookup = {} + sFit = Fit.getInstance() + fit = sFit.getFit(self.mainFrame.getActiveFit()) def get_metalevel(x): if "metaLevel" not in x.attributes: @@ -114,6 +117,7 @@ class MetaSwap(ContextMenu): id = ContextMenu.nextID() mitem = wx.MenuItem(rootMenu, id, item.name) + mitem.Enable(fit.canFit(item)) bindmenu.Bind(wx.EVT_MENU, self.handleModule, mitem) self.moduleLookup[id] = item, context diff --git a/gui/fitCommands/calc/fitReplaceModule.py b/gui/fitCommands/calc/fitReplaceModule.py index b2d36314c..1a171ea3b 100644 --- a/gui/fitCommands/calc/fitReplaceModule.py +++ b/gui/fitCommands/calc/fitReplaceModule.py @@ -73,19 +73,21 @@ class FitReplaceModuleCommand(wx.Command): # Dummy it out in case the next bit fails fit.modules.toDummy(self.position) - if self.module.fits(fit): - self.module.owner = fit - fit.modules.toModule(self.position, self.module) - if self.module.isValidState(FittingModuleState.ACTIVE): - self.module.state = FittingModuleState.ACTIVE + if not self.module.fits(fit): + self.Undo() + return False - if self.old_module and self.old_module.charge and self.module.isValidCharge(self.old_module.charge): - self.module.charge = self.old_module.charge + self.module.owner = fit + fit.modules.toModule(self.position, self.module) + if self.module.isValidState(FittingModuleState.ACTIVE): + self.module.state = FittingModuleState.ACTIVE - # Then, check states of all modules and change where needed. This will recalc if needed - # self.checkStates(fit, m) + if self.old_module and self.old_module.charge and self.module.isValidCharge(self.old_module.charge): + self.module.charge = self.old_module.charge - # fit.fill() - eos.db.commit() - return True - return False + # Then, check states of all modules and change where needed. This will recalc if needed + # self.checkStates(fit, m) + + # fit.fill() + eos.db.commit() + return True