Merged differences from master (more catching up)
This commit is contained in:
@@ -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")
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
|
||||
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()
|
||||
|
||||
Reference in New Issue
Block a user