Compare commits

..

5 Commits

Author SHA1 Message Date
DarkPhoenix
56672f5830 Merge branch 'master' into singularity 2019-08-22 19:35:27 +03:00
DarkPhoenix
1bff10c973 Bump version 2019-08-22 17:56:51 +03:00
DarkPhoenix
1d4aece7cc Limit max range of FoF missiles 2019-08-22 17:54:44 +03:00
DarkPhoenix
cdb79f499a Allow non-integer amount of cycles in spool calculator 2019-08-22 17:35:16 +03:00
DarkPhoenix
837dbb3677 Update database and effects to 1554701 2019-08-22 16:51:33 +03:00
40 changed files with 341 additions and 382 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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:

View File

@@ -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):

View File

@@ -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):

View File

@@ -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()

View File

@@ -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

BIN
eve.db

Binary file not shown.

View File

@@ -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)

View File

@@ -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,

View File

@@ -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():

View File

@@ -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)]

View File

@@ -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)

View File

@@ -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:

View File

@@ -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}

View File

@@ -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'))

View File

@@ -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

View File

@@ -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)

View File

@@ -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.")

View File

@@ -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

View File

@@ -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)]

View File

@@ -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)]

View File

@@ -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))

View File

@@ -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'

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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)

View File

@@ -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)

View File

@@ -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))

View File

@@ -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)

View File

@@ -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

View File

@@ -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()

View File

@@ -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))

View File

@@ -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

View File

@@ -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

View File

@@ -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:

View File

@@ -1 +1 @@
version: v2.10.1
version: v2.11.0dev1