Implement hybrid extended attribute getter and few scram-related functions for DPS graph

This commit is contained in:
DarkPhoenix
2019-08-23 11:53:13 +03:00
parent 0e57258cc5
commit f4a635eb43
4 changed files with 74 additions and 58 deletions

View File

@@ -67,14 +67,8 @@ class ItemAttrShortcut:
return_value = self.itemModifiedAttributes.get(key) return_value = self.itemModifiedAttributes.get(key)
return return_value or default return return_value or default
def getModifiedItemAttrWithExtraMods(self, key, extraMultipliers=None, default=0): def getModifiedItemAttrExtended(self, key, extraMultipliers=None, ignoreAfflictors=(), default=0):
"""Returns attribute value with passed modifiers applied to it.""" return_value = self.itemModifiedAttributes.getExtended(key, extraMultipliers=extraMultipliers, ignoreAfflictors=ignoreAfflictors)
return_value = self.itemModifiedAttributes.getWithExtraMods(key, extraMultipliers=extraMultipliers)
return return_value or default
def getModifiedItemAttrWithoutAfflictors(self, key, afflictors, default=0):
"""Returns attribute value with passed afflictors' modification removed."""
return_value = self.itemModifiedAttributes.getWithoutAfflictors(key, afflictors)
return return_value or default return return_value or default
def getItemBaseAttrValue(self, key, default=0): def getItemBaseAttrValue(self, key, default=0):
@@ -88,14 +82,8 @@ class ChargeAttrShortcut:
return_value = self.chargeModifiedAttributes.get(key) return_value = self.chargeModifiedAttributes.get(key)
return return_value or default return return_value or default
def getModifiedChargeAttrWithExtraMods(self, key, extraMultipliers=None, default=0): def getModifiedChargeAttrExtended(self, key, extraMultipliers=None, ignoreAfflictors=(), default=0):
"""Returns attribute value with passed modifiers applied to it.""" return_value = self.chargeModifiedAttributes.getExtended(key, extraMultipliers=extraMultipliers, ignoreAfflictors=ignoreAfflictors)
return_value = self.chargeModifiedAttributes.getWithExtraMods(key, extraMultipliers=extraMultipliers)
return return_value or default
def getModifiedChargeAttrWithoutAfflictors(self, key, afflictors, default=0):
"""Returns attribute value with passed afflictors' modification removed."""
return_value = self.chargeModifiedAttributes.getWithoutAfflictors(key, afflictors)
return return_value or default return return_value or default
def getChargeBaseAttrValue(self, key, default=0): def getChargeBaseAttrValue(self, key, default=0):
@@ -211,32 +199,11 @@ class ModifiedAttributeDict(collections.MutableMapping):
# Original value is the least priority # Original value is the least priority
return self.getOriginal(key) return self.getOriginal(key)
def getWithExtraMods(self, key, extraMultipliers=None, default=0): def getExtended(self, key, extraMultipliers=None, ignoreAfflictors=None, default=0):
"""Copy of __getitem__ with some modifications.""" """
if not extraMultipliers: Here we consider couple of parameters. If they affect final result, we do
return self.get(key, default=default) not store result, and if they are - we do.
"""
val = self.__calculateValue(key, extraMultipliers=extraMultipliers)
if val is not None:
return val
# Then in values which are not yet calculated
if self.__intermediary:
val = self.__intermediary.get(key)
else:
val = None
if val is not None:
return val
# Original value
val = self.getOriginal(key)
if val is not None:
return val
# Passed in default value
return default
def getWithoutAfflictors(self, key, ignoredAfflictors, default=0):
# Here we do not have support for preAssigns/forceds, as doing them would # Here we do not have support for preAssigns/forceds, as doing them would
# mean that we have to store all of them in a list which increases memory use, # mean that we have to store all of them in a list which increases memory use,
# and we do not actually need those operators atm # and we do not actually need those operators atm
@@ -246,7 +213,7 @@ class ModifiedAttributeDict(collections.MutableMapping):
postIncreaseAdjustment = 0 postIncreaseAdjustment = 0
for fit, afflictors in self.getAfflictions(key).items(): for fit, afflictors in self.getAfflictions(key).items():
for afflictor, operator, stackingGroup, preResAmount, postResAmount, used in afflictors: for afflictor, operator, stackingGroup, preResAmount, postResAmount, used in afflictors:
if afflictor in ignoredAfflictors: if afflictor in ignoreAfflictors:
if operator == Operator.MULTIPLY: if operator == Operator.MULTIPLY:
if stackingGroup is None: if stackingGroup is None:
multiplierAdjustment /= postResAmount multiplierAdjustment /= postResAmount
@@ -257,29 +224,31 @@ class ModifiedAttributeDict(collections.MutableMapping):
elif operator == Operator.POSTINCREASE: elif operator == Operator.POSTINCREASE:
postIncreaseAdjustment -= postResAmount postIncreaseAdjustment -= postResAmount
if preIncreaseAdjustment == 0 and multiplierAdjustment == 1 and postIncreaseAdjustment == 0 and len(ignorePenalizedMultipliers) == 0: # If we apply no customizations - use regular getter
if (
not extraMultipliers and
preIncreaseAdjustment == 0 and multiplierAdjustment == 1 and
postIncreaseAdjustment == 0 and len(ignorePenalizedMultipliers) == 0
):
return self.get(key, default=default) return self.get(key, default=default)
# Try to calculate custom values
val = self.__calculateValue( val = self.__calculateValue(
key, preIncAdj=preIncreaseAdjustment, multAdj=multiplierAdjustment, key, extraMultipliers=extraMultipliers, preIncAdj=preIncreaseAdjustment, multAdj=multiplierAdjustment,
postIncAdj=postIncreaseAdjustment, ignorePenMult=ignorePenalizedMultipliers) postIncAdj=postIncreaseAdjustment, ignorePenMult=ignorePenalizedMultipliers)
if val is not None: if val is not None:
return val return val
# Then in values which are not yet calculated # Then the same fallbacks as in regular getter
if self.__intermediary: if self.__intermediary:
val = self.__intermediary.get(key) val = self.__intermediary.get(key)
else: else:
val = None val = None
if val is not None: if val is not None:
return val return val
# Original value
val = self.getOriginal(key) val = self.getOriginal(key)
if val is not None: if val is not None:
return val return val
# Passed in default value
return default return default
def __delitem__(self, key): def __delitem__(self, key):

