Compare commits
5 Commits
v2.10.1
...
v2.11.0dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
56672f5830 | ||
|
|
1bff10c973 | ||
|
|
1d4aece7cc | ||
|
|
cdb79f499a | ||
|
|
837dbb3677 |
@@ -148,7 +148,6 @@ class CapSimulator:
|
||||
stability_precision = self.stability_precision
|
||||
period = self.period
|
||||
|
||||
activation = None
|
||||
iterations = 0
|
||||
|
||||
capCapacity = self.capacitorCapacity
|
||||
@@ -163,12 +162,7 @@ class CapSimulator:
|
||||
t_max = self.t_max
|
||||
|
||||
while 1:
|
||||
# Nothing to pop - might happen when no mods are activated, or when
|
||||
# only cap injectors are active (and are postponed by code below)
|
||||
try:
|
||||
activation = pop(state)
|
||||
except IndexError:
|
||||
break
|
||||
activation = pop(state)
|
||||
t_now, duration, capNeed, shot, clipSize, reloadTime, isInjector = activation
|
||||
|
||||
# Max time reached, stop simulation - we're stable
|
||||
@@ -281,8 +275,7 @@ class CapSimulator:
|
||||
activation[3] = shot
|
||||
|
||||
push(state, activation)
|
||||
if activation is not None:
|
||||
push(state, activation)
|
||||
push(state, activation)
|
||||
|
||||
# update instance with relevant results.
|
||||
self.t = t_last
|
||||
|
||||
@@ -90,9 +90,12 @@ class FittingHardpoint(IntEnum):
|
||||
|
||||
@unique
|
||||
class SpoolType(IntEnum):
|
||||
SCALE = 0 # [0..1]
|
||||
TIME = 1 # Expressed via time in seconds since spool up started
|
||||
CYCLES = 2 # Expressed in amount of cycles since spool up started
|
||||
# Spool and cycle scale are different in case if max spool amount cannot
|
||||
# be divided by spool step without remainder
|
||||
SPOOL_SCALE = 0 # [0..1]
|
||||
CYCLE_SCALE = 1 # [0..1]
|
||||
TIME = 2 # Expressed via time in seconds since spool up started
|
||||
CYCLES = 3 # Expressed in amount of cycles since spool up started
|
||||
|
||||
|
||||
@unique
|
||||
|
||||
@@ -4261,7 +4261,7 @@ class Effect1434(BaseEffect):
|
||||
for sensorType in ('Gravimetric', 'Ladar', 'Magnetometric', 'Radar'):
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill('Electronic Warfare'),
|
||||
'scan{0}StrengthBonus'.format(sensorType),
|
||||
ship.getModifiedItemAttr('shipBonusCB'),
|
||||
ship.getModifiedItemAttr('shipBonusCB'), stackingPenalties=True,
|
||||
skill='Caldari Battleship', **kwargs)
|
||||
|
||||
|
||||
@@ -5851,6 +5851,7 @@ class Effect2008(BaseEffect):
|
||||
cynosuralDurationBonus
|
||||
|
||||
Used by:
|
||||
Ships from group: Black Ops (5 of 5)
|
||||
Ships from group: Force Recon Ship (8 of 9)
|
||||
"""
|
||||
|
||||
@@ -5858,7 +5859,7 @@ class Effect2008(BaseEffect):
|
||||
|
||||
@staticmethod
|
||||
def handler(fit, ship, context, **kwargs):
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == 'Cynosural Field Generator',
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill('Cynosural Field Theory'),
|
||||
'duration', ship.getModifiedItemAttr('durationBonus'), **kwargs)
|
||||
|
||||
|
||||
@@ -5966,10 +5967,8 @@ class Effect2019(BaseEffect):
|
||||
@staticmethod
|
||||
def handler(fit, container, context, **kwargs):
|
||||
level = container.level if 'skill' in context else 1
|
||||
penalized = False if 'skill' in context else True
|
||||
fit.drones.filteredItemBoost(lambda drone: drone.item.group.name == 'Logistic Drone',
|
||||
'shieldBonus', container.getModifiedItemAttr('damageHP') * level,
|
||||
stackingPenalties=penalized, **kwargs)
|
||||
'shieldBonus', container.getModifiedItemAttr('damageHP') * level, **kwargs)
|
||||
|
||||
|
||||
class Effect2020(BaseEffect):
|
||||
@@ -6722,10 +6721,10 @@ class Effect2251(BaseEffect):
|
||||
|
||||
@staticmethod
|
||||
def handler(fit, src, context, **kwargs):
|
||||
fit.modules.filteredItemIncrease(lambda mod: mod.item.requiresSkill('Leadership'), 'maxGroupOnline',
|
||||
src.getModifiedItemAttr('maxGangModules'), **kwargs)
|
||||
fit.modules.filteredItemIncrease(lambda mod: mod.item.requiresSkill('Leadership'), 'maxGroupActive',
|
||||
src.getModifiedItemAttr('maxGangModules'), **kwargs)
|
||||
fit.modules.filteredItemIncrease(lambda mod: mod.item.requiresSkill('Leadership'), 'maxGroupOnline',
|
||||
src.getModifiedItemAttr('maxGangModules'), **kwargs)
|
||||
|
||||
|
||||
class Effect2252(BaseEffect):
|
||||
@@ -29504,8 +29503,6 @@ class Effect6613(BaseEffect):
|
||||
|
||||
@staticmethod
|
||||
def handler(fit, src, context, **kwargs):
|
||||
fit.modules.filteredItemIncrease(lambda mod: mod.item.requiresSkill('Leadership'), 'maxGroupOnline',
|
||||
src.getModifiedItemAttr('shipBonusRole1'), **kwargs)
|
||||
fit.modules.filteredItemIncrease(lambda mod: mod.item.requiresSkill('Leadership'), 'maxGroupActive',
|
||||
src.getModifiedItemAttr('shipBonusRole1'), **kwargs)
|
||||
|
||||
@@ -29608,8 +29605,6 @@ class Effect6619(BaseEffect):
|
||||
|
||||
@staticmethod
|
||||
def handler(fit, src, context, **kwargs):
|
||||
fit.modules.filteredItemIncrease(lambda mod: mod.item.requiresSkill('Leadership'), 'maxGroupOnline',
|
||||
src.getModifiedItemAttr('shipBonusRole1'), **kwargs)
|
||||
fit.modules.filteredItemIncrease(lambda mod: mod.item.requiresSkill('Leadership'), 'maxGroupActive',
|
||||
src.getModifiedItemAttr('shipBonusRole1'), **kwargs)
|
||||
|
||||
@@ -29922,8 +29917,6 @@ class Effect6640(BaseEffect):
|
||||
|
||||
@staticmethod
|
||||
def handler(fit, src, context, **kwargs):
|
||||
fit.modules.filteredItemIncrease(lambda mod: mod.item.requiresSkill('Leadership'), 'maxGroupOnline',
|
||||
src.getModifiedItemAttr('shipBonusRole1'), **kwargs)
|
||||
fit.modules.filteredItemIncrease(lambda mod: mod.item.requiresSkill('Leadership'), 'maxGroupActive',
|
||||
src.getModifiedItemAttr('shipBonusRole1'), **kwargs)
|
||||
|
||||
@@ -32681,14 +32674,16 @@ class Effect6898(BaseEffect):
|
||||
Subsystems named like: Offensive Support Processor (3 of 4)
|
||||
"""
|
||||
|
||||
runTime = 'early'
|
||||
type = 'passive'
|
||||
|
||||
@staticmethod
|
||||
def handler(fit, src, context, **kwargs):
|
||||
fit.modules.filteredItemBoost(
|
||||
lambda mod: mod.item.requiresSkill('Remote Armor Repair Systems'),
|
||||
'mediumRemoteRepFittingMultiplier', src.getModifiedItemAttr('subsystemMRARFittingReduction'), **kwargs)
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill('Remote Armor Repair Systems') and
|
||||
mod.getModifiedItemAttr('mediumRemoteRepFittingMultiplier', 0) == 1,
|
||||
'cpu', src.getModifiedItemAttr('subsystemMRARFittingReduction'), **kwargs)
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill('Remote Armor Repair Systems') and
|
||||
mod.getModifiedItemAttr('mediumRemoteRepFittingMultiplier', 0) == 1,
|
||||
'power', src.getModifiedItemAttr('subsystemMRARFittingReduction'), **kwargs)
|
||||
|
||||
|
||||
class Effect6899(BaseEffect):
|
||||
@@ -32704,9 +32699,12 @@ class Effect6899(BaseEffect):
|
||||
|
||||
@staticmethod
|
||||
def handler(fit, src, context, **kwargs):
|
||||
fit.modules.filteredItemBoost(
|
||||
lambda mod: mod.item.requiresSkill('Shield Emission Systems'),
|
||||
'mediumRemoteRepFittingMultiplier', src.getModifiedItemAttr('subsystemMRSBFittingReduction'), **kwargs)
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill('Shield Emission Systems') and
|
||||
mod.getModifiedItemAttr('mediumRemoteRepFittingMultiplier', 0) == 1,
|
||||
'cpu', src.getModifiedItemAttr('subsystemMRSBFittingReduction'), **kwargs)
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill('Shield Emission Systems') and
|
||||
mod.getModifiedItemAttr('mediumRemoteRepFittingMultiplier', 0) == 1,
|
||||
'power', src.getModifiedItemAttr('subsystemMRSBFittingReduction'), **kwargs)
|
||||
|
||||
|
||||
class Effect6900(BaseEffect):
|
||||
@@ -35295,10 +35293,10 @@ class Effect7166(BaseEffect):
|
||||
repSpoolMax = container.getModifiedItemAttr('repairMultiplierBonusMax')
|
||||
repSpoolPerCycle = container.getModifiedItemAttr('repairMultiplierBonusPerCycle')
|
||||
defaultSpoolValue = eos.config.settings['globalDefaultSpoolupPercentage']
|
||||
spoolType, spoolAmount = resolveSpoolOptions(SpoolOptions(SpoolType.SCALE, defaultSpoolValue, False), container)
|
||||
spoolType, spoolAmount = resolveSpoolOptions(SpoolOptions(SpoolType.SPOOL_SCALE, defaultSpoolValue, False), container)
|
||||
rps = repAmountBase * (1 + calculateSpoolup(repSpoolMax, repSpoolPerCycle, cycleTime, spoolType, spoolAmount)[0]) / cycleTime
|
||||
rpsPreSpool = repAmountBase * (1 + calculateSpoolup(repSpoolMax, repSpoolPerCycle, cycleTime, SpoolType.SCALE, 0)[0]) / cycleTime
|
||||
rpsFullSpool = repAmountBase * (1 + calculateSpoolup(repSpoolMax, repSpoolPerCycle, cycleTime, SpoolType.SCALE, 1)[0]) / cycleTime
|
||||
rpsPreSpool = repAmountBase * (1 + calculateSpoolup(repSpoolMax, repSpoolPerCycle, cycleTime, SpoolType.SPOOL_SCALE, 0)[0]) / cycleTime
|
||||
rpsFullSpool = repAmountBase * (1 + calculateSpoolup(repSpoolMax, repSpoolPerCycle, cycleTime, SpoolType.SPOOL_SCALE, 1)[0]) / cycleTime
|
||||
fit.extraAttributes.increase('armorRepair', rps, **kwargs)
|
||||
fit.extraAttributes.increase('armorRepairPreSpool', rpsPreSpool, **kwargs)
|
||||
fit.extraAttributes.increase('armorRepairFullSpool', rpsFullSpool, **kwargs)
|
||||
@@ -35804,3 +35802,58 @@ class Effect7231(BaseEffect):
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill('Repair Systems'),
|
||||
'armorDamageAmount', ship.getModifiedItemAttr('shipBonusGC3'),
|
||||
skill='Gallente Cruiser', **kwargs)
|
||||
|
||||
|
||||
class Effect7232(BaseEffect):
|
||||
"""
|
||||
modifyDamageMultiplierBonusMax
|
||||
|
||||
Used by:
|
||||
Implants named like: Low Grade Kostenadza (5 of 6)
|
||||
"""
|
||||
|
||||
type = 'passive'
|
||||
|
||||
@staticmethod
|
||||
def handler(fit, implant, context, **kwargs):
|
||||
fit.modules.filteredItemBoost(
|
||||
lambda mod: mod.item.group.name == 'Precursor Weapon', 'damageMultiplierBonusMax',
|
||||
implant.getModifiedItemAttr('damageMultiplierBonusMaxModifier'), **kwargs)
|
||||
|
||||
|
||||
class Effect7233(BaseEffect):
|
||||
"""
|
||||
modifyDamageMultiplierBonusPerCycle
|
||||
|
||||
Used by:
|
||||
Implants named like: Low Grade Kostenadza (5 of 6)
|
||||
"""
|
||||
|
||||
type = 'passive'
|
||||
|
||||
@staticmethod
|
||||
def handler(fit, implant, context, **kwargs):
|
||||
fit.modules.filteredItemBoost(
|
||||
lambda mod: mod.item.group.name == 'Precursor Weapon', 'damageMultiplierBonusPerCycle',
|
||||
implant.getModifiedItemAttr('damageMultiplierBonusPerCycleModifier'), **kwargs)
|
||||
|
||||
|
||||
class Effect7234(BaseEffect):
|
||||
"""
|
||||
implantSetKostenadza
|
||||
|
||||
Used by:
|
||||
Implants named like: Low Grade Kostenadza (6 of 6)
|
||||
"""
|
||||
|
||||
runTime = 'early'
|
||||
type = 'passive'
|
||||
|
||||
@staticmethod
|
||||
def handler(fit, implant, context, **kwargs):
|
||||
fit.appliedImplants.filteredItemMultiply(
|
||||
lambda imp: imp.item.group.name == 'Cyberimplant', 'damageMultiplierBonusMaxModifier',
|
||||
implant.getModifiedItemAttr('setBonusKostenadza'), **kwargs)
|
||||
fit.appliedImplants.filteredItemMultiply(
|
||||
lambda imp: imp.item.group.name == 'Cyberimplant', 'damageMultiplierBonusPerCycleModifier',
|
||||
implant.getModifiedItemAttr('setBonusKostenadza'), **kwargs)
|
||||
|
||||
@@ -29,7 +29,6 @@ from eos.db.gamedata.queries import getAttributeInfo
|
||||
|
||||
defaultValuesCache = {}
|
||||
cappingAttrKeyCache = {}
|
||||
resistanceCache = {}
|
||||
|
||||
|
||||
def getAttrDefault(key, fallback=None):
|
||||
@@ -47,23 +46,19 @@ def getAttrDefault(key, fallback=None):
|
||||
|
||||
|
||||
def getResistanceAttrID(modifyingItem, effect):
|
||||
# If it doesn't exist on the effect, check the modifying module's attributes.
|
||||
# If it's there, cache it and return
|
||||
if effect.resistanceID:
|
||||
return effect.resistanceID
|
||||
cacheKey = (modifyingItem.item.ID, effect.ID)
|
||||
try:
|
||||
return resistanceCache[cacheKey]
|
||||
except KeyError:
|
||||
# If it doesn't exist on the effect, check the modifying modules attributes. If it's there, set it on the
|
||||
# effect for this session so that we don't have to look here again (won't always work when it's None, but
|
||||
# will catch most)
|
||||
if not effect.getattr('resistanceCalculated'):
|
||||
attrPrefix = effect.getattr('prefix')
|
||||
if attrPrefix:
|
||||
resistanceID = int(modifyingItem.getModifiedItemAttr('{}ResistanceID'.format(attrPrefix))) or None
|
||||
if not resistanceID:
|
||||
resistanceID = int(modifyingItem.getModifiedItemAttr('{}RemoteResistanceID'.format(attrPrefix))) or None
|
||||
effect.resistanceID = int(modifyingItem.getModifiedItemAttr('{}ResistanceID'.format(attrPrefix))) or None
|
||||
if not effect.resistanceID:
|
||||
effect.resistanceID = int(modifyingItem.getModifiedItemAttr('{}RemoteResistanceID'.format(attrPrefix))) or None
|
||||
else:
|
||||
resistanceID = int(modifyingItem.getModifiedItemAttr("remoteResistanceID")) or None
|
||||
resistanceCache[cacheKey] = resistanceID
|
||||
return resistanceID
|
||||
effect.resistanceID = int(modifyingItem.getModifiedItemAttr("remoteResistanceID")) or None
|
||||
effect.resistanceCalculated = True
|
||||
return effect.resistanceID
|
||||
|
||||
|
||||
class ItemAttrShortcut:
|
||||
@@ -72,8 +67,14 @@ class ItemAttrShortcut:
|
||||
return_value = self.itemModifiedAttributes.get(key)
|
||||
return return_value or default
|
||||
|
||||
def getModifiedItemAttrExtended(self, key, extraMultipliers=None, ignoreAfflictors=(), default=0):
|
||||
return_value = self.itemModifiedAttributes.getExtended(key, extraMultipliers=extraMultipliers, ignoreAfflictors=ignoreAfflictors)
|
||||
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 getModifiedItemAttrWithoutAfflictor(self, key, afflictor, default=0):
|
||||
"""Returns attribute value with passed afflictor modification removed."""
|
||||
return_value = self.itemModifiedAttributes.getWithoutAfflictor(key, afflictor)
|
||||
return return_value or default
|
||||
|
||||
def getItemBaseAttrValue(self, key, default=0):
|
||||
@@ -87,8 +88,14 @@ class ChargeAttrShortcut:
|
||||
return_value = self.chargeModifiedAttributes.get(key)
|
||||
return return_value or default
|
||||
|
||||
def getModifiedChargeAttrExtended(self, key, extraMultipliers=None, ignoreAfflictors=(), default=0):
|
||||
return_value = self.chargeModifiedAttributes.getExtended(key, extraMultipliers=extraMultipliers, ignoreAfflictors=ignoreAfflictors)
|
||||
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 getModifiedChargeAttrWithoutAfflictor(self, key, afflictor, default=0):
|
||||
"""Returns attribute value with passed modifiers applied to it."""
|
||||
return_value = self.chargeModifiedAttributes.getWithoutAfflictor(key, afflictor)
|
||||
return return_value or default
|
||||
|
||||
def getChargeBaseAttrValue(self, key, default=0):
|
||||
@@ -204,11 +211,32 @@ class ModifiedAttributeDict(collections.MutableMapping):
|
||||
# Original value is the least priority
|
||||
return self.getOriginal(key)
|
||||
|
||||
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.
|
||||
"""
|
||||
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 getWithoutAfflictor(self, key, afflictor, default=0):
|
||||
# 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
|
||||
@@ -217,8 +245,8 @@ class ModifiedAttributeDict(collections.MutableMapping):
|
||||
ignorePenalizedMultipliers = {}
|
||||
postIncreaseAdjustment = 0
|
||||
for fit, afflictors in self.getAfflictions(key).items():
|
||||
for afflictor, operator, stackingGroup, preResAmount, postResAmount, used in afflictors:
|
||||
if afflictor in ignoreAfflictors:
|
||||
for innerAfflictor, operator, stackingGroup, preResAmount, postResAmount, used in afflictors:
|
||||
if innerAfflictor is afflictor:
|
||||
if operator == Operator.MULTIPLY:
|
||||
if stackingGroup is None:
|
||||
multiplierAdjustment /= postResAmount
|
||||
@@ -229,31 +257,29 @@ class ModifiedAttributeDict(collections.MutableMapping):
|
||||
elif operator == Operator.POSTINCREASE:
|
||||
postIncreaseAdjustment -= postResAmount
|
||||
|
||||
# If we apply no customizations - use regular getter
|
||||
if (
|
||||
not extraMultipliers and
|
||||
preIncreaseAdjustment == 0 and multiplierAdjustment == 1 and
|
||||
postIncreaseAdjustment == 0 and len(ignorePenalizedMultipliers) == 0
|
||||
):
|
||||
if 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, extraMultipliers=extraMultipliers, preIncAdj=preIncreaseAdjustment, multAdj=multiplierAdjustment,
|
||||
key, preIncAdj=preIncreaseAdjustment, multAdj=multiplierAdjustment,
|
||||
postIncAdj=postIncreaseAdjustment, ignorePenMult=ignorePenalizedMultipliers)
|
||||
if val is not None:
|
||||
return val
|
||||
|
||||
# Then the same fallbacks as in regular getter
|
||||
# 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 __delitem__(self, key):
|
||||
@@ -558,12 +584,10 @@ class ModifiedAttributeDict(collections.MutableMapping):
|
||||
if 'projected' not in effectType:
|
||||
return 1
|
||||
remoteResistID = getResistanceAttrID(modifyingItem=fit.getModifier(), effect=effect)
|
||||
if not remoteResistID:
|
||||
return 1
|
||||
attrInfo = getAttributeInfo(remoteResistID)
|
||||
# Get the attribute of the resist
|
||||
resist = fit.ship.itemModifiedAttributes[attrInfo.attributeName] or None
|
||||
return resist or 1
|
||||
return resist or 1.0
|
||||
|
||||
|
||||
class Affliction:
|
||||
|
||||
@@ -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.getModifiedItemAttrExtended("capacitorCapacity", ignoreAfflictors=[mod]),
|
||||
rechargeRate=self.ship.getModifiedItemAttrExtended("rechargeRate", ignoreAfflictors=[mod]) / 1000.0)
|
||||
capacity=self.ship.getModifiedItemAttrWithoutAfflictor("capacitorCapacity", mod),
|
||||
rechargeRate=self.ship.getModifiedItemAttrWithoutAfflictor("rechargeRate", mod) / 1000.0)
|
||||
return currentRegen - nomodRegen
|
||||
|
||||
def getRemoteReps(self, spoolOptions=None):
|
||||
|
||||
@@ -339,7 +339,12 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
duringAcceleration = maxVelocity / 2 * accelTime
|
||||
# Distance done after being at full speed
|
||||
fullSpeed = maxVelocity * (flightTime - accelTime)
|
||||
return duringAcceleration + fullSpeed
|
||||
maxRange = duringAcceleration + fullSpeed
|
||||
if 'fofMissileLaunching' in self.charge.effects:
|
||||
rangeLimit = self.getModifiedChargeAttr("maxFOFTargetRange")
|
||||
if rangeLimit:
|
||||
maxRange = min(maxRange, rangeLimit)
|
||||
return maxRange
|
||||
|
||||
@property
|
||||
def falloff(self):
|
||||
|
||||
@@ -77,8 +77,6 @@ class TargetProfile:
|
||||
|
||||
@signatureRadius.setter
|
||||
def signatureRadius(self, val):
|
||||
if val is not None and math.isinf(val):
|
||||
val = None
|
||||
self._signatureRadius = val
|
||||
|
||||
@property
|
||||
@@ -108,7 +106,7 @@ class TargetProfile:
|
||||
continue
|
||||
line = line.split('#', 1)[0] # allows for comments
|
||||
type, data = line.rsplit('=', 1)
|
||||
type, data = type.strip(), [d.strip() for d in data.split(',')]
|
||||
type, data = type.strip(), data.split(',')
|
||||
except:
|
||||
pyfalog.warning("Data isn't in correct format, continue to next line.")
|
||||
continue
|
||||
@@ -117,13 +115,11 @@ class TargetProfile:
|
||||
continue
|
||||
|
||||
numPatterns += 1
|
||||
name, dataRes, dataMisc = data[0], data[1:5], data[5:8]
|
||||
name, data = data[0], data[1:5]
|
||||
fields = {}
|
||||
|
||||
for index, val in enumerate(dataRes):
|
||||
val = float(val) if val else 0
|
||||
if math.isinf(val):
|
||||
val = 0
|
||||
for index, val in enumerate(data):
|
||||
val = float(val)
|
||||
try:
|
||||
assert 0 <= val <= 100
|
||||
fields["%sAmount" % cls.DAMAGE_TYPES[index]] = val / 100
|
||||
@@ -131,18 +127,7 @@ class TargetProfile:
|
||||
pyfalog.warning("Caught unhandled exception in import patterns.")
|
||||
continue
|
||||
|
||||
if len(dataMisc) == 3:
|
||||
for index, val in enumerate(dataMisc):
|
||||
try:
|
||||
fieldName = ("maxVelocity", "signatureRadius", "radius")[index]
|
||||
except IndexError:
|
||||
break
|
||||
val = float(val) if val else 0
|
||||
if fieldName != "signatureRadius" and math.isinf(val):
|
||||
val = 0
|
||||
fields[fieldName] = val
|
||||
|
||||
if len(fields) in (4, 7): # Avoid possible blank lines
|
||||
if len(fields) == 4: # Avoid possible blank lines
|
||||
if name.strip() in lookup:
|
||||
pattern = lookup[name.strip()]
|
||||
pattern.update(**fields)
|
||||
@@ -157,23 +142,20 @@ class TargetProfile:
|
||||
|
||||
return patterns, numPatterns
|
||||
|
||||
EXPORT_FORMAT = "TargetProfile = %s,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f\n"
|
||||
EXPORT_FORMAT = "TargetProfile = %s,%.1f,%.1f,%.1f,%.1f\n"
|
||||
|
||||
@classmethod
|
||||
def exportPatterns(cls, *patterns):
|
||||
out = "# Exported from pyfa\n#\n"
|
||||
out += "# Values are in following format:\n"
|
||||
out += "# TargetProfile = [name],[EM %],[Thermal %],[Kinetic %],[Explosive %],[Max velocity m/s],[Signature radius m],[Radius m]\n\n"
|
||||
out += "# TargetProfile = [name],[EM %],[Thermal %],[Kinetic %],[Explosive %]\n\n"
|
||||
for dp in patterns:
|
||||
out += cls.EXPORT_FORMAT % (
|
||||
dp.name,
|
||||
dp.emAmount * 100,
|
||||
dp.thermalAmount * 100,
|
||||
dp.kineticAmount * 100,
|
||||
dp.explosiveAmount * 100,
|
||||
dp.maxVelocity,
|
||||
dp.signatureRadius,
|
||||
dp.radius
|
||||
dp.explosiveAmount * 100
|
||||
)
|
||||
|
||||
return out.strip()
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
# ===============================================================================
|
||||
|
||||
|
||||
import math
|
||||
from collections import namedtuple
|
||||
|
||||
from eos.const import SpoolType
|
||||
@@ -36,15 +37,32 @@ def calculateSpoolup(modMaxValue, modStepValue, modCycleTime, spoolType, spoolAm
|
||||
"""
|
||||
if not modMaxValue or not modStepValue:
|
||||
return 0, 0, 0
|
||||
if spoolType == SpoolType.SCALE:
|
||||
cycles = int(floatUnerr(spoolAmount * modMaxValue / modStepValue))
|
||||
return cycles * modStepValue, cycles, cycles * modCycleTime
|
||||
if spoolType == SpoolType.SPOOL_SCALE:
|
||||
# For spool scale, round to closest cycle for scaled spool amount
|
||||
cycles = round(spoolAmount * modMaxValue / modStepValue)
|
||||
spoolValue = min(modMaxValue, cycles * modStepValue)
|
||||
return spoolValue, cycles, cycles * modCycleTime
|
||||
elif spoolType == SpoolType.CYCLE_SCALE:
|
||||
# For cycle scale, find out max amount of cycles and scale against it
|
||||
cycles = round(spoolAmount * math.ceil(floatUnerr(modMaxValue / modStepValue)))
|
||||
spoolValue = min(modMaxValue, cycles * modStepValue)
|
||||
return spoolValue, cycles, cycles * modCycleTime
|
||||
elif spoolType == SpoolType.TIME:
|
||||
cycles = min(int(floatUnerr(spoolAmount / modCycleTime)), int(floatUnerr(modMaxValue / modStepValue)))
|
||||
return cycles * modStepValue, cycles, cycles * modCycleTime
|
||||
cycles = min(
|
||||
# How many full cycles mod had by passed time
|
||||
math.floor(floatUnerr(spoolAmount / modCycleTime)),
|
||||
# Max amount of cycles
|
||||
math.ceil(floatUnerr(modMaxValue / modStepValue)))
|
||||
spoolValue = min(modMaxValue, cycles * modStepValue)
|
||||
return spoolValue, cycles, cycles * modCycleTime
|
||||
elif spoolType == SpoolType.CYCLES:
|
||||
cycles = min(int(spoolAmount), int(floatUnerr(modMaxValue / modStepValue)))
|
||||
return cycles * modStepValue, cycles, cycles * modCycleTime
|
||||
cycles = min(
|
||||
# Consider full cycles only
|
||||
math.floor(spoolAmount),
|
||||
# Max amount of cycles
|
||||
math.ceil(floatUnerr(modMaxValue / modStepValue)))
|
||||
spoolValue = min(modMaxValue, cycles * modStepValue)
|
||||
return spoolValue, cycles, cycles * modCycleTime
|
||||
else:
|
||||
return 0, 0, 0
|
||||
|
||||
|
||||
@@ -26,59 +26,15 @@ 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.activeModulesIter():
|
||||
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.activeModulesIter():
|
||||
if not mod.item:
|
||||
continue
|
||||
if {'moduleBonusMicrowarpdrive', 'microJumpDrive', 'microJumpPortalDrive'}.intersection(mod.item.effects):
|
||||
scrammables.append(mod)
|
||||
return scrammables
|
||||
|
||||
|
||||
def getTackledSpeed(src, tgt, currentUntackledSpeed, srcScramRange, tgtScrammables, webMods, webDrones, webFighters, distance):
|
||||
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'):
|
||||
return currentUntackledSpeed
|
||||
maxUntackledSpeed = tgt.getMaxVelocity()
|
||||
return currentUnwebbedSpeed
|
||||
maxUnwebbedSpeed = tgt.getMaxVelocity()
|
||||
# What's immobile cannot be slowed
|
||||
if maxUntackledSpeed == 0:
|
||||
return maxUntackledSpeed
|
||||
speedRatio = currentUntackledSpeed / maxUntackledSpeed
|
||||
# No scrams or distance is longer than longest scram - nullify scrammables list
|
||||
if srcScramRange is None or (distance is not None and distance > srcScramRange):
|
||||
tgtScrammables = ()
|
||||
if maxUnwebbedSpeed == 0:
|
||||
return maxUnwebbedSpeed
|
||||
speedRatio = currentUnwebbedSpeed / maxUnwebbedSpeed
|
||||
appliedMultipliers = {}
|
||||
# Modules first, they are applied always the same way
|
||||
for wData in webMods:
|
||||
@@ -88,8 +44,8 @@ def getTackledSpeed(src, tgt, currentUntackledSpeed, srcScramRange, tgtScrammabl
|
||||
distance=distance)
|
||||
if appliedBoost:
|
||||
appliedMultipliers.setdefault(wData.stackingGroup, []).append((1 + appliedBoost / 100, wData.resAttrID))
|
||||
maxTackledSpeed = tgt.getMaxVelocity(extraMultipliers=appliedMultipliers, ignoreAfflictors=tgtScrammables)
|
||||
currentTackledSpeed = maxTackledSpeed * speedRatio
|
||||
maxWebbedSpeed = tgt.getMaxVelocity(extraMultipliers=appliedMultipliers)
|
||||
currentWebbedSpeed = maxWebbedSpeed * speedRatio
|
||||
# Drones and fighters
|
||||
mobileWebs = []
|
||||
mobileWebs.extend(webFighters)
|
||||
@@ -104,8 +60,8 @@ def getTackledSpeed(src, tgt, currentUntackledSpeed, srcScramRange, tgtScrammabl
|
||||
for mwData in longEnoughMws:
|
||||
appliedMultipliers.setdefault(mwData.stackingGroup, []).append((1 + mwData.boost / 100, mwData.resAttrID))
|
||||
mobileWebs.remove(mwData)
|
||||
maxTackledSpeed = tgt.getMaxVelocity(extraMultipliers=appliedMultipliers, ignoreAfflictors=tgtScrammables)
|
||||
currentTackledSpeed = maxTackledSpeed * speedRatio
|
||||
maxWebbedSpeed = tgt.getMaxVelocity(extraMultipliers=appliedMultipliers)
|
||||
currentWebbedSpeed = maxWebbedSpeed * speedRatio
|
||||
# Apply remaining webs, from fastest to slowest
|
||||
droneOpt = GraphSettings.getInstance().get('mobileDroneMode')
|
||||
while mobileWebs:
|
||||
@@ -114,7 +70,7 @@ def getTackledSpeed(src, tgt, currentUntackledSpeed, srcScramRange, tgtScrammabl
|
||||
fastestMws = [mw for mw in mobileWebs if mw.speed == fastestMwSpeed]
|
||||
for mwData in fastestMws:
|
||||
# Faster than target or set to follow it - apply full slowdown
|
||||
if (droneOpt == GraphDpsDroneMode.auto and mwData.speed >= currentTackledSpeed) or droneOpt == GraphDpsDroneMode.followTarget:
|
||||
if (droneOpt == GraphDpsDroneMode.auto and mwData.speed >= currentWebbedSpeed) or droneOpt == GraphDpsDroneMode.followTarget:
|
||||
appliedMwBoost = mwData.boost
|
||||
# Otherwise project from the center of the ship
|
||||
else:
|
||||
@@ -128,21 +84,18 @@ def getTackledSpeed(src, tgt, currentUntackledSpeed, srcScramRange, tgtScrammabl
|
||||
distance=rangeFactorDistance)
|
||||
appliedMultipliers.setdefault(mwData.stackingGroup, []).append((1 + appliedMwBoost / 100, mwData.resAttrID))
|
||||
mobileWebs.remove(mwData)
|
||||
maxTackledSpeed = tgt.getMaxVelocity(extraMultipliers=appliedMultipliers, ignoreAfflictors=tgtScrammables)
|
||||
currentTackledSpeed = maxTackledSpeed * speedRatio
|
||||
maxWebbedSpeed = tgt.getMaxVelocity(extraMultipliers=appliedMultipliers)
|
||||
currentWebbedSpeed = maxWebbedSpeed * speedRatio
|
||||
# Ensure consistent results - round off a little to avoid float errors
|
||||
return floatUnerr(currentTackledSpeed)
|
||||
return floatUnerr(currentWebbedSpeed)
|
||||
|
||||
|
||||
def getSigRadiusMult(src, tgt, tgtSpeed, srcScramRange, tgtScrammables, tpMods, tpDrones, tpFighters, distance):
|
||||
def getTpMult(src, tgt, tgtSpeed, tpMods, tpDrones, tpFighters, distance):
|
||||
# Can blow non-immune ships and target profiles
|
||||
if tgt.isFit and tgt.item.ship.getModifiedItemAttr('disallowOffensiveModifiers'):
|
||||
return 1
|
||||
initSig = tgt.getSigRadius()
|
||||
# No scrams or distance is longer than longest scram - nullify scrammables list
|
||||
if srcScramRange is None or (distance is not None and distance > srcScramRange):
|
||||
tgtScrammables = ()
|
||||
# TPing modules
|
||||
untpedSig = tgt.getSigRadius()
|
||||
# Modules
|
||||
appliedMultipliers = {}
|
||||
for tpData in tpMods:
|
||||
appliedBoost = tpData.boost * calculateRangeFactor(
|
||||
@@ -151,7 +104,7 @@ def getSigRadiusMult(src, tgt, tgtSpeed, srcScramRange, tgtScrammables, tpMods,
|
||||
distance=distance)
|
||||
if appliedBoost:
|
||||
appliedMultipliers.setdefault(tpData.stackingGroup, []).append((1 + appliedBoost / 100, tpData.resAttrID))
|
||||
# TPing drones
|
||||
# Drones and fighters
|
||||
mobileTps = []
|
||||
mobileTps.extend(tpFighters)
|
||||
# Drones have range limit
|
||||
@@ -174,9 +127,9 @@ def getSigRadiusMult(src, tgt, tgtSpeed, srcScramRange, tgtScrammables, tpMods,
|
||||
srcFalloffRange=mtpData.falloff,
|
||||
distance=rangeFactorDistance)
|
||||
appliedMultipliers.setdefault(mtpData.stackingGroup, []).append((1 + appliedMtpBoost / 100, mtpData.resAttrID))
|
||||
modifiedSig = tgt.getSigRadius(extraMultipliers=appliedMultipliers, ignoreAfflictors=tgtScrammables)
|
||||
if modifiedSig == math.inf and initSig == math.inf:
|
||||
tpedSig = tgt.getSigRadius(extraMultipliers=appliedMultipliers)
|
||||
if tpedSig == math.inf and untpedSig == math.inf:
|
||||
return 1
|
||||
mult = modifiedSig / initSig
|
||||
mult = tpedSig / untpedSig
|
||||
# Ensure consistent results - round off a little to avoid float errors
|
||||
return floatUnerr(mult)
|
||||
|
||||
@@ -24,7 +24,7 @@ from eos.utils.stats import DmgTypes
|
||||
from graphs.data.base import PointGetter, SmoothPointGetter
|
||||
from service.settings import GraphSettings
|
||||
from .calc.application import getApplicationPerKey
|
||||
from .calc.projected import getScramRange, getScrammables, getTackledSpeed, getSigRadiusMult
|
||||
from .calc.projected import getTpMult, getWebbedSpeed
|
||||
|
||||
|
||||
def applyDamage(dmgMap, applicationMap, tgtResists):
|
||||
@@ -54,7 +54,7 @@ class YDpsMixin:
|
||||
for mod in src.item.activeModulesIter():
|
||||
if not mod.isDealingDamage():
|
||||
continue
|
||||
dpsMap[mod] = mod.getDps(spoolOptions=SpoolOptions(SpoolType.SCALE, defaultSpoolValue, False))
|
||||
dpsMap[mod] = mod.getDps(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, defaultSpoolValue, False))
|
||||
for drone in src.item.activeDronesIter():
|
||||
if not drone.isDealingDamage():
|
||||
continue
|
||||
@@ -88,7 +88,7 @@ class YVolleyMixin:
|
||||
for mod in src.item.activeModulesIter():
|
||||
if not mod.isDealingDamage():
|
||||
continue
|
||||
volleyMap[mod] = mod.getVolley(spoolOptions=SpoolOptions(SpoolType.SCALE, defaultSpoolValue, False))
|
||||
volleyMap[mod] = mod.getVolley(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, defaultSpoolValue, False))
|
||||
for drone in src.item.activeDronesIter():
|
||||
if not drone.isDealingDamage():
|
||||
continue
|
||||
@@ -138,11 +138,8 @@ class XDistanceMixin(SmoothPointGetter):
|
||||
# Prepare time cache here because we need to do it only once,
|
||||
# and this function is called once per point info fetch
|
||||
self._prepareTimeCache(src=src, maxTime=miscParams['time'])
|
||||
applyProjected = GraphSettings.getInstance().get('applyProjected')
|
||||
return {
|
||||
'applyProjected': applyProjected,
|
||||
'srcScramRange': getScramRange(src=src) if applyProjected else None,
|
||||
'tgtScrammables': getScrammables(tgt=tgt) if applyProjected else (),
|
||||
'applyProjected': GraphSettings.getInstance().get('applyProjected'),
|
||||
'dmgMap': self._getDamagePerKey(src=src, time=miscParams['time']),
|
||||
'tgtResists': tgt.getResists()}
|
||||
|
||||
@@ -154,22 +151,18 @@ class XDistanceMixin(SmoothPointGetter):
|
||||
webMods, tpMods = self.graph._projectedCache.getProjModData(src)
|
||||
webDrones, tpDrones = self.graph._projectedCache.getProjDroneData(src)
|
||||
webFighters, tpFighters = self.graph._projectedCache.getProjFighterData(src)
|
||||
tgtSpeed = getTackledSpeed(
|
||||
tgtSpeed = getWebbedSpeed(
|
||||
src=src,
|
||||
tgt=tgt,
|
||||
currentUntackledSpeed=tgtSpeed,
|
||||
srcScramRange=commonData['srcScramRange'],
|
||||
tgtScrammables=commonData['tgtScrammables'],
|
||||
currentUnwebbedSpeed=tgtSpeed,
|
||||
webMods=webMods,
|
||||
webDrones=webDrones,
|
||||
webFighters=webFighters,
|
||||
distance=distance)
|
||||
tgtSigRadius = tgtSigRadius * getSigRadiusMult(
|
||||
tgtSigRadius = tgtSigRadius * getTpMult(
|
||||
src=src,
|
||||
tgt=tgt,
|
||||
tgtSpeed=tgtSpeed,
|
||||
srcScramRange=commonData['srcScramRange'],
|
||||
tgtScrammables=commonData['tgtScrammables'],
|
||||
tpMods=tpMods,
|
||||
tpDrones=tpDrones,
|
||||
tpFighters=tpFighters,
|
||||
@@ -196,27 +189,21 @@ class XTimeMixin(PointGetter):
|
||||
tgtSpeed = miscParams['tgtSpeed']
|
||||
tgtSigRadius = tgt.getSigRadius()
|
||||
if GraphSettings.getInstance().get('applyProjected'):
|
||||
srcScramRange = getScramRange(src=src)
|
||||
tgtScrammables = getScrammables(tgt=tgt)
|
||||
webMods, tpMods = self.graph._projectedCache.getProjModData(src)
|
||||
webDrones, tpDrones = self.graph._projectedCache.getProjDroneData(src)
|
||||
webFighters, tpFighters = self.graph._projectedCache.getProjFighterData(src)
|
||||
tgtSpeed = getTackledSpeed(
|
||||
tgtSpeed = getWebbedSpeed(
|
||||
src=src,
|
||||
tgt=tgt,
|
||||
currentUntackledSpeed=tgtSpeed,
|
||||
srcScramRange=srcScramRange,
|
||||
tgtScrammables=tgtScrammables,
|
||||
currentUnwebbedSpeed=tgtSpeed,
|
||||
webMods=webMods,
|
||||
webDrones=webDrones,
|
||||
webFighters=webFighters,
|
||||
distance=miscParams['distance'])
|
||||
tgtSigRadius = tgtSigRadius * getSigRadiusMult(
|
||||
tgtSigRadius = tgtSigRadius * getTpMult(
|
||||
src=src,
|
||||
tgt=tgt,
|
||||
tgtSpeed=tgtSpeed,
|
||||
srcScramRange=srcScramRange,
|
||||
tgtScrammables=tgtScrammables,
|
||||
tpMods=tpMods,
|
||||
tpDrones=tpDrones,
|
||||
tpFighters=tpFighters,
|
||||
@@ -316,27 +303,21 @@ class XTgtSpeedMixin(SmoothPointGetter):
|
||||
tgtSpeed = x
|
||||
tgtSigRadius = tgt.getSigRadius()
|
||||
if commonData['applyProjected']:
|
||||
srcScramRange = getScramRange(src=src)
|
||||
tgtScrammables = getScrammables(tgt=tgt)
|
||||
webMods, tpMods = self.graph._projectedCache.getProjModData(src)
|
||||
webDrones, tpDrones = self.graph._projectedCache.getProjDroneData(src)
|
||||
webFighters, tpFighters = self.graph._projectedCache.getProjFighterData(src)
|
||||
tgtSpeed = getTackledSpeed(
|
||||
tgtSpeed = getWebbedSpeed(
|
||||
src=src,
|
||||
tgt=tgt,
|
||||
currentUntackledSpeed=tgtSpeed,
|
||||
srcScramRange=srcScramRange,
|
||||
tgtScrammables=tgtScrammables,
|
||||
currentUnwebbedSpeed=tgtSpeed,
|
||||
webMods=webMods,
|
||||
webDrones=webDrones,
|
||||
webFighters=webFighters,
|
||||
distance=miscParams['distance'])
|
||||
tgtSigRadius = tgtSigRadius * getSigRadiusMult(
|
||||
tgtSigRadius = tgtSigRadius * getTpMult(
|
||||
src=src,
|
||||
tgt=tgt,
|
||||
tgtSpeed=tgtSpeed,
|
||||
srcScramRange=srcScramRange,
|
||||
tgtScrammables=tgtScrammables,
|
||||
tpMods=tpMods,
|
||||
tpDrones=tpDrones,
|
||||
tpFighters=tpFighters,
|
||||
@@ -366,27 +347,21 @@ class XTgtSigRadiusMixin(SmoothPointGetter):
|
||||
tgtSpeed = miscParams['tgtSpeed']
|
||||
tgtSigMult = 1
|
||||
if GraphSettings.getInstance().get('applyProjected'):
|
||||
srcScramRange = getScramRange(src=src)
|
||||
tgtScrammables = getScrammables(tgt=tgt)
|
||||
webMods, tpMods = self.graph._projectedCache.getProjModData(src)
|
||||
webDrones, tpDrones = self.graph._projectedCache.getProjDroneData(src)
|
||||
webFighters, tpFighters = self.graph._projectedCache.getProjFighterData(src)
|
||||
tgtSpeed = getTackledSpeed(
|
||||
tgtSpeed = getWebbedSpeed(
|
||||
src=src,
|
||||
tgt=tgt,
|
||||
currentUntackledSpeed=tgtSpeed,
|
||||
srcScramRange=srcScramRange,
|
||||
tgtScrammables=tgtScrammables,
|
||||
currentUnwebbedSpeed=tgtSpeed,
|
||||
webMods=webMods,
|
||||
webDrones=webDrones,
|
||||
webFighters=webFighters,
|
||||
distance=miscParams['distance'])
|
||||
tgtSigMult = getSigRadiusMult(
|
||||
tgtSigMult = getTpMult(
|
||||
src=src,
|
||||
tgt=tgt,
|
||||
tgtSpeed=tgtSpeed,
|
||||
srcScramRange=srcScramRange,
|
||||
tgtScrammables=tgtScrammables,
|
||||
tpMods=tpMods,
|
||||
tpDrones=tpDrones,
|
||||
tpFighters=tpFighters,
|
||||
|
||||
@@ -50,7 +50,7 @@ class YRpsMixin:
|
||||
isAncShield = 'shipModuleAncillaryRemoteShieldBooster' in mod.item.effects
|
||||
isAncArmor = 'shipModuleAncillaryRemoteArmorRepairer' in mod.item.effects
|
||||
rpsMap[mod] = mod.getRemoteReps(
|
||||
spoolOptions=SpoolOptions(SpoolType.SCALE, defaultSpoolValue, False),
|
||||
spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, defaultSpoolValue, False),
|
||||
reloadOverride=ancReload if (isAncShield or isAncArmor) else None)
|
||||
for drone in src.item.activeDronesIter():
|
||||
if not drone.isRemoteRepping():
|
||||
|
||||
@@ -106,9 +106,7 @@ class GraphCanvasPanel(wx.Panel):
|
||||
legendData = []
|
||||
chosenX = self.graphFrame.ctrlPanel.xType
|
||||
chosenY = self.graphFrame.ctrlPanel.yType
|
||||
self.subplot.set(
|
||||
xlabel=self.graphFrame.ctrlPanel.formatLabel(chosenX),
|
||||
ylabel=self.graphFrame.ctrlPanel.formatLabel(chosenY))
|
||||
self.subplot.set(xlabel=self.graphFrame.ctrlPanel.formatLabel(chosenX), ylabel=self.graphFrame.ctrlPanel.formatLabel(chosenY))
|
||||
|
||||
mainInput, miscInputs = self.graphFrame.ctrlPanel.getValues()
|
||||
view = self.graphFrame.getView()
|
||||
@@ -188,7 +186,6 @@ class GraphCanvasPanel(wx.Panel):
|
||||
if minX is not None and maxX is not None:
|
||||
minY = min(allYs, default=None)
|
||||
maxY = max(allYs, default=None)
|
||||
yDiff = (maxY or 0) - (minY or 0)
|
||||
xMark = max(min(self.xMark, maxX), minX)
|
||||
# If in top 10% of X coordinates, align labels differently
|
||||
if xMark > canvasMinX + 0.9 * (canvasMaxX - canvasMinX):
|
||||
@@ -215,16 +212,14 @@ class GraphCanvasPanel(wx.Panel):
|
||||
def addYMark(val):
|
||||
if val is None:
|
||||
return
|
||||
# Round according to shown Y range - the bigger the range,
|
||||
# the rougher the rounding
|
||||
if yDiff != 0:
|
||||
rounded = roundToPrec(val, 4, nsValue=yDiff)
|
||||
else:
|
||||
rounded = val
|
||||
# If due to some bug or insufficient plot density we're
|
||||
# out of bounds, do not add anything
|
||||
if minY <= val <= maxY or minY <= rounded <= maxY:
|
||||
yMarks.add(rounded)
|
||||
if minY <= val <= maxY:
|
||||
if abs(val) < 0.0001:
|
||||
val = 0
|
||||
else:
|
||||
val = roundToPrec(val, 4)
|
||||
yMarks.add(val)
|
||||
|
||||
for source, target in iterList:
|
||||
xs, ys = plotData[(source, target)]
|
||||
|
||||
@@ -38,9 +38,6 @@ from .ctrlPanel import GraphControlPanel
|
||||
pyfalog = Logger(__name__)
|
||||
|
||||
|
||||
REDRAW_DELAY = 500
|
||||
|
||||
|
||||
class GraphFrame(AuxiliaryFrame):
|
||||
|
||||
def __init__(self, parent):
|
||||
@@ -48,7 +45,7 @@ class GraphFrame(AuxiliaryFrame):
|
||||
pyfalog.warning('Matplotlib is not enabled. Skipping initialization.')
|
||||
return
|
||||
|
||||
super().__init__(parent, title='Graphs', size=(520, 390), resizeable=True)
|
||||
super().__init__(parent, title='Graphs', style=wx.RESIZE_BORDER, size=(520, 390))
|
||||
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
|
||||
|
||||
self.SetIcon(wx.Icon(BitmapLoader.getBitmap('graphs_small', 'gui')))
|
||||
@@ -93,9 +90,6 @@ class GraphFrame(AuxiliaryFrame):
|
||||
self.mainFrame.Bind(GE.GRAPH_OPTION_CHANGED, self.OnGraphOptionChanged)
|
||||
self.mainFrame.Bind(GE.EFFECTIVE_HP_TOGGLED, self.OnEffectiveHpToggled)
|
||||
|
||||
self.drawTimer = wx.Timer(self)
|
||||
self.Bind(wx.EVT_TIMER, self.OnDrawTimer, self.drawTimer)
|
||||
|
||||
self.Layout()
|
||||
self.UpdateWindowSize()
|
||||
self.draw()
|
||||
@@ -134,10 +128,7 @@ class GraphFrame(AuxiliaryFrame):
|
||||
for fitID in event.fitIDs:
|
||||
self.clearCache(reason=GraphCacheCleanupReason.fitChanged, extraData=fitID)
|
||||
self.ctrlPanel.OnFitChanged(event)
|
||||
# Data has to be recalculated - delay redraw
|
||||
# to give time to finish UI update in main window
|
||||
self.drawTimer.Stop()
|
||||
self.drawTimer.Start(REDRAW_DELAY, True)
|
||||
self.draw()
|
||||
|
||||
def OnFitRemoved(self, event):
|
||||
event.Skip()
|
||||
@@ -193,10 +184,7 @@ class GraphFrame(AuxiliaryFrame):
|
||||
self.ctrlPanel.refreshAxeLabels(restoreSelection=True)
|
||||
self.Layout()
|
||||
self.clearCache(reason=GraphCacheCleanupReason.hpEffectivityChanged)
|
||||
# Data has to be recalculated - delay redraw
|
||||
# to give time to finish UI update in main window
|
||||
self.drawTimer.Stop()
|
||||
self.drawTimer.Start(REDRAW_DELAY, True)
|
||||
self.draw()
|
||||
# Even if graph is not selected, keep it updated
|
||||
for idx in range(self.graphSelection.GetCount()):
|
||||
view = self.getView(idx=idx)
|
||||
@@ -214,10 +202,6 @@ class GraphFrame(AuxiliaryFrame):
|
||||
self.draw()
|
||||
event.Skip()
|
||||
|
||||
def OnDrawTimer(self, event):
|
||||
event.Skip()
|
||||
self.draw()
|
||||
|
||||
def OnClose(self, event):
|
||||
self.mainFrame.Unbind(GE.FIT_RENAMED, handler=self.OnFitRenamed)
|
||||
self.mainFrame.Unbind(GE.FIT_CHANGED, handler=self.OnFitChanged)
|
||||
|
||||
@@ -54,13 +54,10 @@ class BaseWrapper:
|
||||
return self.item.name
|
||||
return ''
|
||||
|
||||
def getMaxVelocity(self, extraMultipliers=None, ignoreAfflictors=()):
|
||||
def getMaxVelocity(self, extraMultipliers=None):
|
||||
if self.isFit:
|
||||
if extraMultipliers or ignoreAfflictors:
|
||||
maxVelocity = self.item.ship.getModifiedItemAttrExtended(
|
||||
'maxVelocity',
|
||||
extraMultipliers=extraMultipliers,
|
||||
ignoreAfflictors=ignoreAfflictors)
|
||||
if extraMultipliers:
|
||||
maxVelocity = self.item.ship.getModifiedItemAttrWithExtraMods('maxVelocity', extraMultipliers=extraMultipliers)
|
||||
else:
|
||||
maxVelocity = self.item.ship.getModifiedItemAttr('maxVelocity')
|
||||
elif self.isProfile:
|
||||
@@ -71,13 +68,10 @@ class BaseWrapper:
|
||||
maxVelocity = None
|
||||
return maxVelocity
|
||||
|
||||
def getSigRadius(self, extraMultipliers=None, ignoreAfflictors=()):
|
||||
def getSigRadius(self, extraMultipliers=None):
|
||||
if self.isFit:
|
||||
if extraMultipliers or ignoreAfflictors:
|
||||
sigRadius = self.item.ship.getModifiedItemAttrExtended(
|
||||
'signatureRadius',
|
||||
extraMultipliers=extraMultipliers,
|
||||
ignoreAfflictors=ignoreAfflictors)
|
||||
if extraMultipliers:
|
||||
sigRadius = self.item.ship.getModifiedItemAttrWithExtraMods('signatureRadius', extraMultipliers=extraMultipliers)
|
||||
else:
|
||||
sigRadius = self.item.ship.getModifiedItemAttr('signatureRadius')
|
||||
elif self.isProfile:
|
||||
|
||||
@@ -26,10 +26,8 @@ class AuxiliaryFrame(wx.Frame):
|
||||
|
||||
_instance = None
|
||||
|
||||
def __init__(self, parent, id=None, title=None, pos=None, size=None, style=None, name=None, resizeable=False):
|
||||
def __init__(self, parent, id=None, title=None, pos=None, size=None, style=None, name=None):
|
||||
baseStyle = wx.FRAME_NO_TASKBAR | wx.FRAME_FLOAT_ON_PARENT | wx.CAPTION | wx.CLOSE_BOX | wx.SYSTEM_MENU
|
||||
if resizeable:
|
||||
baseStyle = baseStyle | wx.RESIZE_BORDER | wx.MAXIMIZE_BOX
|
||||
kwargs = {
|
||||
'parent': parent,
|
||||
'style': baseStyle if style is None else baseStyle | style}
|
||||
|
||||
@@ -17,7 +17,7 @@ class GraphDmgApplyProjectedMenu(ContextMenuUnconditional):
|
||||
return srcContext == 'dmgStatsGraph'
|
||||
|
||||
def getText(self, callingWindow, itmContext):
|
||||
return 'Apply Projected Items'
|
||||
return 'Apply Attacker Webs and TPs'
|
||||
|
||||
def activate(self, callingWindow, fullContext, i):
|
||||
self.settings.set('applyProjected', not self.settings.get('applyProjected'))
|
||||
|
||||
@@ -51,7 +51,6 @@ class ChangeItemToVariation(ContextMenuCombined):
|
||||
def getSubMenu(self, callingWindow, context, mainItem, selection, rootMenu, i, pitem):
|
||||
self.moduleLookup = {}
|
||||
sFit = Fit.getInstance()
|
||||
sMkt = Market.getInstance()
|
||||
fit = sFit.getFit(self.mainFrame.getActiveFit())
|
||||
|
||||
def get_metalevel(x):
|
||||
@@ -62,8 +61,7 @@ class ChangeItemToVariation(ContextMenuCombined):
|
||||
def get_metagroup(x):
|
||||
# We want deadspace before officer mods
|
||||
remap = {5: 6, 6: 5}
|
||||
metaGroup = sMkt.getMetaGroupByItem(x)
|
||||
return remap.get(metaGroup.ID, metaGroup.ID) if metaGroup is not None else 0
|
||||
return remap.get(x.metaGroup.ID, x.metaGroup.ID) if x.metaGroup is not None else 0
|
||||
|
||||
def get_boosterrank(x):
|
||||
# If we're returning a lot of items, sort my name
|
||||
@@ -86,9 +84,7 @@ class ChangeItemToVariation(ContextMenuCombined):
|
||||
bindmenu = m
|
||||
|
||||
# Do not show abyssal items
|
||||
items = list(
|
||||
i for i in self.mainVariations
|
||||
if sMkt.getMetaGroupByItem(i) is None or sMkt.getMetaGroupByItem(i).ID != 15)
|
||||
items = list(i for i in self.mainVariations if i.metaGroup is None or i.metaGroup.ID != 15)
|
||||
# Sort items by metalevel, and group within that metalevel
|
||||
# Sort all items by name first
|
||||
items.sort(key=lambda x: x.name)
|
||||
@@ -106,13 +102,12 @@ class ChangeItemToVariation(ContextMenuCombined):
|
||||
group = None
|
||||
for item in items:
|
||||
# Apparently no metaGroup for the Tech I variant:
|
||||
metaGroup = sMkt.getMetaGroupByItem(item)
|
||||
if 'subSystem' in item.effects:
|
||||
thisgroup = item.marketGroup.marketGroupName
|
||||
elif metaGroup is None:
|
||||
elif item.metaGroup is None:
|
||||
thisgroup = 'Tech I'
|
||||
else:
|
||||
thisgroup = metaGroup.name
|
||||
thisgroup = item.metaGroup.name
|
||||
|
||||
if thisgroup != group and context not in ('implantItem', 'boosterItem'):
|
||||
group = thisgroup
|
||||
|
||||
@@ -45,10 +45,10 @@ class ChangeModuleSpool(ContextMenuSingle):
|
||||
bindmenu = m
|
||||
|
||||
isNotDefault = self.mod.spoolType is not None and self.mod.spoolAmount is not None
|
||||
cycleDefault = self.mod.getSpoolData(spoolOptions=SpoolOptions(SpoolType.SCALE, eos.config.settings['globalDefaultSpoolupPercentage'], True))[0]
|
||||
cycleCurrent = self.mod.getSpoolData(spoolOptions=SpoolOptions(SpoolType.SCALE, eos.config.settings['globalDefaultSpoolupPercentage'], False))[0]
|
||||
cycleMin = self.mod.getSpoolData(spoolOptions=SpoolOptions(SpoolType.SCALE, 0, True))[0]
|
||||
cycleMax = self.mod.getSpoolData(spoolOptions=SpoolOptions(SpoolType.SCALE, 1, True))[0]
|
||||
cycleDefault = self.mod.getSpoolData(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, eos.config.settings['globalDefaultSpoolupPercentage'], True))[0]
|
||||
cycleCurrent = self.mod.getSpoolData(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, eos.config.settings['globalDefaultSpoolupPercentage'], False))[0]
|
||||
cycleMin = self.mod.getSpoolData(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, 0, True))[0]
|
||||
cycleMax = self.mod.getSpoolData(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, 1, True))[0]
|
||||
cycleTotalMin = min(cycleDefault, cycleCurrent, cycleMin)
|
||||
cycleTotalMax = max(cycleDefault, cycleCurrent, cycleMax)
|
||||
|
||||
|
||||
@@ -344,13 +344,14 @@ class FitItem(SFItem.SFBrowserItem):
|
||||
if mstate.GetModifiers() == wx.MOD_SHIFT or mstate.MiddleIsDown():
|
||||
self.deleteFit()
|
||||
else:
|
||||
dlg = wx.MessageDialog(
|
||||
self, "Do you really want to delete this fit?", "Confirm Delete",
|
||||
wx.YES | wx.NO | wx.ICON_QUESTION)
|
||||
if dlg.ShowModal() == wx.ID_YES:
|
||||
self.deleteFit()
|
||||
else:
|
||||
dlg.Destroy()
|
||||
with wx.MessageDialog(
|
||||
self,
|
||||
"Do you really want to delete this fit?",
|
||||
"Confirm Delete",
|
||||
wx.YES | wx.NO | wx.ICON_QUESTION
|
||||
) as dlg:
|
||||
if dlg.ShowModal() == wx.ID_YES:
|
||||
self.deleteFit()
|
||||
|
||||
def deleteFit(self, event=None):
|
||||
pyfalog.debug("Deleting ship fit.")
|
||||
|
||||
@@ -163,9 +163,9 @@ class FirepowerViewFull(StatsView):
|
||||
stats = (
|
||||
(
|
||||
"labelFullDpsWeapon",
|
||||
lambda: fit.getWeaponDps(spoolOptions=SpoolOptions(SpoolType.SCALE, defaultSpoolValue, False)).total,
|
||||
lambda: fit.getWeaponDps(spoolOptions=SpoolOptions(SpoolType.SCALE, 0, True)).total,
|
||||
lambda: fit.getWeaponDps(spoolOptions=SpoolOptions(SpoolType.SCALE, 1, True)).total,
|
||||
lambda: fit.getWeaponDps(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, defaultSpoolValue, False)).total,
|
||||
lambda: fit.getWeaponDps(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, 0, True)).total,
|
||||
lambda: fit.getWeaponDps(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, 1, True)).total,
|
||||
3, 0, 0, "{}{} DPS"),
|
||||
(
|
||||
"labelFullDpsDrone",
|
||||
@@ -175,15 +175,15 @@ class FirepowerViewFull(StatsView):
|
||||
3, 0, 0, "{}{} DPS"),
|
||||
(
|
||||
"labelFullVolleyTotal",
|
||||
lambda: fit.getTotalVolley(spoolOptions=SpoolOptions(SpoolType.SCALE, defaultSpoolValue, False)).total,
|
||||
lambda: fit.getTotalVolley(spoolOptions=SpoolOptions(SpoolType.SCALE, 0, True)).total,
|
||||
lambda: fit.getTotalVolley(spoolOptions=SpoolOptions(SpoolType.SCALE, 1, True)).total,
|
||||
lambda: fit.getTotalVolley(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, defaultSpoolValue, False)).total,
|
||||
lambda: fit.getTotalVolley(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, 0, True)).total,
|
||||
lambda: fit.getTotalVolley(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, 1, True)).total,
|
||||
3, 0, 0, "{}{}"),
|
||||
(
|
||||
"labelFullDpsTotal",
|
||||
lambda: fit.getTotalDps(spoolOptions=SpoolOptions(SpoolType.SCALE, defaultSpoolValue, False)).total,
|
||||
lambda: fit.getTotalDps(spoolOptions=SpoolOptions(SpoolType.SCALE, 0, True)).total,
|
||||
lambda: fit.getTotalDps(spoolOptions=SpoolOptions(SpoolType.SCALE, 1, True)).total,
|
||||
lambda: fit.getTotalDps(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, defaultSpoolValue, False)).total,
|
||||
lambda: fit.getTotalDps(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, 0, True)).total,
|
||||
lambda: fit.getTotalDps(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, 1, True)).total,
|
||||
3, 0, 0, "{}{}"))
|
||||
|
||||
counter = 0
|
||||
|
||||
@@ -29,27 +29,27 @@ import eos.config
|
||||
stats = [
|
||||
(
|
||||
"labelRemoteCapacitor", "Capacitor:", "{}{} GJ/s", "capacitorInfo", "Capacitor restored",
|
||||
lambda fit, spool: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SCALE, spool, False)).capacitor,
|
||||
lambda fit: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SCALE, 0, True)).capacitor,
|
||||
lambda fit: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SCALE, 1, True)).capacitor,
|
||||
lambda fit, spool: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, spool, False)).capacitor,
|
||||
lambda fit: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, 0, True)).capacitor,
|
||||
lambda fit: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, 1, True)).capacitor,
|
||||
3, 0, 0),
|
||||
(
|
||||
"labelRemoteShield", "Shield:", "{}{} HP/s", "shieldActive", "Shield restored",
|
||||
lambda fit, spool: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SCALE, spool, False)).shield,
|
||||
lambda fit: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SCALE, 0, True)).shield,
|
||||
lambda fit: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SCALE, 1, True)).shield,
|
||||
lambda fit, spool: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, spool, False)).shield,
|
||||
lambda fit: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, 0, True)).shield,
|
||||
lambda fit: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, 1, True)).shield,
|
||||
3, 0, 0),
|
||||
(
|
||||
"labelRemoteArmor", "Armor:", "{}{} HP/s", "armorActive", "Armor restored",
|
||||
lambda fit, spool: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SCALE, spool, False)).armor,
|
||||
lambda fit: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SCALE, 0, True)).armor,
|
||||
lambda fit: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SCALE, 1, True)).armor,
|
||||
lambda fit, spool: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, spool, False)).armor,
|
||||
lambda fit: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, 0, True)).armor,
|
||||
lambda fit: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, 1, True)).armor,
|
||||
3, 0, 0),
|
||||
(
|
||||
"labelRemoteHull", "Hull:", "{}{} HP/s", "hullActive", "Hull restored",
|
||||
lambda fit, spool: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SCALE, spool, False)).hull,
|
||||
lambda fit: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SCALE, 0, True)).hull,
|
||||
lambda fit: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SCALE, 1, True)).hull,
|
||||
lambda fit, spool: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, spool, False)).hull,
|
||||
lambda fit: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, 0, True)).hull,
|
||||
lambda fit: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, 1, True)).hull,
|
||||
3, 0, 0)]
|
||||
|
||||
|
||||
|
||||
@@ -28,27 +28,27 @@ import eos.config
|
||||
stats = [
|
||||
(
|
||||
"labelRemoteCapacitor", "Capacitor:", "{}{} GJ/s", "capacitorInfo", "Capacitor restored",
|
||||
lambda fit, spool: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SCALE, spool, False)).capacitor,
|
||||
lambda fit: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SCALE, 0, True)).capacitor,
|
||||
lambda fit: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SCALE, 1, True)).capacitor,
|
||||
lambda fit, spool: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, spool, False)).capacitor,
|
||||
lambda fit: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, 0, True)).capacitor,
|
||||
lambda fit: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, 1, True)).capacitor,
|
||||
3, 0, 0),
|
||||
(
|
||||
"labelRemoteShield", "Shield:", "{}{} HP/s", "shieldActive", "Shield restored",
|
||||
lambda fit, spool: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SCALE, spool, False)).shield,
|
||||
lambda fit: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SCALE, 0, True)).shield,
|
||||
lambda fit: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SCALE, 1, True)).shield,
|
||||
lambda fit, spool: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, spool, False)).shield,
|
||||
lambda fit: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, 0, True)).shield,
|
||||
lambda fit: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, 1, True)).shield,
|
||||
3, 0, 0),
|
||||
(
|
||||
"labelRemoteArmor", "Armor:", "{}{} HP/s", "armorActive", "Armor restored",
|
||||
lambda fit, spool: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SCALE, spool, False)).armor,
|
||||
lambda fit: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SCALE, 0, True)).armor,
|
||||
lambda fit: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SCALE, 1, True)).armor,
|
||||
lambda fit, spool: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, spool, False)).armor,
|
||||
lambda fit: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, 0, True)).armor,
|
||||
lambda fit: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, 1, True)).armor,
|
||||
3, 0, 0),
|
||||
(
|
||||
"labelRemoteHull", "Hull:", "{}{} HP/s", "hullActive", "Hull restored",
|
||||
lambda fit, spool: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SCALE, spool, False)).hull,
|
||||
lambda fit: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SCALE, 0, True)).hull,
|
||||
lambda fit: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SCALE, 1, True)).hull,
|
||||
lambda fit, spool: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, spool, False)).hull,
|
||||
lambda fit: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, 0, True)).hull,
|
||||
lambda fit: fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, 1, True)).hull,
|
||||
3, 0, 0)]
|
||||
|
||||
|
||||
|
||||
@@ -84,12 +84,11 @@ class AttributeDisplay(ViewColumn):
|
||||
return ""
|
||||
|
||||
if self.info.name == "volume":
|
||||
if getattr(mod, "amount", 1) != 1:
|
||||
attr = "{} m\u00B3 ({} m\u00B3)".format(
|
||||
formatAmount(attr, 3, 0, 6),
|
||||
formatAmount(attr * mod.amount, 3, 0, 6))
|
||||
else:
|
||||
attr = "{} m\u00B3".format(formatAmount(attr, 3, 0, 6))
|
||||
str_ = (formatAmount(attr, 3, 0, 3))
|
||||
if hasattr(mod, "amount"):
|
||||
str_ += "m\u00B3 (%s m\u00B3)" % (formatAmount(attr * mod.amount, 3, 0, 3))
|
||||
attr = str_
|
||||
|
||||
if isinstance(attr, (float, int)):
|
||||
attr = (formatAmount(attr, 3, 0, 3))
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ class DpsColumn(GraphColumn):
|
||||
|
||||
def _getValue(self, fit):
|
||||
defaultSpoolValue = eos.config.settings['globalDefaultSpoolupPercentage']
|
||||
return fit.getTotalDps(spoolOptions=SpoolOptions(SpoolType.SCALE, defaultSpoolValue, False)).total, None
|
||||
return fit.getTotalDps(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, defaultSpoolValue, False)).total, None
|
||||
|
||||
def _getFitTooltip(self):
|
||||
return 'Declared DPS'
|
||||
@@ -102,7 +102,7 @@ class VolleyColumn(GraphColumn):
|
||||
|
||||
def _getValue(self, fit):
|
||||
defaultSpoolValue = eos.config.settings['globalDefaultSpoolupPercentage']
|
||||
return fit.getTotalVolley(spoolOptions=SpoolOptions(SpoolType.SCALE, defaultSpoolValue, False)).total, None
|
||||
return fit.getTotalVolley(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, defaultSpoolValue, False)).total, None
|
||||
|
||||
def _getFitTooltip(self):
|
||||
return 'Declared volley'
|
||||
@@ -329,7 +329,7 @@ class ShieldRRColumn(GraphColumn):
|
||||
|
||||
def _getValue(self, fit):
|
||||
defaultSpoolValue = eos.config.settings['globalDefaultSpoolupPercentage']
|
||||
return fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SCALE, defaultSpoolValue, False)).shield, 'HP/s'
|
||||
return fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, defaultSpoolValue, False)).shield, 'HP/s'
|
||||
|
||||
def _getFitTooltip(self):
|
||||
return 'Declared shield repair speed'
|
||||
@@ -348,7 +348,7 @@ class ArmorRRColumn(GraphColumn):
|
||||
|
||||
def _getValue(self, fit):
|
||||
defaultSpoolValue = eos.config.settings['globalDefaultSpoolupPercentage']
|
||||
return fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SCALE, defaultSpoolValue, False)).armor, 'HP/s'
|
||||
return fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, defaultSpoolValue, False)).armor, 'HP/s'
|
||||
|
||||
def _getFitTooltip(self):
|
||||
return 'Declared armor repair speed'
|
||||
@@ -367,7 +367,7 @@ class HullRRColumn(GraphColumn):
|
||||
|
||||
def _getValue(self, fit):
|
||||
defaultSpoolValue = eos.config.settings['globalDefaultSpoolupPercentage']
|
||||
return fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SCALE, defaultSpoolValue, False)).hull, 'HP/s'
|
||||
return fit.getRemoteReps(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, defaultSpoolValue, False)).hull, 'HP/s'
|
||||
|
||||
def _getFitTooltip(self):
|
||||
return 'Declared hull repair speed'
|
||||
|
||||
@@ -33,7 +33,6 @@ from eos.saveddata.module import Module, Rack
|
||||
from eos.saveddata.targetProfile import TargetProfile
|
||||
from graphs.wrapper import BaseWrapper
|
||||
from gui.builtinContextMenus.envEffectAdd import AddEnvironmentEffect
|
||||
from gui.utils.numberFormatter import formatAmount
|
||||
from gui.viewColumn import ViewColumn
|
||||
from service.fit import Fit as FitSvc
|
||||
from service.market import Market
|
||||
@@ -65,11 +64,7 @@ class BaseName(ViewColumn):
|
||||
return "%d/%d %s" % \
|
||||
(stuff.amount, stuff.getModifiedItemAttr("fighterSquadronMaxSize"), stuff.item.name)
|
||||
elif isinstance(stuff, Cargo):
|
||||
if stuff.item.group.name in ("Cargo Container", "Secure Cargo Container", "Audit Log Secure Container", "Freight Container"):
|
||||
capacity = stuff.item.getAttribute('capacity')
|
||||
if capacity:
|
||||
return "{:d}x {} ({} m\u00B3)".format(stuff.amount, stuff.item.name, formatAmount(capacity, 3, 0, 6))
|
||||
return "{:d}x {}".format(stuff.amount, stuff.item.name)
|
||||
return "%dx %s" % (stuff.amount, stuff.item.name)
|
||||
elif isinstance(stuff, Fit):
|
||||
if self.projectedView:
|
||||
# we need a little more information for the projected view
|
||||
|
||||
@@ -113,7 +113,7 @@ class Miscellanea(ViewColumn):
|
||||
info.append((text, tooltip))
|
||||
|
||||
defaultSpoolValue = eos.config.settings['globalDefaultSpoolupPercentage']
|
||||
spoolTime = stuff.getSpoolData(spoolOptions=SpoolOptions(SpoolType.SCALE, defaultSpoolValue, False))[1]
|
||||
spoolTime = stuff.getSpoolData(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, defaultSpoolValue, False))[1]
|
||||
if spoolTime:
|
||||
text = "{0}s".format(formatAmount(spoolTime, 3, 0, 3))
|
||||
tooltip = "spool up time"
|
||||
@@ -396,9 +396,9 @@ class Miscellanea(ViewColumn):
|
||||
return text, tooltip
|
||||
elif itemGroup == "Mutadaptive Remote Armor Repairer":
|
||||
defaultSpoolValue = eos.config.settings['globalDefaultSpoolupPercentage']
|
||||
spoolOptDefault = SpoolOptions(SpoolType.SCALE, defaultSpoolValue, False)
|
||||
spoolOptPre = SpoolOptions(SpoolType.SCALE, 0, True)
|
||||
spoolOptFull = SpoolOptions(SpoolType.SCALE, 1, True)
|
||||
spoolOptDefault = SpoolOptions(SpoolType.SPOOL_SCALE, defaultSpoolValue, False)
|
||||
spoolOptPre = SpoolOptions(SpoolType.SPOOL_SCALE, 0, True)
|
||||
spoolOptFull = SpoolOptions(SpoolType.SPOOL_SCALE, 1, True)
|
||||
rps = stuff.getRemoteReps(spoolOptions=spoolOptDefault, ignoreState=True).armor
|
||||
rpsPre = stuff.getRemoteReps(spoolOptions=spoolOptPre, ignoreState=True).armor
|
||||
rpsFull = stuff.getRemoteReps(spoolOptions=spoolOptFull, ignoreState=True).armor
|
||||
|
||||
@@ -154,9 +154,7 @@ class CharacterEntityEditor(EntityEditor):
|
||||
class CharacterEditor(AuxiliaryFrame):
|
||||
|
||||
def __init__(self, parent):
|
||||
super().__init__(
|
||||
parent, id=wx.ID_ANY, title="Character Editor", resizeable=True,
|
||||
pos=wx.DefaultPosition, size=wx.Size(640, 600))
|
||||
super().__init__(parent, id=wx.ID_ANY, title="Character Editor", pos=wx.DefaultPosition, size=wx.Size(640, 600))
|
||||
|
||||
i = wx.Icon(BitmapLoader.getBitmap("character_small", "gui"))
|
||||
self.SetIcon(i)
|
||||
|
||||
@@ -39,7 +39,7 @@ class DevTools(AuxiliaryFrame):
|
||||
|
||||
def __init__(self, parent):
|
||||
super().__init__(
|
||||
parent, id=wx.ID_ANY, title="Development Tools", resizeable=True,
|
||||
parent, id=wx.ID_ANY, title="Development Tools", style=wx.RESIZE_BORDER,
|
||||
size=wx.Size(400, 320) if "wxGTK" in wx.PlatformInfo else wx.Size(400, 240))
|
||||
self.mainFrame = parent
|
||||
self.block = False
|
||||
|
||||
@@ -25,7 +25,7 @@ class EveFittings(AuxiliaryFrame):
|
||||
def __init__(self, parent):
|
||||
super().__init__(
|
||||
parent, id=wx.ID_ANY, title="Browse EVE Fittings", pos=wx.DefaultPosition,
|
||||
size=wx.Size(750, 450), resizeable=True)
|
||||
size=wx.Size(750, 450), style=wx.RESIZE_BORDER)
|
||||
|
||||
self.mainFrame = parent
|
||||
mainSizer = wx.BoxSizer(wx.VERTICAL)
|
||||
@@ -204,7 +204,7 @@ class ExportToEve(AuxiliaryFrame):
|
||||
def __init__(self, parent):
|
||||
super().__init__(
|
||||
parent, id=wx.ID_ANY, title="Export fit to EVE", pos=wx.DefaultPosition,
|
||||
size=wx.Size(400, 120) if "wxGTK" in wx.PlatformInfo else wx.Size(350, 100), resizeable=True)
|
||||
size=wx.Size(400, 120) if "wxGTK" in wx.PlatformInfo else wx.Size(350, 100), style=wx.RESIZE_BORDER)
|
||||
|
||||
self.mainFrame = parent
|
||||
|
||||
@@ -273,15 +273,7 @@ class ExportToEve(AuxiliaryFrame):
|
||||
sEsi = Esi.getInstance()
|
||||
|
||||
sFit = Fit.getInstance()
|
||||
try:
|
||||
data = sPort.exportESI(sFit.getFit(fitID))
|
||||
except ESIExportException as e:
|
||||
msg = str(e)
|
||||
if not msg:
|
||||
msg = "Failed to generate export data"
|
||||
pyfalog.warning(msg)
|
||||
self.statusbar.SetStatusText(msg, 1)
|
||||
return
|
||||
data = sPort.exportESI(sFit.getFit(fitID))
|
||||
activeChar = self.getActiveCharacter()
|
||||
if activeChar is None:
|
||||
msg = "Need at least one ESI character to export"
|
||||
@@ -317,7 +309,7 @@ class SsoCharacterMgmt(AuxiliaryFrame):
|
||||
def __init__(self, parent):
|
||||
super().__init__(
|
||||
parent, id=wx.ID_ANY, title="SSO Character Management", pos=wx.DefaultPosition,
|
||||
size=wx.Size(550, 250), resizeable=True)
|
||||
size=wx.Size(550, 250), style=wx.RESIZE_BORDER)
|
||||
self.mainFrame = parent
|
||||
mainSizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ class ItemStatsFrame(AuxiliaryFrame):
|
||||
title="Item stats",
|
||||
pos=pos,
|
||||
size=size,
|
||||
resizeable=True)
|
||||
style=wx.RESIZE_BORDER)
|
||||
|
||||
empty = getattr(victim, "isEmpty", False)
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ class DmgPatternEditor(AuxiliaryFrame):
|
||||
|
||||
def __init__(self, parent):
|
||||
super().__init__(
|
||||
parent, id=wx.ID_ANY, title="Damage Pattern Editor", resizeable=True,
|
||||
parent, id=wx.ID_ANY, title="Damage Pattern Editor", style=wx.RESIZE_BORDER,
|
||||
# Dropdown list widget is scaled to its longest content line on GTK, adapt to that
|
||||
size=wx.Size(500, 240) if "wxGTK" in wx.PlatformInfo else wx.Size(400, 240))
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ class AttributeEditor(AuxiliaryFrame):
|
||||
def __init__(self, parent):
|
||||
super().__init__(
|
||||
parent, wx.ID_ANY, title="Attribute Editor", pos=wx.DefaultPosition,
|
||||
size=wx.Size(650, 600), resizeable=True)
|
||||
size=wx.Size(650, 600), style=wx.RESIZE_BORDER)
|
||||
|
||||
i = wx.Icon(BitmapLoader.getBitmap("fit_rename_small", "gui"))
|
||||
self.SetIcon(i)
|
||||
|
||||
@@ -119,7 +119,7 @@ class ImplantSetEditor(AuxiliaryFrame):
|
||||
|
||||
def __init__(self, parent):
|
||||
super().__init__(
|
||||
parent, id=wx.ID_ANY, title="Implant Set Editor", resizeable=True,
|
||||
parent, id=wx.ID_ANY, title="Implant Set Editor", style=wx.RESIZE_BORDER,
|
||||
size=wx.Size(950, 500) if "wxGTK" in wx.PlatformInfo else wx.Size(850, 420))
|
||||
|
||||
self.block = False
|
||||
|
||||
@@ -33,18 +33,23 @@ class SsoLogin(wx.Dialog):
|
||||
self.SetSizer(bSizer1)
|
||||
self.Center()
|
||||
|
||||
mainFrame.Bind(GE.EVT_SSO_LOGIN, self.OnLogin)
|
||||
|
||||
from service.esi import Esi
|
||||
|
||||
self.sEsi = Esi.getInstance()
|
||||
uri = self.sEsi.getLoginURI(None)
|
||||
webbrowser.open(uri)
|
||||
|
||||
def OnLogin(self, event):
|
||||
self.Close()
|
||||
event.Skip()
|
||||
|
||||
|
||||
class SsoLoginServer(wx.Dialog):
|
||||
|
||||
def __init__(self, port):
|
||||
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
|
||||
super().__init__(self.mainFrame, id=wx.ID_ANY, title="SSO Login", size=(-1, -1), style=wx.DEFAULT_DIALOG_STYLE)
|
||||
mainFrame = gui.mainFrame.MainFrame.getInstance()
|
||||
super().__init__(mainFrame, id=wx.ID_ANY, title="SSO Login", size=(-1, -1), style=wx.DEFAULT_DIALOG_STYLE)
|
||||
|
||||
from service.esi import Esi
|
||||
|
||||
@@ -54,8 +59,8 @@ class SsoLoginServer(wx.Dialog):
|
||||
uri = self.sEsi.getLoginURI(serverAddr)
|
||||
|
||||
bSizer1 = wx.BoxSizer(wx.VERTICAL)
|
||||
self.mainFrame.Bind(GE.EVT_SSO_LOGIN, self.OnLogin)
|
||||
self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy)
|
||||
mainFrame.Bind(GE.EVT_SSO_LOGIN, self.OnLogin)
|
||||
self.Bind(wx.EVT_CLOSE, self.OnClose)
|
||||
|
||||
text = wx.StaticText(self, wx.ID_ANY, "Waiting for character login through EVE Single Sign-On.")
|
||||
bSizer1.Add(text, 0, wx.ALL | wx.EXPAND, 10)
|
||||
@@ -73,10 +78,9 @@ class SsoLoginServer(wx.Dialog):
|
||||
webbrowser.open(uri)
|
||||
|
||||
def OnLogin(self, event):
|
||||
self.EndModal(wx.ID_OK)
|
||||
self.Close()
|
||||
event.Skip()
|
||||
|
||||
def OnDestroy(self, event):
|
||||
self.mainFrame.Unbind(GE.EVT_SSO_LOGIN, handler=self.OnLogin)
|
||||
def OnClose(self, event):
|
||||
self.sEsi.stopServer()
|
||||
event.Skip()
|
||||
|
||||
@@ -126,7 +126,7 @@ class TargetProfileEditor(AuxiliaryFrame):
|
||||
|
||||
def __init__(self, parent):
|
||||
super().__init__(
|
||||
parent, id=wx.ID_ANY, title="Target Profile Editor", resizeable=True,
|
||||
parent, id=wx.ID_ANY, title="Target Profile Editor", style=wx.RESIZE_BORDER,
|
||||
# Dropdown list widget is scaled to its longest content line on GTK, adapt to that
|
||||
size=wx.Size(500, 240) if "wxGTK" in wx.PlatformInfo else wx.Size(350, 240))
|
||||
|
||||
|
||||
@@ -99,15 +99,14 @@ def formatAmount(val, prec=3, lowest=0, highest=0, currency=False, forceSign=Fal
|
||||
return result
|
||||
|
||||
|
||||
def roundToPrec(val, prec, nsValue=None):
|
||||
"""
|
||||
nsValue: custom value which should be used to determine normalization shift
|
||||
"""
|
||||
def roundToPrec(val, prec):
|
||||
# We're not rounding integers anyway
|
||||
# Also make sure that we do not ask to calculate logarithm of zero
|
||||
if int(val) == val:
|
||||
return int(val)
|
||||
roundFactor = int(prec - math.floor(math.log10(abs(val if nsValue is None else nsValue))) - 1)
|
||||
# Find round factor, taking into consideration that we want to keep at least prec
|
||||
# positions for fractions with zero integer part (e.g. 0.0000354 for prec=3)
|
||||
roundFactor = int(prec - math.ceil(math.log10(abs(val))))
|
||||
# But we don't want to round integers
|
||||
if roundFactor < 0:
|
||||
roundFactor = 0
|
||||
|
||||
@@ -305,10 +305,9 @@ class Market:
|
||||
self.ITEMS_FORCEDMARKETGROUP_R = self.__makeRevDict(self.ITEMS_FORCEDMARKETGROUP)
|
||||
|
||||
self.FORCEDMARKETGROUP = {
|
||||
685: False, # Ship Equipment > Electronic Warfare > ECCM
|
||||
681: False, # Ship Equipment > Electronic Warfare > Sensor Backup Arrays
|
||||
1639: False, # Ship Equipment > Fleet Assistance > Command Processors
|
||||
2527: True, # Ship Equipment > Hull & Armor > Mutadaptive Remote Armor Repairers - has hasTypes set to 1 while actually having no types
|
||||
685: False, # Ship Equipment > Electronic Warfare > ECCM
|
||||
681: False, # Ship Equipment > Electronic Warfare > Sensor Backup Arrays
|
||||
1639: False # Ship Equipment > Fleet Assistance > Command Processors
|
||||
}
|
||||
|
||||
# Misc definitions
|
||||
@@ -329,7 +328,7 @@ class Market:
|
||||
"Structure",
|
||||
"Structure Module",
|
||||
)
|
||||
self.SEARCH_GROUPS = ("Ice Product", "Cargo Container", "Secure Cargo Container", "Audit Log Secure Container", "Freight Container")
|
||||
self.SEARCH_GROUPS = ("Ice Product",)
|
||||
self.ROOT_MARKET_GROUPS = (9, # Ship Equipment
|
||||
1111, # Rigs
|
||||
157, # Drones
|
||||
|
||||
@@ -363,7 +363,7 @@ class EfsPort:
|
||||
groups = {}
|
||||
# Export at maximum spool for consistency, spoolup data is exported anyway.
|
||||
defaultSpoolValue = 1
|
||||
spoolOptions = SpoolOptions(SpoolType.SCALE, defaultSpoolValue, True)
|
||||
spoolOptions = SpoolOptions(SpoolType.SPOOL_SCALE, defaultSpoolValue, True)
|
||||
for mod in fit.modules:
|
||||
if mod.getDps(spoolOptions=spoolOptions).total > 0:
|
||||
# Group weapon + ammo combinations that occur more than once
|
||||
@@ -689,7 +689,7 @@ class EfsPort:
|
||||
shipSize = EfsPort.getShipSize(fit.ship.item.groupID)
|
||||
# Export at maximum spool for consistency, spoolup data is exported anyway.
|
||||
defaultSpoolValue = 1
|
||||
spoolOptions = SpoolOptions(SpoolType.SCALE, defaultSpoolValue, True)
|
||||
spoolOptions = SpoolOptions(SpoolType.SPOOL_SCALE, defaultSpoolValue, True)
|
||||
|
||||
cargoIDs = []
|
||||
for cargo in fit.cargo:
|
||||
|
||||
@@ -1 +1 @@
|
||||
version: v2.10.1
|
||||
version: v2.11.0dev1
|
||||
|
||||
Reference in New Issue
Block a user