diff --git a/config.py b/config.py index b5d8a27fb..b87d80f90 100644 --- a/config.py +++ b/config.py @@ -18,10 +18,10 @@ debug = False saveInRoot = False # Version data -version = "1.22.2" -tag = "Stable" -expansionName = "YC 118.6" -expansionVersion = "1.0" +version = "1.22.3" +tag = "git" +expansionName = "Singularity" +expansionVersion = "1053072" evemonMinVersion = "4081" pyfaPath = None diff --git a/eos/effects/lightningweapon.py b/eos/effects/lightningweapon.py new file mode 100644 index 000000000..3136bc64c --- /dev/null +++ b/eos/effects/lightningweapon.py @@ -0,0 +1,3 @@ +type = 'active' +def handler(fit, module, context): + pass diff --git a/eos/effects/missileaoecloudsizebonusonline.py b/eos/effects/missileaoecloudsizebonusonline.py index 843fc0c47..11ebe04f2 100644 --- a/eos/effects/missileaoecloudsizebonusonline.py +++ b/eos/effects/missileaoecloudsizebonusonline.py @@ -3,7 +3,7 @@ # Used by: # Modules from group: Missile Guidance Enhancer (3 of 3) type = "passive" -def handler(fit, container, context): +def handler(fit, module, context): fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("Missile Launcher Operation"), - "aoeCloudSize", container.getModifiedItemAttr("aoeCloudSizeBonus"), + "aoeCloudSize", module.getModifiedItemAttr("aoeCloudSizeBonus"), stackingPenalties=True) diff --git a/eos/effects/missileaoevelocitybonusonline.py b/eos/effects/missileaoevelocitybonusonline.py index 66eb5321b..acfa8c8ec 100644 --- a/eos/effects/missileaoevelocitybonusonline.py +++ b/eos/effects/missileaoevelocitybonusonline.py @@ -3,7 +3,7 @@ # Used by: # Modules from group: Missile Guidance Enhancer (3 of 3) type = "passive" -def handler(fit, container, context): +def handler(fit, module, context): fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("Missile Launcher Operation"), - "aoeVelocity", container.getModifiedItemAttr("aoeVelocityBonus"), + "aoeVelocity", module.getModifiedItemAttr("aoeVelocityBonus"), stackingPenalties=True) diff --git a/eos/effects/missileexplosiondelaybonusonline.py b/eos/effects/missileexplosiondelaybonusonline.py index 5d2c770d9..3f6949217 100644 --- a/eos/effects/missileexplosiondelaybonusonline.py +++ b/eos/effects/missileexplosiondelaybonusonline.py @@ -3,7 +3,7 @@ # Used by: # Modules from group: Missile Guidance Enhancer (3 of 3) type = "passive" -def handler(fit, container, context): +def handler(fit, module, context): fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("Missile Launcher Operation"), - "explosionDelay", container.getModifiedItemAttr("explosionDelayBonus"), + "explosionDelay", module.getModifiedItemAttr("explosionDelayBonus"), stackingPenalties=True) diff --git a/eos/effects/missilevelocitybonusonline.py b/eos/effects/missilevelocitybonusonline.py index 95280821a..947a2dfac 100644 --- a/eos/effects/missilevelocitybonusonline.py +++ b/eos/effects/missilevelocitybonusonline.py @@ -3,7 +3,7 @@ # Used by: # Modules from group: Missile Guidance Enhancer (3 of 3) type = "passive" -def handler(fit, container, context): +def handler(fit, module, context): fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("Missile Launcher Operation"), - "maxVelocity", container.getModifiedItemAttr("missileVelocityBonus"), + "maxVelocity", module.getModifiedItemAttr("missileVelocityBonus"), stackingPenalties=True) diff --git a/eos/effects/pointdefense.py b/eos/effects/pointdefense.py new file mode 100644 index 000000000..41574b8ab --- /dev/null +++ b/eos/effects/pointdefense.py @@ -0,0 +1,7 @@ +# targetAttack +# +# Used by: +# Citadel Point Defense +type = 'active' +def handler(fit, module, context): + pass diff --git a/eos/effects/remoteguidancedisruptfalloff.py b/eos/effects/remoteguidancedisruptfalloff.py index 48fadecaa..ede3f06f5 100644 --- a/eos/effects/remoteguidancedisruptfalloff.py +++ b/eos/effects/remoteguidancedisruptfalloff.py @@ -4,7 +4,7 @@ # Variations of module: Guidance Disruptor I (6 of 6) type = "active", "projected" -def handler(fit, src, context): +def handler(fit, module, context): if "projected" in context: for srcAttr, tgtAttr in ( ("aoeCloudSizeBonus", "aoeCloudSize"), @@ -13,5 +13,5 @@ def handler(fit, src, context): ("explosionDelayBonus", "explosionDelay"), ): fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("Missile Launcher Operation"), - tgtAttr, src.getModifiedItemAttr(srcAttr), + tgtAttr, module.getModifiedItemAttr(srcAttr), stackingPenalties=True, remoteResists=True) diff --git a/eos/effects/skillstructuredoomsdaydurationbonus.py b/eos/effects/skillstructuredoomsdaydurationbonus.py new file mode 100644 index 000000000..7185051a7 --- /dev/null +++ b/eos/effects/skillstructuredoomsdaydurationbonus.py @@ -0,0 +1,4 @@ +type = "passive", "structure" +def handler(fit, src, context): + fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Structure Doomsday Weapon", + "duration", src.getModifiedItemAttr("durationBonus"), skill="Structure Doomsday Operation") diff --git a/eos/effects/skillstructureelectronicsystemscapneedbonus.py b/eos/effects/skillstructureelectronicsystemscapneedbonus.py new file mode 100644 index 000000000..b1067ce90 --- /dev/null +++ b/eos/effects/skillstructureelectronicsystemscapneedbonus.py @@ -0,0 +1,5 @@ +type = "passive", "structure" +def handler(fit, src, context): + groups = ("Structure Warp Scrambler", "Structure Disruption Battery", "Structure Stasis Webifier") + fit.modules.filteredItemBoost(lambda mod: mod.item.group.name in groups, + "capacitorNeed", src.getModifiedItemAttr("capNeedBonus"), skill="Structure Electronic Systems") diff --git a/eos/effects/skillstructureengineeringsystemscapneedbonus.py b/eos/effects/skillstructureengineeringsystemscapneedbonus.py new file mode 100644 index 000000000..c251a210c --- /dev/null +++ b/eos/effects/skillstructureengineeringsystemscapneedbonus.py @@ -0,0 +1,5 @@ +type = "passive", "structure" +def handler(fit, src, context): + groups = ("Structure Energy Neutralizer", "Structure Area Denial Module") + fit.modules.filteredItemBoost(lambda mod: mod.item.group.name in groups, + "capacitorNeed", src.getModifiedItemAttr("capNeedBonus"), skill="Structure Engineering Systems") diff --git a/eos/effects/skillstructuremissiledamagebonus.py b/eos/effects/skillstructuremissiledamagebonus.py new file mode 100644 index 000000000..e1dc32096 --- /dev/null +++ b/eos/effects/skillstructuremissiledamagebonus.py @@ -0,0 +1,6 @@ +type = "passive", "structure" +def handler(fit, src, context): + groups = ("Structure Anti-Capital Missile", "Structure Anti-Subcapital Missile", "Structure Guided Bomb") + for damageType in ("em", "thermal", "explosive", "kinetic"): + fit.modules.filteredChargeBoost(lambda mod: mod.charge.group.name in groups, + "%sDamage"%damageType, src.getModifiedItemAttr("damageMultiplierBonus"), skill="Structure Missile Systems") diff --git a/eos/effects/structureMissileGuidanceEnhancer.py b/eos/effects/structureMissileGuidanceEnhancer.py new file mode 100644 index 000000000..3e06f4488 --- /dev/null +++ b/eos/effects/structureMissileGuidanceEnhancer.py @@ -0,0 +1,19 @@ +# missileAOECloudSizeBonusOnline +# +# Used by: +# Modules from group: Missile Guidance Enhancer (3 of 3) +type = "passive" +def handler(fit, module, context): + groups = ("Structure Anti-Capital Missile", "Structure Anti-Subcapital Missile") + fit.modules.filteredChargeBoost(lambda mod: mod.charge.group.name in groups, + "aoeCloudSize", module.getModifiedItemAttr("aoeCloudSizeBonus"), + stackingPenalties=True) + fit.modules.filteredChargeBoost(lambda mod: mod.charge.group.name in groups, + "aoeVelocity", module.getModifiedItemAttr("aoeVelocityBonus"), + stackingPenalties=True) + fit.modules.filteredChargeBoost(lambda mod: mod.charge.group.name in groups, + "explosionDelay", module.getModifiedItemAttr("explosionDelayBonus"), + stackingPenalties=True) + fit.modules.filteredChargeBoost(lambda mod: mod.charge.group.name in groups, + "maxVelocity", module.getModifiedItemAttr("missileVelocityBonus"), + stackingPenalties=True) \ No newline at end of file diff --git a/eos/effects/structureballisticcontrolsystem.py b/eos/effects/structureballisticcontrolsystem.py new file mode 100644 index 000000000..b21499c99 --- /dev/null +++ b/eos/effects/structureballisticcontrolsystem.py @@ -0,0 +1,13 @@ +type = "passive" +def handler(fit, module, context): + missileGroups = ("Structure Anti-Capital Missile", "Structure Anti-Subcapital Missile") + + for dmgType in ("em", "kinetic", "explosive", "thermal"): + fit.modules.filteredChargeMultiply(lambda mod: mod.charge.group.name in missileGroups, + "%sDamage" % dmgType, module.getModifiedItemAttr("missileDamageMultiplierBonus"), + stackingPenalties = True) + + launcherGroups = ("Structure AXL Missile Launcher", "Structure ASML Missile Launcher") + fit.modules.filteredItemMultiply(lambda mod: mod.item.group.name in launcherGroups, + "speed", module.getModifiedItemAttr("speedMultiplier"), + stackingPenalties=True) diff --git a/eos/effects/structureenergyneutralizerfalloff.py b/eos/effects/structureenergyneutralizerfalloff.py new file mode 100644 index 000000000..8a5754ef6 --- /dev/null +++ b/eos/effects/structureenergyneutralizerfalloff.py @@ -0,0 +1,8 @@ +from eos.types import State +type = "active", "projected" +def handler(fit, container, context): + if "projected" in context and ((hasattr(container, "state") \ + and container.state >= State.ACTIVE) or hasattr(container, "amountActive")): + amount = container.getModifiedItemAttr("energyNeutralizerAmount") + time = container.getModifiedItemAttr("duration") + fit.addDrain(time, amount, 0) diff --git a/eos/effects/structuremoduleeffectecm.py b/eos/effects/structuremoduleeffectecm.py new file mode 100644 index 000000000..ff841419e --- /dev/null +++ b/eos/effects/structuremoduleeffectecm.py @@ -0,0 +1,7 @@ +type = "projected", "active" +def handler(fit, module, context): + if "projected" in context: + # jam formula: 1 - (1- (jammer str/ship str))^(# of jam mods with same str)) + strModifier = 1 - module.getModifiedItemAttr("scan{0}StrengthBonus".format(fit.scanType))/fit.scanStrength + + fit.ecmProjectedStr *= strModifier diff --git a/eos/effects/structuremoduleeffectremotesensordampener.py b/eos/effects/structuremoduleeffectremotesensordampener.py new file mode 100644 index 000000000..5ec677fcc --- /dev/null +++ b/eos/effects/structuremoduleeffectremotesensordampener.py @@ -0,0 +1,11 @@ + +type= "projected", "active" +def handler(fit, module, context): + if "projected" not in context: + return + + fit.ship.boostItemAttr("maxTargetRange", module.getModifiedItemAttr("maxTargetRangeBonus"), + stackingPenalties = True, remoteResists=True) + + fit.ship.boostItemAttr("scanResolution", module.getModifiedItemAttr("scanResolutionBonus"), + stackingPenalties = True, remoteResists=True) diff --git a/eos/effects/structuremoduleeffectstasiswebifier.py b/eos/effects/structuremoduleeffectstasiswebifier.py new file mode 100644 index 000000000..f0c5872a1 --- /dev/null +++ b/eos/effects/structuremoduleeffectstasiswebifier.py @@ -0,0 +1,5 @@ +type = "active", "projected" +def handler(fit, module, context): + if "projected" not in context: return + fit.ship.boostItemAttr("maxVelocity", module.getModifiedItemAttr("speedFactor"), + stackingPenalties = True, remoteResists=True) diff --git a/eos/effects/structuremoduleeffecttargetpainter.py b/eos/effects/structuremoduleeffecttargetpainter.py new file mode 100644 index 000000000..e86453eb5 --- /dev/null +++ b/eos/effects/structuremoduleeffecttargetpainter.py @@ -0,0 +1,5 @@ +type = "projected", "active" +def handler(fit, container, context): + if "projected" in context: + fit.ship.boostItemAttr("signatureRadius", container.getModifiedItemAttr("signatureRadiusBonus"), + stackingPenalties = True, remoteResists=True) diff --git a/eos/effects/structuremoduleeffectweapondisruption.py b/eos/effects/structuremoduleeffectweapondisruption.py new file mode 100644 index 000000000..7c25bd67a --- /dev/null +++ b/eos/effects/structuremoduleeffectweapondisruption.py @@ -0,0 +1,24 @@ + +type = "active", "projected" + +def handler(fit, module, context): + if "projected" in context: + for srcAttr, tgtAttr in ( + ("aoeCloudSizeBonus", "aoeCloudSize"), + ("aoeVelocityBonus", "aoeVelocity"), + ("missileVelocityBonus", "maxVelocity"), + ("explosionDelayBonus", "explosionDelay"), + ): + fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("Missile Launcher Operation"), + tgtAttr, module.getModifiedItemAttr(srcAttr), + stackingPenalties=True, remoteResists=True) + + fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Gunnery"), + "trackingSpeed", module.getModifiedItemAttr("trackingSpeedBonus"), + stackingPenalties = True, remoteResists=True) + fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Gunnery"), + "maxRange", module.getModifiedItemAttr("maxRangeBonus"), + stackingPenalties = True, remoteResists=True) + fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Gunnery"), + "falloff", module.getModifiedItemAttr("falloffBonus"), + stackingPenalties = True, remoteResists=True) diff --git a/eos/effects/structurerigaoevelocitybonussingletargetmissiles.py b/eos/effects/structurerigaoevelocitybonussingletargetmissiles.py new file mode 100644 index 000000000..1953e5faf --- /dev/null +++ b/eos/effects/structurerigaoevelocitybonussingletargetmissiles.py @@ -0,0 +1,7 @@ +type = "passive" +def handler(fit, src, context): + groups = ("Structure Anti-Subcapital Missile", "Structure Anti-Capital Missile") + + fit.modules.filteredChargeMultiply(lambda mod: mod.charge.group.name in groups, + "aoeVelocity", src.getModifiedItemAttr("structureRigMissileExploVeloBonus"), + stackingPenalties=True) diff --git a/eos/effects/structurerigdoomsdaydamageloss.py b/eos/effects/structurerigdoomsdaydamageloss.py new file mode 100644 index 000000000..3a9b795e9 --- /dev/null +++ b/eos/effects/structurerigdoomsdaydamageloss.py @@ -0,0 +1,5 @@ +type = "passive" +def handler(fit, src, context): + fit.modules.filteredItemMultiply(lambda mod: mod.item.group.name == "Structure Doomsday Weapon", + "lightningWeaponDamageLossTarget", src.getModifiedItemAttr("structureRigDoomsdayDamageLossTargetBonus"), + stackingPenalties=True) diff --git a/eos/effects/structurerigdoomsdaytargetamountbonus.py b/eos/effects/structurerigdoomsdaytargetamountbonus.py new file mode 100644 index 000000000..3adeb5b07 --- /dev/null +++ b/eos/effects/structurerigdoomsdaytargetamountbonus.py @@ -0,0 +1,5 @@ +type = "passive" +def handler(fit, src, context): + fit.modules.filteredItemMultiply(lambda mod: mod.item.group.name == "Structure Doomsday Weapon", + "lightningWeaponTargetAmount", src.getModifiedItemAttr("structureRigDoomsdayTargetAmountBonus"), + stackingPenalties=True) diff --git a/eos/effects/structurerigewcapacitorneed.py b/eos/effects/structurerigewcapacitorneed.py new file mode 100644 index 000000000..267ea1f83 --- /dev/null +++ b/eos/effects/structurerigewcapacitorneed.py @@ -0,0 +1,6 @@ +type = "passive" +def handler(fit, src, context): + groups = ("Structure ECM Battery", "Structure Disruption Battery") + fit.modules.filteredItemMultiply(lambda mod: mod.item.group.name in groups, + "capacitorNeed", src.getModifiedItemAttr("structureRigEwarCapUseBonus"), + stackingPenalties=True) \ No newline at end of file diff --git a/eos/effects/structurerigewmaxrangefalloff.py b/eos/effects/structurerigewmaxrangefalloff.py new file mode 100644 index 000000000..ed7729f31 --- /dev/null +++ b/eos/effects/structurerigewmaxrangefalloff.py @@ -0,0 +1,15 @@ +type = "passive" +def handler(fit, src, context): + groups = ("Structure ECM Battery", "Structure Disruption Battery") + + fit.modules.filteredItemMultiply(lambda mod: mod.item.group.name in groups, + "falloff", src.getModifiedItemAttr("structureRigEwarFalloffBonus"), + stackingPenalties=True) + + fit.modules.filteredItemMultiply(lambda mod: mod.item.group.name in groups, + "maxRange", src.getModifiedItemAttr("structureRigEwarOptimalBonus"), + stackingPenalties=True) + + fit.modules.filteredItemMultiply(lambda mod: mod.item.group.name in groups, + "falloffEffectiveness", src.getModifiedItemAttr("structureRigEwarFalloffBonus"), + stackingPenalties=True) \ No newline at end of file diff --git a/eos/effects/structurerigexplosionradiusbonusaoemissiles.py b/eos/effects/structurerigexplosionradiusbonusaoemissiles.py new file mode 100644 index 000000000..8a1781940 --- /dev/null +++ b/eos/effects/structurerigexplosionradiusbonusaoemissiles.py @@ -0,0 +1,5 @@ +type = "passive" +def handler(fit, src, context): + fit.modules.filteredChargeMultiply(lambda mod: mod.charge.group.name == "Structure Guided Bomb", + "aoeCloudSize", src.getModifiedItemAttr("structureRigMissileExplosionRadiusBonus"), + stackingPenalties=True) diff --git a/eos/effects/structurerigmaxtargets.py b/eos/effects/structurerigmaxtargets.py new file mode 100644 index 000000000..a0bc8158d --- /dev/null +++ b/eos/effects/structurerigmaxtargets.py @@ -0,0 +1,3 @@ +type = "passive" +def handler(fit, src, context): + fit.ship.increaseItemAttr("maxLockedTargets", src.getModifiedItemAttr("structureRigMaxTargetBonus")) diff --git a/eos/effects/structurerigneutralizercapacitorneed.py b/eos/effects/structurerigneutralizercapacitorneed.py new file mode 100644 index 000000000..d17e771fd --- /dev/null +++ b/eos/effects/structurerigneutralizercapacitorneed.py @@ -0,0 +1,5 @@ +type = "passive" +def handler(fit, src, context): + fit.modules.filteredItemMultiply(lambda mod: mod.item.group.name == "Structure Energy Neutralizer", + "capacitorNeed", src.getModifiedItemAttr("structureRigEwarCapUseBonus"), + stackingPenalties=True) diff --git a/eos/effects/structurerigneutralizermaxrangefalloffeffectiveness.py b/eos/effects/structurerigneutralizermaxrangefalloffeffectiveness.py new file mode 100644 index 000000000..f6f1ef046 --- /dev/null +++ b/eos/effects/structurerigneutralizermaxrangefalloffeffectiveness.py @@ -0,0 +1,9 @@ +type = "passive" +def handler(fit, src, context): + fit.modules.filteredItemMultiply(lambda mod: mod.item.group.name == "Structure Energy Neutralizer", + "maxRange", src.getModifiedItemAttr("structureRigEwarOptimalBonus"), + stackingPenalties=True) + + fit.modules.filteredItemMultiply(lambda mod: mod.item.group.name == "Structure Energy Neutralizer", + "falloffEffectiveness", src.getModifiedItemAttr("structureRigEwarFalloffBonus"), + stackingPenalties=True) diff --git a/eos/effects/structurerigpdbcapacitorneed.py b/eos/effects/structurerigpdbcapacitorneed.py new file mode 100644 index 000000000..92bf64b72 --- /dev/null +++ b/eos/effects/structurerigpdbcapacitorneed.py @@ -0,0 +1,5 @@ +type = "passive" +def handler(fit, src, context): + fit.modules.filteredItemMultiply(lambda mod: mod.item.group.name == "Structure Area Denial Module", + "capacitorNeed", src.getModifiedItemAttr("structureRigPDCapUseBonus"), + stackingPenalties=True) diff --git a/eos/effects/structurerigpdbmaxrange.py b/eos/effects/structurerigpdbmaxrange.py new file mode 100644 index 000000000..f3223cde8 --- /dev/null +++ b/eos/effects/structurerigpdbmaxrange.py @@ -0,0 +1,5 @@ +type = "passive" +def handler(fit, src, context): + fit.modules.filteredItemMultiply(lambda mod: mod.item.group.name == "Structure Area Denial Module", + "empFieldRange", src.getModifiedItemAttr("structureRigPDRangeBonus"), + stackingPenalties=True) diff --git a/eos/effects/structurerigsensorresolution.py b/eos/effects/structurerigsensorresolution.py new file mode 100644 index 000000000..b5881194a --- /dev/null +++ b/eos/effects/structurerigsensorresolution.py @@ -0,0 +1,4 @@ +type = "passive" +def handler(fit, src, context): + fit.ship.boostItemAttr("scanResolution", src.getModifiedItemAttr("structureRigScanResBonus"), + stackingPenalties=True) diff --git a/eos/effects/structurerigvelocitybonusaoemissiles.py b/eos/effects/structurerigvelocitybonusaoemissiles.py new file mode 100644 index 000000000..c8ec1d01a --- /dev/null +++ b/eos/effects/structurerigvelocitybonusaoemissiles.py @@ -0,0 +1,5 @@ +type = "passive" +def handler(fit, src, context): + fit.modules.filteredChargeMultiply(lambda mod: mod.charge.group.name == "Structure Guided Bomb", + "maxVelocity", src.getModifiedItemAttr("structureRigMissileVelocityBonus"), + stackingPenalties=True) diff --git a/eos/effects/structurerigvelocitybonussingletargetmissiles.py b/eos/effects/structurerigvelocitybonussingletargetmissiles.py new file mode 100644 index 000000000..bd6ed2665 --- /dev/null +++ b/eos/effects/structurerigvelocitybonussingletargetmissiles.py @@ -0,0 +1,6 @@ +type = "passive" +def handler(fit, src, context): + groups = ("Structure Anti-Subcapital Missile", "Structure Anti-Capital Missile") + fit.modules.filteredChargeMultiply(lambda mod: mod.charge.group.name in groups, + "maxVelocity", src.getModifiedItemAttr("structureRigMissileVelocityBonus"), + stackingPenalties=True) diff --git a/eos/effects/structurewarpscrambleblockmwdwithnpceffect.py b/eos/effects/structurewarpscrambleblockmwdwithnpceffect.py new file mode 100644 index 000000000..c04eca1dd --- /dev/null +++ b/eos/effects/structurewarpscrambleblockmwdwithnpceffect.py @@ -0,0 +1,12 @@ +runTime = "early" +type = "projected", "active" + +from eos.types import State + +def handler(fit, module, context): + if "projected" not in context: + return + # this is such a dirty hack + for mod in fit.modules: + if not mod.isEmpty and mod.item.requiresSkill("High Speed Maneuvering") and mod.state > State.ONLINE: + mod.state = State.ONLINE diff --git a/eos/gamedata.py b/eos/gamedata.py index a2869fd84..2125cd7e1 100644 --- a/eos/gamedata.py +++ b/eos/gamedata.py @@ -89,7 +89,7 @@ class Effect(EqBase): The type of the effect, automaticly fetched from effects/.py if the file exists. Valid values are: - "passive", "active", "projected", "gang" + "passive", "active", "projected", "gang", "structure" Each gives valuable information to eos about what type the module having the effect is. passive vs active gives eos clues about wether to module diff --git a/eos/saveddata/character.py b/eos/saveddata/character.py index adbb1fbf9..1f5832ea2 100644 --- a/eos/saveddata/character.py +++ b/eos/saveddata/character.py @@ -24,6 +24,7 @@ from itertools import chain from eos.effectHandlerHelpers import HandledItem, HandledImplantBoosterList import eos.db import eos +import eos.types import logging logger = logging.getLogger(__name__) @@ -329,7 +330,7 @@ class Skill(HandledItem): return for effect in item.effects.itervalues(): - if effect.runTime == runTime and effect.isType("passive"): + if effect.runTime == runTime and effect.isType("passive") and (not fit.isStructure or effect.isType("structure")): try: effect.handler(fit, self, ("skill",)) except AttributeError: diff --git a/eos/saveddata/citadel.py b/eos/saveddata/citadel.py new file mode 100644 index 000000000..f4d5fed47 --- /dev/null +++ b/eos/saveddata/citadel.py @@ -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 . +#=============================================================================== + +from eos.modifiedAttributeDict import ModifiedAttributeDict, ItemAttrShortcut +from eos.effectHandlerHelpers import HandledItem +from eos.saveddata.mode import Mode +import eos.db +from eos.types import Ship +import logging + +logger = logging.getLogger(__name__) + +class Citadel(Ship): + + def validate(self, item): + if item.category.name != "Structure": + raise ValueError('Passed item "%s" (category: (%s)) is not under Structure category'%(item.name, item.category.name)) + + def __deepcopy__(self, memo): + copy = Citadel(self.item) + return copy + + def __repr__(self): + return "Citadel(ID={}, name={}) at {}".format( + self.item.ID, self.item.name, hex(id(self)) + ) diff --git a/eos/saveddata/fighter.py b/eos/saveddata/fighter.py index ebbffb814..f7b58a2ba 100644 --- a/eos/saveddata/fighter.py +++ b/eos/saveddata/fighter.py @@ -35,7 +35,7 @@ class Fighter(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): def __init__(self, item): """Initialize a fighter from the program""" self.__item = item - print self.__item.category.name + if self.isInvalid: raise ValueError("Passed item is not a Fighter") diff --git a/eos/saveddata/fit.py b/eos/saveddata/fit.py index 843abceb8..a3000267f 100644 --- a/eos/saveddata/fit.py +++ b/eos/saveddata/fit.py @@ -24,7 +24,7 @@ from itertools import chain from eos import capSim from copy import deepcopy from math import sqrt, log, asinh -from eos.types import Drone, Cargo, Ship, Character, State, Slot, Module, Implant, Booster, Skill +from eos.types import Drone, Cargo, Ship, Character, State, Slot, Module, Implant, Booster, Skill, Citadel from eos.saveddata.module import State, Hardpoint from eos.saveddata.mode import Mode import eos.db @@ -92,7 +92,10 @@ class Fit(object): return try: - self.__ship = Ship(item, self) + try: + self.__ship = Ship(item, self) + except ValueError: + self.__ship = Citadel(item, self) # @todo extra attributes is now useless, however it set to be # the same as ship attributes for ease (so we don't have to # change all instances in source). Remove this at some point @@ -191,6 +194,10 @@ class Fit(object): # set fit attributes the same as ship self.extraAttributes = self.ship.itemModifiedAttributes + @property + def isStructure(self): + return isinstance(self.ship, Citadel) + @property def drones(self): return self.__drones @@ -331,7 +338,7 @@ class Fit(object): @property def alignTime(self): - agility = self.ship.getModifiedItemAttr("agility") + agility = self.ship.getModifiedItemAttr("agility") or 0 mass = self.ship.getModifiedItemAttr("mass") return -log(0.25) * agility * mass / 1000000 @@ -510,6 +517,11 @@ class Fit(object): self.boosters, self.appliedImplants, self.modules + ] if not self.isStructure else [ + # Ensure a restricted set for citadels + (self.character, self.ship), + self.fighters, + self.modules ] # Items that are restricted. These items are only run on the local @@ -564,7 +576,7 @@ class Fit(object): if self.ship is None: return - for slotType in (Slot.LOW, Slot.MED, Slot.HIGH, Slot.RIG, Slot.SUBSYSTEM): + for slotType in (Slot.LOW, Slot.MED, Slot.HIGH, Slot.RIG, Slot.SUBSYSTEM, Slot.SERVICE): amount = self.getSlotsFree(slotType, True) if amount > 0: for _ in xrange(int(amount)): @@ -639,6 +651,7 @@ class Fit(object): Slot.HIGH: "hiSlots", Slot.RIG: "rigSlots", Slot.SUBSYSTEM: "maxSubSystems", + Slot.SERVICE: "serviceSlots", Slot.F_LIGHT: "fighterLightSlots", Slot.F_SUPPORT: "fighterSupportSlots", Slot.F_HEAVY: "fighterHeavySlots"} @@ -743,6 +756,10 @@ class Fit(object): capacity = self.ship.getModifiedItemAttr("capacitorCapacity") mass = self.ship.getModifiedItemAttr("mass") warpCapNeed = self.ship.getModifiedItemAttr("warpCapacitorNeed") + + if not warpCapNeed: + return 0 + return capacity / (mass * warpCapNeed) @property diff --git a/eos/saveddata/module.py b/eos/saveddata/module.py index f5197f6f0..049e98939 100644 --- a/eos/saveddata/module.py +++ b/eos/saveddata/module.py @@ -24,6 +24,7 @@ from eos.effectHandlerHelpers import HandledItem, HandledCharge from eos.enum import Enum from eos.mathUtils import floorFloat import eos.db +from eos.types import Citadel import logging logger = logging.getLogger(__name__) @@ -46,6 +47,8 @@ class Slot(Enum): # system effects. They are projected "modules" and pyfa assumes all modules # have a slot. In this case, make one up. SYSTEM = 7 + # used for citadel services + SERVICE = 8 # fighter 'slots'. Just easier to put them here... F_LIGHT = 10 F_SUPPORT = 11 @@ -151,7 +154,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): def isInvalid(self): if self.isEmpty: return False - return self.__item is None or (self.__item.category.name not in ("Module", "Subsystem") and self.__item.group.name != "Effect Beacon") + return self.__item is None or (self.__item.category.name not in ("Module", "Subsystem", "Structure Module") and self.__item.group.name != "Effect Beacon") @property def numCharges(self): @@ -393,6 +396,11 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): if (len(fitsOnGroup) > 0 or len(fitsOnType) > 0) and fit.ship.item.group.ID not in fitsOnGroup and fit.ship.item.ID not in fitsOnType: return False + # AFAIK Citadel modules will always be restricted based on canFitShipType/Group. If we are fitting to a Citadel + # and the module does not have these properties, return false to prevent regular ship modules from being used + if isinstance(fit.ship, Citadel) and len(fitsOnGroup) == 0 and len(fitsOnType) == 0: + return False + # If the mod is a subsystem, don't let two subs in the same slot fit if self.slot == Slot.SUBSYSTEM: subSlot = self.getModifiedItemAttr("subSystemSlot") @@ -534,7 +542,8 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): "loPower" : Slot.LOW, "medPower" : Slot.MED, "hiPower" : Slot.HIGH, - "subSystem" : Slot.SUBSYSTEM} + "subSystem" : Slot.SUBSYSTEM, + "serviceSlot": Slot.SERVICE} if item is None: return None for effectName, slot in effectSlotMap.iteritems(): diff --git a/eos/saveddata/ship.py b/eos/saveddata/ship.py index 3a78fd122..6dd20feb1 100644 --- a/eos/saveddata/ship.py +++ b/eos/saveddata/ship.py @@ -42,9 +42,7 @@ class Ship(ItemAttrShortcut, HandledItem): } def __init__(self, item, parent=None): - - if item.category.name != "Ship": - raise ValueError('Passed item "%s" (category: (%s)) is not under Ship category'%(item.name, item.category.name)) + self.validate(item) self.__item = item self.__modeItems = self.__getModeItems() @@ -58,6 +56,10 @@ class Ship(ItemAttrShortcut, HandledItem): self.parent = parent self.commandBonus = 0 + def validate(self, item): + if item.category.name != "Ship": + raise ValueError('Passed item "%s" (category: (%s)) is not under Ship category'%(item.name, item.category.name)) + @property def item(self): return self.__item diff --git a/eos/types.py b/eos/types.py index fc25741b2..12e7eb281 100644 --- a/eos/types.py +++ b/eos/types.py @@ -25,6 +25,8 @@ from eos.saveddata.crestchar import CrestChar from eos.saveddata.damagePattern import DamagePattern from eos.saveddata.targetResists import TargetResists from eos.saveddata.character import Character, Skill +from eos.saveddata.ship import Ship +from eos.saveddata.citadel import Citadel from eos.saveddata.module import Module, State, Slot, Hardpoint, Rack from eos.saveddata.drone import Drone from eos.saveddata.fighterAbility import FighterAbility @@ -34,10 +36,10 @@ from eos.saveddata.implant import Implant from eos.saveddata.implantSet import ImplantSet from eos.saveddata.booster import SideEffect from eos.saveddata.booster import Booster -from eos.saveddata.ship import Ship from eos.saveddata.fit import Fit, ImplantLocation from eos.saveddata.mode import Mode from eos.saveddata.fleet import Fleet, Wing, Squad from eos.saveddata.miscData import MiscData from eos.saveddata.override import Override + import eos.db diff --git a/eve.db b/eve.db index 0c2623139..85b72599d 100644 Binary files a/eve.db and b/eve.db differ diff --git a/gui/additionsPane.py b/gui/additionsPane.py index d108686cc..8c855dc95 100644 --- a/gui/additionsPane.py +++ b/gui/additionsPane.py @@ -58,23 +58,36 @@ class AdditionsPane(TogglePanel): gangImg = BitmapLoader.getImage("fleet_fc_small", "gui") cargoImg = BitmapLoader.getImage("cargo_small", "gui") - self.notebook.AddPage(DroneView(self.notebook), "Drones", tabImage = droneImg, showClose = False) - self.notebook.AddPage(FighterView(self.notebook), "Fighters", tabImage = fighterImg, showClose = False) - self.notebook.AddPage(CargoView(self.notebook), "Cargo", tabImage = cargoImg, showClose = False) - self.notebook.AddPage(ImplantView(self.notebook), "Implants", tabImage = implantImg, showClose = False) - self.notebook.AddPage(BoosterView(self.notebook), "Boosters", tabImage = boosterImg, showClose = False) + self.drone = DroneView(self.notebook) + self.notebook.AddPage(self.drone, "Drones", tabImage = droneImg, showClose = False) + + self.fighter = FighterView(self.notebook) + self.notebook.AddPage(self.fighter, "Fighters", tabImage = fighterImg, showClose = False) + + self.cargo = CargoView(self.notebook) + self.notebook.AddPage(self.cargo, "Cargo", tabImage = cargoImg, showClose = False) + + self.implant = ImplantView(self.notebook) + self.notebook.AddPage(self.implant, "Implants", tabImage = implantImg, showClose = False) + + self.booster = BoosterView(self.notebook) + self.notebook.AddPage(self.booster, "Boosters", tabImage = boosterImg, showClose = False) self.projectedPage = ProjectedView(self.notebook) self.notebook.AddPage(self.projectedPage, "Projected", tabImage = projectedImg, showClose = False) self.gangPage = GangView(self.notebook) self.notebook.AddPage(self.gangPage, "Fleet", tabImage = gangImg, showClose = False) + self.notebook.SetSelection(0) PANES = ["Drones", "Fighters", "Cargo", "Implants", "Boosters", "Projected", "Fleet"] def select(self, name): self.notebook.SetSelection(self.PANES.index(name)) + def toggleBoosters(self, event): + self.notebook.ToggleShown(self.booster) + def getName(self, idx): return self.PANES[idx] diff --git a/gui/boosterView.py b/gui/boosterView.py index 2ad9cf349..5c8dca993 100644 --- a/gui/boosterView.py +++ b/gui/boosterView.py @@ -85,6 +85,11 @@ class BoosterView(d.Display): event.Skip() def fitChanged(self, event): + sFit = service.Fit.getInstance() + fit = sFit.getFit(event.fitID) + + self.Parent.Parent.DisablePage(self, not fit or fit.isStructure) + #Clear list and get out if current fitId is None if event.fitID is None and self.lastFitId is not None: self.DeleteAllItems() @@ -92,9 +97,6 @@ class BoosterView(d.Display): event.Skip() return - sFit = service.Fit.getInstance() - fit = sFit.getFit(event.fitID) - self.origional = fit.boosters if fit is not None else None self.boosters = stuff = fit.boosters[:] if fit is not None else None @@ -115,6 +117,12 @@ class BoosterView(d.Display): def addItem(self, event): sFit = service.Fit.getInstance() fitID = self.mainFrame.getActiveFit() + + fit = sFit.getFit(fitID) + + if fit.isStructure: + return + trigger = sFit.addBooster(fitID, event.itemID) if trigger: wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID)) diff --git a/gui/builtinContextMenus/cargo.py b/gui/builtinContextMenus/cargo.py index 3cc86902b..0b4c031b4 100644 --- a/gui/builtinContextMenus/cargo.py +++ b/gui/builtinContextMenus/cargo.py @@ -11,8 +11,12 @@ class Cargo(ContextMenu): self.mainFrame = gui.mainFrame.MainFrame.getInstance() def display(self, srcContext, selection): + sFit = service.Fit.getInstance() + fitID = self.mainFrame.getActiveFit() + + fit = sFit.getFit(fitID) # Make sure context menu registers in the correct view - if srcContext not in ("marketItemGroup", "marketItemMisc") or self.mainFrame.getActiveFit() is None: + if srcContext not in ("marketItemGroup", "marketItemMisc") or not fit or fit.isStructure: return False return True diff --git a/gui/builtinContextMenus/metaSwap.py b/gui/builtinContextMenus/metaSwap.py index 5377b40dd..0b2d847ac 100644 --- a/gui/builtinContextMenus/metaSwap.py +++ b/gui/builtinContextMenus/metaSwap.py @@ -29,6 +29,9 @@ class MetaSwap(ContextMenu): self.selection = selection + if len(self.variations) == 1: + return False # no variations from current module + return True def getText(self, itmContext, selection): @@ -38,6 +41,7 @@ class MetaSwap(ContextMenu): self.moduleLookup = {} def get_metalevel(x): + if "metaLevel" not in x.attributes: return 0 return x.attributes["metaLevel"].value def get_metagroup(x): diff --git a/gui/builtinContextMenus/shipJump.py b/gui/builtinContextMenus/shipJump.py index d7ea3b343..bc332e4a4 100644 --- a/gui/builtinContextMenus/shipJump.py +++ b/gui/builtinContextMenus/shipJump.py @@ -12,7 +12,7 @@ class ShipJump(ContextMenu): return srcContext == "fittingShip" def getText(self, itmContext, selection): - return "Open in Ship Browser" + return "Open in Fitting Browser" def activate(self, fullContext, selection, i): fitID = self.mainFrame.getActiveFit() diff --git a/gui/builtinStatsViews/targetingMiscViewFull.py b/gui/builtinStatsViews/targetingMiscViewFull.py index af6a195ad..207fe46c5 100644 --- a/gui/builtinStatsViews/targetingMiscViewFull.py +++ b/gui/builtinStatsViews/targetingMiscViewFull.py @@ -201,7 +201,7 @@ class TargetingMiscViewFull(StatsView): elif labelName == "labelFullAlignTime": alignTime = "Align:\t%.3fs"%mainValue mass = 'Mass:\t{:,.0f}kg'.format(fit.ship.getModifiedItemAttr("mass")) - agility = "Agility:\t%.3fx"%fit.ship.getModifiedItemAttr("agility") + agility = "Agility:\t%.3fx"%(fit.ship.getModifiedItemAttr("agility") or 0) label.SetToolTip(wx.ToolTip("%s\n%s\n%s" % (alignTime, mass, agility))) elif labelName == "labelFullCargo": tipLines = [] diff --git a/gui/builtinViews/fittingView.py b/gui/builtinViews/fittingView.py index 7db037082..8d6ed961b 100644 --- a/gui/builtinViews/fittingView.py +++ b/gui/builtinViews/fittingView.py @@ -409,7 +409,7 @@ class FittingView(d.Display): sFit = service.Fit.getInstance() fit = sFit.getFit(self.activeFitID) - slotOrder = [Slot.SUBSYSTEM, Slot.HIGH, Slot.MED, Slot.LOW, Slot.RIG] + slotOrder = [Slot.SUBSYSTEM, Slot.HIGH, Slot.MED, Slot.LOW, Slot.RIG, Slot.SERVICE] if fit is not None: self.mods = fit.modules[:] @@ -503,7 +503,10 @@ class FittingView(d.Display): sel = self.GetNextSelected(sel) - contexts.append(("fittingShip", "Ship")) + sFit = service.Fit.getInstance() + fit = sFit.getFit(self.activeFitID) + + contexts.append(("fittingShip", "Ship" if not fit.isStructure else "Citadel")) menu = ContextMenu.getMenu(selection, *contexts) self.PopupMenu(menu) diff --git a/gui/cargoView.py b/gui/cargoView.py index f7c856e1b..91bfb2b5f 100644 --- a/gui/cargoView.py +++ b/gui/cargoView.py @@ -125,6 +125,11 @@ class CargoView(d.Display): wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.mainFrame.getActiveFit())) def fitChanged(self, event): + sFit = service.Fit.getInstance() + fit = sFit.getFit(event.fitID) + + self.Parent.Parent.DisablePage(self, not fit or fit.isStructure) + #Clear list and get out if current fitId is None if event.fitID is None and self.lastFitId is not None: self.DeleteAllItems() @@ -132,9 +137,6 @@ class CargoView(d.Display): event.Skip() return - sFit = service.Fit.getInstance() - fit = sFit.getFit(event.fitID) - self.original = fit.cargo if fit is not None else None self.cargo = stuff = fit.cargo if fit is not None else None if stuff is not None: stuff.sort(key=lambda cargo: cargo.itemID) diff --git a/gui/chromeTabs.py b/gui/chromeTabs.py index 06ed1d5a1..bfc3adeb4 100644 --- a/gui/chromeTabs.py +++ b/gui/chromeTabs.py @@ -227,6 +227,18 @@ class PFNotebook(wx.Panel): self.activePage = tabWnd self.ShowActive(True) + def DisablePage(self, page, toggle): + idx = self.GetPageIndex(page) + + if toggle and page == self.activePage: + try: + # Set page to the first non-disabled page + self.SetSelection(next(i for i, _ in enumerate(self.pages) if not self.tabsContainer.tabs[i].disabled)) + except StopIteration, ex: + self.SetSelection(0) + + self.tabsContainer.DisableTab(idx, toggle) + def SetSelection(self, page): oldsel = self.GetSelection() if oldsel != page: @@ -354,6 +366,7 @@ class PFTabRenderer: self.inclination = inclination self.text = text + self.disabled = False self.tabSize = (width, height) self.closeButton = closeButton self.selected = False @@ -548,7 +561,7 @@ class PFTabRenderer: mdc.DrawBitmap(self.tabBackBitmap, 0, 0, True) if self.tabImg: - bmp = wx.BitmapFromImage(self.tabImg) + bmp = wx.BitmapFromImage(self.tabImg.ConvertToGreyscale() if self.disabled else self.tabImg) if self.contentWidth > 16: # @todo: is this conditional relevant anymore? # Draw tab icon mdc.DrawBitmap(bmp, self.leftWidth + self.padding - bmp.GetWidth()/2, (height - bmp.GetHeight())/2) @@ -591,6 +604,10 @@ class PFTabRenderer: bmp = wx.BitmapFromImage(img) self.tabBitmap = bmp + def __repr__(self): + return "PFTabRenderer(text={}, disabled={}) at {}".format( + self.text, self.disabled, hex(id(self)) + ) class PFAddRenderer: def __init__(self): @@ -848,6 +865,7 @@ class PFTabsContainer(wx.Panel): return True if self.TabHitTest(tab, x, y): + if tab.disabled: return tab.SetSelected(True) oldSelTab.SetSelected(False) @@ -1186,6 +1204,13 @@ class PFTabsContainer(wx.Panel): for tab in self.tabs: tab.SetSelected(False) + def DisableTab(self, tab, disabled=True): + tabRenderer = self.tabs[tab] + tabRenderer.disabled = disabled + + self.AdjustTabsSize() + self.Refresh() + def DeleteTab(self, tab, external=False): tabRenderer = self.tabs[tab] wasSelected = tabRenderer.GetSelected() diff --git a/gui/droneView.py b/gui/droneView.py index f71c7cb25..531c28d05 100644 --- a/gui/droneView.py +++ b/gui/droneView.py @@ -159,6 +159,10 @@ class DroneView(d.Display): drone.item.name) def fitChanged(self, event): + sFit = service.Fit.getInstance() + fit = sFit.getFit(event.fitID) + + self.Parent.Parent.DisablePage(self, not fit or fit.isStructure) #Clear list and get out if current fitId is None if event.fitID is None and self.lastFitId is not None: @@ -167,9 +171,6 @@ class DroneView(d.Display): event.Skip() return - sFit = service.Fit.getInstance() - fit = sFit.getFit(event.fitID) - self.original = fit.drones if fit is not None else None self.drones = stuff = fit.drones[:] if fit is not None else None @@ -194,6 +195,12 @@ class DroneView(d.Display): def addItem(self, event): sFit = service.Fit.getInstance() fitID = self.mainFrame.getActiveFit() + + fit = sFit.getFit(fitID) + + if fit.isStructure: + return + trigger = sFit.addDrone(fitID, event.itemID) if trigger: wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID)) diff --git a/gui/fighterView.py b/gui/fighterView.py index b011f89d0..b4468c94f 100644 --- a/gui/fighterView.py +++ b/gui/fighterView.py @@ -224,6 +224,10 @@ class FighterDisplay(d.Display): ''' def fitChanged(self, event): + sFit = service.Fit.getInstance() + fit = sFit.getFit(event.fitID) + + self.Parent.Parent.Parent.DisablePage(self.Parent, not fit) #Clear list and get out if current fitId is None if event.fitID is None and self.lastFitId is not None: @@ -232,9 +236,6 @@ class FighterDisplay(d.Display): event.Skip() return - sFit = service.Fit.getInstance() - fit = sFit.getFit(event.fitID) - self.original = fit.fighters if fit is not None else None self.fighters = stuff = fit.fighters[:] if fit is not None else None diff --git a/gui/gangView.py b/gui/gangView.py index 25a457301..704ea31d3 100644 --- a/gui/gangView.py +++ b/gui/gangView.py @@ -26,7 +26,6 @@ import gui.globalEvents as GE from gui import characterEditor as CharEditor - class GangView ( ScrolledPanel ): def __init__( self, parent ): @@ -247,6 +246,9 @@ class GangView ( ScrolledPanel ): activeFitID = self.mainFrame.getActiveFit() sFit = service.Fit.getInstance() fit = sFit.getFit(event.fitID or activeFitID) + + self.Parent.Parent.DisablePage(self, not fit or fit.isStructure) + commanders = (None, None, None) if activeFitID: @@ -363,8 +365,10 @@ class GangView ( ScrolledPanel ): #Those are drags coming from pyfa sources, NOT builtin wx drags self.draggedFitID = None if type == "fit": - activeFit = self.mainFrame.getActiveFit() - if activeFit: + sFit = service.Fit.getInstance() + fit = sFit.getFit(self.mainFrame.getActiveFit()) + + if fit and not fit.isStructuree: self.draggedFitID = fitID pos = wx.GetMousePosition() diff --git a/gui/implantView.py b/gui/implantView.py index 8ae9ac50a..15da4d097 100644 --- a/gui/implantView.py +++ b/gui/implantView.py @@ -107,6 +107,11 @@ class ImplantDisplay(d.Display): event.Skip() def fitChanged(self, event): + sFit = service.Fit.getInstance() + fit = sFit.getFit(event.fitID) + + self.Parent.Parent.Parent.DisablePage(self.Parent, not fit or fit.isStructure) + #Clear list and get out if current fitId is None if event.fitID is None and self.lastFitId is not None: self.DeleteAllItems() @@ -114,9 +119,6 @@ class ImplantDisplay(d.Display): event.Skip() return - sFit = service.Fit.getInstance() - fit = sFit.getFit(event.fitID) - self.original = fit.implants if fit is not None else None self.implants = stuff = fit.appliedImplants if fit is not None else None if stuff is not None: stuff.sort(key=lambda implant: implant.slot) @@ -137,6 +139,12 @@ class ImplantDisplay(d.Display): def addItem(self, event): sFit = service.Fit.getInstance() fitID = self.mainFrame.getActiveFit() + + fit = sFit.getFit(fitID) + + if fit.isStructure: + return + trigger = sFit.addImplant(fitID, event.itemID) if trigger: wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID)) diff --git a/gui/itemStats.py b/gui/itemStats.py index 87ec947dc..f154d277a 100644 --- a/gui/itemStats.py +++ b/gui/itemStats.py @@ -24,7 +24,7 @@ from gui.bitmapLoader import BitmapLoader import sys import wx.lib.mixins.listctrl as listmix import wx.html -from eos.types import Fit, Ship, Module, Skill, Booster, Implant, Drone, Mode, Fighter +from eos.types import Fit, Ship, Citadel, Module, Skill, Booster, Implant, Drone, Mode, Fighter from gui.utils.numberFormatter import formatAmount import service import config @@ -747,7 +747,7 @@ class ItemEffects (wx.Panel): class ItemAffectedBy (wx.Panel): - ORDER = [Fit, Ship, Mode, Module, Drone, Fighter, Implant, Booster, Skill] + ORDER = [Fit, Ship, Citadel, Mode, Module, Drone, Fighter, Implant, Booster, Skill] def __init__(self, parent, stuff, item): wx.Panel.__init__(self, parent) self.stuff = stuff diff --git a/gui/mainFrame.py b/gui/mainFrame.py index 74918118f..c209a0422 100644 --- a/gui/mainFrame.py +++ b/gui/mainFrame.py @@ -156,7 +156,7 @@ class MainFrame(wx.Frame): self.marketBrowser.splitter.SetSashPosition(self.marketHeight) self.shipBrowser = ShipBrowser(self.notebookBrowsers) - self.notebookBrowsers.AddPage(self.shipBrowser, "Ships", tabImage = shipBrowserImg, showClose = False) + self.notebookBrowsers.AddPage(self.shipBrowser, "Fittings", tabImage = shipBrowserImg, showClose = False) #======================================================================= # DISABLED FOR RC2 RELEASE diff --git a/gui/projectedView.py b/gui/projectedView.py index 3600620fd..76b101293 100644 --- a/gui/projectedView.py +++ b/gui/projectedView.py @@ -159,6 +159,11 @@ class ProjectedView(d.Display): return fit.name def fitChanged(self, event): + sFit = service.Fit.getInstance() + fit = sFit.getFit(event.fitID) + + self.Parent.Parent.DisablePage(self, not fit or fit.isStructure) + #Clear list and get out if current fitId is None if event.fitID is None and self.lastFitId is not None: self.DeleteAllItems() @@ -166,8 +171,6 @@ class ProjectedView(d.Display): event.Skip() return - sFit = service.Fit.getInstance() - fit = sFit.getFit(event.fitID) stuff = [] if fit is not None: self.modules = fit.projectedModules[:] diff --git a/gui/shipBrowser.py b/gui/shipBrowser.py index e0aedebe3..94c682101 100644 --- a/gui/shipBrowser.py +++ b/gui/shipBrowser.py @@ -1538,7 +1538,10 @@ class FitItem(SFItem.SFBrowserItem): menu.Check(toggleItem.GetId(), self.fitBooster) self.Bind(wx.EVT_MENU, self.OnToggleBooster, toggleItem) - if self.mainFrame.getActiveFit(): + sFit = service.Fit.getInstance() + fit = sFit.getFit(self.mainFrame.getActiveFit()) + + if fit and not fit.isStructure: # If there is an active fit, get menu for setting individual boosters menu.AppendSeparator() boosterMenu = self.mainFrame.additionsPane.gangPage.buildBoostermenu() diff --git a/imgs/icons/123_10.png b/imgs/icons/123_10.png new file mode 100644 index 000000000..8c62c922f Binary files /dev/null and b/imgs/icons/123_10.png differ diff --git a/imgs/icons/123_11.png b/imgs/icons/123_11.png new file mode 100644 index 000000000..1829dfd0b Binary files /dev/null and b/imgs/icons/123_11.png differ diff --git a/imgs/icons/123_5.png b/imgs/icons/123_5.png new file mode 100644 index 000000000..c360369ca Binary files /dev/null and b/imgs/icons/123_5.png differ diff --git a/imgs/icons/123_6.png b/imgs/icons/123_6.png new file mode 100644 index 000000000..f0e032248 Binary files /dev/null and b/imgs/icons/123_6.png differ diff --git a/imgs/icons/123_8.png b/imgs/icons/123_8.png new file mode 100644 index 000000000..4bf986d3d Binary files /dev/null and b/imgs/icons/123_8.png differ diff --git a/imgs/icons/123_9.png b/imgs/icons/123_9.png new file mode 100644 index 000000000..5b35e2d10 Binary files /dev/null and b/imgs/icons/123_9.png differ diff --git a/imgs/icons/127_1.png b/imgs/icons/127_1.png new file mode 100644 index 000000000..8ecbeda0f Binary files /dev/null and b/imgs/icons/127_1.png differ diff --git a/imgs/icons/127_10.png b/imgs/icons/127_10.png new file mode 100644 index 000000000..135a33de0 Binary files /dev/null and b/imgs/icons/127_10.png differ diff --git a/imgs/icons/127_2.png b/imgs/icons/127_2.png new file mode 100644 index 000000000..5c5177a73 Binary files /dev/null and b/imgs/icons/127_2.png differ diff --git a/imgs/icons/127_3.png b/imgs/icons/127_3.png new file mode 100644 index 000000000..7f67bbee4 Binary files /dev/null and b/imgs/icons/127_3.png differ diff --git a/imgs/icons/127_4.png b/imgs/icons/127_4.png new file mode 100644 index 000000000..c0206012f Binary files /dev/null and b/imgs/icons/127_4.png differ diff --git a/imgs/icons/127_5.png b/imgs/icons/127_5.png new file mode 100644 index 000000000..c80c6f85f Binary files /dev/null and b/imgs/icons/127_5.png differ diff --git a/imgs/icons/127_7.png b/imgs/icons/127_7.png new file mode 100644 index 000000000..c76cc4f0b Binary files /dev/null and b/imgs/icons/127_7.png differ diff --git a/imgs/icons/127_9.png b/imgs/icons/127_9.png new file mode 100644 index 000000000..122f363a8 Binary files /dev/null and b/imgs/icons/127_9.png differ diff --git a/imgs/icons/45_12.png b/imgs/icons/45_12.png new file mode 100644 index 000000000..a9cc45916 Binary files /dev/null and b/imgs/icons/45_12.png differ diff --git a/imgs/icons/64_12.png b/imgs/icons/64_12.png index b1afaf334..f4831e81f 100644 Binary files a/imgs/icons/64_12.png and b/imgs/icons/64_12.png differ diff --git a/imgs/icons/89_4.png b/imgs/icons/89_4.png index 2b7790645..f5134aee1 100644 Binary files a/imgs/icons/89_4.png and b/imgs/icons/89_4.png differ diff --git a/imgs/renders/35832.png b/imgs/renders/35832.png new file mode 100644 index 000000000..e4f3f70d8 Binary files /dev/null and b/imgs/renders/35832.png differ diff --git a/imgs/renders/35833.png b/imgs/renders/35833.png new file mode 100644 index 000000000..bc3743124 Binary files /dev/null and b/imgs/renders/35833.png differ diff --git a/imgs/renders/35834.png b/imgs/renders/35834.png new file mode 100644 index 000000000..9224ba047 Binary files /dev/null and b/imgs/renders/35834.png differ diff --git a/imgs/renders/40340.png b/imgs/renders/40340.png new file mode 100644 index 000000000..38e9179ac Binary files /dev/null and b/imgs/renders/40340.png differ diff --git a/scripts/icons_update.py b/scripts/icons_update.py index a88ad4283..261ee7e89 100644 --- a/scripts/icons_update.py +++ b/scripts/icons_update.py @@ -38,7 +38,8 @@ ITEM_CATEGORIES = ( 16, # Skill 18, # Drone 20, # Implant - 32 # Subsystem + 32, # Subsystem + 66, # Structure Module ) MARKET_ROOTS = { @@ -48,7 +49,9 @@ MARKET_ROOTS = { 11, # Ammo 1112, # Subsystems 24, # Implants & Boosters - 404 # Deployables + 404, # Deployables + 2202, # Structure Equipment + 2203 # Structure Modifications (Rigs) } # Add children to market group list @@ -153,7 +156,7 @@ for fname in os.listdir(icons_dir): print fname,"exists" existing.add(fname) -# Get a list of all the icons currently available +# Get a list of all the icons currently available in export for dir in dirs: for fname in os.listdir(dir): if not os.path.isfile(os.path.join(dir, fname)): @@ -164,7 +167,7 @@ for dir in dirs: # convention without size specification sizeless = re.sub('^(?P[^_]+)_(?P\d+)_(?P[^_]+)$', r'\1_\3', stripped) # Often items referred to with 01_01 format, - fnames = export.setdefault(stripped.lower(), set()) + fnames = export.setdefault(sizeless.lower(), set()) fnames.add(fname) def crop_image(img): diff --git a/scripts/renders_update.py b/scripts/renders_update.py index b3c42e5fb..8cb734720 100644 --- a/scripts/renders_update.py +++ b/scripts/renders_update.py @@ -30,7 +30,7 @@ cursor = db.cursor() RENDER_SIZE = (32, 32) -query_ships = 'select it.typeID from invtypes as it inner join invgroups as ig on it.groupID = ig.groupID where ig.categoryID = 6' +query_ships = 'select it.typeID from invtypes as it inner join invgroups as ig on it.groupID = ig.groupID where ig.categoryID in (6, 65)' needed = set() diff --git a/service/fit.py b/service/fit.py index 8ae9c6e4d..455e76463 100644 --- a/service/fit.py +++ b/service/fit.py @@ -158,7 +158,10 @@ class Fit(object): return fit.modules[pos] def newFit(self, shipID, name=None): - ship = eos.types.Ship(eos.db.getItem(shipID)) + try: + ship = eos.types.Ship(eos.db.getItem(shipID)) + except ValueError: + ship = eos.types.Citadel(eos.db.getItem(shipID)) fit = eos.types.Fit(ship) fit.name = name if name is not None else "New %s" % fit.ship.item.name fit.damagePattern = self.pattern @@ -361,7 +364,6 @@ class Fit(object): drone.amount += 1 elif thing.category.name == "Fighter": - print "dskfnds" fighter = eos.types.Fighter(thing) fit.projectedFighters.append(fighter) elif thing.group.name == "Effect Beacon": diff --git a/service/market.py b/service/market.py index 6c6578b58..4cfc1a9dd 100644 --- a/service/market.py +++ b/service/market.py @@ -331,7 +331,7 @@ class Market(): ("faction", frozenset((4, 3))), ("complex", frozenset((6,))), ("officer", frozenset((5,)))]) - self.SEARCH_CATEGORIES = ("Drone", "Module", "Subsystem", "Charge", "Implant", "Deployable", "Fighter") + self.SEARCH_CATEGORIES = ("Drone", "Module", "Subsystem", "Charge", "Implant", "Deployable", "Fighter", "Structure", "Structure Module") self.SEARCH_GROUPS = ("Ice Product",) self.ROOT_MARKET_GROUPS = (9, # Modules 1111, # Rigs @@ -339,7 +339,10 @@ class Market(): 11, # Ammo 1112, # Subsystems 24, # Implants & Boosters - 404) # Deployables + 404, # Deployables + 2202, # Structure Equipment + 2203 # Structure Modifications + ) # Tell other threads that Market is at their service mktRdy.set() @@ -666,8 +669,10 @@ class Market(): return root def getShipRoot(self): - cat = self.getCategory("Ship") - root = set(self.getGroupsByCategory(cat)) + cat1 = self.getCategory("Ship") + cat2 = self.getCategory("Structure") + root = set(self.getGroupsByCategory(cat1) | self.getGroupsByCategory(cat2)) + return root def getShipList(self, grpid):