Compare commits

...

39 Commits

Author SHA1 Message Date
DarkPhoenix
47c34f2186 Sort implant sets by name 2019-05-10 16:22:57 +03:00
DarkPhoenix
2ca418c287 Add damage over time graph 2019-05-10 03:18:25 +03:00
DarkPhoenix
775e69305c Make graphs switchable 2019-05-10 03:06:00 +03:00
DarkPhoenix
0f1cbb4234 Add support for dps over time graph 2019-05-10 02:46:50 +03:00
DarkPhoenix
306710a314 Bump version 2019-05-09 20:12:37 +03:00
DarkPhoenix
776a4ee977 Update effects 2019-05-09 20:11:31 +03:00
DarkPhoenix
9dccfd756a Update database to 1503340 2019-05-09 19:49:13 +03:00
DarkPhoenix
15281ee6ce Merge branch 'master' into singularity 2019-05-07 10:27:01 +03:00
DarkPhoenix
9a0dd6c521 Copy empty spots on fit as well when making copy 2019-05-06 20:21:28 +03:00
DarkPhoenix
a570f291ae Merge branch 'master' into singularity 2019-05-06 15:32:52 +03:00
DarkPhoenix
cde7fdcaba Do not activate MJD and MJFG upon fitting 2019-05-05 05:06:15 +03:00
DarkPhoenix
e4780bc8ba Merge branch 'master' into singularity 2019-05-04 12:18:50 +03:00
DarkPhoenix
4d35e5aee1 Comment out some conflicting jargon entries 2019-05-04 12:18:07 +03:00
DarkPhoenix
f7b705b9e2 Add focused void bomb jargon entry 2019-05-04 12:16:04 +03:00
DarkPhoenix
48f44cdb0c Merge branch 'master' into singularity 2019-05-04 02:44:12 +03:00
DarkPhoenix
013a2264c0 Show tooltip only if there's something to show 2019-05-04 02:43:33 +03:00
DarkPhoenix
8222686dda Enable tooltips for export options 2019-05-04 02:43:02 +03:00
DarkPhoenix
7f2121e98d Add possibility to export formatted DNA 2019-05-04 02:38:19 +03:00
DarkPhoenix
4b6c881dca Re-enable DNA export 2019-05-04 02:26:09 +03:00
DarkPhoenix
154db5df0b Merge branch 'master' into singularity 2019-05-03 22:29:26 +03:00
DarkPhoenix
95a1d669f5 Invasion effects affect module mining cycle only 2019-05-03 19:01:10 +03:00
DarkPhoenix
9e3c9bd056 Merge branch 'master' into singularity 2019-05-03 16:30:38 +03:00
DarkPhoenix
52a1314803 Merge branch 'master' into singularity 2019-05-03 04:25:27 +03:00
DarkPhoenix
ba0a5db72f Remove stacking penalties from duration attribute
It cannot be stacking penalized
2019-05-03 04:04:58 +03:00
DarkPhoenix
2bac4a954f Merge branch 'master' into singularity 2019-05-03 04:04:11 +03:00
DarkPhoenix
1cd42669a0 Merge branch 'master' into singularity 2019-05-03 03:37:48 +03:00
DarkPhoenix
4932b685e1 Merge branch 'master' into singularity 2019-05-03 02:31:22 +03:00
DarkPhoenix
44a7e53b9e Bump version 2019-05-02 19:54:29 +03:00
DarkPhoenix
b35bdd4e33 Add triglavian invasion effects 2019-05-02 19:50:40 +03:00
DarkPhoenix
7f52f6fe44 Show spoolup time for MJFGs 2019-05-02 19:13:21 +03:00
DarkPhoenix
34e49da0c1 Add renders of new ships 2019-05-02 18:52:53 +03:00
DarkPhoenix
5132698974 Add draugur effect 2019-05-02 18:24:47 +03:00
DarkPhoenix
832cebcaaf Add ikitursa effects 2019-05-02 18:17:23 +03:00
DarkPhoenix
4eaccd1eed Change spoolup context menu to show 20-ish amount of items 2019-05-02 18:03:31 +03:00
DarkPhoenix
5245f289a5 Add nergal effects 2019-05-02 17:16:38 +03:00
DarkPhoenix
672aed44f2 Add trig frigate resist effects 2019-05-02 16:40:38 +03:00
DarkPhoenix
8c890cf9a5 Rerun effectUsedBy script 2019-05-02 16:30:28 +03:00
DarkPhoenix
8f9a95db93 Do not crash when icons are missing, and add ADC mutaplasmid override 2019-05-02 16:10:22 +03:00
DarkPhoenix
5a056e6d47 Update database to 1498791 2019-05-02 15:54:04 +03:00
32 changed files with 642 additions and 86 deletions

View File

