Merge branch 'master' into wx3

Conflicts:
	gui/characterEditor.py
This commit is contained in:
blitzmann
2015-09-26 18:53:28 -04:00
105 changed files with 508 additions and 234 deletions

View File

@@ -18,8 +18,8 @@ debug = False
saveInRoot = False
# Version data
version = "1.14.0"
tag = "Stable"
version = "1.14.1"
tag = "git"
expansionName = "Galatea"
expansionVersion = "1.2"
evemonMinVersion = "4081"

View File

@@ -5,7 +5,7 @@ debug = False
gamedataCache = True
saveddataCache = True
gamedata_connectionstring = 'sqlite:///' + unicode(realpath(join(dirname(abspath(__file__)), "..", "staticdata", "eve.db")), sys.getfilesystemencoding())
saveddata_connectionstring = 'sqlite:///:memory:'
saveddata_connectionstring = 'sqlite:///' + unicode(realpath(join(dirname(abspath(__file__)), "..", "saveddata", "saveddata.db")), sys.getfilesystemencoding())
#Autodetect path, only change if the autodetection bugs out.
path = dirname(unicode(__file__, sys.getfilesystemencoding()))

View File

@@ -1,7 +1,7 @@
# eliteBonusHeavyInterdictorsWarpDisruptFieldGeneratorWarpScrambleRange2
#
# Used by:
# Ships from group: Heavy Interdiction Cruiser (4 of 5)
# Ships from group: Heavy Interdiction Cruiser (5 of 5)
type = "passive"
def handler(fit, ship, context):
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Warp Disrupt Field Generator",

View File

@@ -1,7 +1,7 @@
# Interceptor2WarpScrambleRange
#
# Used by:
# Ships from group: Interceptor (5 of 10)
# Ships from group: Interceptor (6 of 10)
type = "passive"
def handler(fit, ship, context):
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Warp Scrambler",

View File

@@ -1,7 +1,7 @@
# interceptorMWDSignatureRadiusBonus
#
# Used by:
# Ships from group: Interceptor (9 of 10)
# Ships from group: Interceptor (10 of 10)
type = "passive"
def handler(fit, ship, context):
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("High Speed Maneuvering"),

View File

@@ -4,7 +4,7 @@
# Celestials named like: Drifter Incursion (6 of 6)
# Celestials named like: Incursion ship attributes effects (3 of 3)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
damages = ("em", "thermal", "kinetic", "explosive")
for damage in damages:

View File

@@ -3,6 +3,6 @@
# Used by:
# Modules from group: Jump Drive Economizer (3 of 3)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, module, context):
fit.ship.boostItemAttr("jumpDriveConsumptionAmount", module.getModifiedItemAttr("consumptionQuantityBonusPercentage"), stackingPenalties=True)

View File

@@ -0,0 +1,13 @@
# shipBonusWDFGnullSpeedEffects
#
# Used by:
# Ship: Fiend
runTime = "early"
type = "passive"
def handler(fit, ship, context):
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Propulsion Jamming"),
"speedFactorBonus", ship.getModifiedItemAttr("shipBonusAT"))
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Propulsion Jamming"),
"speedBoostFactorBonus", ship.getModifiedItemAttr("shipBonusAT"))
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Propulsion Jamming"),
"massBonusPercentage", ship.getModifiedItemAttr("shipBonusAT"))

View File

@@ -1,7 +1,7 @@
# shipCapPropulsionJamming
#
# Used by:
# Ships from group: Interceptor (9 of 10)
# Ships from group: Interceptor (10 of 10)
# Ship: Atron
# Ship: Condor
# Ship: Executioner

View File

@@ -1,9 +1,8 @@
# shipShieldEMResistanceRookie
#
# Used by:
# Ship: Broadsword
# Ships from group: Heavy Interdiction Cruiser (3 of 5)
# Ship: Ibis
# Ship: Onyx
# Ship: Taipan
type = "passive"
def handler(fit, ship, context):

View File

@@ -1,9 +1,8 @@
# shipShieldExplosiveResistanceRookie
#
# Used by:
# Ship: Broadsword
# Ships from group: Heavy Interdiction Cruiser (3 of 5)
# Ship: Ibis
# Ship: Onyx
# Ship: Taipan
type = "passive"
def handler(fit, ship, context):

View File

@@ -1,9 +1,8 @@
# shipShieldKineticResistanceRookie
#
# Used by:
# Ship: Broadsword
# Ships from group: Heavy Interdiction Cruiser (3 of 5)
# Ship: Ibis
# Ship: Onyx
# Ship: Taipan
type = "passive"
def handler(fit, ship, context):

View File

@@ -1,9 +1,8 @@
# shipShieldThermalResistanceRookie
#
# Used by:
# Ship: Broadsword
# Ships from group: Heavy Interdiction Cruiser (3 of 5)
# Ship: Ibis
# Ship: Onyx
# Ship: Taipan
type = "passive"
def handler(fit, ship, context):

View File

@@ -3,6 +3,6 @@
# Used by:
# Celestials named like: Black Hole Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.ship.multiplyItemAttr("agility", beacon.getModifiedItemAttr("agilityMultiplier"), stackingPenalties=True)

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Magnetar Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.modules.filteredChargeMultiply(lambda mod: mod.charge.requiresSkill("Missile Launcher Operation"),
"aoeCloudSize", beacon.getModifiedItemAttr("aoeCloudSizeMultiplier"))

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Black Hole Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.modules.filteredChargeMultiply(lambda mod: mod.charge.requiresSkill("Missile Launcher Operation"),
"aoeVelocity", beacon.getModifiedItemAttr("aoeVelocityMultiplier"))

View File

@@ -4,7 +4,7 @@
# Celestials named like: Incursion Effect (2 of 2)
# Celestials named like: Pulsar Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.ship.boostItemAttr("armorEmDamageResonance", beacon.getModifiedItemAttr("armorEmDamageResistanceBonus"),
stackingPenalties=True)

View File

@@ -4,7 +4,7 @@
# Celestials named like: Incursion Effect (2 of 2)
# Celestials named like: Pulsar Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.ship.boostItemAttr("armorExplosiveDamageResonance", beacon.getModifiedItemAttr("armorExplosiveDamageResistanceBonus"),
stackingPenalties=True)

View File

@@ -3,6 +3,6 @@
# Used by:
# Celestials named like: Wolf Rayet Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.ship.multiplyItemAttr("armorHP", beacon.getModifiedItemAttr("armorHPMultiplier"))

View File

@@ -4,7 +4,7 @@
# Celestials named like: Incursion Effect (2 of 2)
# Celestials named like: Pulsar Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.ship.boostItemAttr("armorKineticDamageResonance", beacon.getModifiedItemAttr("armorKineticDamageResistanceBonus"),
stackingPenalties=True)

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Cataclysmic Variable Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, module, context):
fit.modules.filteredItemMultiply(lambda mod: mod.item.group.name == "Remote Armor Repairer",
"armorDamageAmount", module.getModifiedItemAttr("armorDamageAmountMultiplierRemote"),

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Cataclysmic Variable Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, module, context):
fit.modules.filteredItemMultiply(lambda mod: mod.item.group.name == "Armor Repair Unit",
"armorDamageAmount", module.getModifiedItemAttr("armorDamageAmountMultiplier"),

View File

@@ -4,7 +4,7 @@
# Celestials named like: Incursion Effect (2 of 2)
# Celestials named like: Pulsar Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.ship.boostItemAttr("armorThermalDamageResonance", beacon.getModifiedItemAttr("armorThermalDamageResistanceBonus"),
stackingPenalties=True)

