diff --git a/graphs/data/fitDamageStats/calc/application.py b/graphs/data/fitDamageStats/calc/application.py index a4d9aa552..88bc6bef6 100644 --- a/graphs/data/fitDamageStats/calc/application.py +++ b/graphs/data/fitDamageStats/calc/application.py @@ -200,7 +200,11 @@ def getGuidedBombMult(mod, src, distance, tgtSigRadius): def getDroneMult(drone, src, tgt, atkSpeed, atkAngle, distance, tgtSpeed, tgtAngle, tgtSigRadius): - if distance is not None and distance > src.item.extraAttributes['droneControlRange']: + if ( + distance is not None and + not GraphSettings.getInstance().get('ignoreDCR') and + distance > src.item.extraAttributes['droneControlRange'] + ): return 0 droneSpeed = drone.getModifiedItemAttr('maxVelocity') # Hard to simulate drone behavior, so assume chance to hit is 1 for mobile drones diff --git a/graphs/data/fitDamageStats/calc/projected.py b/graphs/data/fitDamageStats/calc/projected.py index fce671f67..be50fe061 100644 --- a/graphs/data/fitDamageStats/calc/projected.py +++ b/graphs/data/fitDamageStats/calc/projected.py @@ -94,7 +94,11 @@ def getTackledSpeed(src, tgt, currentUntackledSpeed, srcScramRange, tgtScrammabl mobileWebs = [] mobileWebs.extend(webFighters) # Drones have range limit - if distance is None or distance <= src.item.extraAttributes['droneControlRange']: + if ( + distance is None or + GraphSettings.getInstance().get('ignoreDCR') or + distance <= src.item.extraAttributes['droneControlRange'] + ): mobileWebs.extend(webDrones) atkRadius = src.getRadius() # As mobile webs either follow the target or stick to the attacking ship, @@ -155,7 +159,11 @@ def getSigRadiusMult(src, tgt, tgtSpeed, srcScramRange, tgtScrammables, tpMods, mobileTps = [] mobileTps.extend(tpFighters) # Drones have range limit - if distance is None or distance <= src.item.extraAttributes['droneControlRange']: + if ( + distance is None or + GraphSettings.getInstance().get('ignoreDCR') or + distance <= src.item.extraAttributes['droneControlRange'] + ): mobileTps.extend(tpDrones) droneOpt = GraphSettings.getInstance().get('mobileDroneMode') atkRadius = src.getRadius() diff --git a/graphs/data/fitEwarStats/getter.py b/graphs/data/fitEwarStats/getter.py index cbc820b86..ea850437b 100644 --- a/graphs/data/fitEwarStats/getter.py +++ b/graphs/data/fitEwarStats/getter.py @@ -22,6 +22,7 @@ import math from graphs.calc import calculateMultiplier, calculateRangeFactor from graphs.data.base import SmoothPointGetter +from service.settings import GraphSettings class Distance2NeutingStrGetter(SmoothPointGetter): @@ -51,7 +52,8 @@ class Distance2NeutingStrGetter(SmoothPointGetter): if 'entityEnergyNeutralizerFalloff' in drone.item.effects: neuts.extend(drone.amountActive * (( drone.getModifiedItemAttr('energyNeutralizerAmount') / (drone.getModifiedItemAttr('energyNeutralizerDuration') / 1000) * resonance, - src.item.extraAttributes['droneControlRange'], 0),)) + math.inf if GraphSettings.getInstance().get('ignoreDCR') else src.item.extraAttributes['droneControlRange'], + 0),)) for fighter, ability in src.item.activeFighterAbilityIter(): if ability.effect.name == 'fighterAbilityEnergyNeutralizer': nps = fighter.getModifiedItemAttr('fighterAbilityEnergyNeutralizerAmount') / (ability.cycleTime / 1000) @@ -94,7 +96,8 @@ class Distance2WebbingStrGetter(SmoothPointGetter): if 'remoteWebifierEntity' in drone.item.effects: webs.extend(drone.amountActive * (( drone.getModifiedItemAttr('speedFactor') * resonance, - src.item.extraAttributes['droneControlRange'], 0, 'default'),)) + math.inf if GraphSettings.getInstance().get('ignoreDCR') else src.item.extraAttributes['droneControlRange'], + 0, 'default'),)) for fighter, ability in src.item.activeFighterAbilityIter(): if ability.effect.name == 'fighterAbilityStasisWebifier': webs.append(( @@ -139,7 +142,8 @@ class Distance2EcmStrMaxGetter(SmoothPointGetter): if 'entityECMFalloff' in drone.item.effects: ecms.extend(drone.amountActive * (( max(drone.getModifiedItemAttr(a) for a in self.ECM_ATTRS_GENERAL) * resonance, - src.item.extraAttributes['droneControlRange'], 0),)) + math.inf if GraphSettings.getInstance().get('ignoreDCR') else src.item.extraAttributes['droneControlRange'], + 0),)) for fighter, ability in src.item.activeFighterAbilityIter(): if ability.effect.name == 'fighterAbilityECM': ecms.append(( @@ -178,7 +182,8 @@ class Distance2DampStrLockRangeGetter(SmoothPointGetter): if 'remoteSensorDampEntity' in drone.item.effects: damps.extend(drone.amountActive * (( drone.getModifiedItemAttr('maxTargetRangeBonus') * resonance, - src.item.extraAttributes['droneControlRange'], 0, 'default'),)) + math.inf if GraphSettings.getInstance().get('ignoreDCR') else src.item.extraAttributes['droneControlRange'], + 0, 'default'),)) return {'damps': damps} def _calculatePoint(self, x, miscParams, src, tgt, commonData): @@ -215,7 +220,8 @@ class Distance2TdStrOptimalGetter(SmoothPointGetter): if 'npcEntityWeaponDisruptor' in drone.item.effects: tds.extend(drone.amountActive * (( drone.getModifiedItemAttr('maxRangeBonus') * resonance, - src.item.extraAttributes['droneControlRange'], 0, 'default'),)) + math.inf if GraphSettings.getInstance().get('ignoreDCR') else src.item.extraAttributes['droneControlRange'], + 0, 'default'),)) return {'tds': tds} def _calculatePoint(self, x, miscParams, src, tgt, commonData): @@ -291,7 +297,8 @@ class Distance2TpStrGetter(SmoothPointGetter): if 'remoteTargetPaintEntity' in drone.item.effects: tps.extend(drone.amountActive * (( drone.getModifiedItemAttr('signatureRadiusBonus') * resonance, - src.item.extraAttributes['droneControlRange'], 0, 'default'),)) + math.inf if GraphSettings.getInstance().get('ignoreDCR') else src.item.extraAttributes['droneControlRange'], + 0, 'default'),)) return {'tps': tps} def _calculatePoint(self, x, miscParams, src, tgt, commonData): diff --git a/graphs/data/fitRemoteReps/calc.py b/graphs/data/fitRemoteReps/calc.py index 74350dc55..57b018323 100644 --- a/graphs/data/fitRemoteReps/calc.py +++ b/graphs/data/fitRemoteReps/calc.py @@ -20,6 +20,7 @@ from eos.utils.float import floatUnerr from graphs.calc import calculateRangeFactor +from service.settings import GraphSettings def getApplicationPerKey(src, distance): @@ -34,7 +35,14 @@ def getApplicationPerKey(src, distance): for drone in src.item.activeDronesIter(): if not drone.isRemoteRepping(): continue - applicationMap[drone] = 1 if distance is None or distance <= src.item.extraAttributes['droneControlRange'] else 0 + if ( + distance is None or + GraphSettings.getInstance().get('ignoreDCR') or + distance <= src.item.extraAttributes['droneControlRange'] + ): + applicationMap[drone] = 1 + else: + applicationMap[drone] = 0 # Ensure consistent results - round off a little to avoid float errors for k, v in applicationMap.items(): applicationMap[k] = floatUnerr(v) diff --git a/gui/builtinContextMenus/__init__.py b/gui/builtinContextMenus/__init__.py index 8b2a93e3b..43b081a7e 100644 --- a/gui/builtinContextMenus/__init__.py +++ b/gui/builtinContextMenus/__init__.py @@ -46,6 +46,7 @@ from gui.builtinContextMenus.targetProfile import switcher # Graph extra options from gui.builtinContextMenus import graphDmgIgnoreResists from gui.builtinContextMenus import graphDmgApplyProjected +from gui.builtinContextMenus import graphDroneControlRange from gui.builtinContextMenus import graphDmgDroneMode # Additions panel menus from gui.builtinContextMenus import additionsExportSelection diff --git a/gui/builtinContextMenus/graphDroneControlRange.py b/gui/builtinContextMenus/graphDroneControlRange.py new file mode 100644 index 000000000..203e05a14 --- /dev/null +++ b/gui/builtinContextMenus/graphDroneControlRange.py @@ -0,0 +1,30 @@ +# noinspection PyPackageRequirements +import wx + +import gui.globalEvents as GE +import gui.mainFrame +from gui.contextMenu import ContextMenuUnconditional +from service.settings import GraphSettings + + +class GraphIgnoreDcrMenu(ContextMenuUnconditional): + + def __init__(self): + self.mainFrame = gui.mainFrame.MainFrame.getInstance() + self.settings = GraphSettings.getInstance() + + def display(self, callingWindow, srcContext): + return srcContext in ('dmgStatsGraph', 'remoteRepsGraph', 'ewarStatsGraph') + + def getText(self, callingWindow, itmContext): + return 'Ignore Drone Control Range' + + def activate(self, callingWindow, fullContext, i): + self.settings.set('ignoreDCR', not self.settings.get('ignoreDCR')) + wx.PostEvent(self.mainFrame, GE.GraphOptionChanged()) + + def isChecked(self, i): + return self.settings.get('ignoreDCR') + + +GraphIgnoreDcrMenu.register() diff --git a/service/settings.py b/service/settings.py index d8e5d0927..dcaa16bf6 100644 --- a/service/settings.py +++ b/service/settings.py @@ -519,6 +519,7 @@ class GraphSettings: def __init__(self): defaults = { 'mobileDroneMode': GraphDpsDroneMode.auto, + 'ignoreDCR': False, 'ignoreResists': True, 'applyProjected': True} self.settings = SettingsProvider.getInstance().getSettings('graphSettings', defaults)