Add a jam chance ewar graph
This commit is contained in:
@@ -332,3 +332,79 @@ class Distance2TpStrGetter(SmoothPointGetter):
|
||||
strMult = calculateMultiplier(strMults)
|
||||
strength = (strMult - 1) * 100
|
||||
return strength
|
||||
|
||||
|
||||
class Distance2JamChanceGetter(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):
|
||||
resonance = 1 - (miscParams['resist'] or 0)
|
||||
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, True, False))
|
||||
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, False, False))
|
||||
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, True, True),))
|
||||
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, True, False))
|
||||
# Determine target's strongest 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}
|
||||
|
||||
def _calculatePoint(self, x, miscParams, src, tgt, commonData):
|
||||
distance = x
|
||||
inLockRange = checkLockRange(src=src, distance=distance)
|
||||
inDroneRange = checkDroneControlRange(src=src, distance=distance)
|
||||
jamStrengths = []
|
||||
targetScanTypeIndex = commonData['targetScanTypeIndex']
|
||||
for strengths, optimal, falloff, needsLock, needsDcr in commonData['ecms']:
|
||||
if (needsLock and not inLockRange) or (needsDcr and not inDroneRange):
|
||||
continue
|
||||
rangeFactor = calculateRangeFactor(srcOptimalRange=optimal, srcFalloffRange=falloff, distance=distance)
|
||||
# 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
|
||||
# Get sensor strength from target
|
||||
if tgt is None:
|
||||
return 0
|
||||
sensorStrength = max([tgt.item.ship.getModifiedItemAttr('scan%sStrength' % scanType)
|
||||
for scanType in self.SCAN_TYPES]) or 0
|
||||
if sensorStrength <= 0:
|
||||
return 100 # If target has no sensor strength, 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
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
import wx
|
||||
|
||||
from graphs.data.base import FitGraph, Input, XDef, YDef
|
||||
from .getter import (Distance2DampStrLockRangeGetter, Distance2EcmStrMaxGetter, Distance2GdStrRangeGetter, Distance2NeutingStrGetter, Distance2TdStrOptimalGetter,
|
||||
Distance2TpStrGetter, Distance2WebbingStrGetter)
|
||||
from .getter import (Distance2DampStrLockRangeGetter, Distance2EcmStrMaxGetter, Distance2GdStrRangeGetter, Distance2JamChanceGetter, Distance2NeutingStrGetter,
|
||||
Distance2TdStrOptimalGetter, Distance2TpStrGetter, Distance2WebbingStrGetter)
|
||||
|
||||
_t = wx.GetTranslation
|
||||
|
||||
@@ -31,11 +31,13 @@ class FitEwarStatsGraph(FitGraph):
|
||||
# UI stuff
|
||||
internalName = 'ewarStatsGraph'
|
||||
name = _t('Electronic Warfare Stats')
|
||||
hasTargets = True
|
||||
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')),
|
||||
YDef(handle='ecmStrMax', unit=None, label=_t('Combined ECM strength'), selectorLabel=_t('ECM: combined strength')),
|
||||
YDef(handle='jamChance', unit='%', label=_t('Jam chance'), selectorLabel=_t('ECM: jam chance')),
|
||||
YDef(handle='dampStrLockRange', unit='%', label=_t('Lock range reduction'), selectorLabel=_t('Damps: lock range reduction')),
|
||||
YDef(handle='tdStrOptimal', unit='%', label=_t('Turret optimal range reduction'), selectorLabel=_t('TDs: turret optimal range reduction')),
|
||||
YDef(handle='gdStrRange', unit='%', label=_t('Missile flight range reduction'), selectorLabel=_t('GDs: missile flight range reduction')),
|
||||
@@ -53,6 +55,7 @@ class FitEwarStatsGraph(FitGraph):
|
||||
('distance', 'neutStr'): Distance2NeutingStrGetter,
|
||||
('distance', 'webStr'): Distance2WebbingStrGetter,
|
||||
('distance', 'ecmStrMax'): Distance2EcmStrMaxGetter,
|
||||
('distance', 'jamChance'): Distance2JamChanceGetter,
|
||||
('distance', 'dampStrLockRange'): Distance2DampStrLockRangeGetter,
|
||||
('distance', 'tdStrOptimal'): Distance2TdStrOptimalGetter,
|
||||
('distance', 'gdStrRange'): Distance2GdStrRangeGetter,
|
||||
|
||||
Reference in New Issue
Block a user