View File

@@ -3,6 +3,6 @@
# Used by:
# Celestials named like: Cataclysmic Variable Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.ship.multiplyItemAttr("capacitorCapacity", beacon.getModifiedItemAttr("capacitorCapacityMultiplierSystem"))

View File

@@ -4,6 +4,6 @@
# Celestials named like: Cataclysmic Variable Effect Beacon Class (6 of 6)
# Celestials named like: Pulsar Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.ship.multiplyItemAttr("rechargeRate", beacon.getModifiedItemAttr("rechargeRateMultiplier"))

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Magnetar Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.drones.filteredItemMultiply(lambda drone: drone.item.requiresSkill("Drones"),
"damageMultiplier", beacon.getModifiedItemAttr("damageMultiplierMultiplier"),

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Red Giant Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.modules.filteredChargeMultiply(lambda mod: mod.charge.requiresSkill("Bomb Deployment"),
"emDamage", beacon.getModifiedItemAttr("smartbombDamageMultiplier"),

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Magnetar Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.modules.filteredChargeMultiply(lambda mod: mod.charge.requiresSkill("Missile Launcher Operation"),
"emDamage", beacon.getModifiedItemAttr("damageMultiplierMultiplier"),

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Red Giant Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.modules.filteredChargeMultiply(lambda mod: mod.charge.requiresSkill("Bomb Deployment"),
"explosiveDamage", beacon.getModifiedItemAttr("smartbombDamageMultiplier"),

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Magnetar Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.modules.filteredChargeMultiply(lambda mod: mod.charge.requiresSkill("Missile Launcher Operation"),
"explosiveDamage", beacon.getModifiedItemAttr("damageMultiplierMultiplier"),

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Magnetar Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.drones.filteredItemMultiply(lambda drone: drone.item.requiresSkill("Fighters"),
"damageMultiplier", beacon.getModifiedItemAttr("damageMultiplierMultiplier"),

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Red Giant Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.modules.filteredChargeMultiply(lambda mod: mod.charge.requiresSkill("Bomb Deployment"),
"kineticDamage", beacon.getModifiedItemAttr("smartbombDamageMultiplier"),

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Magnetar Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.modules.filteredChargeMultiply(lambda mod: mod.charge.requiresSkill("Missile Launcher Operation"),
"kineticDamage", beacon.getModifiedItemAttr("damageMultiplierMultiplier"),

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Magnetar Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.modules.filteredItemMultiply(lambda mod: mod.item.requiresSkill("Gunnery"),
"damageMultiplier", beacon.getModifiedItemAttr("damageMultiplierMultiplier"),

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Red Giant Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.modules.filteredChargeMultiply(lambda mod: mod.charge.requiresSkill("Bomb Deployment"),
"thermalDamage", beacon.getModifiedItemAttr("smartbombDamageMultiplier"),

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Magnetar Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.modules.filteredChargeMultiply(lambda mod: mod.charge.requiresSkill("Missile Launcher Operation"),
"thermalDamage", beacon.getModifiedItemAttr("damageMultiplierMultiplier"),

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Magnetar Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.drones.filteredItemMultiply(lambda drone: True,
"trackingSpeed", beacon.getModifiedItemAttr("trackingSpeedMultiplier"),

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Pulsar Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.modules.filteredItemMultiply(lambda mod: mod.item.group.name == "Energy Destabilizer",
"energyDestabilizationAmount", beacon.getModifiedItemAttr("energyWarfareStrengthMultiplier"),

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Pulsar Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.modules.filteredItemMultiply(lambda mod: mod.item.group.name == "Energy Vampire",
"powerTransferAmount", beacon.getModifiedItemAttr("energyWarfareStrengthMultiplier"),

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Red Giant Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.modules.filteredChargeMultiply(lambda mod: mod.charge.requiresSkill("Bomb Deployment"),
"scanGravimetricStrengthBonus", beacon.getModifiedItemAttr("smartbombDamageMultiplier"),

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Red Giant Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, module, context):
fit.modules.filteredItemMultiply(lambda mod: "heatDamage" in mod.itemModifiedAttributes,
"heatDamage", module.getModifiedItemAttr("heatDamageMultiplier"))

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Red Giant Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.modules.filteredChargeMultiply(lambda mod: mod.charge.requiresSkill("Bomb Deployment"),
"scanLadarStrengthBonus", beacon.getModifiedItemAttr("smartbombDamageMultiplier"),

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Red Giant Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.modules.filteredChargeMultiply(lambda mod: mod.charge.requiresSkill("Bomb Deployment"),
"scanMagnetometricStrengthBonus", beacon.getModifiedItemAttr("smartbombDamageMultiplier"),

View File

@@ -3,6 +3,6 @@
# Used by:
# Celestials named like: Black Hole Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.ship.multiplyItemAttr("maxVelocity", beacon.getModifiedItemAttr("maxVelocityMultiplier"), stackingPenalties=True, penaltyGroup="postMul")

View File

@@ -3,6 +3,6 @@
# Used by:
# Celestials named like: Drifter Incursion (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.ship.boostItemAttr("maxVelocity", beacon.getModifiedItemAttr("maxVelocityMultiplier"), stackingPenalties=True)

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Black Hole Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.modules.filteredChargeMultiply(lambda mod: mod.charge.requiresSkill("Missile Launcher Operation"),
"maxVelocity", beacon.getModifiedItemAttr("missileVelocityMultiplier"),

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Red Giant Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.modules.filteredChargeMultiply(lambda mod: mod.charge.requiresSkill("Bomb Deployment"),
"energyDestabilizationAmount", beacon.getModifiedItemAttr("smartbombDamageMultiplier"),

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Red Giant Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, module, context):
fit.modules.filteredItemMultiply(lambda mod: "overloadArmorDamageAmount" in mod.itemModifiedAttributes,
"overloadArmorDamageAmount", module.getModifiedItemAttr("overloadBonusMultiplier"))

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Red Giant Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, module, context):
fit.modules.filteredItemMultiply(lambda mod: "overloadDamageModifier" in mod.itemModifiedAttributes,
"overloadDamageModifier", module.getModifiedItemAttr("overloadBonusMultiplier"))

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Red Giant Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, module, context):
fit.modules.filteredItemMultiply(lambda mod: "overloadDurationBonus" in mod.itemModifiedAttributes,
"overloadDurationBonus", module.getModifiedItemAttr("overloadBonusMultiplier"))

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Red Giant Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, module, context):
fit.modules.filteredItemMultiply(lambda mod: "overloadECCMStrenghtBonus" in mod.itemModifiedAttributes,
"overloadECCMStrenghtBonus", module.getModifiedItemAttr("overloadBonusMultiplier"))

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Red Giant Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, module, context):
fit.modules.filteredItemMultiply(lambda mod: "overloadECMStrenghtBonus" in mod.itemModifiedAttributes,
"overloadECMStrenghtBonus", module.getModifiedItemAttr("overloadBonusMultiplier"))

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Red Giant Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, module, context):
fit.modules.filteredItemMultiply(lambda mod: "overloadHardeningBonus" in mod.itemModifiedAttributes,
"overloadHardeningBonus", module.getModifiedItemAttr("overloadBonusMultiplier"))

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Red Giant Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, module, context):
fit.modules.filteredItemMultiply(lambda mod: "overloadRangeBonus" in mod.itemModifiedAttributes,
"overloadRangeBonus", module.getModifiedItemAttr("overloadBonusMultiplier"))

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Red Giant Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, module, context):
fit.modules.filteredItemMultiply(lambda mod: "overloadRofBonus" in mod.itemModifiedAttributes,
"overloadRofBonus", module.getModifiedItemAttr("overloadBonusMultiplier"))

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Red Giant Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, module, context):
fit.modules.filteredItemMultiply(lambda mod: "overloadSelfDurationBonus" in mod.itemModifiedAttributes,
"overloadSelfDurationBonus", module.getModifiedItemAttr("overloadBonusMultiplier"))

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Red Giant Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, module, context):
fit.modules.filteredItemMultiply(lambda mod: "overloadShieldBonus" in mod.itemModifiedAttributes,
"overloadShieldBonus", module.getModifiedItemAttr("overloadBonusMultiplier"))

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Red Giant Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, module, context):
fit.modules.filteredItemMultiply(lambda mod: "overloadSpeedFactorBonus" in mod.itemModifiedAttributes,
"overloadSpeedFactorBonus", module.getModifiedItemAttr("overloadBonusMultiplier"))

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Red Giant Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.modules.filteredChargeMultiply(lambda mod: mod.charge.requiresSkill("Bomb Deployment"),
"scanRadarStrengthBonus", beacon.getModifiedItemAttr("smartbombDamageMultiplier"),

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Cataclysmic Variable Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.modules.filteredItemMultiply(lambda mod: mod.item.group.name == "Remote Capacitor Transmitter",
"powerTransferAmount", beacon.getModifiedItemAttr("energyTransferAmountBonus"),

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Wolf Rayet Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.modules.filteredChargeMultiply(lambda mod: mod.charge.requiresSkill("Rockets"),
"emDamage", beacon.getModifiedItemAttr("smallWeaponDamageMultiplier"),

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Wolf Rayet Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.modules.filteredChargeMultiply(lambda mod: mod.charge.requiresSkill("Rockets"),
"explosiveDamage", beacon.getModifiedItemAttr("smallWeaponDamageMultiplier"),

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Wolf Rayet Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.modules.filteredChargeMultiply(lambda mod: mod.charge.requiresSkill("Rockets"),
"kineticDamage", beacon.getModifiedItemAttr("smallWeaponDamageMultiplier"),

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Wolf Rayet Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.modules.filteredChargeMultiply(lambda mod: mod.charge.requiresSkill("Rockets"),
"thermalDamage", beacon.getModifiedItemAttr("smallWeaponDamageMultiplier"),

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Wolf Rayet Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.ship.boostItemAttr("shieldEmDamageResonance", beacon.getModifiedItemAttr("shieldEmDamageResistanceBonus"),
stackingPenalties=True)

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Wolf Rayet Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.ship.boostItemAttr("shieldExplosiveDamageResonance", beacon.getModifiedItemAttr("shieldExplosiveDamageResistanceBonus"),
stackingPenalties=True)

View File

@@ -3,6 +3,6 @@
# Used by:
# Celestials named like: Pulsar Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.ship.multiplyItemAttr("shieldCapacity", beacon.getModifiedItemAttr("shieldCapacityMultiplier"))

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Wolf Rayet Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.ship.boostItemAttr("shieldKineticDamageResonance", beacon.getModifiedItemAttr("shieldKineticDamageResistanceBonus"),
stackingPenalties=True)

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Cataclysmic Variable Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, module, context):
fit.modules.filteredItemMultiply(lambda mod: mod.item.group.name == "Remote Shield Booster",
"shieldBonus", module.getModifiedItemAttr("shieldBonusMultiplierRemote"),

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Cataclysmic Variable Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, module, context):
fit.modules.filteredItemMultiply(lambda mod: mod.item.requiresSkill("Shield Operation") or mod.item.requiresSkill("Capital Shield Operation"),
"shieldBonus", module.getModifiedItemAttr("shieldBonusMultiplier"),

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Wolf Rayet Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.ship.boostItemAttr("shieldThermalDamageResonance", beacon.getModifiedItemAttr("shieldThermalDamageResistanceBonus"),
stackingPenalties=True)

View File

@@ -4,7 +4,7 @@
# Celestials named like: Pulsar Effect Beacon Class (6 of 6)
# Celestials named like: Wolf Rayet Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.ship.multiplyItemAttr("signatureRadius", beacon.getModifiedItemAttr("signatureRadiusMultiplier"),
stackingPenalties=True, penaltyGroup="postMul")

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Wolf Rayet Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, module, context):
fit.modules.filteredItemMultiply(lambda mod: mod.item.requiresSkill("Small Energy Turret"),
"damageMultiplier", module.getModifiedItemAttr("smallWeaponDamageMultiplier"),

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Wolf Rayet Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, module, context):
fit.modules.filteredItemMultiply(lambda mod: mod.item.requiresSkill("Small Hybrid Turret"),
"damageMultiplier", module.getModifiedItemAttr("smallWeaponDamageMultiplier"),

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Wolf Rayet Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, module, context):
fit.modules.filteredItemMultiply(lambda mod: mod.item.requiresSkill("Small Projectile Turret"),
"damageMultiplier", module.getModifiedItemAttr("smallWeaponDamageMultiplier"),

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Red Giant Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, module, context):
fit.modules.filteredItemMultiply(lambda mod: mod.item.group.name == "Smart Bomb",
"emDamage", module.getModifiedItemAttr("smartbombDamageMultiplier"))

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Red Giant Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, module, context):
fit.modules.filteredItemMultiply(lambda mod: mod.item.group.name == "Smart Bomb",
"explosiveDamage", module.getModifiedItemAttr("smartbombDamageMultiplier"))

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Red Giant Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, module, context):
fit.modules.filteredItemMultiply(lambda mod: mod.item.group.name == "Smart Bomb",
"kineticDamage", module.getModifiedItemAttr("smartbombDamageMultiplier"))

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Red Giant Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, module, context):
fit.modules.filteredItemMultiply(lambda mod: mod.item.group.name == "Smart Bomb",
"empFieldRange", module.getModifiedItemAttr("empFieldRangeMultiplier"))

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Red Giant Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, module, context):
fit.modules.filteredItemMultiply(lambda mod: mod.item.group.name == "Smart Bomb",
"thermalDamage", module.getModifiedItemAttr("smartbombDamageMultiplier"))

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Wolf Rayet Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.modules.filteredChargeMultiply(lambda mod: mod.charge.requiresSkill("Light Missiles"),
"emDamage", beacon.getModifiedItemAttr("smallWeaponDamageMultiplier"),

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Wolf Rayet Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.modules.filteredChargeMultiply(lambda mod: mod.charge.requiresSkill("Light Missiles"),
"explosiveDamage", beacon.getModifiedItemAttr("smallWeaponDamageMultiplier"),

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Wolf Rayet Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.modules.filteredChargeMultiply(lambda mod: mod.charge.requiresSkill("Light Missiles"),
"kineticDamage", beacon.getModifiedItemAttr("smallWeaponDamageMultiplier"),

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Wolf Rayet Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.modules.filteredChargeMultiply(lambda mod: mod.charge.requiresSkill("Light Missiles"),
"thermalDamage", beacon.getModifiedItemAttr("smallWeaponDamageMultiplier"),

View File

@@ -4,7 +4,7 @@
# Celestials named like: Black Hole Effect Beacon Class (6 of 6)
# Celestials named like: Magnetar Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.ship.multiplyItemAttr("maxTargetRange", beacon.getModifiedItemAttr("maxTargetRangeMultiplier"),
stackingPenalties=True, penaltyGroup="postMul")

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Magnetar Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.modules.filteredItemMultiply(lambda mod: mod.item.requiresSkill("Target Painting"),
"signatureRadiusBonus", beacon.getModifiedItemAttr("targetPainterStrengthMultiplier"),

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Magnetar Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, module, context):
fit.modules.filteredItemMultiply(lambda mod: mod.item.requiresSkill("Gunnery"),
"trackingSpeed", module.getModifiedItemAttr("trackingSpeedMultiplier"),

View File

@@ -3,7 +3,7 @@
# Used by:
# Celestials named like: Black Hole Effect Beacon Class (6 of 6)
runTime = "early"
type = ("projected", "offline")
type = ("projected", "passive")
def handler(fit, beacon, context):
fit.modules.filteredItemMultiply(lambda mod: mod.item.group.name == "Stasis Web",
"speedFactor", beacon.getModifiedItemAttr("stasisWebStrengthMultiplier"),

View File

@@ -4,5 +4,13 @@
# Variations of module: Warp Scrambler I (19 of 19)
runTime = "early"
type = "projected", "active"
from eos.types import State
def handler(fit, module, context):
pass
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

View File

@@ -250,11 +250,11 @@ class ModifiedAttributeDict(collections.MutableMapping):
def increase(self, attributeName, increase, position="pre", skill=None):
"""Increase value of given attribute by given number"""
# Increases applied before multiplications and after them are
# written in separate maps
if skill:
increase *= self.__handleSkill(skill)
# Increases applied before multiplications and after them are
# written in separate maps
if position == "pre":
tbl = self.__preIncreases
elif position == "post":
@@ -269,11 +269,11 @@ class ModifiedAttributeDict(collections.MutableMapping):
def multiply(self, attributeName, multiplier, stackingPenalties=False, penaltyGroup="default", skill=None):
"""Multiply value of given attribute by given factor"""
# If we're asked to do stacking penalized multiplication, append values
# to per penalty group lists
if skill:
multiplier *= self.__handleSkill(skill)
# If we're asked to do stacking penalized multiplication, append values
# to per penalty group lists
if stackingPenalties:
if not attributeName in self.__penalizedMultipliers:
self.__penalizedMultipliers[attributeName] = {}
@@ -291,9 +291,10 @@ class ModifiedAttributeDict(collections.MutableMapping):
def boost(self, attributeName, boostFactor, skill=None, *args, **kwargs):
"""Boost value by some percentage"""
# We just transform percentage boost into multiplication factor
if skill:
boostFactor *= self.__handleSkill(skill)
# We just transform percentage boost into multiplication factor
self.multiply(attributeName, 1 + boostFactor / 100.0, *args, **kwargs)
def force(self, attributeName, value):

View File

@@ -21,11 +21,11 @@
from sqlalchemy.orm import validates, reconstructor
from eos.effectHandlerHelpers import HandledItem
import eos.db
import eos
class Character(object):
__all5 = None
__all0 = None
__itemList = None
__itemIDMap = None
__itemNameMap = None
@@ -33,7 +33,6 @@ class Character(object):
@classmethod
def getSkillList(cls):
if cls.__itemList is None:
import eos.db
cls.__itemList = eos.db.getItemsByCategory("Skill")
return cls.__itemList
@@ -66,36 +65,39 @@ class Character(object):
@classmethod
def getAll5(cls):
if cls.__all5 is None:
import eos.db
all5 = eos.db.getCharacter("All 5")
if all5 is None:
all5 = Character("All 5")
all5.defaultLevel = 5
eos.db.add(all5)
all5 = eos.db.getCharacter("All 5")
cls.__all5 = all5
return cls.__all5
if all5 is None:
# We do not have to be afraid of committing here and saving
# edited character data. If this ever runs, it will be during the
# get character list phase when pyfa first starts
all5 = Character("All 5", 5)
eos.db.save(all5)
return all5
@classmethod
def getAll0(cls):
if cls.__all0 is None:
import eos.db
all0 = eos.db.getCharacter("All 0")
if all0 is None:
all0 = Character("All 0")
all0.defaultLevel = None
eos.db.add(all0)
all0 = eos.db.getCharacter("All 0")
cls.__all0 = all0
return cls.__all0
if all0 is None:
all0 = Character("All 0")
eos.db.save(all0)
def __init__(self, name):
return all0
def __init__(self, name, defaultLevel=None, initSkills=True):
self.name = name
self.__owner = None
self.defaultLevel = None
self.defaultLevel = defaultLevel
self.__skills = []
self.__skillIdMap = {}
self.dirtySkills = set()
if initSkills:
for item in self.getSkillList():
self.addSkill(Skill(item.ID, self.defaultLevel))
self.__implants = eos.saveddata.fit.HandledImplantBoosterList()
self.apiKey = None
@@ -104,14 +106,18 @@ class Character(object):
self.__skillIdMap = {}
for skill in self.__skills:
self.__skillIdMap[skill.itemID] = skill
self.dirtySkills = set()
def apiUpdateCharSheet(self, skills):
del self.__skills[:]
self.__skillIdMap.clear()
for skillRow in skills:
self.addSkill(Skill(skillRow["typeID"], skillRow["level"]))
@property
def ro(self):
return self == self.getAll0() or self == self.getAll5()
@property
def owner(self):
return self.__owner
@@ -120,6 +126,10 @@ class Character(object):
def owner(self, owner):
self.__owner = owner
@property
def skills(self):
return self.__skills
def addSkill(self, skill):
self.__skills.append(skill)
self.__skillIdMap[skill.itemID] = skill
@@ -137,11 +147,7 @@ class Character(object):
skill = self.__skillIdMap.get(item.ID)
if skill is None:
if self.defaultLevel is None:
skill = Skill(item, 0, False, False)
else:
skill = Skill(item, self.defaultLevel, False, True)
skill = Skill(item, self.defaultLevel, False, True)
self.addSkill(skill)
return skill
@@ -150,40 +156,57 @@ class Character(object):
def implants(self):
return self.__implants
def iterSkills(self):
for item in self.getSkillList():
yield self.getSkill(item)
@property
def isDirty(self):
return len(self.dirtySkills) > 0
def saveLevels(self):
if self == self.getAll5() or self == self.getAll0():
raise ReadOnlyException("This character is read-only")
for skill in self.dirtySkills.copy():
skill.saveLevel()
self.dirtySkills = set()
eos.db.commit()
def revertLevels(self):
for skill in self.dirtySkills.copy():
skill.revert()
self.dirtySkills = set()
def filteredSkillIncrease(self, filter, *args, **kwargs):
for element in self.iterSkills():
for element in self.skills:
if filter(element):
element.increaseItemAttr(*args, **kwargs)
def filteredSkillMultiply(self, filter, *args, **kwargs):
for element in self.iterSkills():
for element in self.skills:
if filter(element):
element.multiplyItemAttr(*args, **kwargs)
def filteredSkillBoost(self, filter, *args, **kwargs):
for element in self.iterSkills():
for element in self.skills:
if filter(element):
element.boostItemAttr(*args, **kwargs)
def calculateModifiedAttributes(self, fit, runTime, forceProjected = False):
if forceProjected: return
for skill in self.iterSkills():
for skill in self.skills:
fit.register(skill)
skill.calculateModifiedAttributes(fit, runTime)
def clear(self):
for skill in self.iterSkills():
for skill in self.skills:
skill.clear()
def __deepcopy__(self, memo):
copy = Character("%s copy" % self.name)
copy = Character("%s copy" % self.name, initSkills=False)
copy.apiKey = self.apiKey
copy.apiID = self.apiID
for skill in self.iterSkills():
for skill in self.skills:
copy.addSkill(Skill(skill.itemID, skill.level, False, skill.learned))
return copy
@@ -199,7 +222,7 @@ class Character(object):
else: return val
class Skill(HandledItem):
def __init__(self, item, level = 0, ro = False, learned = True):
def __init__(self, item, level=0, ro=False, learned=True):
self.__item = item if not isinstance(item, int) else None
self.itemID = item.ID if not isinstance(item, int) else item
self.__level = level if learned else None
@@ -214,14 +237,28 @@ class Skill(HandledItem):
def build(self, ro):
self.__ro = ro
self.__suppressed = False
self.activeLevel = self.__level
def saveLevel(self):
self.__level = self.activeLevel
if self in self.character.dirtySkills:
self.character.dirtySkills.remove(self)
def revert(self):
self.level = self.__level
@property
def isDirty(self):
return self.__level != self.activeLevel
@property
def learned(self):
return self.__level is not None
return self.activeLevel is not None
@property
def level(self):
return self.__level or 0
return self.activeLevel or 0
@level.setter
def level(self, level):
@@ -231,7 +268,12 @@ class Skill(HandledItem):
if hasattr(self, "_Skill__ro") and self.__ro == True:
raise ReadOnlyException()
self.__level = level
self.activeLevel = level
self.character.dirtySkills.add(self)
if self.activeLevel == self.__level and self in self.character.dirtySkills:
self.character.dirtySkills.remove(self)
@property
def item(self):

View File

@@ -401,7 +401,7 @@ class Fit(object):
return self.__origin
def __calculateGangBoosts(self, runTime):
logger.debug("Applying gang boosts in `%s` runtime for %s", runTime, repr(self))
logger.debug("Applying gang boosts in `%s` runtime for %r", runTime, self)
for name, info in self.gangBoosts.iteritems():
# Unpack all data required to run effect properly
effect, thing = info[1]
@@ -425,12 +425,12 @@ class Fit(object):
pass
def calculateModifiedAttributes(self, targetFit=None, withBoosters=False, dirtyStorage=None):
timer = Timer('Fit: {}, {}'.format(self.ID, self.name), logger)
logger.debug("Starting fit calculation on: %s, withBoosters: %s", repr(self), withBoosters)
timer = Timer(u'Fit: {}, {}'.format(self.ID, self.name), logger)
logger.debug("Starting fit calculation on: %r, withBoosters: %s", self, withBoosters)
shadow = False
if targetFit:
logger.debug("Applying projections to target: %s", repr(targetFit))
logger.debug("Applying projections to target: %r", targetFit)
projectionInfo = self.getProjectionInfo(targetFit.ID)
logger.debug("ProjectionInfo: %s", projectionInfo)
if self == targetFit:
@@ -438,7 +438,7 @@ class Fit(object):
shadow = True
self = copy.deepcopy(self)
self.fleet = copied.fleet
logger.debug("Handling self projection - making shadow copy of fit. %s => %s", repr(copied), repr(self))
logger.debug("Handling self projection - making shadow copy of fit. %r => %r", copied, self)
# we delete the fit because when we copy a fit, flush() is
# called to properly handle projection updates. However, we do
# not want to save this fit to the database, so simply remove it
@@ -447,7 +447,7 @@ class Fit(object):
if self.fleet is not None and withBoosters is True:
logger.debug("Fleet is set, gathering gang boosts")
self.gangBoosts = self.fleet.recalculateLinear(withBoosters=withBoosters)
timer.checkpoint("Done calculating gang boosts for %s"%repr(self))
timer.checkpoint("Done calculating gang boosts for %r"%self)
elif self.fleet is None:
self.gangBoosts = None
@@ -473,7 +473,7 @@ class Fit(object):
# projection have modifying stuff applied, such as gang boosts and other
# local modules that may help
if self.__calculated and not projected:
logger.debug("Fit has already been calculated and is not projected, returning: %s", repr(self))
logger.debug("Fit has already been calculated and is not projected, returning: %r", self)
return
# Mark fit as calculated
@@ -604,8 +604,8 @@ class Fit(object):
Slot.RIG: "rigSlots",
Slot.SUBSYSTEM: "maxSubSystems"}
if type == Slot.MODE:
# Mode slot doesn't really exist, return default 0
if type in (Slot.MODE, Slot.SYSTEM):
# These slots don't really exist, return default 0
return 0
slotsUsed = self.getSlotsUsed(type, countDummies)
@@ -1000,11 +1000,11 @@ class Fit(object):
return copy
def __repr__(self):
return "Fit(ID={}, ship={}, name={}) at {}".format(
return u"Fit(ID={}, ship={}, name={}) at {}".format(
self.ID, self.ship.item.name, self.name, hex(id(self))
)
).encode('utf8')
def __str__(self):
return "{} ({})".format(
return u"{} ({})".format(
self.name, self.ship.item.name
)
).encode('utf8')

View File

@@ -247,7 +247,7 @@ class Store(object):
dict.clear()
# Go through everything which can be used as gang booster
for thing in chain(fitBooster.modules, fitBooster.implants, fitBooster.character.iterSkills(), (fitBooster.ship,)):
for thing in chain(fitBooster.modules, fitBooster.implants, fitBooster.character.skills, (fitBooster.ship,)):
if thing.item is None:
continue
for effect in thing.item.effects.itervalues():

View File

@@ -35,12 +35,17 @@ class State(Enum):
OVERHEATED = 2
class Slot(Enum):
# These are self-explanatory
LOW = 1
MED = 2
HIGH = 3
RIG = 4
SUBSYSTEM = 5
MODE = 6 # not a real slot, need for pyfa display rack separation
# not a real slot, need for pyfa display rack separation
MODE = 6
# system effects. They are projected "modules" and pyfa assumes all modules
# have a slot. In this case, make one up.
SYSTEM = 7
class Hardpoint(Enum):
NONE = 0
@@ -528,7 +533,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
if effectName in item.effects:
return slot
if item.group.name == "Effect Beacon":
return Slot.RIG
return Slot.SYSTEM
raise ValueError("Passed item does not fit in any known slot")

View File

@@ -70,6 +70,14 @@ class Ship(ItemAttrShortcut, HandledItem):
if forceProjected: return
for effect in self.item.effects.itervalues():
if effect.runTime == runTime and effect.isType("passive"):
# Ships have effects that utilize the level of a skill as an
# additional operator to the modifier. These are defined in
# the effect itself, and these skillbooks are registered when
# they are provided. However, we must re-register the ship
# before each effect, otherwise effects that do not have
# skillbook modifiers will use the stale modifier value
# GH issue #351
fit.register(self)
effect.handler(fit, self, ("ship",))
def validateModeItem(self, item):

View File

@@ -21,8 +21,8 @@ class ChangeAffectingSkills(ContextMenu):
self.charID = fit.character.ID
if self.sChar.getCharName(self.charID) in ("All 0", "All 5"):
return False
#if self.sChar.getCharName(self.charID) in ("All 0", "All 5"):
# return False
if srcContext == "fittingShip":
fitID = self.mainFrame.getActiveFit()
@@ -94,6 +94,7 @@ class ChangeAffectingSkills(ContextMenu):
fitID = self.mainFrame.getActiveFit()
self.sFit.changeChar(fitID, self.charID)
wx.PostEvent(self.mainFrame, GE.CharListUpdated())
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
ChangeAffectingSkills.register()

View File

@@ -35,6 +35,9 @@ class CharacterEditor(wx.Frame):
size=wx.Size(641, 600), style=wx.DEFAULT_FRAME_STYLE|wx.FRAME_FLOAT_ON_PARENT|wx.TAB_TRAVERSAL)
i = wx.IconFromBitmap(BitmapLoader.getBitmap("character_small", "gui"))
self.mainFrame = parent
self.SetIcon(i)
self.disableWin= wx.WindowDisabler(self)
@@ -45,8 +48,6 @@ class CharacterEditor(wx.Frame):
self.navSizer = wx.BoxSizer(wx.HORIZONTAL)
sChar = service.Character.getInstance()
charList = sChar.getCharacterList()
charList.sort(key=lambda t: t[1])
self.btnSave = wx.Button(self, wx.ID_SAVE)
self.btnSave.Hide()
@@ -56,15 +57,15 @@ class CharacterEditor(wx.Frame):
self.characterRename.Hide()
self.characterRename.Bind(wx.EVT_TEXT_ENTER, self.processRename)
self.skillTreeChoice = wx.Choice(self, wx.ID_ANY, style=0)
self.charChoice = wx.Choice(self, wx.ID_ANY, style=0)
self.navSizer.Add(self.charChoice, 1, wx.ALL | wx.EXPAND, 5)
charList = sChar.getCharacterList()
for id, name, active in charList:
i = self.skillTreeChoice.Append(name, id)
i = self.charChoice.Append(name, id)
if active:
self.skillTreeChoice.SetSelection(i)
self.navSizer.Add(self.skillTreeChoice, 1, wx.ALL | wx.EXPAND, 5)
self.navSizer.Add(self.btnSave, 0, wx.ALIGN_CENTER)
self.charChoice.SetSelection(i)
buttons = (("new", wx.ART_NEW),
("rename", BitmapLoader.getBitmap("rename", "gui")),
@@ -111,12 +112,26 @@ class CharacterEditor(wx.Frame):
bSizerButtons = wx.BoxSizer(wx.HORIZONTAL)
self.btnSave = wx.Button(self, wx.ID_ANY, "Save")
self.btnSaveAs = wx.Button(self, wx.ID_ANY, "Save As...")
self.btnRevert = wx.Button(self, wx.ID_ANY, "Revert")
self.btnOK = wx.Button(self, wx.ID_OK)
bSizerButtons.Add(self.btnSave, 0, wx.ALL, 5)
bSizerButtons.Add(self.btnSaveAs, 0, wx.ALL, 5)
bSizerButtons.Add(self.btnRevert, 0, wx.ALL, 5)
bSizerButtons.AddStretchSpacer()
bSizerButtons.Add(self.btnOK, 0, wx.ALL, 5)
self.btnSave.Bind(wx.EVT_BUTTON, self.saveChar)
self.btnSaveAs.Bind(wx.EVT_BUTTON, self.saveCharAs)
self.btnRevert.Bind(wx.EVT_BUTTON, self.revertChar)
self.btnOK.Bind(wx.EVT_BUTTON, self.editingFinished)
mainSizer.Add(bSizerButtons, 0, wx.ALIGN_RIGHT, 5)
mainSizer.Add(bSizerButtons, 0, wx.EXPAND, 5)
self.btnRestrict()
self.SetSizer(mainSizer)
self.Layout()
@@ -129,7 +144,28 @@ class CharacterEditor(wx.Frame):
self.registerEvents()
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
def btnRestrict(self):
sChar = service.Character.getInstance()
charID = self.getActiveCharacter()
char = sChar.getCharacter(charID)
# enable/disable character saving stuff
self.btnSave.Enable(not char.ro and char.isDirty)
self.btnSaveAs.Enable(char.isDirty)
self.btnRevert.Enable(char.isDirty)
def refreshCharacterList(self, event=None):
sChar = service.Character.getInstance()
charList = sChar.getCharacterList()
active = self.getActiveCharacter()
self.charChoice.Clear()
for id, name, _ in charList:
i = self.charChoice.Append(name, id)
if active == id:
self.charChoice.SetSelection(i)
self.btnRestrict()
def editingFinished(self, event):
del self.disableWin
@@ -138,7 +174,29 @@ class CharacterEditor(wx.Frame):
def registerEvents(self):
self.Bind(wx.EVT_CLOSE, self.closeEvent)
self.skillTreeChoice.Bind(wx.EVT_CHOICE, self.charChanged)
self.Bind(GE.CHAR_LIST_UPDATED, self.refreshCharacterList)
self.charChoice.Bind(wx.EVT_CHOICE, self.charChanged)
def saveChar(self, event):
sChr = service.Character.getInstance()
charID = self.getActiveCharacter()
sChr.saveCharacter(charID)
self.sview.populateSkillTree()
wx.PostEvent(self, GE.CharListUpdated())
def saveCharAs(self, event):
charID = self.getActiveCharacter()
dlg = SaveCharacterAs(self, charID)
dlg.ShowModal()
dlg.Destroy()
self.sview.populateSkillTree()
def revertChar(self, event):
sChr = service.Character.getInstance()
charID = self.getActiveCharacter()
sChr.revertCharacter(charID)
self.sview.populateSkillTree()
wx.PostEvent(self, GE.CharListUpdated())
def closeEvent(self, event):
del self.disableWin
@@ -148,7 +206,7 @@ class CharacterEditor(wx.Frame):
def restrict(self):
self.btnRename.Enable(False)
self.btnDelete.Enable(False)
self.aview.stDisabledTip.Show(True)
self.aview.stDisabledTip.Show()
self.aview.inputID.Enable(False)
self.aview.inputKey.Enable(False)
self.aview.charChoice.Enable(False)
@@ -160,7 +218,7 @@ class CharacterEditor(wx.Frame):
def unrestrict(self):
self.btnRename.Enable(True)
self.btnDelete.Enable(True)
self.aview.stDisabledTip.Show(False)
self.aview.stDisabledTip.Hide()
self.aview.inputID.Enable(True)
self.aview.inputKey.Enable(True)
self.aview.btnFetchCharList.Enable(True)
@@ -169,7 +227,6 @@ class CharacterEditor(wx.Frame):
self.aview.Layout()
def charChanged(self, event):
self.sview.skillTreeListCtrl.DeleteChildren(self.sview.root)
self.sview.populateSkillTree()
sChar = service.Character.getInstance()
charID = self.getActiveCharacter()
@@ -183,14 +240,14 @@ class CharacterEditor(wx.Frame):
event.Skip()
def getActiveCharacter(self):
selection = self.skillTreeChoice.GetCurrentSelection()
return self.skillTreeChoice.GetClientData(selection) if selection is not None else None
selection = self.charChoice.GetCurrentSelection()
return self.charChoice.GetClientData(selection) if selection is not None else None
def new(self, event):
sChar = service.Character.getInstance()
charID = sChar.new()
id = self.skillTreeChoice.Append(sChar.getCharName(charID), charID)
self.skillTreeChoice.SetSelection(id)
id = self.charChoice.Append(sChar.getCharName(charID), charID)
self.charChoice.SetSelection(id)
self.unrestrict()
self.btnSave.SetLabel("Create")
self.rename(None)
@@ -199,9 +256,9 @@ class CharacterEditor(wx.Frame):
def rename(self, event):
if event is not None:
self.btnSave.SetLabel("Rename")
self.skillTreeChoice.Hide()
self.charChoice.Hide()
self.characterRename.Show()
self.navSizer.Replace(self.skillTreeChoice, self.characterRename)
self.navSizer.Replace(self.charChoice, self.characterRename)
self.characterRename.SetFocus()
for btn in (self.btnNew, self.btnCopy, self.btnRename, self.btnDelete):
btn.Hide()
@@ -224,24 +281,21 @@ class CharacterEditor(wx.Frame):
charID = self.getActiveCharacter()
sChar.rename(charID, newName)
self.skillTreeChoice.Show()
self.charChoice.Show()
self.characterRename.Hide()
self.navSizer.Replace(self.characterRename, self.skillTreeChoice)
self.navSizer.Replace(self.characterRename, self.charChoice)
for btn in (self.btnNew, self.btnCopy, self.btnRename, self.btnDelete):
btn.Show()
self.btnSave.Hide()
self.navSizer.Layout()
selection = self.skillTreeChoice.GetCurrentSelection()
self.skillTreeChoice.Delete(selection)
self.skillTreeChoice.Insert(newName, selection, charID)
self.skillTreeChoice.SetSelection(selection)
self.refreshCharacterList()
def copy(self, event):
sChar = service.Character.getInstance()
charID = sChar.copy(self.getActiveCharacter())
id = self.skillTreeChoice.Append(sChar.getCharName(charID), charID)
self.skillTreeChoice.SetSelection(id)
id = self.charChoice.Append(sChar.getCharName(charID), charID)
self.charChoice.SetSelection(id)
self.unrestrict()
self.btnSave.SetLabel("Copy")
self.rename(None)
@@ -250,9 +304,9 @@ class CharacterEditor(wx.Frame):
def delete(self, event):
sChar = service.Character.getInstance()
sChar.delete(self.getActiveCharacter())
sel = self.skillTreeChoice.GetSelection()
self.skillTreeChoice.Delete(sel)
self.skillTreeChoice.SetSelection(sel - 1)
sel = self.charChoice.GetSelection()
self.charChoice.Delete(sel)
self.charChoice.SetSelection(sel - 1)
newSelection = self.getActiveCharacter()
if sChar.getCharName(newSelection) in ("All 0", "All 5"):
self.restrict()
@@ -314,6 +368,14 @@ class SkillTreeView (wx.Panel):
self.levelIds[id] = level
self.levelChangeMenu.Append(id, "Level %d" % level)
self.levelChangeMenu.AppendSeparator()
self.revertID = wx.NewId()
self.levelChangeMenu.Append(self.revertID, "Revert")
self.saveID = wx.NewId()
self.levelChangeMenu.Append(self.saveID, "Save")
self.levelChangeMenu.Bind(wx.EVT_MENU, self.changeLevel)
self.SetSizer(pmainSizer)
@@ -321,15 +383,22 @@ class SkillTreeView (wx.Panel):
def populateSkillTree(self):
sChar = service.Character.getInstance()
charID = self.Parent.Parent.getActiveCharacter()
dirtySkills = sChar.getDirtySkills(charID)
dirtyGroups = set([skill.item.group.ID for skill in dirtySkills])
groups = sChar.getSkillGroups()
imageId = self.skillBookImageId
root = self.root
tree = self.skillTreeListCtrl
tree.DeleteChildren(root)
for id, name in groups:
childId = tree.AppendItem(root, name, imageId)
tree.SetPyData(childId, id)
tree.AppendItem(childId, "dummy")
if id in dirtyGroups:
tree.SetItemTextColour(childId, wx.BLUE)
tree.SortChildren(root)
@@ -346,8 +415,10 @@ class SkillTreeView (wx.Panel):
for id, name in sChar.getSkills(tree.GetPyData(root)):
iconId = self.skillBookImageId
childId = tree.AppendItem(root, name, iconId, data=wx.TreeItemData(id))
level = sChar.getSkillLevel(char, id)
level, dirty = sChar.getSkillLevel(char, id)
tree.SetItemText(childId, "Level %d" % level if isinstance(level, int) else level, 1)
if dirty:
tree.SetItemTextColour(childId, wx.BLUE)
tree.SortChildren(root)
@@ -372,18 +443,34 @@ class SkillTreeView (wx.Panel):
def changeLevel(self, event):
level = self.levelIds.get(event.Id)
sChar = service.Character.getInstance()
charID = self.Parent.Parent.getActiveCharacter()
selection = self.skillTreeListCtrl.GetSelection()
skillID = self.skillTreeListCtrl.GetPyData(selection)
if level is not None:
sChar = service.Character.getInstance()
charID = self.Parent.Parent.getActiveCharacter()
selection = self.skillTreeListCtrl.GetSelection()
skillID = self.skillTreeListCtrl.GetPyData(selection)
self.skillTreeListCtrl.SetItemText(selection, "Level %d" % level if isinstance(level, int) else level, 1)
sChar.changeLevel(charID, skillID, level)
sChar.changeLevel(charID, skillID, level, persist=True)
elif event.Id == self.revertID:
sChar.revertLevel(charID, skillID)
elif event.Id == self.saveID:
sChar.saveSkill(charID, skillID)
self.skillTreeListCtrl.SetItemTextColour(selection, None)
dirtySkills = sChar.getDirtySkills(charID)
dirtyGroups = set([skill.item.group.ID for skill in dirtySkills])
parentID = self.skillTreeListCtrl.GetItemParent(selection)
groupID = self.skillTreeListCtrl.GetPyData(parentID)
if groupID not in dirtyGroups:
self.skillTreeListCtrl.SetItemTextColour(parentID, None)
wx.PostEvent(self.Parent.Parent, GE.CharListUpdated())
event.Skip()
class ImplantsTreeView (wx.Panel):
def addMarketViewImage(self, iconFile):
if iconFile is None:
@@ -544,6 +631,7 @@ class APIView (wx.Panel):
u"Please select another character or make a new one.", style=wx.ALIGN_CENTER )
self.stDisabledTip.Wrap( -1 )
hintSizer.Add( self.stDisabledTip, 0, wx.TOP | wx.BOTTOM, 10 )
self.stDisabledTip.Hide()
hintSizer.AddStretchSpacer()
pmainSizer.Add(hintSizer, 0, wx.EXPAND, 5)
@@ -649,7 +737,7 @@ class APIView (wx.Panel):
sChar = service.Character.getInstance()
try:
list = sChar.charList(self.Parent.Parent.getActiveCharacter(), self.inputID.GetLineText(0), self.inputKey.GetLineText(0))
list = sChar.apiCharList(self.Parent.Parent.getActiveCharacter(), self.inputID.GetLineText(0), self.inputKey.GetLineText(0))
except service.network.AuthenticationError, e:
self.stStatus.SetLabel("Authentication failure. Please check keyID and vCode combination.")
except service.network.TimeoutError, e:
@@ -677,3 +765,34 @@ class APIView (wx.Panel):
self.stStatus.SetLabel("Successfully fetched %s\'s skills from EVE API." % charName)
except Exception, e:
self.stStatus.SetLabel("Unable to retrieve %s\'s skills. Error message:\n%s" % (charName, e))
class SaveCharacterAs(wx.Dialog):
def __init__(self, parent, charID):
wx.Dialog.__init__(self, parent, title="Save Character As...", size=wx.Size(300, 60))
self.charID = charID
self.parent = parent
sChar = service.Character.getInstance()
name = sChar.getCharName(charID)
bSizer1 = wx.BoxSizer(wx.HORIZONTAL)
self.input = wx.TextCtrl(self, wx.ID_ANY, name, style=wx.TE_PROCESS_ENTER)
bSizer1.Add(self.input, 1, wx.ALL, 5)
self.input.Bind(wx.EVT_TEXT_ENTER, self.change)
self.button = wx.Button(self, wx.ID_OK, u"Save")
bSizer1.Add(self.button, 0, wx.ALL, 5)
self.SetSizer(bSizer1)
self.Layout()
self.Centre(wx.BOTH)
self.button.Bind(wx.EVT_BUTTON, self.change)
def change(self, event):
sChar = service.Character.getInstance()
sChar.saveCharacterAs(self.charID, self.input.GetLineText(0))
wx.PostEvent(self.parent, GE.CharListUpdated())
event.Skip()
self.Destroy()

View File

@@ -81,7 +81,6 @@ class CharacterSelection(wx.Panel):
choice.Clear()
charList = sChar.getCharacterList()
sChar.getCharacterList()
picked = False
for id, name, active in charList:

View File

@@ -43,7 +43,7 @@ from gui.marketBrowser import MarketBrowser, ItemSelected
from gui.multiSwitch import MultiSwitch
from gui.statsPane import StatsPane
from gui.shipBrowser import ShipBrowser, FitSelected, ImportSelected, Stage3Selected
from gui.characterEditor import CharacterEditor
from gui.characterEditor import CharacterEditor, SaveCharacterAs
from gui.characterSelection import CharacterSelection
from gui.patternEditor import DmgPatternEditorDlg
from gui.resistsEditor import ResistsEditorDlg
@@ -416,6 +416,12 @@ class MainFrame(wx.Frame):
self.Bind(wx.EVT_MENU, self.goWiki, id = menuBar.wikiId)
# EVE Forums
self.Bind(wx.EVT_MENU, self.goForums, id = menuBar.forumId)
# Save current character
self.Bind(wx.EVT_MENU, self.saveChar, id = menuBar.saveCharId)
# Save current character as another character
self.Bind(wx.EVT_MENU, self.saveCharAs, id = menuBar.saveCharAsId)
# Save current character
self.Bind(wx.EVT_MENU, self.revertChar, id = menuBar.revertCharId)
#Clipboard exports
self.Bind(wx.EVT_MENU, self.exportToClipboard, id=wx.ID_COPY)
@@ -480,6 +486,24 @@ class MainFrame(wx.Frame):
atable = wx.AcceleratorTable(actb)
self.SetAcceleratorTable(atable)
def saveChar(self, event):
sChr = service.Character.getInstance()
charID = self.charSelection.getActiveCharacter()
sChr.saveCharacter(charID)
wx.PostEvent(self, GE.CharListUpdated())
def saveCharAs(self, event):
charID = self.charSelection.getActiveCharacter()
dlg = SaveCharacterAs(self, charID)
dlg.ShowModal()
dlg.Destroy()
def revertChar(self, event):
sChr = service.Character.getInstance()
charID = self.charSelection.getActiveCharacter()
sChr.revertCharacter(charID)
wx.PostEvent(self, GE.CharListUpdated())
def AdditionsTabSelect(self, event):
selTab = self.additionsSelect.index(event.GetId())

View File

@@ -23,6 +23,7 @@ from gui.bitmapLoader import BitmapLoader
import gui.mainFrame
import gui.graphFrame
import gui.globalEvents as GE
import service
class MainMenuBar(wx.MenuBar):
def __init__(self):
@@ -36,6 +37,9 @@ class MainMenuBar(wx.MenuBar):
self.exportHtmlId = wx.NewId()
self.wikiId = wx.NewId()
self.forumId = wx.NewId()
self.saveCharId = wx.NewId()
self.saveCharAsId = wx.NewId()
self.revertCharId = wx.NewId()
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
@@ -70,7 +74,10 @@ class MainMenuBar(wx.MenuBar):
pasteText = "&From Clipboard" + ("\tCTRL+V" if 'wxMSW' in wx.PlatformInfo else "")
editMenu.Append(wx.ID_COPY, copyText, "Export a fit to the clipboard")
editMenu.Append(wx.ID_PASTE, pasteText, "Import a fit from the clipboard")
editMenu.AppendSeparator()
editMenu.Append(self.saveCharId, "Save Character")
editMenu.Append(self.saveCharAsId, "Save Character As...")
editMenu.Append(self.revertCharId, "Revert Character")
# Character menu
windowMenu = wx.Menu()
self.Append(windowMenu, "&Window")
@@ -113,5 +120,14 @@ class MainMenuBar(wx.MenuBar):
self.Enable(wx.ID_SAVEAS, enable)
self.Enable(wx.ID_COPY, enable)
self.Enable(self.exportSkillsNeededId, enable)
event.Skip()
sChar = service.Character.getInstance()
charID = self.mainFrame.charSelection.getActiveCharacter()
char = sChar.getCharacter(charID)
# enable/disable character saving stuff
self.Enable(self.saveCharId, not char.ro and char.isDirty)
self.Enable(self.saveCharAsId, char.isDirty)
self.Enable(self.revertCharId, char.isDirty)
event.Skip()

Some files were not shown because too many files have changed in this diff Show More