From 47828c38d25ccdf767005d372a7a3f906e398604 Mon Sep 17 00:00:00 2001 From: Ebag333 Date: Wed, 15 Jun 2016 19:40:45 -0700 Subject: [PATCH] Merged differences from master (more catching up) --- eos/effects/adaptivearmorhardener.py | 8 ++++ eos/effects/fighterabilitylaunchbomb.py | 3 ++ eos/effects/fighterabilitymissiles.py | 3 ++ eos/saveddata/fighterAbility.py | 34 ++++++++++++++- gui/builtinViews/fittingView.py | 16 ++++++- service/fit.py | 57 ++++++++++++------------- 6 files changed, 90 insertions(+), 31 deletions(-) diff --git a/eos/effects/adaptivearmorhardener.py b/eos/effects/adaptivearmorhardener.py index f2951320b..c3955ebf0 100644 --- a/eos/effects/adaptivearmorhardener.py +++ b/eos/effects/adaptivearmorhardener.py @@ -6,5 +6,13 @@ type = "active" def handler(fit, module, context): for type in ("kinetic", "thermal", "explosive", "em"): attr = "armor%sDamageResonance" % type.capitalize() + + #Adjust RAH to match the current damage pattern + damagePattern = fit.damagePattern + attrDamagePattern = "%sAmount" % type + damagePatternModifier = getattr(damagePattern,attrDamagePattern)/float(sum((damagePattern.emAmount,damagePattern.thermalAmount,damagePattern.kineticAmount,damagePattern.explosiveAmount))) + modifiedResistModifier = (1-(((1-module.getModifiedItemAttr(attr))*4)*(damagePatternModifier))) + module.forceItemAttr(attr, modifiedResistModifier) + fit.ship.multiplyItemAttr(attr, module.getModifiedItemAttr(attr), stackingPenalties=True, penaltyGroup="preMul") diff --git a/eos/effects/fighterabilitylaunchbomb.py b/eos/effects/fighterabilitylaunchbomb.py index 5a9513e1d..bc76f2a19 100644 --- a/eos/effects/fighterabilitylaunchbomb.py +++ b/eos/effects/fighterabilitylaunchbomb.py @@ -11,5 +11,8 @@ prefix = "fighterAbilityLaunchBomb" type = "active" +# This flag is required for effects that use charges in order to properly calculate reload time +hasCharges = True + def handler(fit, src, context): pass \ No newline at end of file diff --git a/eos/effects/fighterabilitymissiles.py b/eos/effects/fighterabilitymissiles.py index 7615f5616..c002ea5ac 100644 --- a/eos/effects/fighterabilitymissiles.py +++ b/eos/effects/fighterabilitymissiles.py @@ -11,5 +11,8 @@ prefix = "fighterAbilityMissiles" type = "active" +# This flag is required for effects that use charges in order to properly calculate reload time +hasCharges = True + def handler(fit, src, context): pass \ No newline at end of file diff --git a/eos/saveddata/fighterAbility.py b/eos/saveddata/fighterAbility.py index e7756bde1..027ffa30f 100644 --- a/eos/saveddata/fighterAbility.py +++ b/eos/saveddata/fighterAbility.py @@ -26,6 +26,14 @@ class FighterAbility(object): DAMAGE_TYPES = ("em", "kinetic", "explosive", "thermal") DAMAGE_TYPES2 = ("EM", "Kin", "Exp", "Therm") + # We aren't able to get data on the charges that can be stored with fighters. So we hardcode that data here, keyed + # with the fighter squadron role + NUM_SHOTS_MAPPING = { + 2: 8, # Light fighter / Attack + 4: 6, # Heavy fighter / Heavy attack + 5: 2, # Heavy fighter / Long range attack + } + def __init__(self, effect): """Initialize from the program""" self.__effect = effect @@ -71,12 +79,36 @@ class FighterAbility(object): # is the ability applied per fighter (webs, returns False), or as a group (MWD, returned True) return self.__effect.getattr('grouped') + @property + def hasCharges(self): + return self.__effect.getattr('hasCharges') + + @property + def reloadTime(self): + return self.fighter.getModifiedItemAttr("fighterRefuelingTime") * self.numShots + + @property + def numShots(self): + return self.NUM_SHOTS_MAPPING[self.fighter.getModifiedItemAttr("fighterSquadronRole")] or 0 if self.hasCharges else 0 + + @property + def cycleTime(self): + speed = self.fighter.getModifiedItemAttr("{}Duration".format(self.attrPrefix)) + reload = self.reloadTime + + if self.fighter.owner.factorReload: + numShots = self.numShots + # Speed here already takes into consideration reactivation time + speed = (speed * numShots + reload) / numShots if numShots > 0 else speed + + return speed + def damageStats(self, targetResists=None): if self.__dps is None: self.__volley = 0 self.__dps = 0 if self.dealsDamage and self.active: - cycleTime = self.fighter.getModifiedItemAttr("{}Duration".format(self.attrPrefix)) + cycleTime = self.cycleTime if self.attrPrefix == "fighterAbilityLaunchBomb": # bomb calcs diff --git a/gui/builtinViews/fittingView.py b/gui/builtinViews/fittingView.py index d16c0f251..7db037082 100644 --- a/gui/builtinViews/fittingView.py +++ b/gui/builtinViews/fittingView.py @@ -186,7 +186,7 @@ class FittingView(d.Display): elif data[0] == "cargo": self.swapCargo(x, y, int(data[1])) elif data[0] == "market": - wx.PostEvent(self.mainFrame, gui.marketBrowser.ItemSelected(itemID=int(data[1]))) + self.addModule(x, y, int(data[1])) def handleDrag(self, type, fitID): #Those are drags coming from pyfa sources, NOT builtin wx drags @@ -343,6 +343,20 @@ class FittingView(d.Display): self.slotsChanged() wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.activeFitID)) + def addModule(self, x, y, srcIdx): + '''Add a module from the market browser''' + mstate = wx.GetMouseState() + + dstRow, _ = self.HitTest((x, y)) + if dstRow != -1 and dstRow not in self.blanks: + sFit = service.Fit.getInstance() + fitID = self.mainFrame.getActiveFit() + moduleChanged = sFit.changeModule(fitID, self.mods[dstRow].position, srcIdx) + if moduleChanged is None: + # the new module doesn't fit in specified slot, try to simply append it + wx.PostEvent(self.mainFrame, gui.marketBrowser.ItemSelected(itemID=srcIdx)) + wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.mainFrame.getActiveFit())) + def swapCargo(self, x, y, srcIdx): '''Swap a module from cargo to fitting window''' mstate = wx.GetMouseState() diff --git a/service/fit.py b/service/fit.py index 71f8c873d..8ae9c6e4d 100644 --- a/service/fit.py +++ b/service/fit.py @@ -1,4 +1,4 @@ -#=============================================================================== +# =============================================================================== # Copyright (C) 2010 Diego Duclos # # This file is part of pyfa. @@ -15,7 +15,7 @@ # # You should have received a copy of the GNU General Public License # along with pyfa. If not, see . -#=============================================================================== +# =============================================================================== import locale import copy @@ -40,6 +40,7 @@ from service.port import Port logger = logging.getLogger(__name__) + class FitBackupThread(threading.Thread): def __init__(self, path, callback): threading.Thread.__init__(self) @@ -257,7 +258,7 @@ class Fit(object): if not projected: for fitP in fit.projectedFits: - self.getFit(fitP.ID, projected = True) + self.getFit(fitP.ID, projected=True) self.recalc(fit, withBoosters=True) fit.fill() @@ -413,7 +414,7 @@ class Fit(object): def changeActiveFighters(self, fitID, fighter, amount): fit = eos.db.getFit(fitID) fighter.amountActive = amount - + eos.db.commit() self.recalc(fit) @@ -427,7 +428,7 @@ class Fit(object): fit.projectedFighters.remove(thing) else: del fit.__projectedFits[thing.ID] - #fit.projectedFits.remove(thing) + # fit.projectedFits.remove(thing) eos.db.commit() self.recalc(fit) @@ -477,8 +478,6 @@ class Fit(object): def changeModule(self, fitID, position, newItemID): fit = eos.db.getFit(fitID) - if fit.modules[position].isEmpty: - return None # Dummy it out in case the next bit fails fit.modules.toDummy(position) @@ -945,7 +944,7 @@ class Fit(object): fits = [] for path in paths: if callback: # Pulse - wx.CallAfter(callback, 1, "Processing file:\n%s"%path) + wx.CallAfter(callback, 1, "Processing file:\n%s" % path) file = open(path, "r") srcString = file.read() @@ -957,38 +956,38 @@ class Fit(object): # If file had ANSI encoding, decode it to unicode using detection # of BOM header or if there is no header try default # codepage then fallback to utf-16, cp1252 - + if isinstance(srcString, str): encoding_map = ( - ('\xef\xbb\xbf', 'utf-8'), - ('\xff\xfe\0\0', 'utf-32'), - ('\0\0\xfe\xff', 'UTF-32BE'), - ('\xff\xfe', 'utf-16'), - ('\xfe\xff', 'UTF-16BE')) + ('\xef\xbb\xbf', 'utf-8'), + ('\xff\xfe\0\0', 'utf-32'), + ('\0\0\xfe\xff', 'UTF-32BE'), + ('\xff\xfe', 'utf-16'), + ('\xfe\xff', 'UTF-16BE')) for bom, encoding in encoding_map: if srcString.startswith(bom): codec_found = encoding savebom = bom - + if codec_found is None: logger.info("Unicode BOM not found in file %s.", path) attempt_codecs = (defcodepage, "utf-8", "utf-16", "cp1252") for page in attempt_codecs: - try: - logger.info("Attempting to decode file %s using %s page.", path, page) - srcString = unicode(srcString, page) - codec_found = page - logger.info("File %s decoded using %s page.", path, page) - except UnicodeDecodeError: - logger.info("Error unicode decoding %s from page %s, trying next codec", path, page) - else: - break + try: + logger.info("Attempting to decode file %s using %s page.", path, page) + srcString = unicode(srcString, page) + codec_found = page + logger.info("File %s decoded using %s page.", path, page) + except UnicodeDecodeError: + logger.info("Error unicode decoding %s from page %s, trying next codec", path, page) + else: + break else: logger.info("Unicode BOM detected in %s, using %s page.", path, codec_found) srcString = unicode(srcString[len(savebom):], codec_found) - + else: # nasty hack to detect other transparent utf-16 loading if srcString[0] == '<' and 'utf-16' in srcString[:128].lower(): @@ -1003,10 +1002,10 @@ class Fit(object): _, fitsImport = Port.importAuto(srcString, path, callback=callback, encoding=codec_found) fits += fitsImport except xml.parsers.expat.ExpatError, e: - return False, "Malformed XML in %s"%path + return False, "Malformed XML in %s" % path except Exception, e: logger.exception("Unknown exception processing: %s", path) - return False, "Unknown Error while processing %s"%path + return False, "Unknown Error while processing %s" % path IDs = [] numFits = len(fits) @@ -1021,7 +1020,7 @@ class Fit(object): wx.CallAfter( callback, 1, "Processing complete, saving fits to database\n(%d/%d)" % - (i+1, numFits) + (i + 1, numFits) ) return True, fits @@ -1124,7 +1123,7 @@ class Fit(object): self.recalc(fit) def recalc(self, fit, withBoosters=True): - logger.debug("="*10+"recalc"+"="*10) + logger.debug("=" * 10 + "recalc" + "=" * 10) if fit.factorReload is not self.serviceFittingOptions["useGlobalForceReload"]: fit.factorReload = self.serviceFittingOptions["useGlobalForceReload"] fit.clear()