@@ -6739,7 +6739,7 @@ class Effect2302(BaseEffect):
damageControl
Used by:
Modules from group: Damage Control (22 of 27)
Modules from group: Damage Control (24 of 29)
"""
type = 'passive'
@@ -9050,7 +9050,7 @@ class Effect3001(BaseEffect):
Used by:
Modules from group: Missile Launcher Torpedo (22 of 22)
Items from market group: Ship Equipment > Turrets & Bays (429 of 883)
Items from market group: Ship Equipment > Turrets & Bays (429 of 888)
Module: Interdiction Sphere Launcher I
"""
@@ -9113,7 +9113,7 @@ class Effect3025(BaseEffect):
Used by:
Modules from group: Energy Weapon (101 of 214)
Modules from group: Hybrid Weapon (105 of 221)
Modules from group: Precursor Weapon (15 of 15)
Modules from group: Precursor Weapon (18 of 18)
Modules from group: Projectile Weapon (99 of 165)
"""
@@ -16246,9 +16246,9 @@ class Effect4902(BaseEffect):
MWDSignatureRadiusRoleBonus
Used by:
Ships from group: Assault Frigate (8 of 12)
Ships from group: Command Destroyer (4 of 4)
Ships from group: Heavy Assault Cruiser (8 of 11)
Ships from group: Assault Frigate (9 of 13)
Ships from group: Command Destroyer (5 of 5)
Ships from group: Heavy Assault Cruiser (9 of 12)
"""
type = 'passive'
@@ -25191,7 +25191,7 @@ class Effect6214(BaseEffect):
roleBonusCDLinksPGReduction
Used by:
Ships from group: Command Destroyer (4 of 4)
Ships from group: Command Destroyer (5 of 5)
Ship: Porpoise
"""
@@ -25773,8 +25773,7 @@ class Effect6315(BaseEffect):
eliteBonusCommandDestroyerSkirmish1
Used by:
Ship: Bifrost
Ship: Magus
Ships from group: Command Destroyer (3 of 5)
"""
type = 'passive'
@@ -25823,7 +25822,7 @@ class Effect6317(BaseEffect):
eliteBonusCommandDestroyerMJFGspool2
Used by:
Ships from group: Command Destroyer (4 of 4)
Ships from group: Command Destroyer (5 of 5)
"""
type = 'passive'
@@ -26096,8 +26095,7 @@ class Effect6334(BaseEffect):
eliteBonusCommandDestroyerInfo1
Used by:
Ship: Pontifex
Ship: Stork
Ships from group: Command Destroyer (3 of 5)
"""
type = 'passive'
@@ -32214,7 +32212,7 @@ class Effect6845(BaseEffect):
shipBonusCommandDestroyerRole1DefenderBonus
Used by:
Ships from group: Command Destroyer (4 of 4)
Ships from group: Command Destroyer (4 of 5)
"""
type = 'passive'
@@ -33763,10 +33761,10 @@ class Effect6994(BaseEffect):
class Effect6995(BaseEffect):
"""
targetABCAttack
targetDisintegratorAttack
Used by:
Modules from group: Precursor Weapon (15 of 15)
Modules from group: Precursor Weapon (18 of 18)
"""
type = 'active'
@@ -33930,6 +33928,7 @@ class Effect7012(BaseEffect):
Used by:
Variations of module: Assault Damage Control I (5 of 5)
Module: Abyssal Assault Damage Control
"""
runTime = 'early'
@@ -34814,7 +34813,7 @@ class Effect7077(BaseEffect):
disintegratorWeaponDamageMultiply
Used by:
Modules from group: Entropic Radiation Sink (4 of 4)
Modules from group: Entropic Radiation Sink (6 of 6)
"""
type = 'passive'
@@ -34831,7 +34830,7 @@ class Effect7078(BaseEffect):
disintegratorWeaponSpeedMultiply
Used by:
Modules from group: Entropic Radiation Sink (4 of 4)
Modules from group: Entropic Radiation Sink (6 of 6)
"""
type = 'passive'
@@ -34880,8 +34879,8 @@ class Effect7085(BaseEffect):
shipbonusPCTDamagePC1
Used by:
Variations of ship: Vedmak (2 of 2)
Ship: Tiamat
Ship: Vedmak
"""
type = 'passive'
@@ -34897,8 +34896,8 @@ class Effect7086(BaseEffect):
shipbonusPCTTrackingPC2
Used by:
Variations of ship: Vedmak (2 of 2)
Ship: Tiamat
Ship: Vedmak
"""
type = 'passive'
@@ -34914,7 +34913,6 @@ class Effect7087(BaseEffect):
shipbonusPCTOptimalPF2
Used by:
Ship: Damavik
Ship: Hydra
"""
@@ -34931,7 +34929,7 @@ class Effect7088(BaseEffect):
shipbonusPCTDamagePF1
Used by:
Ship: Damavik
Variations of ship: Damavik (2 of 2)
Ship: Hydra
"""
@@ -34963,13 +34961,13 @@ class Effect7092(BaseEffect):
shipBonusRemoteRepCapNeedRoleBonus2
Used by:
Ship: Damavik
Variations of ship: Damavik (2 of 2)
Variations of ship: Kikimora (2 of 2)
Variations of ship: Vedmak (2 of 2)
Ship: Drekavac
Ship: Hydra
Ship: Kikimora
Ship: Leshak
Ship: Tiamat
Ship: Vedmak
"""
type = 'passive'
@@ -34985,14 +34983,14 @@ class Effect7093(BaseEffect):
shipBonusSmartbombCapNeedRoleBonus2
Used by:
Variations of ship: Damavik (2 of 2)
Variations of ship: Kikimora (2 of 2)
Variations of ship: Rodiva (2 of 2)
Ship: Damavik
Variations of ship: Vedmak (2 of 2)
Ship: Drekavac
Ship: Hydra
Ship: Kikimora
Ship: Leshak
Ship: Tiamat
Ship: Vedmak
"""
type = 'passive'
@@ -35008,13 +35006,13 @@ class Effect7094(BaseEffect):
shipBonusRemoteRepMaxRangeRoleBonus1
Used by:
Ship: Damavik
Variations of ship: Damavik (2 of 2)
Variations of ship: Kikimora (2 of 2)
Variations of ship: Vedmak (2 of 2)
Ship: Drekavac
Ship: Hydra
Ship: Kikimora
Ship: Leshak
Ship: Tiamat
Ship: Vedmak
"""
type = 'passive'
@@ -35046,7 +35044,7 @@ class Effect7111(BaseEffect):
systemSmallPrecursorTurretDamage
Used by:
Celestials named like: Wolf Rayet Effect Beacon Class (5 of 6)
Celestials named like: Wolf Rayet Effect Beacon Class (6 of 6)
"""
runTime = 'early'
@@ -35064,13 +35062,13 @@ class Effect7112(BaseEffect):
shipBonusNeutCapNeedRoleBonus2
Used by:
Ship: Damavik
Variations of ship: Damavik (2 of 2)
Variations of ship: Kikimora (2 of 2)
Variations of ship: Vedmak (2 of 2)
Ship: Drekavac
Ship: Hydra
Ship: Kikimora
Ship: Leshak
Ship: Tiamat
Ship: Vedmak
"""
type = 'passive'
@@ -35176,7 +35174,7 @@ class Effect7154(BaseEffect):
shipBonusPD1DisintegratorDamage
Used by:
Ship: Kikimora
Variations of ship: Kikimora (2 of 2)
"""
type = 'passive'
@@ -35226,7 +35224,7 @@ class Effect7157(BaseEffect):
shipBonusPD2DisintegratorMaxRange
Used by:
Ship: Kikimora
Variations of ship: Kikimora (2 of 2)
"""
type = 'passive'
@@ -35583,3 +35581,232 @@ class Effect7186(BaseEffect):
def handler(fit, ship, context):
fit.drones.filteredItemBoost(lambda drone: drone.item.requiresSkill('Medium Drone Operation'),
'armorHP', ship.getModifiedItemAttr('shipBonusRole8'))
class Effect7193(BaseEffect):
"""
systemMiningCycleTimeBonus
Used by:
Celestials named like: Invasion Effects (3 of 3)
"""
runTime = 'early'
type = ('projected', 'passive')
@staticmethod
def handler(fit, beacon, context):
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill('Mining'),
'duration', beacon.getModifiedItemAttr('miningDurationMultiplier'))
class Effect7202(BaseEffect):
"""
systemDroneSpeedBonusPercent
Used by:
Celestials named like: Invasion Effects (3 of 3)
"""
runTime = 'early'
type = ('projected', 'passive')
@staticmethod
def handler(fit, beacon, context):
fit.drones.filteredItemBoost(lambda drone: drone.item.requiresSkill('Drones'),
'maxVelocity', beacon.getModifiedItemAttr('droneMaxVelocityBonus'),
stackingPenalties=True)
class Effect7203(BaseEffect):
"""
systemDroneDamageBonusPercent
Used by:
Celestials named like: Invasion Effects (3 of 3)
"""
runTime = 'early'
type = ('projected', 'passive')
@staticmethod
def handler(fit, beacon, context):
fit.drones.filteredItemBoost(lambda drone: drone.item.requiresSkill('Drones'),
'damageMultiplier', beacon.getModifiedItemAttr('droneDamageBonus'),
stackingPenalties=True)
class Effect7204(BaseEffect):
"""
shipArmorEMResistancePF2
Used by:
Variations of ship: Damavik (2 of 2)
"""
type = 'passive'
@staticmethod
def handler(fit, ship, context):
fit.ship.boostItemAttr('armorEmDamageResonance', ship.getModifiedItemAttr('shipBonusPF2'), skill='Precursor Frigate')
class Effect7205(BaseEffect):
"""
shipArmorKinResistancePF2
Used by:
Variations of ship: Damavik (2 of 2)
"""
type = 'passive'
@staticmethod
def handler(fit, ship, context):
fit.ship.boostItemAttr('armorKineticDamageResonance', ship.getModifiedItemAttr('shipBonusPF2'), skill='Precursor Frigate')
class Effect7206(BaseEffect):
"""
shipArmorThermResistancePF2
Used by:
Variations of ship: Damavik (2 of 2)
"""
type = 'passive'
@staticmethod
def handler(fit, ship, context):
fit.ship.boostItemAttr('armorThermalDamageResonance', ship.getModifiedItemAttr('shipBonusPF2'), skill='Precursor Frigate')
class Effect7207(BaseEffect):
"""
shipArmorExpResistancePF2
Used by:
Variations of ship: Damavik (2 of 2)
"""
type = 'passive'
@staticmethod
def handler(fit, ship, context):
fit.ship.boostItemAttr('armorExplosiveDamageResonance', ship.getModifiedItemAttr('shipBonusPF2'), skill='Precursor Frigate')
class Effect7209(BaseEffect):
"""
shipPCTOptimalBonusEliteGunship2
Used by:
Ship: Nergal
"""
type = 'passive'
@staticmethod
def handler(fit, ship, context):
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill('Small Precursor Weapon'),
'maxRange', ship.getModifiedItemAttr('eliteBonusGunship2'),
skill='Assault Frigates')
class Effect7210(BaseEffect):
"""
shipBonusCommandDestroyerRole2DefenderBonus
Used by:
Ship: Draugur
"""
type = 'passive'
@staticmethod
def handler(fit, ship, context):
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill('Defender Missiles'),
'moduleReactivationDelay', ship.getModifiedItemAttr('shipBonusRole2'))
class Effect7211(BaseEffect):
"""
shipDmgMultiMaxEliteHeavyGunship1
Used by:
Ship: Ikitursa
"""
type = 'passive'
@staticmethod
def handler(fit, ship, context):
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill('Medium Precursor Weapon'),
'damageMultiplierBonusMax', ship.getModifiedItemAttr('eliteBonusHeavyGunship1'),
skill='Heavy Assault Cruisers')
class Effect7216(BaseEffect):
"""
shipDmgMultiMaxEliteGunship1
Used by:
Ship: Nergal
"""
type = 'passive'
@staticmethod
def handler(fit, ship, context):
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill('Small Precursor Weapon'),
'damageMultiplierBonusMax', ship.getModifiedItemAttr('eliteBonusGunship1'),
skill='Assault Frigates')
class Effect7223(BaseEffect):
"""
systemAgilityBonusPercentItem
Used by:
Celestials named like: Invasion Effects (3 of 3)
"""
runTime = 'early'
type = ('projected', 'passive')
@staticmethod
def handler(fit, beacon, context):
fit.ship.boostItemAttr('agility', beacon.getModifiedItemAttr('agilityBonus'), stackingPenalties=True)
class Effect7227(BaseEffect):
"""
systemHullHPBonusPercentItem
Used by:
Celestials named like: Invasion Effects (3 of 3)
"""
runTime = 'early'
type = ('projected', 'passive')
@staticmethod
def handler(fit, beacon, context):
fit.ship.boostItemAttr('hp', beacon.getModifiedItemAttr('hullHpBonus'))
class Effect7228(BaseEffect):
"""
shipMediumPrecursorWeaponOptimalEliteHeavyGunship2
Used by:
Ship: Ikitursa
"""
type = 'passive'
@staticmethod
def handler(fit, ship, context):
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill('Medium Precursor Weapon'),
'maxRange', ship.getModifiedItemAttr('eliteBonusHeavyGunship2'),
skill='Heavy Assault Cruisers')

View File

@@ -21,6 +21,7 @@ import itertools
class Graph(object):
def __init__(self, fit, function, data=None):
self.fit = fit
self.data = {}

43
eos/graph/fitDmgTime.py Normal file
View File

@@ -0,0 +1,43 @@
# ===============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of eos.
#
# eos is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# eos is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with eos. If not, see <http://www.gnu.org/licenses/>.
# ===============================================================================
from logbook import Logger
from eos.graph import Graph
from eos.utils.spoolSupport import SpoolType, SpoolOptions
pyfalog = Logger(__name__)
class FitDmgTimeGraph(Graph):
defaults = {"time": 0}
def __init__(self, fit, data=None):
Graph.__init__(self, fit, self.calcDps, data if data is not None else self.defaults)
self.fit = fit
def calcDps(self, data):
fit = self.fit
time = data["time"]
dmg = 0
for i in range(round(time) + 1):
dmg += fit.getTotalDps(spoolOptions=SpoolOptions(SpoolType.TIME, i, True)).total
return dmg

View File

@@ -17,16 +17,19 @@
# along with eos. If not, see <http://www.gnu.org/licenses/>.
# ===============================================================================
from math import log, sin, radians, exp
from math import exp, log, radians, sin
from eos.graph import Graph
from eos.const import FittingModuleState, FittingHardpoint
from logbook import Logger
from eos.const import FittingHardpoint, FittingModuleState
from eos.graph import Graph
pyfalog = Logger(__name__)
class FitDpsGraph(Graph):
class FitDpsRangeGraph(Graph):
defaults = {
"angle" : 0,
"distance" : 0,

42
eos/graph/fitDpsTime.py Normal file
View File

@@ -0,0 +1,42 @@
# ===============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of eos.
#
# eos is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# eos is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with eos. If not, see <http://www.gnu.org/licenses/>.
# ===============================================================================
from logbook import Logger
from eos.graph import Graph
from eos.utils.spoolSupport import SpoolType, SpoolOptions
pyfalog = Logger(__name__)
class FitDpsTimeGraph(Graph):
defaults = {"time": 0}
def __init__(self, fit, data=None):
Graph.__init__(self, fit, self.calcDps, data if data is not None else self.defaults)
self.fit = fit
def calcDps(self, data):
fit = self.fit
time = data["time"]
dps = fit.getTotalDps(spoolOptions=SpoolOptions(SpoolType.TIME, time, True)).total
return dps

View File

@@ -1547,8 +1547,9 @@ class Fit(object):
fitCopy.systemSecurity = self.systemSecurity
fitCopy.notes = self.notes
for i in self.modules:
fitCopy.modules.appendIgnoreEmpty(deepcopy(i))
toCopy = (
"modules",
"drones",
"fighters",
"cargo",

BIN
eve.db

Binary file not shown.

View File

@@ -50,8 +50,11 @@ class BitmapLoader(object):
@classmethod
def getStaticBitmap(cls, name, parent, location):
bitmap = cls.getBitmap(name or 0, location)
if bitmap is None:
return None
static = wx.StaticBitmap(parent)
static.SetBitmap(cls.getBitmap(name or 0, location))
static.SetBitmap(bitmap)
return static
@classmethod

View File

@@ -123,7 +123,8 @@ class AddEnvironmentEffect(ContextMenuUnconditional):
# Expressions for matching when detecting effects we're looking for
if incursions:
validgroups = ("Incursion ship attributes effects",)
validgroups = ("Incursion ship attributes effects",
"Invasion Effects")
else:
validgroups = ("Black Hole Effect Beacon",
"Cataclysmic Variable Effect Beacon",
@@ -133,7 +134,7 @@ class AddEnvironmentEffect(ContextMenuUnconditional):
"Wolf Rayet Effect Beacon")
# Stuff we don't want to see in names
garbages = ("Effect", "Beacon", "ship attributes effects")
garbages = ("Effects?", "Beacon", "ship attributes effects")
# Get group with all the system-wide beacons
grp = sMkt.getGroup("Effect Beacon")

View File

@@ -54,7 +54,7 @@ class AddImplantSet(ContextMenuSingle):
self.idmap = {}
for set in implantSets:
for set in sorted(implantSets, key=lambda i: i.name):
id = ContextMenuSingle.nextID()
mitem = wx.MenuItem(rootMenu, id, set.name)
bindmenu.Bind(wx.EVT_MENU, self.handleSelection, mitem)

View File

@@ -1,3 +1,5 @@
import math
# noinspection PyPackageRequirements
import wx
@@ -48,15 +50,44 @@ class ChangeModuleSpool(ContextMenuSingle):
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]
cycleTotalMin = min(cycleDefault, cycleCurrent, cycleMin)
cycleTotalMax = max(cycleDefault, cycleCurrent, cycleMax)
for cycle in range(cycleMin, cycleMax + 1):
def findCycles(val1, val2):
# Try to compose list of 21 steps max (0-20)
maxSteps = 20
valDiff = val2 - val1
valScale = valDiff / maxSteps
minStep = math.ceil(round(valScale, 9))
maxStep = math.floor(round(valDiff / 4, 9))
# Check steps from smallest to highest and see if we can go from min value
# to max value using those
for currentStep in range(minStep, maxStep + 1):
if valDiff % currentStep == 0:
return set(range(val1, val2 + currentStep, currentStep))
# Otherwise just split range in halves and go both ends using min values
else:
cycles = set()
while val2 >= val1:
cycles.add(val1)
cycles.add(val2)
val1 += minStep
val2 -= minStep
return cycles
cyclesToShow = findCycles(cycleMin, cycleMax)
for cycle in range(cycleTotalMin, cycleTotalMax + 1):
menuId = ContextMenuSingle.nextID()
# Show default only for current value and when not overriden
if not isNotDefault and cycle == cycleDefault:
text = "{} (default)".format(cycle)
else:
# Always show current selection and stuff which we decided to show via the cycles function
elif cycle == cycleCurrent or cycle in cyclesToShow:
text = "{}".format(cycle)
# Ignore the rest to not have very long menu
else:
continue
item = wx.MenuItem(m, menuId, text, kind=wx.ITEM_CHECK)
bindmenu.Bind(wx.EVT_MENU, self.handleSpoolChange, item)

View File

@@ -1 +1,5 @@
__all__ = ["fitDps"]
__all__ = [
"fitDpsRange",
"fitDpsTime",
"fitDmgTime"
]

View File

@@ -0,0 +1,82 @@
# =============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of pyfa.
#
# pyfa is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# pyfa is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
# =============================================================================
import gui.mainFrame
from eos.graph import Data
from eos.graph.fitDmgTime import FitDmgTimeGraph as EosFitDmgTimeGraph
from gui.bitmap_loader import BitmapLoader
from gui.graph import Graph
from service.attribute import Attribute
class FitDmgTimeGraph(Graph):
propertyLabelMap = {"time": "Time (seconds)"}
defaults = EosFitDmgTimeGraph.defaults.copy()
def __init__(self):
Graph.__init__(self)
self.defaults["time"] = "0-300"
self.name = "Damage over time"
self.fitDmgTime = None
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
def getFields(self):
return self.defaults
def getLabels(self):
return self.propertyLabelMap
def getIcons(self):
iconFile = Attribute.getInstance().getAttributeInfo('duration').iconID
bitmap = BitmapLoader.getBitmap(iconFile, "icons")
return {"time": bitmap}
def getPoints(self, fit, fields):
fitDmgTime = getattr(self, "fitDmgTime", None)
if fitDmgTime is None or fitDmgTime.fit != fit:
fitDmgTime = self.fitDmgTime = EosFitDmgTimeGraph(fit)
fitDmgTime.clearData()
variable = None
for fieldName, value in fields.items():
d = Data(fieldName, value)
if not d.isConstant():
if variable is None:
variable = fieldName
else:
# We can't handle more then one variable atm, OOPS FUCK OUT
return False, "Can only handle 1 variable"
fitDmgTime.setData(d)
if variable is None:
return False, "No variable"
x = []
y = []
for point, val in fitDmgTime.getIterator():
x.append(point[variable])
y.append(val)
return x, y
FitDmgTimeGraph.register()

View File

@@ -17,15 +17,16 @@
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
# =============================================================================
from gui.graph import Graph
from gui.bitmap_loader import BitmapLoader
from eos.graph.fitDps import FitDpsGraph as FitDps
from eos.graph import Data
import gui.mainFrame
from eos.graph import Data
from eos.graph.fitDpsRange import FitDpsRangeGraph as EosFitDpsRangeGraph
from gui.bitmap_loader import BitmapLoader
from gui.graph import Graph
from service.attribute import Attribute
class FitDpsGraph(Graph):
class FitDpsRangeGraph(Graph):
propertyAttributeMap = {"angle": "maxVelocity",
"distance": "maxRange",
"signatureRadius": "signatureRadius",
@@ -36,13 +37,13 @@ class FitDpsGraph(Graph):
"signatureRadius": "Target Signature Radius (m)",
"velocity": "Target Velocity (m/s)"}
defaults = FitDps.defaults.copy()
defaults = EosFitDpsRangeGraph.defaults.copy()
def __init__(self):
Graph.__init__(self)
self.defaults["distance"] = "0-100"
self.name = "DPS"
self.fitDps = None
self.name = "DPS over range"
self.fitDpsRange = None
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
def getFields(self):
@@ -63,11 +64,11 @@ class FitDpsGraph(Graph):
return icons
def getPoints(self, fit, fields):
fitDps = getattr(self, "fitDps", None)
if fitDps is None or fitDps.fit != fit:
fitDps = self.fitDps = FitDps(fit)
fitDpsRange = getattr(self, "fitDpsRange", None)
if fitDpsRange is None or fitDpsRange.fit != fit:
fitDpsRange = self.fitDpsRange = EosFitDpsRangeGraph(fit)
fitDps.clearData()
fitDpsRange.clearData()
variable = None
for fieldName, value in fields.items():
d = Data(fieldName, value)
@@ -78,18 +79,18 @@ class FitDpsGraph(Graph):
# We can't handle more then one variable atm, OOPS FUCK OUT
return False, "Can only handle 1 variable"
fitDps.setData(d)
fitDpsRange.setData(d)
if variable is None:
return False, "No variable"
x = []
y = []
for point, val in fitDps.getIterator():
for point, val in fitDpsRange.getIterator():
x.append(point[variable])
y.append(val)
return x, y
FitDpsGraph.register()
FitDpsRangeGraph.register()

View File

@@ -0,0 +1,82 @@
# =============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of pyfa.
#
# pyfa is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# pyfa is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
# =============================================================================
import gui.mainFrame
from eos.graph import Data
from eos.graph.fitDpsTime import FitDpsTimeGraph as EosFitDpsTimeGraph
from gui.bitmap_loader import BitmapLoader
from gui.graph import Graph
from service.attribute import Attribute
class FitDpsTimeGraph(Graph):
propertyLabelMap = {"time": "Time (seconds)"}
defaults = EosFitDpsTimeGraph.defaults.copy()
def __init__(self):
Graph.__init__(self)
self.defaults["time"] = "0-300"
self.name = "DPS over time"
self.fitDpsTime = None
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
def getFields(self):
return self.defaults
def getLabels(self):
return self.propertyLabelMap
def getIcons(self):
iconFile = Attribute.getInstance().getAttributeInfo('duration').iconID
bitmap = BitmapLoader.getBitmap(iconFile, "icons")
return {"time": bitmap}
def getPoints(self, fit, fields):
fitDpsTime = getattr(self, "fitDpsTime", None)
if fitDpsTime is None or fitDpsTime.fit != fit:
fitDpsTime = self.fitDpsTime = EosFitDpsTimeGraph(fit)
fitDpsTime.clearData()
variable = None
for fieldName, value in fields.items():
d = Data(fieldName, value)
if not d.isConstant():
if variable is None:
variable = fieldName
else:
# We can't handle more then one variable atm, OOPS FUCK OUT
return False, "Can only handle 1 variable"
fitDpsTime.setData(d)
if variable is None:
return False, "No variable"
x = []
y = []
for point, val in fitDpsTime.getIterator():
x.append(point[variable])
y.append(val)
return x, y
FitDpsTimeGraph.register()

View File

@@ -26,8 +26,12 @@ class ItemMutatorPanel(wx.Panel):
headerSizer = wx.BoxSizer(wx.HORIZONTAL)
headerSizer.AddStretchSpacer()
headerSizer.Add(BitmapLoader.getStaticBitmap(mod.item.iconID, self, "icons"), 0, 0, 0)
headerSizer.Add(BitmapLoader.getStaticBitmap(mod.mutaplasmid.item.iconID, self, "icons"), 0, wx.LEFT, 0)
itemIcon = BitmapLoader.getStaticBitmap(mod.item.iconID, self, "icons")
if itemIcon is not None:
headerSizer.Add(itemIcon, 0, 0, 0)
mutaIcon = BitmapLoader.getStaticBitmap(mod.mutaplasmid.item.iconID, self, "icons")
if mutaIcon is not None:
headerSizer.Add(mutaIcon, 0, wx.LEFT, 0)
sourceItemShort = "{} {}".format(mod.mutaplasmid.item.name.split(" ")[0], mod.baseItem.name)
sourceItemText = wx.StaticText(self, wx.ID_ANY, sourceItemShort)
font = parent.GetFont()
@@ -81,6 +85,7 @@ class ItemMutatorList(wx.ScrolledWindow):
self.event_mapping = {}
higOverrides = {
('Stasis Web', 'speedFactor'): False,
('Damage Control', 'duration'): True,
}
first = True

View File

@@ -528,9 +528,9 @@ class Miscellanea(ViewColumn):
text = "{0}/s".format(formatAmount(capPerSec, 3, 0, 3))
tooltip = "Energy neutralization per second"
return text, tooltip
elif itemGroup == "Micro Jump Drive":
elif itemGroup in ("Micro Jump Drive", "Micro Jump Field Generators"):
cycleTime = stuff.getModifiedItemAttr("duration") / 1000
text = "{0}s".format(cycleTime)
text = "{0}s".format(formatAmount(cycleTime, 3, 0, 3))
tooltip = "Spoolup time"
return text, tooltip
elif itemGroup in ("Siege Module", "Cynosural Field Generator"):

View File

@@ -23,13 +23,14 @@ from collections import OrderedDict
# noinspection PyPackageRequirements
import wx
from eos.db import getFit
from gui.utils.clipboard import toClipboard
from service.const import PortMultiBuyOptions
from service.port import EfsPort, Port
from service.port.dna import DNA_OPTIONS
from service.port.eft import EFT_OPTIONS
from service.port.multibuy import MULTIBUY_OPTIONS
from service.settings import SettingsProvider
from service.port import EfsPort, Port
from service.const import PortMultiBuyOptions
from eos.db import getFit
from gui.utils.clipboard import toClipboard
class CopySelectDialog(wx.Dialog):
@@ -60,9 +61,9 @@ class CopySelectDialog(wx.Dialog):
("EFT", (CopySelectDialog.copyFormatEft, EFT_OPTIONS)),
("MultiBuy", (CopySelectDialog.copyFormatMultiBuy, MULTIBUY_OPTIONS)),
("ESI", (CopySelectDialog.copyFormatEsi, None)),
("DNA", (CopySelectDialog.copyFormatDna, DNA_OPTIONS)),
("EFS", (CopySelectDialog.copyFormatEfs, None)),
# ("XML", (CopySelectDialog.copyFormatXml, None)),
# ("DNA", (CopySelectDialog.copyFormatDna, None)),
))
defaultFormatOptions = {}
@@ -99,6 +100,8 @@ class CopySelectDialog(wx.Dialog):
for optId, optName, optDesc, _ in formatOptions:
checkbox = wx.CheckBox(self, -1, optName)
if optDesc:
checkbox.SetToolTip(wx.ToolTip(optDesc))
self.options[formatId][optId] = checkbox
if self.settings['options'].get(formatId, {}).get(optId, defaultFormatOptions.get(formatId, {}).get(optId)):
checkbox.SetValue(True)
@@ -166,7 +169,7 @@ class CopySelectDialog(wx.Dialog):
def exportDna(self, options, callback):
fit = getFit(self.mainFrame.getActiveFit())
Port.exportDna(fit, callback)
Port.exportDna(fit, options, callback)
def exportEsi(self, options, callback):
fit = getFit(self.mainFrame.getActiveFit())

View File

@@ -319,7 +319,10 @@ class CargoInfo:
def activeStateLimit(itemIdentity):
item = Market.getInstance().getItem(itemIdentity)
if {'moduleBonusAssaultDamageControl', 'moduleBonusIndustrialInvulnerability'}.intersection(item.effects):
if {
'moduleBonusAssaultDamageControl', 'moduleBonusIndustrialInvulnerability',
'microJumpDrive', 'microJumpPortalDrive'
}.intersection(item.effects):
return FittingModuleState.ONLINE
return FittingModuleState.ACTIVE

View File

@@ -36,4 +36,8 @@ class Graph(object):
# noinspection PyUnresolvedReferences
from gui.builtinGraphs import fitDps # noqa: E402, F401
from gui.builtinGraphs import (
fitDpsRange, # noqa: E402, F401
fitDpsTime, # noqa: E402, F401
fitDmgTime, # noqa: E402, F401
)

View File

@@ -163,6 +163,7 @@ class GraphFrame(wx.Frame):
self.mainFrame.Bind(GE.FIT_CHANGED, self.draw)
self.Bind(wx.EVT_CLOSE, self.closeEvent)
self.Bind(wx.EVT_CHAR_HOOK, self.kbEvent)
self.Bind(wx.EVT_CHOICE, self.graphChanged)
self.Fit()
self.SetMinSize(self.GetSize())
@@ -182,6 +183,10 @@ class GraphFrame(wx.Frame):
return
event.Skip()
def graphChanged(self, event):
self.select(self.graphSelection.GetSelection())
event.Skip()
def closeWindow(self):
self.fitList.fitList.Unbind(wx.EVT_LEFT_DCLICK, handler=self.removeItem)
self.mainFrame.Unbind(GE.FIT_CHANGED, handler=self.draw)
@@ -202,6 +207,7 @@ class GraphFrame(wx.Frame):
icons = view.getIcons()
labels = view.getLabels()
sizer = self.gridSizer
sizer.Clear()
self.gridPanel.DestroyChildren()
self.fields.clear()
@@ -237,6 +243,7 @@ class GraphFrame(wx.Frame):
imgLabelSizer.Add(wx.StaticText(self.gridPanel, wx.ID_ANY, label), 0,
wx.LEFT | wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 3)
sizer.Add(imgLabelSizer, 0, wx.ALIGN_CENTER_VERTICAL)
sizer.Layout()
self.draw()
def draw(self, event=None):

BIN
imgs/renders/24469@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

BIN
imgs/renders/24469@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
imgs/renders/24470@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

BIN
imgs/renders/24470@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
imgs/renders/24471@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

BIN
imgs/renders/24471@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -81,6 +81,14 @@ class PortEftRigSize(IntEnum):
CAPITAL = 4
@unique
class PortDnaOptions(IntEnum):
"""
Contains different types of items for DNA export
"""
FORMATTING = 1
@unique
class GuiAttrGroup(IntEnum):
"""
@@ -101,4 +109,4 @@ class GuiAttrGroup(IntEnum):
JUMP_SYSTEMS = auto()
PROPULSIONS = auto()
FIGHTERS = auto()
SHIP_GROUP = auto()
SHIP_GROUP = auto()

