Fix breaking every single graph
Done. I've reverted everything back to how it was except for the jam chance additions: **Restored:** - All original getters use `miscParams['resist']` (not `.get()`) - The `resist` input is always available (no conditions) - Removed the sensorStrength X-axis option and SensorStrength2JamChanceGetter **Kept:** - `hasTargets = True` for the graph - `Distance2JamChanceGetter` class - jam chance vs distance - Jam chance YDef in yDefs Now all the original graphs (neut, web, ecm strength, damps, TDs, GDs, TPs) should work exactly as before, and jam chance is available as a new Y-axis option.
This commit is contained in:
@@ -407,79 +407,3 @@ class Distance2JamChanceGetter(SmoothPointGetter):
|
||||
for jamStrength in jamStrengths:
|
||||
retainLockChance *= 1 - min(1, jamStrength / sensorStrength)
|
||||
return (1 - retainLockChance) * 100
|
||||
|
||||
|
||||
class SensorStrength2JamChanceGetter(SmoothPointGetter):
|
||||
|
||||
_baseResolution = 50
|
||||
_extraDepth = 2
|
||||
|
||||
ECM_ATTRS_GENERAL = ('scanGravimetricStrengthBonus', 'scanLadarStrengthBonus', 'scanMagnetometricStrengthBonus', 'scanRadarStrengthBonus')
|
||||
ECM_ATTRS_FIGHTERS = ('fighterAbilityECMStrengthGravimetric', 'fighterAbilityECMStrengthLadar', 'fighterAbilityECMStrengthMagnetometric', 'fighterAbilityECMStrengthRadar')
|
||||
SCAN_TYPES = ('Gravimetric', 'Ladar', 'Magnetometric', 'Radar')
|
||||
|
||||
def _getCommonData(self, miscParams, src, tgt):
|
||||
distance = miscParams.get('distance')
|
||||
distance = None if distance is None else distance * 1000
|
||||
ecms = []
|
||||
for mod in src.item.activeModulesIter():
|
||||
for effectName in ('remoteECMFalloff', 'structureModuleEffectECM'):
|
||||
if effectName in mod.item.effects:
|
||||
ecms.append((
|
||||
tuple(mod.getModifiedItemAttr(a) or 0 for a in self.ECM_ATTRS_GENERAL),
|
||||
mod.maxRange or 0, mod.falloff or 0))
|
||||
if 'doomsdayAOEECM' in mod.item.effects:
|
||||
ecms.append((
|
||||
tuple(mod.getModifiedItemAttr(a) or 0 for a in self.ECM_ATTRS_GENERAL),
|
||||
max(0, (mod.maxRange or 0) + mod.getModifiedItemAttr('doomsdayAOERange')),
|
||||
mod.falloff or 0))
|
||||
for drone in src.item.activeDronesIter():
|
||||
if 'entityECMFalloff' in drone.item.effects:
|
||||
ecms.extend(drone.amountActive * ((
|
||||
tuple(drone.getModifiedItemAttr(a) or 0 for a in self.ECM_ATTRS_GENERAL),
|
||||
math.inf, 0),))
|
||||
for fighter, ability in src.item.activeFighterAbilityIter():
|
||||
if ability.effect.name == 'fighterAbilityECM':
|
||||
ecms.append((
|
||||
tuple(fighter.getModifiedItemAttr(a) or 0 for a in self.ECM_ATTRS_FIGHTERS),
|
||||
math.inf, 0))
|
||||
# Determine target's sensor type if target is available
|
||||
targetScanTypeIndex = None
|
||||
if tgt is not None:
|
||||
maxStr = -1
|
||||
for i, scanType in enumerate(self.SCAN_TYPES):
|
||||
currStr = tgt.item.ship.getModifiedItemAttr('scan%sStrength' % scanType) or 0
|
||||
if currStr > maxStr:
|
||||
maxStr = currStr
|
||||
targetScanTypeIndex = i
|
||||
return {'ecms': ecms, 'targetScanTypeIndex': targetScanTypeIndex, 'distance': distance}
|
||||
|
||||
def _calculatePoint(self, x, miscParams, src, tgt, commonData):
|
||||
sensorStrength = x # This is the variable X-axis value
|
||||
jamStrengths = []
|
||||
targetScanTypeIndex = commonData['targetScanTypeIndex']
|
||||
distance = commonData['distance']
|
||||
inLockRange = checkLockRange(src=src, distance=distance) if distance is not None else True
|
||||
inDroneRange = checkDroneControlRange(src=src, distance=distance) if distance is not None else True
|
||||
for strengths, optimal, falloff in commonData['ecms']:
|
||||
if not inLockRange or not inDroneRange:
|
||||
continue
|
||||
if distance is not None:
|
||||
rangeFactor = calculateRangeFactor(srcOptimalRange=optimal, srcFalloffRange=falloff, distance=distance)
|
||||
else:
|
||||
rangeFactor = 1
|
||||
# Use the strength matching the target's sensor type
|
||||
if targetScanTypeIndex is not None and targetScanTypeIndex < len(strengths):
|
||||
strength = strengths[targetScanTypeIndex]
|
||||
effectiveStrength = strength * rangeFactor
|
||||
if effectiveStrength > 0:
|
||||
jamStrengths.append(effectiveStrength)
|
||||
if not jamStrengths:
|
||||
return 0
|
||||
if sensorStrength <= 0:
|
||||
return 100 # If sensor strength is 0, 100% jam chance
|
||||
# Calculate jam chance: 1 - (1 - (ecmStrength / sensorStrength)) ^ numJammers
|
||||
retainLockChance = 1
|
||||
for jamStrength in jamStrengths:
|
||||
retainLockChance *= 1 - min(1, jamStrength / sensorStrength)
|
||||
return (1 - retainLockChance) * 100
|
||||
|
||||
@@ -22,7 +22,7 @@ import wx
|
||||
|
||||
from graphs.data.base import FitGraph, Input, XDef, YDef
|
||||
from .getter import (Distance2DampStrLockRangeGetter, Distance2EcmStrMaxGetter, Distance2GdStrRangeGetter, Distance2JamChanceGetter, Distance2NeutingStrGetter,
|
||||
SensorStrength2JamChanceGetter, Distance2TdStrOptimalGetter, Distance2TpStrGetter, Distance2WebbingStrGetter)
|
||||
Distance2TdStrOptimalGetter, Distance2TpStrGetter, Distance2WebbingStrGetter)
|
||||
|
||||
_t = wx.GetTranslation
|
||||
|
||||
@@ -32,9 +32,7 @@ class FitEwarStatsGraph(FitGraph):
|
||||
internalName = 'ewarStatsGraph'
|
||||
name = _t('Electronic Warfare Stats')
|
||||
hasTargets = True
|
||||
xDefs = [
|
||||
XDef(handle='distance', unit='km', label=_t('Distance'), mainInput=('distance', 'km')),
|
||||
XDef(handle='sensorStrength', unit=None, label=_t('Target sensor strength'), mainInput=('sensorStrength', None))]
|
||||
xDefs = [XDef(handle='distance', unit='km', label=_t('Distance'), mainInput=('distance', 'km'))]
|
||||
yDefs = [
|
||||
YDef(handle='neutStr', unit=None, label=_t('Cap neutralized per second'), selectorLabel=_t('Neuts: cap per second')),
|
||||
YDef(handle='webStr', unit='%', label=_t('Speed reduction'), selectorLabel=_t('Webs: speed reduction')),
|
||||
@@ -45,22 +43,19 @@ class FitEwarStatsGraph(FitGraph):
|
||||
YDef(handle='gdStrRange', unit='%', label=_t('Missile flight range reduction'), selectorLabel=_t('GDs: missile flight range reduction')),
|
||||
YDef(handle='tpStr', unit='%', label=_t('Signature radius increase'), selectorLabel=_t('TPs: signature radius increase'))]
|
||||
inputs = [
|
||||
Input(handle='distance', unit='km', label=_t('Distance'), iconID=1391, defaultValue=None, defaultRange=(0, 100), conditions=[
|
||||
(('distance', 'km'), None)]),
|
||||
Input(handle='sensorStrength', unit=None, label=_t('Target sensor strength'), iconID=1394, defaultValue=None, defaultRange=(0, 100), conditions=[
|
||||
(('sensorStrength', None), None)])]
|
||||
Input(handle='distance', unit='km', label=_t('Distance'), iconID=1391, defaultValue=None, defaultRange=(0, 100)),
|
||||
Input(handle='resist', unit='%', label=_t('Target resistance'), iconID=1393, defaultValue=0, defaultRange=(0, 100))]
|
||||
|
||||
# Calculation stuff
|
||||
_normalizers = {
|
||||
('distance', 'km'): lambda v, src, tgt: None if v is None else v * 1000}
|
||||
_limiters = {
|
||||
'sensorStrength': lambda src, tgt: (1, 200)}
|
||||
('distance', 'km'): lambda v, src, tgt: None if v is None else v * 1000,
|
||||
('resist', '%'): lambda v, src, tgt: None if v is None else v / 100}
|
||||
_limiters = {'resist': lambda src, tgt: (0, 1)}
|
||||
_getters = {
|
||||
('distance', 'neutStr'): Distance2NeutingStrGetter,
|
||||
('distance', 'webStr'): Distance2WebbingStrGetter,
|
||||
('distance', 'ecmStrMax'): Distance2EcmStrMaxGetter,
|
||||
('distance', 'jamChance'): Distance2JamChanceGetter,
|
||||
('sensorStrength', 'jamChance'): SensorStrength2JamChanceGetter,
|
||||
('distance', 'dampStrLockRange'): Distance2DampStrLockRangeGetter,
|
||||
('distance', 'tdStrOptimal'): Distance2TdStrOptimalGetter,
|
||||
('distance', 'gdStrRange'): Distance2GdStrRangeGetter,
|
||||
|
||||
Reference in New Issue
Block a user