View File

@@ -1320,8 +1320,8 @@ class Fit:
"""Return how much cap regen do we gain from having this module""" """Return how much cap regen do we gain from having this module"""
currentRegen = self.calculateCapRecharge() currentRegen = self.calculateCapRecharge()
nomodRegen = self.calculateCapRecharge( nomodRegen = self.calculateCapRecharge(
capacity=self.ship.getModifiedItemAttrWithoutAfflictors("capacitorCapacity", [mod]), capacity=self.ship.getModifiedItemAttrExtended("capacitorCapacity", ignoreAfflictors=[mod]),
rechargeRate=self.ship.getModifiedItemAttrWithoutAfflictors("rechargeRate", [mod]) / 1000.0) rechargeRate=self.ship.getModifiedItemAttrExtended("rechargeRate", ignoreAfflictors=[mod]) / 1000.0)
return currentRegen - nomodRegen return currentRegen - nomodRegen
def getRemoteReps(self, spoolOptions=None): def getRemoteReps(self, spoolOptions=None):

View File

@@ -26,6 +26,47 @@ from service.const import GraphDpsDroneMode
from service.settings import GraphSettings from service.settings import GraphSettings
def _isRegularScram(mod):
if not mod.item:
return False
if not {'warpScrambleBlockMWDWithNPCEffect', 'structureWarpScrambleBlockMWDWithNPCEffect'}.intersection(mod.item.effects):
return False
if not mod.getModifiedItemAttr('activationBlockedStrenght', 0):
return False
return True
def _isHicScram(mod):
if not mod.item:
return False
if 'warpDisruptSphere' not in mod.item.effects:
return False
if not mod.charge:
return False
if 'shipModuleFocusedWarpScramblingScript' not in mod.charge.effects:
return False
return True
def getScramRange(src):
scramRange = None
for mod in src.item.modules:
if _isRegularScram(mod) or _isHicScram(mod):
scramRange = max(scramRange or 0, mod.maxRange or 0)
return scramRange
def getScrammables(tgt):
scrammables = []
if tgt.isFit:
for mod in tgt.item.modules:
if not mod.item:
continue
if {'moduleBonusMicrowarpdrive', 'microJumpDrive', 'microJumpPortalDrive'}.intersection(mod.item.effects):
scrammables.append(mod)
return scrammables
def getWebbedSpeed(src, tgt, currentUnwebbedSpeed, webMods, webDrones, webFighters, distance): def getWebbedSpeed(src, tgt, currentUnwebbedSpeed, webMods, webDrones, webFighters, distance):
# Can slow down non-immune ships and target profiles # Can slow down non-immune ships and target profiles
if tgt.isFit and tgt.item.ship.getModifiedItemAttr('disallowOffensiveModifiers'): if tgt.isFit and tgt.item.ship.getModifiedItemAttr('disallowOffensiveModifiers'):

View File

@@ -54,10 +54,13 @@ class BaseWrapper:
return self.item.name return self.item.name
return '' return ''
def getMaxVelocity(self, extraMultipliers=None): def getMaxVelocity(self, extraMultipliers=None, ignoreAfflictors=()):
if self.isFit: if self.isFit:
if extraMultipliers: if extraMultipliers or ignoreAfflictors:
maxVelocity = self.item.ship.getModifiedItemAttrWithExtraMods('maxVelocity', extraMultipliers=extraMultipliers) maxVelocity = self.item.ship.getModifiedItemAttrExtended(
'maxVelocity',
extraMultipliers=extraMultipliers,
ignoreAfflictors=ignoreAfflictors)
else: else:
maxVelocity = self.item.ship.getModifiedItemAttr('maxVelocity') maxVelocity = self.item.ship.getModifiedItemAttr('maxVelocity')
elif self.isProfile: elif self.isProfile:
@@ -68,10 +71,13 @@ class BaseWrapper:
maxVelocity = None maxVelocity = None
return maxVelocity return maxVelocity
def getSigRadius(self, extraMultipliers=None): def getSigRadius(self, extraMultipliers=None, ignoreAfflictors=()):
if self.isFit: if self.isFit:
if extraMultipliers: if extraMultipliers or ignoreAfflictors:
sigRadius = self.item.ship.getModifiedItemAttrWithExtraMods('signatureRadius', extraMultipliers=extraMultipliers) sigRadius = self.item.ship.getModifiedItemAttrExtended(
'signatureRadius',
extraMultipliers=extraMultipliers,
ignoreAfflictors=ignoreAfflictors)
else: else:
sigRadius = self.item.ship.getModifiedItemAttr('signatureRadius') sigRadius = self.item.ship.getModifiedItemAttr('signatureRadius')
elif self.isProfile: elif self.isProfile: