Expose breacher DPS and volley to stats
This commit is contained in:
@@ -29,7 +29,7 @@ from eos.saveddata.mutatedMixin import MutatedMixin, MutaError
|
||||
from eos.saveddata.mutator import MutatorDrone
|
||||
from eos.utils.cycles import CycleInfo
|
||||
from eos.utils.default import DEFAULT
|
||||
from eos.utils.stats import DmgTypes, RRTypes
|
||||
from eos.utils.stats import BaseVolleyStats, DmgTypes, RRTypes
|
||||
|
||||
|
||||
pyfalog = Logger(__name__)
|
||||
@@ -161,20 +161,16 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut, Mu
|
||||
|
||||
def getVolleyParameters(self, targetProfile=None):
|
||||
if not self.dealsDamage or self.amountActive <= 0:
|
||||
return {0: DmgTypes(0, 0, 0, 0)}
|
||||
return {0: DmgTypes.default()}
|
||||
if self.__baseVolley is None:
|
||||
dmgGetter = self.getModifiedChargeAttr if self.hasAmmo else self.getModifiedItemAttr
|
||||
dmgMult = self.amountActive * (self.getModifiedItemAttr("damageMultiplier", 1))
|
||||
self.__baseVolley = DmgTypes(
|
||||
self.__baseVolley = BaseVolleyStats(
|
||||
em=(dmgGetter("emDamage", 0)) * dmgMult,
|
||||
thermal=(dmgGetter("thermalDamage", 0)) * dmgMult,
|
||||
kinetic=(dmgGetter("kineticDamage", 0)) * dmgMult,
|
||||
explosive=(dmgGetter("explosiveDamage", 0)) * dmgMult)
|
||||
volley = DmgTypes(
|
||||
em=self.__baseVolley.em * (1 - getattr(targetProfile, "emAmount", 0)),
|
||||
thermal=self.__baseVolley.thermal * (1 - getattr(targetProfile, "thermalAmount", 0)),
|
||||
kinetic=self.__baseVolley.kinetic * (1 - getattr(targetProfile, "kineticAmount", 0)),
|
||||
explosive=self.__baseVolley.explosive * (1 - getattr(targetProfile, "explosiveAmount", 0)))
|
||||
volley = DmgTypes.from_base_and_profile(base=self.__baseVolley, tgtProfile=targetProfile)
|
||||
return {0: volley}
|
||||
|
||||
def getVolley(self, targetProfile=None):
|
||||
@@ -183,16 +179,17 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut, Mu
|
||||
def getDps(self, targetProfile=None):
|
||||
volley = self.getVolley(targetProfile=targetProfile)
|
||||
if not volley:
|
||||
return DmgTypes(0, 0, 0, 0)
|
||||
return DmgTypes.default()
|
||||
cycleParams = self.getCycleParameters()
|
||||
if cycleParams is None:
|
||||
return DmgTypes(0, 0, 0, 0)
|
||||
return DmgTypes.default()
|
||||
dpsFactor = 1 / (cycleParams.averageTime / 1000)
|
||||
dps = DmgTypes(
|
||||
em=volley.em * dpsFactor,
|
||||
thermal=volley.thermal * dpsFactor,
|
||||
kinetic=volley.kinetic * dpsFactor,
|
||||
explosive=volley.explosive * dpsFactor)
|
||||
explosive=volley.explosive * dpsFactor,
|
||||
breacher=volley.breacher * dpsFactor)
|
||||
return dps
|
||||
|
||||
def isRemoteRepping(self, ignoreState=False):
|
||||
|
||||
@@ -206,7 +206,8 @@ class Fighter(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
em=volleyValue.em * (1 - getattr(targetProfile, "emAmount", 0)),
|
||||
thermal=volleyValue.thermal * (1 - getattr(targetProfile, "thermalAmount", 0)),
|
||||
kinetic=volleyValue.kinetic * (1 - getattr(targetProfile, "kineticAmount", 0)),
|
||||
explosive=volleyValue.explosive * (1 - getattr(targetProfile, "explosiveAmount", 0)))
|
||||
explosive=volleyValue.explosive * (1 - getattr(targetProfile, "explosiveAmount", 0)),
|
||||
breacher=volleyValue.breacher)
|
||||
return adjustedVolley
|
||||
|
||||
def getVolleyPerEffect(self, targetProfile=None):
|
||||
@@ -218,28 +219,16 @@ class Fighter(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
|
||||
def getVolley(self, targetProfile=None):
|
||||
volleyParams = self.getVolleyParametersPerEffect(targetProfile=targetProfile)
|
||||
em = 0
|
||||
therm = 0
|
||||
kin = 0
|
||||
exp = 0
|
||||
volley = DmgTypes.default()
|
||||
for volleyData in volleyParams.values():
|
||||
em += volleyData[0].em
|
||||
therm += volleyData[0].thermal
|
||||
kin += volleyData[0].kinetic
|
||||
exp += volleyData[0].explosive
|
||||
return DmgTypes(em, therm, kin, exp)
|
||||
volley += volleyData[0]
|
||||
return volley
|
||||
|
||||
def getDps(self, targetProfile=None):
|
||||
em = 0
|
||||
thermal = 0
|
||||
kinetic = 0
|
||||
explosive = 0
|
||||
for dps in self.getDpsPerEffect(targetProfile=targetProfile).values():
|
||||
em += dps.em
|
||||
thermal += dps.thermal
|
||||
kinetic += dps.kinetic
|
||||
explosive += dps.explosive
|
||||
return DmgTypes(em=em, thermal=thermal, kinetic=kinetic, explosive=explosive)
|
||||
dps = DmgTypes.default()
|
||||
for subdps in self.getDpsPerEffect(targetProfile=targetProfile).values():
|
||||
dps += subdps
|
||||
return dps
|
||||
|
||||
def getDpsPerEffect(self, targetProfile=None):
|
||||
if not self.active or self.amount <= 0:
|
||||
|
||||
@@ -116,7 +116,7 @@ class FighterAbility:
|
||||
|
||||
def getVolley(self, targetProfile=None):
|
||||
if not self.dealsDamage or not self.active:
|
||||
return DmgTypes(0, 0, 0, 0)
|
||||
return DmgTypes.default()
|
||||
if self.attrPrefix == "fighterAbilityLaunchBomb":
|
||||
em = self.fighter.getModifiedChargeAttr("emDamage", 0)
|
||||
therm = self.fighter.getModifiedChargeAttr("thermalDamage", 0)
|
||||
@@ -132,20 +132,22 @@ class FighterAbility:
|
||||
em=em * dmgMult * (1 - getattr(targetProfile, "emAmount", 0)),
|
||||
thermal=therm * dmgMult * (1 - getattr(targetProfile, "thermalAmount", 0)),
|
||||
kinetic=kin * dmgMult * (1 - getattr(targetProfile, "kineticAmount", 0)),
|
||||
explosive=exp * dmgMult * (1 - getattr(targetProfile, "explosiveAmount", 0)))
|
||||
explosive=exp * dmgMult * (1 - getattr(targetProfile, "explosiveAmount", 0)),
|
||||
breacher=0)
|
||||
return volley
|
||||
|
||||
def getDps(self, targetProfile=None, cycleTimeOverride=None):
|
||||
volley = self.getVolley(targetProfile=targetProfile)
|
||||
if not volley:
|
||||
return DmgTypes(0, 0, 0, 0)
|
||||
return DmgTypes.default()
|
||||
cycleTime = cycleTimeOverride if cycleTimeOverride is not None else self.cycleTime
|
||||
dpsFactor = 1 / (cycleTime / 1000)
|
||||
dps = DmgTypes(
|
||||
em=volley.em * dpsFactor,
|
||||
thermal=volley.thermal * dpsFactor,
|
||||
kinetic=volley.kinetic * dpsFactor,
|
||||
explosive=volley.explosive * dpsFactor)
|
||||
explosive=volley.explosive * dpsFactor,
|
||||
breacher=volley.breacher * dpsFactor)
|
||||
return dps
|
||||
|
||||
def clear(self):
|
||||
|
||||
@@ -1688,8 +1688,8 @@ class Fit:
|
||||
self.__droneWaste = droneWaste
|
||||
|
||||
def calculateWeaponDmgStats(self, spoolOptions):
|
||||
weaponVolley = DmgTypes(0, 0, 0, 0)
|
||||
weaponDps = DmgTypes(0, 0, 0, 0)
|
||||
weaponVolley = DmgTypes.default()
|
||||
weaponDps = DmgTypes.default()
|
||||
|
||||
for mod in self.modules:
|
||||
weaponVolley += mod.getVolley(spoolOptions=spoolOptions, targetProfile=self.targetProfile)
|
||||
@@ -1699,8 +1699,8 @@ class Fit:
|
||||
self.__weaponDpsMap[spoolOptions] = weaponDps
|
||||
|
||||
def calculateDroneDmgStats(self):
|
||||
droneVolley = DmgTypes(0, 0, 0, 0)
|
||||
droneDps = DmgTypes(0, 0, 0, 0)
|
||||
droneVolley = DmgTypes.default()
|
||||
droneDps = DmgTypes.default()
|
||||
|
||||
for drone in self.drones:
|
||||
droneVolley += drone.getVolley(targetProfile=self.targetProfile)
|
||||
|
||||
@@ -33,7 +33,7 @@ from eos.utils.cycles import CycleInfo, CycleSequence
|
||||
from eos.utils.default import DEFAULT
|
||||
from eos.utils.float import floatUnerr
|
||||
from eos.utils.spoolSupport import calculateSpoolup, resolveSpoolOptions
|
||||
from eos.utils.stats import BreacherInfo, DmgTypes, RRTypes
|
||||
from eos.utils.stats import BaseVolleyStats, BreacherInfo, DmgTypes, RRTypes
|
||||
|
||||
|
||||
pyfalog = Logger(__name__)
|
||||
@@ -453,6 +453,10 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut, M
|
||||
return True
|
||||
return False
|
||||
|
||||
@property
|
||||
def isBreacher(self):
|
||||
return self.charge and 'dotMissileLaunching' in self.charge.effects
|
||||
|
||||
def canDealDamage(self, ignoreState=False):
|
||||
if self.isEmpty:
|
||||
return False
|
||||
@@ -469,17 +473,17 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut, M
|
||||
|
||||
def getVolleyParameters(self, spoolOptions=None, targetProfile=None, ignoreState=False):
|
||||
if self.isEmpty or (self.state < FittingModuleState.ACTIVE and not ignoreState):
|
||||
return {0: DmgTypes(0, 0, 0, 0)}
|
||||
return {0: DmgTypes.default()}
|
||||
if self.__baseVolley is None:
|
||||
self.__baseVolley = {}
|
||||
if self.charge and 'dotMissileLaunching' in self.charge.effects:
|
||||
if self.isBreacher:
|
||||
dmgDelay = 1
|
||||
subcycles = math.floor(self.getModifiedChargeAttr("dotDuration", 0) / 1000)
|
||||
breacher_info = BreacherInfo(
|
||||
absolute=self.getModifiedChargeAttr("dotMaxDamagePerTick", 0),
|
||||
relative=self.getModifiedChargeAttr("dotMaxHPPercentagePerTick", 0))
|
||||
relative=self.getModifiedChargeAttr("dotMaxHPPercentagePerTick", 0) / 100)
|
||||
for i in range(subcycles):
|
||||
self.__baseVolley[dmgDelay + i] = DmgTypes(0, 0, 0, 0, breachers=[breacher_info])
|
||||
self.__baseVolley[dmgDelay + i] = BaseVolleyStats(0, 0, 0, 0, breachers=[breacher_info])
|
||||
else:
|
||||
dmgGetter = self.getModifiedChargeAttr if self.charge else self.getModifiedItemAttr
|
||||
dmgMult = self.getModifiedItemAttr("damageMultiplier", 1)
|
||||
@@ -498,7 +502,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut, M
|
||||
else:
|
||||
subcycles = 1
|
||||
for i in range(subcycles):
|
||||
self.__baseVolley[dmgDelay + dmgSubcycle * i] = DmgTypes(
|
||||
self.__baseVolley[dmgDelay + dmgSubcycle * i] = BaseVolleyStats(
|
||||
em=(dmgGetter("emDamage", 0)) * dmgMult,
|
||||
thermal=(dmgGetter("thermalDamage", 0)) * dmgMult,
|
||||
kinetic=(dmgGetter("kineticDamage", 0)) * dmgMult,
|
||||
@@ -510,24 +514,24 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut, M
|
||||
self.rawCycleTime / 1000, spoolType, spoolAmount)[0]
|
||||
spoolMultiplier = 1 + spoolBoost
|
||||
adjustedVolley = {}
|
||||
for volleyTime, volleyValue in self.__baseVolley.items():
|
||||
adjustedVolley[volleyTime] = DmgTypes(
|
||||
em=volleyValue.em * spoolMultiplier * (1 - getattr(targetProfile, "emAmount", 0)),
|
||||
thermal=volleyValue.thermal * spoolMultiplier * (1 - getattr(targetProfile, "thermalAmount", 0)),
|
||||
kinetic=volleyValue.kinetic * spoolMultiplier * (1 - getattr(targetProfile, "kineticAmount", 0)),
|
||||
explosive=volleyValue.explosive * spoolMultiplier * (1 - getattr(targetProfile, "explosiveAmount", 0)),
|
||||
breachers=volleyValue.breachers)
|
||||
for volleyTime, baseValue in self.__baseVolley.items():
|
||||
adjustedVolley[volleyTime] = DmgTypes.from_base_and_profile(
|
||||
base=baseValue, tgtProfile=targetProfile, mult=spoolMultiplier)
|
||||
return adjustedVolley
|
||||
|
||||
def getVolley(self, spoolOptions=None, targetProfile=None, ignoreState=False):
|
||||
volleyParams = self.getVolleyParameters(spoolOptions=spoolOptions, targetProfile=targetProfile, ignoreState=ignoreState)
|
||||
if len(volleyParams) == 0:
|
||||
return DmgTypes(0, 0, 0, 0)
|
||||
return DmgTypes.default()
|
||||
return volleyParams[min(volleyParams)]
|
||||
|
||||
def getDps(self, spoolOptions=None, targetProfile=None, ignoreState=False, getSpreadDPS=False):
|
||||
dmgDuringCycle = DmgTypes(0, 0, 0, 0)
|
||||
cycleParams = self.getCycleParameters()
|
||||
dmgDuringCycle = DmgTypes.default()
|
||||
# Special hack for breachers, since those are DoT and work independently of gun cycle
|
||||
if self.isBreacher:
|
||||
cycleParams = CycleInfo(activeTime=1000, inactiveTime=0, quantity=math.inf, isInactivityReload=False)
|
||||
else:
|
||||
cycleParams = self.getCycleParameters()
|
||||
if cycleParams is None:
|
||||
return dmgDuringCycle
|
||||
volleyParams = self.getVolleyParameters(spoolOptions=spoolOptions, targetProfile=targetProfile, ignoreState=ignoreState)
|
||||
@@ -541,13 +545,15 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut, M
|
||||
em=dmgDuringCycle.em * dpsFactor,
|
||||
thermal=dmgDuringCycle.thermal * dpsFactor,
|
||||
kinetic=dmgDuringCycle.kinetic * dpsFactor,
|
||||
explosive=dmgDuringCycle.explosive * dpsFactor)
|
||||
explosive=dmgDuringCycle.explosive * dpsFactor,
|
||||
breacher=dmgDuringCycle.breacher * dpsFactor)
|
||||
if not getSpreadDPS:
|
||||
return dps
|
||||
return {'em': dmgDuringCycle.em * dpsFactor,
|
||||
'therm': dmgDuringCycle.thermal * dpsFactor,
|
||||
'kin': dmgDuringCycle.kinetic * dpsFactor,
|
||||
'exp': dmgDuringCycle.explosive * dpsFactor}
|
||||
'exp': dmgDuringCycle.explosive * dpsFactor,
|
||||
'breach': dmgDuringCycle.breach * dpsFactor}
|
||||
|
||||
def isRemoteRepping(self, ignoreState=False):
|
||||
repParams = self.getRepAmountParameters(ignoreState=ignoreState)
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
# ===============================================================================
|
||||
|
||||
|
||||
import math
|
||||
from typing import NamedTuple
|
||||
|
||||
from eos.utils.float import floatUnerr
|
||||
@@ -32,29 +33,12 @@ class BreacherInfo(NamedTuple):
|
||||
absolute: float
|
||||
relative: float
|
||||
|
||||
def __mul__(self, mul):
|
||||
return type(self)(absolute=self.absolute * mul, relative=self.relative * mul)
|
||||
|
||||
def __imul__(self, mul):
|
||||
if mul == 1:
|
||||
return
|
||||
self.absolute *= mul
|
||||
self.relative *= mul
|
||||
return self
|
||||
|
||||
def __truediv__(self, div):
|
||||
return type(self)(absolute=self.absolute / div, relative=self.relative / div)
|
||||
|
||||
def __itruediv__(self, div):
|
||||
if div == 1:
|
||||
return
|
||||
self.absolute /= div
|
||||
self.relative /= div
|
||||
return self
|
||||
|
||||
|
||||
class DmgTypes:
|
||||
"""Container for damage data stats."""
|
||||
class BaseVolleyStats:
|
||||
"""
|
||||
Container for volley stats, which stores breacher pod data
|
||||
in raw form, before application of it to target profile.
|
||||
"""
|
||||
|
||||
def __init__(self, em, thermal, kinetic, explosive, breachers=None):
|
||||
self.em = em
|
||||
@@ -62,14 +46,67 @@ class DmgTypes:
|
||||
self.kinetic = kinetic
|
||||
self.explosive = explosive
|
||||
self.breachers = [] if breachers is None else breachers
|
||||
|
||||
@classmethod
|
||||
def default(cls):
|
||||
return cls(0, 0, 0, 0)
|
||||
|
||||
def __eq__(self, other):
|
||||
if not isinstance(other, BaseVolleyStats):
|
||||
return NotImplemented
|
||||
# Round for comparison's sake because often damage profiles are
|
||||
# generated from data which includes float errors
|
||||
return (
|
||||
floatUnerr(self.em) == floatUnerr(other.em) and
|
||||
floatUnerr(self.thermal) == floatUnerr(other.thermal) and
|
||||
floatUnerr(self.kinetic) == floatUnerr(other.kinetic) and
|
||||
floatUnerr(self.explosive) == floatUnerr(other.explosive) and
|
||||
sorted(self.breachers) == sorted(other.breachers))
|
||||
|
||||
def __bool__(self):
|
||||
return any((
|
||||
self.em, self.thermal, self.kinetic, self.explosive,
|
||||
any(b.absolute or b.relative for b in self.breachers)))
|
||||
|
||||
def __repr__(self):
|
||||
class_name = type(self).__name__
|
||||
return (f'<{class_name}(em={self.em}, thermal={self.thermal}, kinetic={self.kinetic}, '
|
||||
f'explosive={self.explosive}, breachers={len(self.breachers)})>')
|
||||
|
||||
|
||||
class DmgTypes:
|
||||
"""Container for damage data stats."""
|
||||
|
||||
def __init__(self, em, thermal, kinetic, explosive, breacher):
|
||||
self.em = em
|
||||
self.thermal = thermal
|
||||
self.kinetic = kinetic
|
||||
self.explosive = explosive
|
||||
self.breacher = breacher
|
||||
self._calcTotal()
|
||||
|
||||
@classmethod
|
||||
def default(cls):
|
||||
return cls(0, 0, 0, 0, 0)
|
||||
|
||||
@classmethod
|
||||
def from_base_and_profile(cls, base, tgtProfile, mult=1):
|
||||
return cls(
|
||||
em=base.em * mult * (1 - getattr(tgtProfile, "emAmount", 0)),
|
||||
thermal=base.thermal * mult * (1 - getattr(tgtProfile, "thermalAmount", 0)),
|
||||
kinetic=base.kinetic * mult * (1 - getattr(tgtProfile, "kineticAmount", 0)),
|
||||
explosive=base.explosive * mult * (1 - getattr(tgtProfile, "explosiveAmount", 0)),
|
||||
breacher=max(
|
||||
(min(b.absolute, b.relative * getattr(tgtProfile, "hp", math.inf)) for b in base.breachers),
|
||||
default=0) * mult)
|
||||
|
||||
# Iterator is needed to support tuple-style unpacking
|
||||
def __iter__(self):
|
||||
yield self.em
|
||||
yield self.thermal
|
||||
yield self.kinetic
|
||||
yield self.explosive
|
||||
yield self.breacher
|
||||
yield self.total
|
||||
|
||||
def __eq__(self, other):
|
||||
@@ -82,15 +119,16 @@ class DmgTypes:
|
||||
floatUnerr(self.thermal) == floatUnerr(other.thermal) and
|
||||
floatUnerr(self.kinetic) == floatUnerr(other.kinetic) and
|
||||
floatUnerr(self.explosive) == floatUnerr(other.explosive) and
|
||||
floatUnerr(self.breacher) == floatUnerr(other.breacher) and
|
||||
floatUnerr(self.total) == floatUnerr(other.total))
|
||||
|
||||
def __bool__(self):
|
||||
return any((
|
||||
self.em, self.thermal, self.kinetic,
|
||||
self.explosive, self.total))
|
||||
self.em, self.thermal, self.kinetic, self.explosive,
|
||||
self.breacher, self.total))
|
||||
|
||||
def _calcTotal(self):
|
||||
self.total = self.em + self.thermal + self.kinetic + self.explosive
|
||||
self.total = self.em + self.thermal + self.kinetic + self.explosive + self.breacher
|
||||
|
||||
def __add__(self, other):
|
||||
return type(self)(
|
||||
@@ -98,14 +136,14 @@ class DmgTypes:
|
||||
thermal=self.thermal + other.thermal,
|
||||
kinetic=self.kinetic + other.kinetic,
|
||||
explosive=self.explosive + other.explosive,
|
||||
breachers=self.breachers + other.breachers)
|
||||
breacher=max(self.breacher, other.breacher))
|
||||
|
||||
def __iadd__(self, other):
|
||||
self.em += other.em
|
||||
self.thermal += other.thermal
|
||||
self.kinetic += other.kinetic
|
||||
self.explosive += other.explosive
|
||||
self.breachers += other.breachers
|
||||
self.breacher = max(self.breacher, other.breacher)
|
||||
self._calcTotal()
|
||||
return self
|
||||
|
||||
@@ -115,7 +153,7 @@ class DmgTypes:
|
||||
thermal=self.thermal * mul,
|
||||
kinetic=self.kinetic * mul,
|
||||
explosive=self.explosive * mul,
|
||||
breachers=[b * mul for b in self.breachers])
|
||||
breacher=self.breacher * mul)
|
||||
|
||||
def __imul__(self, mul):
|
||||
if mul == 1:
|
||||
@@ -124,7 +162,7 @@ class DmgTypes:
|
||||
self.thermal *= mul
|
||||
self.kinetic *= mul
|
||||
self.explosive *= mul
|
||||
self.breachers = [b * mul for b in self.breachers]
|
||||
self.breacher *= mul
|
||||
self._calcTotal()
|
||||
return self
|
||||
|
||||
@@ -134,7 +172,7 @@ class DmgTypes:
|
||||
thermal=self.thermal / div,
|
||||
kinetic=self.kinetic / div,
|
||||
explosive=self.explosive / div,
|
||||
breachers=[b / div for b in self.breachers])
|
||||
breacher=self.breacher / div)
|
||||
|
||||
def __itruediv__(self, div):
|
||||
if div == 1:
|
||||
@@ -143,18 +181,16 @@ class DmgTypes:
|
||||
self.thermal /= div
|
||||
self.kinetic /= div
|
||||
self.explosive /= div
|
||||
self.breachers = [b / div for b in self.breachers]
|
||||
self.breacher /= div
|
||||
self._calcTotal()
|
||||
return self
|
||||
|
||||
def __repr__(self):
|
||||
class_name = type(self).__name__
|
||||
return (f'<{class_name}(em={self.em}, thermal={self.thermal}, kinetic={self.kinetic}, '
|
||||
f'explosive={self.explosive}, breachers={len(self.breachers)}, total={self.total})>')
|
||||
return makeReprStr(self, spec=['em', 'thermal', 'kinetic', 'explosive', 'breacher', 'total'])
|
||||
|
||||
@staticmethod
|
||||
def names(short=None, postProcessor=None):
|
||||
value = [_t('em'), _t('th'), _t('kin'), _t('exp')] if short else [_t('em'), _t('thermal'), _t('kinetic'), _t('explosive')]
|
||||
value = [_t('em'), _t('th'), _t('kin'), _t('exp'), _t('breacher')] if short else [_t('em'), _t('thermal'), _t('kinetic'), _t('explosive'), _t('breacher')]
|
||||
|
||||
if postProcessor:
|
||||
value = [postProcessor(x) for x in value]
|
||||
|
||||
@@ -176,6 +176,7 @@ class FirepowerViewFull(StatsView):
|
||||
for dmgType in normal.names():
|
||||
val = getattr(normal, dmgType, None)
|
||||
if val:
|
||||
dmgType = {'breacher': 'pure'}.get(dmgType, dmgType)
|
||||
lines.append("{}{}: {}%".format(
|
||||
" " if hasSpool else "",
|
||||
_t(dmgType).capitalize(),
|
||||
|
||||
Reference in New Issue
Block a user