View File

@@ -84,7 +84,7 @@ capac: 2500mm Repeating Cannon
3500rt: 3500mm Artillery
caprt: 3500mm Artillery
dlp: Dual Light Pulse
gpl: Gatling Pulse Laser
# gpl: Gatling Pulse Laser - conflicts with giga pulse
sfp: Small Focused Pulse
fmp: Focused Medium Pulse
hpl: Heavy Pulse Laser #also catches dual heavy
@@ -110,7 +110,7 @@ hml: Heavy Missile Launcher #gets HAM + RHML launcher too?
rhml: Rapid Heavy Missile Launcher
cml: Cruise Missile Launcher
tpl: Torpedo Launcher
tl: Torpedo Launcher
# tl: Torpedo Launcher - conflicts with tracking link entry
rtl: Rapid Torpedo Launcher
hawml: Rapid Torpedo Launcher
hawtl: Rapid Torpedo Launcher
@@ -124,6 +124,7 @@ dd: Doomsday
rp: Reaper
disco: Smartbomb
sbomb: Smartbomb
fvb: Focused Void Bomb
# Propulsion Modules
ab: Afterburner

View File

@@ -32,12 +32,17 @@ from eos.saveddata.fit import Fit
from eos.saveddata.module import Module
from eos.saveddata.ship import Ship
from gui.fitCommands.helpers import activeStateLimit
from service.const import PortDnaOptions
from service.fit import Fit as svcFit
from service.market import Market
pyfalog = Logger(__name__)
DNA_OPTIONS = (
(PortDnaOptions.FORMATTING, 'Formatting Tags', 'Include formatting tags to paste fit directly into corp bulletins, MOTD, etc.', True),
)
def importDna(string, fitName=None):
sMkt = Market.getInstance()
@@ -130,12 +135,11 @@ def importDna(string, fitName=None):
return f
def exportDna(fit, callback):
def exportDna(fit, options, callback):
dna = str(fit.shipID)
subsystems = [] # EVE cares which order you put these in
mods = OrderedDict()
charges = OrderedDict()
sFit = svcFit.getInstance()
for mod in fit.modules:
if not mod.isEmpty:
if mod.slot == FittingSlot.SUBSYSTEM:
@@ -163,9 +167,6 @@ def exportDna(fit, callback):
for fighter in fit.fighters:
dna += ":{0};{1}".format(fighter.itemID, fighter.amountActive)
for fighter in fit.fighters:
dna += ":{0};{1}".format(fighter.itemID, fighter.amountActive)
for cargo in fit.cargo:
# DNA format is a simple/dumb format. As CCP uses the slot information of the item itself
# without designating slots in the DNA standard, we need to make sure we only include
@@ -182,6 +183,9 @@ def exportDna(fit, callback):
text = dna + "::"
if options[PortDnaOptions.FORMATTING]:
text = '<url=fitting:{}>{}</url>'.format(text, fit.name)
if callback:
callback(text)
else:

View File

@@ -272,8 +272,8 @@ class Port(object):
return importDna(string, fitName=fitName)
@staticmethod
def exportDna(fit, callback=None):
return exportDna(fit, callback=callback)
def exportDna(fit, options, callback=None):
return exportDna(fit, options, callback=callback)
# ESI-related methods
@staticmethod

View File

@@ -1 +1 @@
version: v2.9.3
version: v2.9.4dev1