Merge branch 'feature/allow-restrictions' into dev.

Allows user to turn off most fitting restrictions (#1117)
This commit is contained in:
blitzmann
2017-05-06 12:11:00 -04:00
8 changed files with 92 additions and 5 deletions

View File

@@ -0,0 +1,14 @@
"""
Migration 24
- Adds a boolean value to fit to signify if fit should ignore restrictions
"""
import sqlalchemy
def upgrade(saveddata_engine):
try:
saveddata_engine.execute("SELECT ignoreRestrictions FROM fits LIMIT 1")
except sqlalchemy.exc.DatabaseError:
saveddata_engine.execute("ALTER TABLE fits ADD COLUMN ignoreRestrictions BOOLEAN")
saveddata_engine.execute("UPDATE fits SET ignoreRestrictions = 0")

View File

@@ -58,6 +58,7 @@ fits_table = Table("fits", saveddata_meta,
Column("modeID", Integer, nullable=True),
Column("implantLocation", Integer, nullable=False, default=ImplantLocation.FIT),
Column("notes", String, nullable=True),
Column("ignoreRestrictions", Boolean, default=0),
Column("created", DateTime, nullable=True, default=func.now()),
Column("modified", DateTime, nullable=True, onupdate=func.now())
)

View File

@@ -1404,7 +1404,7 @@ class Fit(object):
@property
def fits(self):
for mod in self.modules:
if not mod.fits(self):
if not mod.isEmpty and not mod.fits(self):
return False
return True

View File

@@ -389,10 +389,24 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
self.__reloadForce = type
def fits(self, fit, hardpointLimit=True):
"""
Function that determines if a module can be fit to the ship. We always apply slot restrictions no matter what
(too many assumptions made on this), however all other fitting restrictions are optional
"""
slot = self.slot
if fit.getSlotsFree(slot) <= (0 if self.owner != fit else -1):
return False
fits = self.__fitRestrictions(fit, hardpointLimit)
if not fits and fit.ignoreRestrictions:
self.restrictionOverridden = True
fits = True
return fits
def __fitRestrictions(self, fit, hardpointLimit=True):
# Check ship type restrictions
fitsOnType = set()
fitsOnGroup = set()
@@ -413,8 +427,9 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
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:
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
# AFAIK Citadel modules will always be restricted based on canFitShipType/Group. If we are fitting to a Citadel

View File

@@ -611,12 +611,13 @@ class FittingView(d.Display):
slotMap[slot] = fit.getSlotsFree(slot) < 0
font = (self.GetClassDefaultAttributes()).font
for i, mod in enumerate(self.mods):
self.SetItemBackgroundColour(i, self.GetBackgroundColour())
# only consider changing color if we're dealing with a Module
if type(mod) is Module:
if slotMap[mod.slot]: # Color too many modules as red
if slotMap[mod.slot] or getattr(mod, 'restrictionOverridden', None): # Color too many modules as red
self.SetItemBackgroundColour(i, wx.Colour(204, 51, 51))
elif sFit.serviceFittingOptions["colorFitBySlot"]: # Color by slot it enabled
self.SetItemBackgroundColour(i, self.slotColour(mod.slot))

View File

@@ -524,6 +524,9 @@ class MainFrame(wx.Frame):
# Clipboard exports
self.Bind(wx.EVT_MENU, self.exportToClipboard, id=wx.ID_COPY)
# Fitting Restrictions
self.Bind(wx.EVT_MENU, self.toggleIgnoreRestriction, id=menuBar.toggleIgnoreRestrictionID)
# Graphs
self.Bind(wx.EVT_MENU, self.openGraphFrame, id=menuBar.graphFrameId)
@@ -584,6 +587,24 @@ class MainFrame(wx.Frame):
atable = wx.AcceleratorTable(actb)
self.SetAcceleratorTable(atable)
def toggleIgnoreRestriction(self, event):
sFit = Fit.getInstance()
fitID = self.getActiveFit()
fit = sFit.getFit(fitID)
if not fit.ignoreRestrictions:
dlg = wx.MessageDialog(self, "Are you sure you wish to ignore fitting restrictions for the "
"current fit? This could lead to wildly inaccurate results and possible errors.", "Confirm", wx.YES_NO | wx.ICON_QUESTION)
else:
dlg = wx.MessageDialog(self, "Re-enabling fitting restrictions for this fit will also remove any illegal items "
"from the fit. Do you want to continue?", "Confirm", wx.YES_NO | wx.ICON_QUESTION)
result = dlg.ShowModal() == wx.ID_YES
dlg.Destroy()
if result:
sFit.toggleRestrictionIgnore(fitID)
wx.PostEvent(self, GE.FitChanged(fitID=fitID))
def eveFittings(self, event):
dlg = CrestFittings(self)
dlg.Show()

View File

@@ -22,6 +22,7 @@ import wx
import config
from service.character import Character
from service.fit import Fit
import gui.graphFrame
import gui.globalEvents as GE
from gui.bitmapLoader import BitmapLoader
@@ -57,6 +58,7 @@ class MainMenuBar(wx.MenuBar):
self.attrEditorId = wx.NewId()
self.toggleOverridesId = wx.NewId()
self.importDatabaseDefaultsId = wx.NewId()
self.toggleIgnoreRestrictionID = wx.NewId()
if 'wxMac' in wx.PlatformInfo and wx.VERSION >= (3, 0):
wx.ID_COPY = wx.NewId()
@@ -96,6 +98,8 @@ class MainMenuBar(wx.MenuBar):
editMenu.Append(self.saveCharId, "Save Character")
editMenu.Append(self.saveCharAsId, "Save Character As...")
editMenu.Append(self.revertCharId, "Revert Character")
editMenu.AppendSeparator()
self.ignoreRestrictionItem = editMenu.Append(self.toggleIgnoreRestrictionID, "Ignore Fitting Restrictions")
# Character menu
windowMenu = wx.Menu()
@@ -170,7 +174,6 @@ class MainMenuBar(wx.MenuBar):
self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged)
def fitChanged(self, event):
pyfalog.debug("fitChanged triggered")
enable = event.fitID is not None
self.Enable(wx.ID_SAVEAS, enable)
self.Enable(wx.ID_COPY, enable)
@@ -185,4 +188,15 @@ class MainMenuBar(wx.MenuBar):
self.Enable(self.saveCharAsId, char.isDirty)
self.Enable(self.revertCharId, char.isDirty)
self.Enable(self.toggleIgnoreRestrictionID, enable)
if event.fitID:
sFit = Fit.getInstance()
fit = sFit.getFit(event.fitID)
if fit.ignoreRestrictions:
self.ignoreRestrictionItem.SetItemLabel("Enable Fitting Restrictions")
else:
self.ignoreRestrictionItem.SetItemLabel("Disable Fitting Restrictions")
event.Skip()

View File

@@ -240,6 +240,12 @@ class Fit(object):
self.recalc(fit)
fit.fill()
# this will loop through modules and set their restriction flag (set in m.fit())
if fit.ignoreRestrictions:
for mod in fit.modules:
if not mod.isEmpty:
mod.fits(fit)
# Check that the states of all modules are valid
self.checkStates(fit, None)
@@ -883,6 +889,21 @@ class Fit(object):
self.recalc(fit)
return True
def toggleRestrictionIgnore(self, fitID):
pyfalog.debug("Toggling restriction ignore for fit ID: {0}", fitID)
fit = eos.db.getFit(fitID)
fit.ignoreRestrictions = not fit.ignoreRestrictions
# remove invalid modules when switching back to enabled fitting restrictions
if not fit.ignoreRestrictions:
for m in fit.modules:
if not m.isEmpty and not m.fits(fit):
self.removeModule(fit.ID, m.modPosition)
eos.db.commit()
self.recalc(fit)
return True
def toggleBooster(self, fitID, i):
pyfalog.debug("Toggling booster for fit ID: {0}", fitID)
fit = eos.db.getFit(fitID)