Process targets in DPS calculation code
This commit is contained in:
@@ -21,6 +21,8 @@
|
||||
from abc import ABCMeta, abstractmethod
|
||||
from collections import OrderedDict, namedtuple
|
||||
|
||||
from eos.saveddata.fit import Fit
|
||||
from eos.saveddata.targetProfile import TargetProfile
|
||||
from service.const import GraphCacheCleanupReason
|
||||
|
||||
|
||||
@@ -94,7 +96,13 @@ class FitGraph(metaclass=ABCMeta):
|
||||
hasTargets = False
|
||||
|
||||
def getPlotPoints(self, mainInput, miscInputs, xSpec, ySpec, fit, tgt=None):
|
||||
cacheKey = (fit.ID, None, tgt.ID)
|
||||
if isinstance(tgt, Fit):
|
||||
tgtType = 'fit'
|
||||
elif isinstance(tgt, TargetProfile):
|
||||
tgtType = 'profile'
|
||||
else:
|
||||
tgtType = None
|
||||
cacheKey = (fit.ID, tgtType, getattr(tgt, 'ID', None))
|
||||
try:
|
||||
plotData = self._plotCache[cacheKey][(ySpec, xSpec)]
|
||||
except KeyError:
|
||||
@@ -111,7 +119,7 @@ class FitGraph(metaclass=ABCMeta):
|
||||
cacheFitID, cacheTgtType, cacheTgtID = cacheKey
|
||||
if extraData == cacheFitID:
|
||||
plotKeysToClear.add(cacheKey)
|
||||
elif extraData == cacheTgtID:
|
||||
elif cacheTgtType == 'fit' and extraData == cacheTgtID:
|
||||
plotKeysToClear.add(cacheKey)
|
||||
for cacheKey in plotKeysToClear:
|
||||
del self._plotCache[cacheKey]
|
||||
|
||||
@@ -21,8 +21,10 @@
|
||||
import math
|
||||
from functools import lru_cache
|
||||
|
||||
from eos.saveddata.fit import Fit
|
||||
from service.const import GraphDpsDroneMode
|
||||
from service.settings import GraphSettings
|
||||
from .helper import getTgtMaxVelocity, getTgtSigRadius, getTgtRadius
|
||||
|
||||
|
||||
def getTurretMult(mod, fit, tgt, atkSpeed, atkAngle, distance, tgtSpeed, tgtAngle, tgtSigRadius):
|
||||
@@ -37,7 +39,7 @@ def getTurretMult(mod, fit, tgt, atkSpeed, atkAngle, distance, tgtSpeed, tgtAngl
|
||||
distance=distance,
|
||||
tgtSpeed=tgtSpeed,
|
||||
tgtAngle=tgtAngle,
|
||||
tgtRadius=tgt.ship.getModifiedItemAttr('radius'),
|
||||
tgtRadius=getTgtRadius(tgt),
|
||||
tgtSigRadius=tgtSigRadius)
|
||||
mult = _calcTurretMult(cth)
|
||||
return mult
|
||||
@@ -74,7 +76,8 @@ def getDoomsdayMult(mod, tgt, distance, tgtSigRadius):
|
||||
return 0
|
||||
# Single-target titan DDs are vs capitals only
|
||||
if {'superWeaponAmarr', 'superWeaponCaldari', 'superWeaponGallente', 'superWeaponMinmatar'}.intersection(mod.item.effects):
|
||||
if not tgt.ship.item.requiresSkill('Capital Ships'):
|
||||
# Disallow only against subcap fits, allow against cap fits and tgt profiles
|
||||
if isinstance(tgt, Fit) and not tgt.ship.item.requiresSkill('Capital Ships'):
|
||||
return 0
|
||||
damageSig = mod.getModifiedItemAttr('doomsdayDamageRadius') or mod.getModifiedItemAttr('signatureRadius')
|
||||
if not damageSig:
|
||||
@@ -88,7 +91,7 @@ def getBombMult(mod, fit, tgt, distance, tgtSigRadius):
|
||||
return 0
|
||||
blastRadius = mod.getModifiedChargeAttr('explosionRange')
|
||||
atkRadius = fit.ship.getModifiedItemAttr('radius')
|
||||
tgtRadius = tgt.ship.getModifiedItemAttr('radius')
|
||||
tgtRadius = getTgtRadius(tgt)
|
||||
# Bomb starts in the center of the ship
|
||||
# Also here we assume that it affects target as long as blast
|
||||
# touches its surface, not center - I did not check this
|
||||
@@ -144,7 +147,7 @@ def getDroneMult(drone, fit, tgt, atkSpeed, atkAngle, distance, tgtSpeed, tgtAng
|
||||
distance=distance + fit.ship.getModifiedItemAttr('radius') - droneRadius,
|
||||
tgtSpeed=tgtSpeed,
|
||||
tgtAngle=tgtAngle,
|
||||
tgtRadius=tgt.ship.getModifiedItemAttr('radius'),
|
||||
tgtRadius=getTgtRadius(tgt),
|
||||
tgtSigRadius=tgtSigRadius)
|
||||
mult = _calcTurretMult(cth)
|
||||
return mult
|
||||
@@ -187,9 +190,10 @@ def getFighterAbilityMult(fighter, ability, fit, distance, tgtSpeed, tgtSigRadiu
|
||||
|
||||
|
||||
def getWebbedSpeed(fit, tgt, currentUnwebbedSpeed, webMods, webDrones, webFighters, distance):
|
||||
if tgt.ship.getModifiedItemAttr('disallowOffensiveModifiers'):
|
||||
# Can slow down non-immune fits and target profiles
|
||||
if isinstance(tgt, Fit) and tgt.ship.getModifiedItemAttr('disallowOffensiveModifiers'):
|
||||
return currentUnwebbedSpeed
|
||||
maxUnwebbedSpeed = tgt.ship.getModifiedItemAttr('maxVelocity')
|
||||
maxUnwebbedSpeed = getTgtMaxVelocity(tgt)
|
||||
try:
|
||||
speedRatio = currentUnwebbedSpeed / maxUnwebbedSpeed
|
||||
except ZeroDivisionError:
|
||||
@@ -204,7 +208,7 @@ def getWebbedSpeed(fit, tgt, currentUnwebbedSpeed, webMods, webDrones, webFighte
|
||||
distance=distance)
|
||||
if appliedBoost:
|
||||
appliedMultipliers.setdefault(wData.stackingGroup, []).append((1 + appliedBoost / 100, wData.resAttrID))
|
||||
maxWebbedSpeed = tgt.ship.getModifiedItemAttrWithExtraMods('maxVelocity', extraMultipliers=appliedMultipliers)
|
||||
maxWebbedSpeed = getTgtMaxVelocity(tgt, extraMultipliers=appliedMultipliers)
|
||||
currentWebbedSpeed = maxWebbedSpeed * speedRatio
|
||||
# Drones and fighters
|
||||
mobileWebs = []
|
||||
@@ -220,7 +224,7 @@ def getWebbedSpeed(fit, 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.ship.getModifiedItemAttrWithExtraMods('maxVelocity', extraMultipliers=appliedMultipliers)
|
||||
maxWebbedSpeed = getTgtMaxVelocity(tgt, extraMultipliers=appliedMultipliers)
|
||||
currentWebbedSpeed = maxWebbedSpeed * speedRatio
|
||||
# Apply remaining webs, from fastest to slowest
|
||||
droneOpt = GraphSettings.getInstance().get('mobileDroneMode')
|
||||
@@ -240,15 +244,16 @@ def getWebbedSpeed(fit, tgt, currentUnwebbedSpeed, webMods, webDrones, webFighte
|
||||
distance=distance + atkRadius - mwData.radius)
|
||||
appliedMultipliers.setdefault(mwData.stackingGroup, []).append((1 + appliedMwBoost / 100, mwData.resAttrID))
|
||||
mobileWebs.remove(mwData)
|
||||
maxWebbedSpeed = tgt.ship.getModifiedItemAttrWithExtraMods('maxVelocity', extraMultipliers=appliedMultipliers)
|
||||
maxWebbedSpeed = getTgtMaxVelocity(tgt, extraMultipliers=appliedMultipliers)
|
||||
currentWebbedSpeed = maxWebbedSpeed * speedRatio
|
||||
return currentWebbedSpeed
|
||||
|
||||
|
||||
def getTpMult(fit, tgt, tgtSpeed, tpMods, tpDrones, tpFighters, distance):
|
||||
if tgt.ship.getModifiedItemAttr('disallowOffensiveModifiers'):
|
||||
# Can blow non-immune fits and target profiles
|
||||
if isinstance(tgt, Fit) and tgt.ship.getModifiedItemAttr('disallowOffensiveModifiers'):
|
||||
return 1
|
||||
untpedSig = tgt.ship.getModifiedItemAttr('signatureRadius')
|
||||
untpedSig = getTgtSigRadius(tgt)
|
||||
# Modules
|
||||
appliedMultipliers = {}
|
||||
for tpData in tpMods:
|
||||
@@ -277,7 +282,7 @@ def getTpMult(fit, tgt, tgtSpeed, tpMods, tpDrones, tpFighters, distance):
|
||||
atkFalloffRange=mtpData.falloff,
|
||||
distance=distance + atkRadius - mtpData.radius)
|
||||
appliedMultipliers.setdefault(mtpData.stackingGroup, []).append((1 + appliedMtpBoost / 100, mtpData.resAttrID))
|
||||
tpedSig = tgt.ship.getModifiedItemAttrWithExtraMods('signatureRadius', extraMultipliers=appliedMultipliers)
|
||||
tpedSig = getTgtSigRadius(tgt, extraMultipliers=appliedMultipliers)
|
||||
mult = tpedSig / untpedSig
|
||||
return mult
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ from .calc import (
|
||||
getTurretMult, getLauncherMult, getDroneMult, getFighterAbilityMult,
|
||||
getSmartbombMult, getDoomsdayMult, getBombMult, getGuidedBombMult,
|
||||
getWebbedSpeed, getTpMult)
|
||||
from .helper import getTgtMaxVelocity, getTgtSigRadius
|
||||
from .projectedCache import ProjectedDataCache
|
||||
from .timeCache import TimeCache
|
||||
|
||||
@@ -82,14 +83,14 @@ class FitDamageStatsGraph(FitGraph):
|
||||
_normalizers = {
|
||||
('distance', 'km'): lambda v, fit, tgt: v * 1000,
|
||||
('atkSpeed', '%'): lambda v, fit, tgt: v / 100 * fit.ship.getModifiedItemAttr('maxVelocity'),
|
||||
('tgtSpeed', '%'): lambda v, fit, tgt: v / 100 * tgt.ship.getModifiedItemAttr('maxVelocity'),
|
||||
('tgtSigRad', '%'): lambda v, fit, tgt: v / 100 * tgt.ship.getModifiedItemAttr('signatureRadius')}
|
||||
('tgtSpeed', '%'): lambda v, fit, tgt: v / 100 * getTgtMaxVelocity(tgt),
|
||||
('tgtSigRad', '%'): lambda v, fit, tgt: v / 100 * getTgtSigRadius(tgt)}
|
||||
_limiters = {
|
||||
'time': lambda fit, tgt: (0, 2500)}
|
||||
_denormalizers = {
|
||||
('distance', 'km'): lambda v, fit, tgt: v / 1000,
|
||||
('tgtSpeed', '%'): lambda v, fit, tgt: v * 100 / tgt.ship.getModifiedItemAttr('maxVelocity'),
|
||||
('tgtSigRad', '%'): lambda v, fit, tgt: v * 100 / tgt.ship.getModifiedItemAttr('signatureRadius')}
|
||||
('tgtSpeed', '%'): lambda v, fit, tgt: v * 100 / getTgtMaxVelocity(tgt),
|
||||
('tgtSigRad', '%'): lambda v, fit, tgt: v * 100 / getTgtSigRadius(tgt)}
|
||||
|
||||
def _distance2dps(self, mainInput, miscInputs, fit, tgt):
|
||||
return self._xDistanceGetter(
|
||||
@@ -178,7 +179,7 @@ class FitDamageStatsGraph(FitGraph):
|
||||
# Go through distances and calculate distance-dependent data
|
||||
for distance in self._iterLinear(mainInput[1]):
|
||||
tgtSpeed = miscInputMap['tgtSpeed']
|
||||
tgtSigRadius = tgt.ship.getModifiedItemAttr('signatureRadius')
|
||||
tgtSigRadius = getTgtSigRadius(tgt)
|
||||
if applyProjected:
|
||||
webMods, tpMods = self._projectedCache.getProjModData(fit)
|
||||
webDrones, tpDrones = self._projectedCache.getProjDroneData(fit)
|
||||
@@ -220,7 +221,7 @@ class FitDamageStatsGraph(FitGraph):
|
||||
# Process inputs into more convenient form
|
||||
miscInputMap = dict(miscInputs)
|
||||
tgtSpeed = miscInputMap['tgtSpeed']
|
||||
tgtSigRadius = tgt.ship.getModifiedItemAttr('signatureRadius')
|
||||
tgtSigRadius = getTgtSigRadius(tgt)
|
||||
if GraphSettings.getInstance().get('applyProjected'):
|
||||
webMods, tpMods = self._projectedCache.getProjModData(fit)
|
||||
webDrones, tpDrones = self._projectedCache.getProjDroneData(fit)
|
||||
@@ -308,7 +309,7 @@ class FitDamageStatsGraph(FitGraph):
|
||||
# Get separate internal speed to calculate proper application, for graph
|
||||
# itself we still want to show pre-modification speed on X axis
|
||||
tgtSpeedInternal = tgtSpeed
|
||||
tgtSigRadius = tgt.ship.getModifiedItemAttr('signatureRadius')
|
||||
tgtSigRadius = getTgtSigRadius(tgt)
|
||||
if applyProjected:
|
||||
webMods, tpMods = self._projectedCache.getProjModData(fit)
|
||||
webDrones, tpDrones = self._projectedCache.getProjDroneData(fit)
|
||||
|
||||
52
gui/builtinGraphs/fitDamageStats/helper.py
Normal file
52
gui/builtinGraphs/fitDamageStats/helper.py
Normal file
@@ -0,0 +1,52 @@
|
||||
# =============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of pyfa.
|
||||
#
|
||||
# pyfa is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# pyfa is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
|
||||
# =============================================================================
|
||||
|
||||
|
||||
from eos.saveddata.fit import Fit
|
||||
from eos.saveddata.targetProfile import TargetProfile
|
||||
|
||||
|
||||
def getTgtMaxVelocity(tgt, extraMultipliers=None):
|
||||
if isinstance(tgt, Fit):
|
||||
if extraMultipliers:
|
||||
return tgt.ship.getModifiedItemAttrWithExtraMods('maxVelocity', extraMultipliers=extraMultipliers)
|
||||
else:
|
||||
return tgt.ship.getModifiedItemAttr('maxVelocity')
|
||||
elif isinstance(tgt, TargetProfile):
|
||||
return tgt.maxVelocity
|
||||
return None
|
||||
|
||||
|
||||
def getTgtSigRadius(tgt, extraMultipliers=None):
|
||||
if isinstance(tgt, Fit):
|
||||
if extraMultipliers:
|
||||
return tgt.ship.getModifiedItemAttrWithExtraMods('signatureRadius', extraMultipliers=extraMultipliers)
|
||||
else:
|
||||
return tgt.ship.getModifiedItemAttr('signatureRadius')
|
||||
elif isinstance(tgt, TargetProfile):
|
||||
return tgt.signatureRadius
|
||||
return None
|
||||
|
||||
|
||||
def getTgtRadius(tgt):
|
||||
if isinstance(tgt, Fit):
|
||||
return tgt.ship.getModifiedItemAttr('radius')
|
||||
elif isinstance(tgt, TargetProfile):
|
||||
return tgt.radius
|
||||
return None
|
||||
@@ -205,9 +205,11 @@ class TargetList(BaseList):
|
||||
super().__init__(graphFrame, parent)
|
||||
self.profiles = []
|
||||
self.profiles.append(TargetProfile.getIdeal())
|
||||
stuff = self.fits + self.profiles
|
||||
self.update(stuff)
|
||||
self.update(self.targets)
|
||||
|
||||
def refreshView(self):
|
||||
stuff = self.fits + self.profiles
|
||||
self.refresh(stuff)
|
||||
self.refresh(self.targets)
|
||||
|
||||
@property
|
||||
def targets(self):
|
||||
return self.fits + self.profiles
|
||||
|
||||
@@ -318,7 +318,7 @@ class GraphControlPanel(wx.Panel):
|
||||
|
||||
@property
|
||||
def targets(self):
|
||||
return self.targetList.fits
|
||||
return self.targetList.targets
|
||||
|
||||
def unbindExternalEvents(self):
|
||||
self.fitList.unbindExternalEvents()
|
||||
|
||||
Reference in New Issue
Block a user