Merge branch 'master' into singularity
This commit is contained in:
@@ -67,14 +67,8 @@ class ItemAttrShortcut:
|
||||
return_value = self.itemModifiedAttributes.get(key)
|
||||
return return_value or default
|
||||
|
||||
def getModifiedItemAttrWithExtraMods(self, key, extraMultipliers=None, default=0):
|
||||
"""Returns attribute value with passed modifiers applied to it."""
|
||||
return_value = self.itemModifiedAttributes.getWithExtraMods(key, extraMultipliers=extraMultipliers)
|
||||
return return_value or default
|
||||
|
||||
def getModifiedItemAttrWithoutAfflictor(self, key, afflictor, default=0):
|
||||
"""Returns attribute value with passed afflictor modification removed."""
|
||||
return_value = self.itemModifiedAttributes.getWithoutAfflictor(key, afflictor)
|
||||
def getModifiedItemAttrExtended(self, key, extraMultipliers=None, ignoreAfflictors=(), default=0):
|
||||
return_value = self.itemModifiedAttributes.getExtended(key, extraMultipliers=extraMultipliers, ignoreAfflictors=ignoreAfflictors)
|
||||
return return_value or default
|
||||
|
||||
def getItemBaseAttrValue(self, key, default=0):
|
||||
@@ -88,14 +82,8 @@ class ChargeAttrShortcut:
|
||||
return_value = self.chargeModifiedAttributes.get(key)
|
||||
return return_value or default
|
||||
|
||||
def getModifiedChargeAttrWithExtraMods(self, key, extraMultipliers=None, default=0):
|
||||
"""Returns attribute value with passed modifiers applied to it."""
|
||||
return_value = self.chargeModifiedAttributes.getWithExtraMods(key, extraMultipliers=extraMultipliers)
|
||||
return return_value or default
|
||||
|
||||
def getModifiedChargeAttrWithoutAfflictor(self, key, afflictor, default=0):
|
||||
"""Returns attribute value with passed modifiers applied to it."""
|
||||
return_value = self.chargeModifiedAttributes.getWithoutAfflictor(key, afflictor)
|
||||
def getModifiedChargeAttrExtended(self, key, extraMultipliers=None, ignoreAfflictors=(), default=0):
|
||||
return_value = self.chargeModifiedAttributes.getExtended(key, extraMultipliers=extraMultipliers, ignoreAfflictors=ignoreAfflictors)
|
||||
return return_value or default
|
||||
|
||||
def getChargeBaseAttrValue(self, key, default=0):
|
||||
@@ -211,32 +199,11 @@ class ModifiedAttributeDict(collections.MutableMapping):
|
||||
# Original value is the least priority
|
||||
return self.getOriginal(key)
|
||||
|
||||
def getWithExtraMods(self, key, extraMultipliers=None, default=0):
|
||||
"""Copy of __getitem__ with some modifications."""
|
||||
if not extraMultipliers:
|
||||
return self.get(key, default=default)
|
||||
|
||||
val = self.__calculateValue(key, extraMultipliers=extraMultipliers)
|
||||
if val is not None:
|
||||
return val
|
||||
|
||||
# Then in values which are not yet calculated
|
||||
if self.__intermediary:
|
||||
val = self.__intermediary.get(key)
|
||||
else:
|
||||
val = None
|
||||
if val is not None:
|
||||
return val
|
||||
|
||||
# Original value
|
||||
val = self.getOriginal(key)
|
||||
if val is not None:
|
||||
return val
|
||||
|
||||
# Passed in default value
|
||||
return default
|
||||
|
||||
def getWithoutAfflictor(self, key, afflictor, default=0):
|
||||
def getExtended(self, key, extraMultipliers=None, ignoreAfflictors=None, default=0):
|
||||
"""
|
||||
Here we consider couple of parameters. If they affect final result, we do
|
||||
not store result, and if they are - we do.
|
||||
"""
|
||||
# Here we do not have support for preAssigns/forceds, as doing them would
|
||||
# mean that we have to store all of them in a list which increases memory use,
|
||||
# and we do not actually need those operators atm
|
||||
@@ -245,8 +212,8 @@ class ModifiedAttributeDict(collections.MutableMapping):
|
||||
ignorePenalizedMultipliers = {}
|
||||
postIncreaseAdjustment = 0
|
||||
for fit, afflictors in self.getAfflictions(key).items():
|
||||
for innerAfflictor, operator, stackingGroup, preResAmount, postResAmount, used in afflictors:
|
||||
if innerAfflictor is afflictor:
|
||||
for afflictor, operator, stackingGroup, preResAmount, postResAmount, used in afflictors:
|
||||
if afflictor in ignoreAfflictors:
|
||||
if operator == Operator.MULTIPLY:
|
||||
if stackingGroup is None:
|
||||
multiplierAdjustment /= postResAmount
|
||||
@@ -257,29 +224,31 @@ class ModifiedAttributeDict(collections.MutableMapping):
|
||||
elif operator == Operator.POSTINCREASE:
|
||||
postIncreaseAdjustment -= postResAmount
|
||||
|
||||
if preIncreaseAdjustment == 0 and multiplierAdjustment == 1 and postIncreaseAdjustment == 0 and len(ignorePenalizedMultipliers) == 0:
|
||||
# If we apply no customizations - use regular getter
|
||||
if (
|
||||
not extraMultipliers and
|
||||
preIncreaseAdjustment == 0 and multiplierAdjustment == 1 and
|
||||
postIncreaseAdjustment == 0 and len(ignorePenalizedMultipliers) == 0
|
||||
):
|
||||
return self.get(key, default=default)
|
||||
|
||||
# Try to calculate custom values
|
||||
val = self.__calculateValue(
|
||||
key, preIncAdj=preIncreaseAdjustment, multAdj=multiplierAdjustment,
|
||||
key, extraMultipliers=extraMultipliers, preIncAdj=preIncreaseAdjustment, multAdj=multiplierAdjustment,
|
||||
postIncAdj=postIncreaseAdjustment, ignorePenMult=ignorePenalizedMultipliers)
|
||||
if val is not None:
|
||||
return val
|
||||
|
||||
# Then in values which are not yet calculated
|
||||
# Then the same fallbacks as in regular getter
|
||||
if self.__intermediary:
|
||||
val = self.__intermediary.get(key)
|
||||
else:
|
||||
val = None
|
||||
if val is not None:
|
||||
return val
|
||||
|
||||
# Original value
|
||||
val = self.getOriginal(key)
|
||||
if val is not None:
|
||||
return val
|
||||
|
||||
# Passed in default value
|
||||
return default
|
||||
|
||||
def __delitem__(self, key):
|
||||
|
||||
@@ -1320,8 +1320,8 @@ class Fit:
|
||||
"""Return how much cap regen do we gain from having this module"""
|
||||
currentRegen = self.calculateCapRecharge()
|
||||
nomodRegen = self.calculateCapRecharge(
|
||||
capacity=self.ship.getModifiedItemAttrWithoutAfflictor("capacitorCapacity", mod),
|
||||
rechargeRate=self.ship.getModifiedItemAttrWithoutAfflictor("rechargeRate", mod) / 1000.0)
|
||||
capacity=self.ship.getModifiedItemAttrExtended("capacitorCapacity", ignoreAfflictors=[mod]),
|
||||
rechargeRate=self.ship.getModifiedItemAttrExtended("rechargeRate", ignoreAfflictors=[mod]) / 1000.0)
|
||||
return currentRegen - nomodRegen
|
||||
|
||||
def getRemoteReps(self, spoolOptions=None):
|
||||
|
||||
@@ -77,6 +77,8 @@ class TargetProfile:
|
||||
|
||||
@signatureRadius.setter
|
||||
def signatureRadius(self, val):
|
||||
if val is not None and math.isinf(val):
|
||||
val = None
|
||||
self._signatureRadius = val
|
||||
|
||||
@property
|
||||
@@ -106,7 +108,7 @@ class TargetProfile:
|
||||
continue
|
||||
line = line.split('#', 1)[0] # allows for comments
|
||||
type, data = line.rsplit('=', 1)
|
||||
type, data = type.strip(), data.split(',')
|
||||
type, data = type.strip(), [d.strip() for d in data.split(',')]
|
||||
except:
|
||||
pyfalog.warning("Data isn't in correct format, continue to next line.")
|
||||
continue
|
||||
@@ -115,11 +117,13 @@ class TargetProfile:
|
||||
continue
|
||||
|
||||
numPatterns += 1
|
||||
name, data = data[0], data[1:5]
|
||||
name, dataRes, dataMisc = data[0], data[1:5], data[5:8]
|
||||
fields = {}
|
||||
|
||||
for index, val in enumerate(data):
|
||||
val = float(val)
|
||||
for index, val in enumerate(dataRes):
|
||||
val = float(val) if val else 0
|
||||
if math.isinf(val):
|
||||
val = 0
|
||||
try:
|
||||
assert 0 <= val <= 100
|
||||
fields["%sAmount" % cls.DAMAGE_TYPES[index]] = val / 100
|
||||
@@ -127,7 +131,18 @@ class TargetProfile:
|
||||
pyfalog.warning("Caught unhandled exception in import patterns.")
|
||||
continue
|
||||
|
||||
if len(fields) == 4: # Avoid possible blank lines
|
||||
if len(dataMisc) == 3:
|
||||
for index, val in enumerate(dataMisc):
|
||||
try:
|
||||
fieldName = ("maxVelocity", "signatureRadius", "radius")[index]
|
||||
except IndexError:
|
||||
break
|
||||
val = float(val) if val else 0
|
||||
if fieldName != "signatureRadius" and math.isinf(val):
|
||||
val = 0
|
||||
fields[fieldName] = val
|
||||
|
||||
if len(fields) in (4, 7): # Avoid possible blank lines
|
||||
if name.strip() in lookup:
|
||||
pattern = lookup[name.strip()]
|
||||
pattern.update(**fields)
|
||||
@@ -142,20 +157,23 @@ class TargetProfile:
|
||||
|
||||
return patterns, numPatterns
|
||||
|
||||
EXPORT_FORMAT = "TargetProfile = %s,%.1f,%.1f,%.1f,%.1f\n"
|
||||
EXPORT_FORMAT = "TargetProfile = %s,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f\n"
|
||||
|
||||
@classmethod
|
||||
def exportPatterns(cls, *patterns):
|
||||
out = "# Exported from pyfa\n#\n"
|
||||
out += "# Values are in following format:\n"
|
||||
out += "# TargetProfile = [name],[EM %],[Thermal %],[Kinetic %],[Explosive %]\n\n"
|
||||
out += "# TargetProfile = [name],[EM %],[Thermal %],[Kinetic %],[Explosive %],[Max velocity m/s],[Signature radius m],[Radius m]\n\n"
|
||||
for dp in patterns:
|
||||
out += cls.EXPORT_FORMAT % (
|
||||
dp.name,
|
||||
dp.emAmount * 100,
|
||||
dp.thermalAmount * 100,
|
||||
dp.kineticAmount * 100,
|
||||
dp.explosiveAmount * 100
|
||||
dp.explosiveAmount * 100,
|
||||
dp.maxVelocity,
|
||||
dp.signatureRadius,
|
||||
dp.radius
|
||||
)
|
||||
|
||||
return out.strip()
|
||||
|
||||
@@ -26,15 +26,59 @@ from service.const import GraphDpsDroneMode
|
||||
from service.settings import GraphSettings
|
||||
|
||||
|
||||
def getWebbedSpeed(src, tgt, currentUnwebbedSpeed, webMods, webDrones, webFighters, distance):
|
||||
def _isRegularScram(mod):
|
||||
if not mod.item:
|
||||
return False
|
||||
if not {'warpScrambleBlockMWDWithNPCEffect', 'structureWarpScrambleBlockMWDWithNPCEffect'}.intersection(mod.item.effects):
|
||||
return False
|
||||
if not mod.getModifiedItemAttr('activationBlockedStrenght', 0):
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def _isHicScram(mod):
|
||||
if not mod.item:
|
||||
return False
|
||||
if 'warpDisruptSphere' not in mod.item.effects:
|
||||
return False
|
||||
if not mod.charge:
|
||||
return False
|
||||
if 'shipModuleFocusedWarpScramblingScript' not in mod.charge.effects:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def getScramRange(src):
|
||||
scramRange = None
|
||||
for mod in src.item.modules:
|
||||
if _isRegularScram(mod) or _isHicScram(mod):
|
||||
scramRange = max(scramRange or 0, mod.maxRange or 0)
|
||||
return scramRange
|
||||
|
||||
|
||||
def getScrammables(tgt):
|
||||
scrammables = []
|
||||
if tgt.isFit:
|
||||
for mod in tgt.item.modules:
|
||||
if not mod.item:
|
||||
continue
|
||||
if {'moduleBonusMicrowarpdrive', 'microJumpDrive', 'microJumpPortalDrive'}.intersection(mod.item.effects):
|
||||
scrammables.append(mod)
|
||||
return scrammables
|
||||
|
||||
|
||||
def getTackledSpeed(src, tgt, currentUntackledSpeed, srcScramRange, tgtScrammables, webMods, webDrones, webFighters, distance):
|
||||
# Can slow down non-immune ships and target profiles
|
||||
if tgt.isFit and tgt.item.ship.getModifiedItemAttr('disallowOffensiveModifiers'):
|
||||
return currentUnwebbedSpeed
|
||||
maxUnwebbedSpeed = tgt.getMaxVelocity()
|
||||
return currentUntackledSpeed
|
||||
maxUntackledSpeed = tgt.getMaxVelocity()
|
||||
# What's immobile cannot be slowed
|
||||
if maxUnwebbedSpeed == 0:
|
||||
return maxUnwebbedSpeed
|
||||
speedRatio = currentUnwebbedSpeed / maxUnwebbedSpeed
|
||||
if maxUntackledSpeed == 0:
|
||||
return maxUntackledSpeed
|
||||
speedRatio = currentUntackledSpeed / maxUntackledSpeed
|
||||
# No scrams or distance is longer than longest scram - nullify scrammables list
|
||||
if srcScramRange is None or (distance is not None and distance > srcScramRange):
|
||||
tgtScrammables = ()
|
||||
appliedMultipliers = {}
|
||||
# Modules first, they are applied always the same way
|
||||
for wData in webMods:
|
||||
@@ -44,8 +88,8 @@ def getWebbedSpeed(src, tgt, currentUnwebbedSpeed, webMods, webDrones, webFighte
|
||||
distance=distance)
|
||||
if appliedBoost:
|
||||
appliedMultipliers.setdefault(wData.stackingGroup, []).append((1 + appliedBoost / 100, wData.resAttrID))
|
||||
maxWebbedSpeed = tgt.getMaxVelocity(extraMultipliers=appliedMultipliers)
|
||||
currentWebbedSpeed = maxWebbedSpeed * speedRatio
|
||||
maxTackledSpeed = tgt.getMaxVelocity(extraMultipliers=appliedMultipliers, ignoreAfflictors=tgtScrammables)
|
||||
currentTackledSpeed = maxTackledSpeed * speedRatio
|
||||
# Drones and fighters
|
||||
mobileWebs = []
|
||||
mobileWebs.extend(webFighters)
|
||||
@@ -60,8 +104,8 @@ def getWebbedSpeed(src, tgt, currentUnwebbedSpeed, webMods, webDrones, webFighte
|
||||
for mwData in longEnoughMws:
|
||||
appliedMultipliers.setdefault(mwData.stackingGroup, []).append((1 + mwData.boost / 100, mwData.resAttrID))
|
||||
mobileWebs.remove(mwData)
|
||||
maxWebbedSpeed = tgt.getMaxVelocity(extraMultipliers=appliedMultipliers)
|
||||
currentWebbedSpeed = maxWebbedSpeed * speedRatio
|
||||
maxTackledSpeed = tgt.getMaxVelocity(extraMultipliers=appliedMultipliers, ignoreAfflictors=tgtScrammables)
|
||||
currentTackledSpeed = maxTackledSpeed * speedRatio
|
||||
# Apply remaining webs, from fastest to slowest
|
||||
droneOpt = GraphSettings.getInstance().get('mobileDroneMode')
|
||||
while mobileWebs:
|
||||
@@ -70,7 +114,7 @@ def getWebbedSpeed(src, tgt, currentUnwebbedSpeed, webMods, webDrones, webFighte
|
||||
fastestMws = [mw for mw in mobileWebs if mw.speed == fastestMwSpeed]
|
||||
for mwData in fastestMws:
|
||||
# Faster than target or set to follow it - apply full slowdown
|
||||
if (droneOpt == GraphDpsDroneMode.auto and mwData.speed >= currentWebbedSpeed) or droneOpt == GraphDpsDroneMode.followTarget:
|
||||
if (droneOpt == GraphDpsDroneMode.auto and mwData.speed >= currentTackledSpeed) or droneOpt == GraphDpsDroneMode.followTarget:
|
||||
appliedMwBoost = mwData.boost
|
||||
# Otherwise project from the center of the ship
|
||||
else:
|
||||
@@ -84,18 +128,21 @@ def getWebbedSpeed(src, tgt, currentUnwebbedSpeed, webMods, webDrones, webFighte
|
||||
distance=rangeFactorDistance)
|
||||
appliedMultipliers.setdefault(mwData.stackingGroup, []).append((1 + appliedMwBoost / 100, mwData.resAttrID))
|
||||
mobileWebs.remove(mwData)
|
||||
maxWebbedSpeed = tgt.getMaxVelocity(extraMultipliers=appliedMultipliers)
|
||||
currentWebbedSpeed = maxWebbedSpeed * speedRatio
|
||||
maxTackledSpeed = tgt.getMaxVelocity(extraMultipliers=appliedMultipliers, ignoreAfflictors=tgtScrammables)
|
||||
currentTackledSpeed = maxTackledSpeed * speedRatio
|
||||
# Ensure consistent results - round off a little to avoid float errors
|
||||
return floatUnerr(currentWebbedSpeed)
|
||||
return floatUnerr(currentTackledSpeed)
|
||||
|
||||
|
||||
def getTpMult(src, tgt, tgtSpeed, tpMods, tpDrones, tpFighters, distance):
|
||||
def getSigRadiusMult(src, tgt, tgtSpeed, srcScramRange, tgtScrammables, tpMods, tpDrones, tpFighters, distance):
|
||||
# Can blow non-immune ships and target profiles
|
||||
if tgt.isFit and tgt.item.ship.getModifiedItemAttr('disallowOffensiveModifiers'):
|
||||
return 1
|
||||
untpedSig = tgt.getSigRadius()
|
||||
# Modules
|
||||
initSig = tgt.getSigRadius()
|
||||
# No scrams or distance is longer than longest scram - nullify scrammables list
|
||||
if srcScramRange is None or (distance is not None and distance > srcScramRange):
|
||||
tgtScrammables = ()
|
||||
# TPing modules
|
||||
appliedMultipliers = {}
|
||||
for tpData in tpMods:
|
||||
appliedBoost = tpData.boost * calculateRangeFactor(
|
||||
@@ -104,7 +151,7 @@ def getTpMult(src, tgt, tgtSpeed, tpMods, tpDrones, tpFighters, distance):
|
||||
distance=distance)
|
||||
if appliedBoost:
|
||||
appliedMultipliers.setdefault(tpData.stackingGroup, []).append((1 + appliedBoost / 100, tpData.resAttrID))
|
||||
# Drones and fighters
|
||||
# TPing drones
|
||||
mobileTps = []
|
||||
mobileTps.extend(tpFighters)
|
||||
# Drones have range limit
|
||||
@@ -127,9 +174,9 @@ def getTpMult(src, tgt, tgtSpeed, tpMods, tpDrones, tpFighters, distance):
|
||||
srcFalloffRange=mtpData.falloff,
|
||||
distance=rangeFactorDistance)
|
||||
appliedMultipliers.setdefault(mtpData.stackingGroup, []).append((1 + appliedMtpBoost / 100, mtpData.resAttrID))
|
||||
tpedSig = tgt.getSigRadius(extraMultipliers=appliedMultipliers)
|
||||
if tpedSig == math.inf and untpedSig == math.inf:
|
||||
modifiedSig = tgt.getSigRadius(extraMultipliers=appliedMultipliers, ignoreAfflictors=tgtScrammables)
|
||||
if modifiedSig == math.inf and initSig == math.inf:
|
||||
return 1
|
||||
mult = tpedSig / untpedSig
|
||||
mult = modifiedSig / initSig
|
||||
# Ensure consistent results - round off a little to avoid float errors
|
||||
return floatUnerr(mult)
|
||||
|
||||
@@ -24,7 +24,7 @@ from eos.utils.stats import DmgTypes
|
||||
from graphs.data.base import PointGetter, SmoothPointGetter
|
||||
from service.settings import GraphSettings
|
||||
from .calc.application import getApplicationPerKey
|
||||
from .calc.projected import getTpMult, getWebbedSpeed
|
||||
from .calc.projected import getScramRange, getScrammables, getTackledSpeed, getSigRadiusMult
|
||||
|
||||
|
||||
def applyDamage(dmgMap, applicationMap, tgtResists):
|
||||
@@ -138,8 +138,11 @@ class XDistanceMixin(SmoothPointGetter):
|
||||
# Prepare time cache here because we need to do it only once,
|
||||
# and this function is called once per point info fetch
|
||||
self._prepareTimeCache(src=src, maxTime=miscParams['time'])
|
||||
applyProjected = GraphSettings.getInstance().get('applyProjected')
|
||||
return {
|
||||
'applyProjected': GraphSettings.getInstance().get('applyProjected'),
|
||||
'applyProjected': applyProjected,
|
||||
'srcScramRange': getScramRange(src=src) if applyProjected else None,
|
||||
'tgtScrammables': getScrammables(tgt=tgt) if applyProjected else (),
|
||||
'dmgMap': self._getDamagePerKey(src=src, time=miscParams['time']),
|
||||
'tgtResists': tgt.getResists()}
|
||||
|
||||
@@ -151,18 +154,22 @@ class XDistanceMixin(SmoothPointGetter):
|
||||
webMods, tpMods = self.graph._projectedCache.getProjModData(src)
|
||||
webDrones, tpDrones = self.graph._projectedCache.getProjDroneData(src)
|
||||
webFighters, tpFighters = self.graph._projectedCache.getProjFighterData(src)
|
||||
tgtSpeed = getWebbedSpeed(
|
||||
tgtSpeed = getTackledSpeed(
|
||||
src=src,
|
||||
tgt=tgt,
|
||||
currentUnwebbedSpeed=tgtSpeed,
|
||||
currentUntackledSpeed=tgtSpeed,
|
||||
srcScramRange=commonData['srcScramRange'],
|
||||
tgtScrammables=commonData['tgtScrammables'],
|
||||
webMods=webMods,
|
||||
webDrones=webDrones,
|
||||
webFighters=webFighters,
|
||||
distance=distance)
|
||||
tgtSigRadius = tgtSigRadius * getTpMult(
|
||||
tgtSigRadius = tgtSigRadius * getSigRadiusMult(
|
||||
src=src,
|
||||
tgt=tgt,
|
||||
tgtSpeed=tgtSpeed,
|
||||
srcScramRange=commonData['srcScramRange'],
|
||||
tgtScrammables=commonData['tgtScrammables'],
|
||||
tpMods=tpMods,
|
||||
tpDrones=tpDrones,
|
||||
tpFighters=tpFighters,
|
||||
@@ -189,21 +196,27 @@ class XTimeMixin(PointGetter):
|
||||
tgtSpeed = miscParams['tgtSpeed']
|
||||
tgtSigRadius = tgt.getSigRadius()
|
||||
if GraphSettings.getInstance().get('applyProjected'):
|
||||
srcScramRange = getScramRange(src=src)
|
||||
tgtScrammables = getScrammables(tgt=tgt)
|
||||
webMods, tpMods = self.graph._projectedCache.getProjModData(src)
|
||||
webDrones, tpDrones = self.graph._projectedCache.getProjDroneData(src)
|
||||
webFighters, tpFighters = self.graph._projectedCache.getProjFighterData(src)
|
||||
tgtSpeed = getWebbedSpeed(
|
||||
tgtSpeed = getTackledSpeed(
|
||||
src=src,
|
||||
tgt=tgt,
|
||||
currentUnwebbedSpeed=tgtSpeed,
|
||||
currentUntackledSpeed=tgtSpeed,
|
||||
srcScramRange=srcScramRange,
|
||||
tgtScrammables=tgtScrammables,
|
||||
webMods=webMods,
|
||||
webDrones=webDrones,
|
||||
webFighters=webFighters,
|
||||
distance=miscParams['distance'])
|
||||
tgtSigRadius = tgtSigRadius * getTpMult(
|
||||
tgtSigRadius = tgtSigRadius * getSigRadiusMult(
|
||||
src=src,
|
||||
tgt=tgt,
|
||||
tgtSpeed=tgtSpeed,
|
||||
srcScramRange=srcScramRange,
|
||||
tgtScrammables=tgtScrammables,
|
||||
tpMods=tpMods,
|
||||
tpDrones=tpDrones,
|
||||
tpFighters=tpFighters,
|
||||
@@ -303,21 +316,27 @@ class XTgtSpeedMixin(SmoothPointGetter):
|
||||
tgtSpeed = x
|
||||
tgtSigRadius = tgt.getSigRadius()
|
||||
if commonData['applyProjected']:
|
||||
srcScramRange = getScramRange(src=src)
|
||||
tgtScrammables = getScrammables(tgt=tgt)
|
||||
webMods, tpMods = self.graph._projectedCache.getProjModData(src)
|
||||
webDrones, tpDrones = self.graph._projectedCache.getProjDroneData(src)
|
||||
webFighters, tpFighters = self.graph._projectedCache.getProjFighterData(src)
|
||||
tgtSpeed = getWebbedSpeed(
|
||||
tgtSpeed = getTackledSpeed(
|
||||
src=src,
|
||||
tgt=tgt,
|
||||
currentUnwebbedSpeed=tgtSpeed,
|
||||
currentUntackledSpeed=tgtSpeed,
|
||||
srcScramRange=srcScramRange,
|
||||
tgtScrammables=tgtScrammables,
|
||||
webMods=webMods,
|
||||
webDrones=webDrones,
|
||||
webFighters=webFighters,
|
||||
distance=miscParams['distance'])
|
||||
tgtSigRadius = tgtSigRadius * getTpMult(
|
||||
tgtSigRadius = tgtSigRadius * getSigRadiusMult(
|
||||
src=src,
|
||||
tgt=tgt,
|
||||
tgtSpeed=tgtSpeed,
|
||||
srcScramRange=srcScramRange,
|
||||
tgtScrammables=tgtScrammables,
|
||||
tpMods=tpMods,
|
||||
tpDrones=tpDrones,
|
||||
tpFighters=tpFighters,
|
||||
@@ -347,21 +366,27 @@ class XTgtSigRadiusMixin(SmoothPointGetter):
|
||||
tgtSpeed = miscParams['tgtSpeed']
|
||||
tgtSigMult = 1
|
||||
if GraphSettings.getInstance().get('applyProjected'):
|
||||
srcScramRange = getScramRange(src=src)
|
||||
tgtScrammables = getScrammables(tgt=tgt)
|
||||
webMods, tpMods = self.graph._projectedCache.getProjModData(src)
|
||||
webDrones, tpDrones = self.graph._projectedCache.getProjDroneData(src)
|
||||
webFighters, tpFighters = self.graph._projectedCache.getProjFighterData(src)
|
||||
tgtSpeed = getWebbedSpeed(
|
||||
tgtSpeed = getTackledSpeed(
|
||||
src=src,
|
||||
tgt=tgt,
|
||||
currentUnwebbedSpeed=tgtSpeed,
|
||||
currentUntackledSpeed=tgtSpeed,
|
||||
srcScramRange=srcScramRange,
|
||||
tgtScrammables=tgtScrammables,
|
||||
webMods=webMods,
|
||||
webDrones=webDrones,
|
||||
webFighters=webFighters,
|
||||
distance=miscParams['distance'])
|
||||
tgtSigMult = getTpMult(
|
||||
tgtSigMult = getSigRadiusMult(
|
||||
src=src,
|
||||
tgt=tgt,
|
||||
tgtSpeed=tgtSpeed,
|
||||
srcScramRange=srcScramRange,
|
||||
tgtScrammables=tgtScrammables,
|
||||
tpMods=tpMods,
|
||||
tpDrones=tpDrones,
|
||||
tpFighters=tpFighters,
|
||||
|
||||
@@ -106,7 +106,9 @@ class GraphCanvasPanel(wx.Panel):
|
||||
legendData = []
|
||||
chosenX = self.graphFrame.ctrlPanel.xType
|
||||
chosenY = self.graphFrame.ctrlPanel.yType
|
||||
self.subplot.set(xlabel=self.graphFrame.ctrlPanel.formatLabel(chosenX), ylabel=self.graphFrame.ctrlPanel.formatLabel(chosenY))
|
||||
self.subplot.set(
|
||||
xlabel=self.graphFrame.ctrlPanel.formatLabel(chosenX),
|
||||
ylabel=self.graphFrame.ctrlPanel.formatLabel(chosenY))
|
||||
|
||||
mainInput, miscInputs = self.graphFrame.ctrlPanel.getValues()
|
||||
view = self.graphFrame.getView()
|
||||
@@ -212,14 +214,11 @@ class GraphCanvasPanel(wx.Panel):
|
||||
def addYMark(val):
|
||||
if val is None:
|
||||
return
|
||||
rounded = roundToPrec(val, 4)
|
||||
# If due to some bug or insufficient plot density we're
|
||||
# out of bounds, do not add anything
|
||||
if minY <= val <= maxY:
|
||||
if abs(val) < 0.0001:
|
||||
val = 0
|
||||
else:
|
||||
val = roundToPrec(val, 4)
|
||||
yMarks.add(val)
|
||||
if minY <= val <= maxY or minY <= rounded <= maxY:
|
||||
yMarks.add(rounded)
|
||||
|
||||
for source, target in iterList:
|
||||
xs, ys = plotData[(source, target)]
|
||||
|
||||
@@ -54,10 +54,13 @@ class BaseWrapper:
|
||||
return self.item.name
|
||||
return ''
|
||||
|
||||
def getMaxVelocity(self, extraMultipliers=None):
|
||||
def getMaxVelocity(self, extraMultipliers=None, ignoreAfflictors=()):
|
||||
if self.isFit:
|
||||
if extraMultipliers:
|
||||
maxVelocity = self.item.ship.getModifiedItemAttrWithExtraMods('maxVelocity', extraMultipliers=extraMultipliers)
|
||||
if extraMultipliers or ignoreAfflictors:
|
||||
maxVelocity = self.item.ship.getModifiedItemAttrExtended(
|
||||
'maxVelocity',
|
||||
extraMultipliers=extraMultipliers,
|
||||
ignoreAfflictors=ignoreAfflictors)
|
||||
else:
|
||||
maxVelocity = self.item.ship.getModifiedItemAttr('maxVelocity')
|
||||
elif self.isProfile:
|
||||
@@ -68,10 +71,13 @@ class BaseWrapper:
|
||||
maxVelocity = None
|
||||
return maxVelocity
|
||||
|
||||
def getSigRadius(self, extraMultipliers=None):
|
||||
def getSigRadius(self, extraMultipliers=None, ignoreAfflictors=()):
|
||||
if self.isFit:
|
||||
if extraMultipliers:
|
||||
sigRadius = self.item.ship.getModifiedItemAttrWithExtraMods('signatureRadius', extraMultipliers=extraMultipliers)
|
||||
if extraMultipliers or ignoreAfflictors:
|
||||
sigRadius = self.item.ship.getModifiedItemAttrExtended(
|
||||
'signatureRadius',
|
||||
extraMultipliers=extraMultipliers,
|
||||
ignoreAfflictors=ignoreAfflictors)
|
||||
else:
|
||||
sigRadius = self.item.ship.getModifiedItemAttr('signatureRadius')
|
||||
elif self.isProfile:
|
||||
|
||||
@@ -17,7 +17,7 @@ class GraphDmgApplyProjectedMenu(ContextMenuUnconditional):
|
||||
return srcContext == 'dmgStatsGraph'
|
||||
|
||||
def getText(self, callingWindow, itmContext):
|
||||
return 'Apply Attacker Webs and TPs'
|
||||
return 'Apply Projected Items'
|
||||
|
||||
def activate(self, callingWindow, fullContext, i):
|
||||
self.settings.set('applyProjected', not self.settings.get('applyProjected'))
|
||||
|
||||
@@ -273,7 +273,15 @@ class ExportToEve(AuxiliaryFrame):
|
||||
sEsi = Esi.getInstance()
|
||||
|
||||
sFit = Fit.getInstance()
|
||||
data = sPort.exportESI(sFit.getFit(fitID))
|
||||
try:
|
||||
data = sPort.exportESI(sFit.getFit(fitID))
|
||||
except ESIExportException as e:
|
||||
msg = str(e)
|
||||
if not msg:
|
||||
msg = "Failed to generate export data"
|
||||
pyfalog.warning(msg)
|
||||
self.statusbar.SetStatusText(msg, 1)
|
||||
return
|
||||
activeChar = self.getActiveCharacter()
|
||||
if activeChar is None:
|
||||
msg = "Need at least one ESI character to export"
|
||||
|
||||
Reference in New Issue
Block a user