diff --git a/eos/modifiedAttributeDict.py b/eos/modifiedAttributeDict.py index ea80992e7..893492f39 100644 --- a/eos/modifiedAttributeDict.py +++ b/eos/modifiedAttributeDict.py @@ -67,14 +67,8 @@ class ItemAttrShortcut: return_value = self.itemModifiedAttributes.get(key) return return_value or default - def getModifiedItemAttrWithExtraMods(self, key, extraMultipliers=None, default=0): - """Returns attribute value with passed modifiers applied to it.""" - 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) + def getModifiedItemAttrExtended(self, key, extraMultipliers=None, ignoreAfflictors=(), default=0): + return_value = self.itemModifiedAttributes.getExtended(key, extraMultipliers=extraMultipliers, ignoreAfflictors=ignoreAfflictors) return return_value or default def getItemBaseAttrValue(self, key, default=0): @@ -88,14 +82,8 @@ class ChargeAttrShortcut: return_value = self.chargeModifiedAttributes.get(key) return return_value or default - def getModifiedChargeAttrWithExtraMods(self, key, extraMultipliers=None, default=0): - """Returns attribute value with passed modifiers applied to it.""" - 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) + def getModifiedChargeAttrExtended(self, key, extraMultipliers=None, ignoreAfflictors=(), default=0): + return_value = self.chargeModifiedAttributes.getExtended(key, extraMultipliers=extraMultipliers, ignoreAfflictors=ignoreAfflictors) return return_value or default def getChargeBaseAttrValue(self, key, default=0): @@ -211,32 +199,11 @@ class ModifiedAttributeDict(collections.MutableMapping): # Original value is the least priority return self.getOriginal(key) - def getWithExtraMods(self, key, extraMultipliers=None, default=0): - """Copy of __getitem__ with some modifications.""" - if not extraMultipliers: - return self.get(key, default=default) - - 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): + def getExtended(self, key, extraMultipliers=None, ignoreAfflictors=None, default=0): + """ + Here we consider couple of parameters. If they affect final result, we do + not store result, and if they are - we do. + """ # 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, # and we do not actually need those operators atm @@ -246,7 +213,7 @@ class ModifiedAttributeDict(collections.MutableMapping): postIncreaseAdjustment = 0 for fit, afflictors in self.getAfflictions(key).items(): for afflictor, operator, stackingGroup, preResAmount, postResAmount, used in afflictors: - if afflictor in ignoredAfflictors: + if afflictor in ignoreAfflictors: if operator == Operator.MULTIPLY: if stackingGroup is None: multiplierAdjustment /= postResAmount @@ -257,29 +224,31 @@ class ModifiedAttributeDict(collections.MutableMapping): elif operator == Operator.POSTINCREASE: 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) + # Try to calculate custom values val = self.__calculateValue( - key, preIncAdj=preIncreaseAdjustment, multAdj=multiplierAdjustment, + key, extraMultipliers=extraMultipliers, preIncAdj=preIncreaseAdjustment, multAdj=multiplierAdjustment, postIncAdj=postIncreaseAdjustment, ignorePenMult=ignorePenalizedMultipliers) if val is not None: return val - # Then in values which are not yet calculated + # Then the same fallbacks as in regular getter 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 __delitem__(self, key): diff --git a/eos/saveddata/fit.py b/eos/saveddata/fit.py index a40a27ded..4c683a26c 100644 --- a/eos/saveddata/fit.py +++ b/eos/saveddata/fit.py @@ -1320,8 +1320,8 @@ class Fit: """Return how much cap regen do we gain from having this module""" currentRegen = self.calculateCapRecharge() nomodRegen = self.calculateCapRecharge( - capacity=self.ship.getModifiedItemAttrWithoutAfflictors("capacitorCapacity", [mod]), - rechargeRate=self.ship.getModifiedItemAttrWithoutAfflictors("rechargeRate", [mod]) / 1000.0) + capacity=self.ship.getModifiedItemAttrExtended("capacitorCapacity", ignoreAfflictors=[mod]), + rechargeRate=self.ship.getModifiedItemAttrExtended("rechargeRate", ignoreAfflictors=[mod]) / 1000.0) return currentRegen - nomodRegen def getRemoteReps(self, spoolOptions=None): diff --git a/graphs/data/fitDamageStats/calc/projected.py b/graphs/data/fitDamageStats/calc/projected.py index 641fc1dbf..876a0f304 100644 --- a/graphs/data/fitDamageStats/calc/projected.py +++ b/graphs/data/fitDamageStats/calc/projected.py @@ -26,6 +26,47 @@ from service.const import GraphDpsDroneMode 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): # Can slow down non-immune ships and target profiles if tgt.isFit and tgt.item.ship.getModifiedItemAttr('disallowOffensiveModifiers'): diff --git a/graphs/wrapper.py b/graphs/wrapper.py index 370e57801..129522792 100644 --- a/graphs/wrapper.py +++ b/graphs/wrapper.py @@ -54,10 +54,13 @@ class BaseWrapper: return self.item.name return '' - def getMaxVelocity(self, extraMultipliers=None): + def getMaxVelocity(self, extraMultipliers=None, ignoreAfflictors=()): if self.isFit: - if extraMultipliers: - maxVelocity = self.item.ship.getModifiedItemAttrWithExtraMods('maxVelocity', extraMultipliers=extraMultipliers) + if extraMultipliers or ignoreAfflictors: + maxVelocity = self.item.ship.getModifiedItemAttrExtended( + 'maxVelocity', + extraMultipliers=extraMultipliers, + ignoreAfflictors=ignoreAfflictors) else: maxVelocity = self.item.ship.getModifiedItemAttr('maxVelocity') elif self.isProfile: @@ -68,10 +71,13 @@ class BaseWrapper: maxVelocity = None return maxVelocity - def getSigRadius(self, extraMultipliers=None): + def getSigRadius(self, extraMultipliers=None, ignoreAfflictors=()): if self.isFit: - if extraMultipliers: - sigRadius = self.item.ship.getModifiedItemAttrWithExtraMods('signatureRadius', extraMultipliers=extraMultipliers) + if extraMultipliers or ignoreAfflictors: + sigRadius = self.item.ship.getModifiedItemAttrExtended( + 'signatureRadius', + extraMultipliers=extraMultipliers, + ignoreAfflictors=ignoreAfflictors) else: sigRadius = self.item.ship.getModifiedItemAttr('signatureRadius') elif self.isProfile: