diff --git a/config.py b/config.py
index 6b10b521b..4e0b019dd 100644
--- a/config.py
+++ b/config.py
@@ -20,8 +20,8 @@ saveInRoot = False
# Version data
version = "1.20.2"
tag = "git"
-expansionName = "March 2016"
-expansionVersion = "1.3"
+expansionName = "Singularity"
+expansionVersion = "1027729"
evemonMinVersion = "4081"
pyfaPath = None
diff --git a/eos/db/migration.py b/eos/db/migration.py
index c99be1ffc..a0824f812 100644
--- a/eos/db/migration.py
+++ b/eos/db/migration.py
@@ -4,6 +4,9 @@ import time
import re
import os
import migrations
+import logging
+
+logger = logging.getLogger(__name__)
def getVersion(db):
cursor = db.execute('PRAGMA user_version')
@@ -30,10 +33,9 @@ def update(saveddata_engine):
shutil.copyfile(config.saveDB, toFile)
for version in xrange(dbVersion, appVersion):
-
func = migrations.updates[version+1]
if func:
- print "applying update",version+1
+ logger.info("Applying database update: %d", version+1)
func(saveddata_engine)
# when all is said and done, set version to current
diff --git a/eos/db/migrations/upgrade13.py b/eos/db/migrations/upgrade13.py
new file mode 100644
index 000000000..047dc7129
--- /dev/null
+++ b/eos/db/migrations/upgrade13.py
@@ -0,0 +1,15 @@
+"""
+Migration 13
+
+- Alters fits table to introduce implant location attribute
+"""
+
+import sqlalchemy
+
+def upgrade(saveddata_engine):
+ # Update fits schema to include implant location attribute
+ try:
+ saveddata_engine.execute("SELECT implantLocation FROM fits LIMIT 1")
+ except sqlalchemy.exc.DatabaseError:
+ saveddata_engine.execute("ALTER TABLE fits ADD COLUMN implantLocation INTEGER;")
+ saveddata_engine.execute("UPDATE fits SET implantLocation = 0")
\ No newline at end of file
diff --git a/eos/db/saveddata/__init__.py b/eos/db/saveddata/__init__.py
index 683fb499d..e43c6e601 100644
--- a/eos/db/saveddata/__init__.py
+++ b/eos/db/saveddata/__init__.py
@@ -13,6 +13,7 @@ __all__ = [
"miscData",
"targetResists",
"override",
- "crest"
+ "crest",
+ "implantSet"
]
diff --git a/eos/db/saveddata/character.py b/eos/db/saveddata/character.py
index 6600d975e..e6be52535 100644
--- a/eos/db/saveddata/character.py
+++ b/eos/db/saveddata/character.py
@@ -36,9 +36,23 @@ characters_table = Table("characters", saveddata_meta,
Column("ownerID", ForeignKey("users.ID"), nullable = True))
mapper(Character, characters_table,
- properties = {"_Character__owner" : relation(User, backref = "characters"),
- "_Character__skills" : relation(Skill, backref="character", cascade = "all,delete-orphan"),
- "_Character__implants" : relation(Implant, collection_class = HandledImplantBoosterList, cascade='all,delete-orphan', single_parent=True,
- primaryjoin = charImplants_table.c.charID == characters_table.c.ID,
- secondaryjoin = charImplants_table.c.implantID == Implant.ID,
- secondary = charImplants_table),})
+ properties = {
+ "savedName": characters_table.c.name,
+ "_Character__owner": relation(
+ User,
+ backref = "characters"),
+ "_Character__skills": relation(
+ Skill,
+ backref="character",
+ cascade = "all,delete-orphan"),
+ "_Character__implants": relation(
+ Implant,
+ collection_class = HandledImplantBoosterList,
+ cascade='all,delete-orphan',
+ backref='character',
+ single_parent=True,
+ primaryjoin = charImplants_table.c.charID == characters_table.c.ID,
+ secondaryjoin = charImplants_table.c.implantID == Implant.ID,
+ secondary = charImplants_table),
+ }
+)
diff --git a/eos/db/saveddata/fighter.py b/eos/db/saveddata/fighter.py
new file mode 100644
index 000000000..1daa37ae7
--- /dev/null
+++ b/eos/db/saveddata/fighter.py
@@ -0,0 +1,51 @@
+#===============================================================================
+# 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 sqlalchemy import Table, Column, Integer, ForeignKey, Boolean
+from sqlalchemy.orm import mapper
+from eos.db import saveddata_meta
+from eos.types import Fighter
+from sqlalchemy.orm import *
+from sqlalchemy.sql import and_
+from eos.effectHandlerHelpers import *
+from eos.types import FighterAbility
+
+
+fighters_table = Table("fighters", saveddata_meta,
+ Column("groupID", Integer, primary_key=True),
+ Column("fitID", Integer, ForeignKey("fits.ID"), nullable = False, index = True),
+ Column("itemID", Integer, nullable = False),
+ Column("active", Boolean, nullable=True),
+ Column("amount", Integer, nullable = False),
+ Column("projected", Boolean, default = False))
+
+fighter_abilities_table = Table("fightersAbilities", saveddata_meta,
+ Column("groupID", Integer, ForeignKey("fighters.groupID"), primary_key=True, index = True),
+ Column("effectID", Integer, nullable = False, primary_key=True),
+ Column("active", Boolean, default = False))
+
+mapper(Fighter, fighters_table,
+ properties = {
+ "_Fighter__abilities": relation(
+ FighterAbility,
+ backref="fighter",
+ cascade='all, delete, delete-orphan'),
+ })
+
+mapper(FighterAbility, fighter_abilities_table)
diff --git a/eos/db/saveddata/fit.py b/eos/db/saveddata/fit.py
index a40d8c7fb..29f51ef6c 100644
--- a/eos/db/saveddata/fit.py
+++ b/eos/db/saveddata/fit.py
@@ -26,9 +26,10 @@ from sqlalchemy.orm.collections import attribute_mapped_collection
from eos.db import saveddata_meta
from eos.db.saveddata.module import modules_table
from eos.db.saveddata.drone import drones_table
+from eos.db.saveddata.fighter import fighters_table
from eos.db.saveddata.cargo import cargo_table
from eos.db.saveddata.implant import fitImplants_table
-from eos.types import Fit, Module, User, Booster, Drone, Cargo, Implant, Character, DamagePattern, TargetResists
+from eos.types import Fit, Module, User, Booster, Drone, Fighter, Cargo, Implant, Character, DamagePattern, TargetResists, ImplantLocation
from eos.effectHandlerHelpers import *
fits_table = Table("fits", saveddata_meta,
@@ -42,6 +43,7 @@ fits_table = Table("fits", saveddata_meta,
Column("booster", Boolean, nullable = False, index = True, default = 0),
Column("targetResistsID", ForeignKey("targetResists.ID"), nullable=True),
Column("modeID", Integer, nullable=True),
+ Column("implantLocation", Integer, nullable=False, default=ImplantLocation.FIT),
)
projectedFits_table = Table("projectedFits", saveddata_meta,
@@ -117,6 +119,12 @@ mapper(Fit, fits_table,
cascade='all, delete, delete-orphan',
single_parent=True,
primaryjoin=and_(drones_table.c.fitID == fits_table.c.ID, drones_table.c.projected == False)),
+ "_Fit__fighters": relation(
+ Fighter,
+ collection_class=HandledDroneCargoList,
+ cascade='all, delete, delete-orphan',
+ single_parent=True,
+ primaryjoin=and_(fighters_table.c.fitID == fits_table.c.ID, fighters_table.c.projected == False)),
"_Fit__cargo": relation(
Cargo,
collection_class=HandledDroneCargoList,
diff --git a/eos/db/saveddata/implant.py b/eos/db/saveddata/implant.py
index 60e40bff7..c74def157 100644
--- a/eos/db/saveddata/implant.py
+++ b/eos/db/saveddata/implant.py
@@ -36,4 +36,8 @@ charImplants_table = Table("charImplants", saveddata_meta,
Column("charID", ForeignKey("characters.ID"), index = True),
Column("implantID", ForeignKey("implants.ID"), primary_key = True))
+implantsSetMap_table = Table("implantSetMap", saveddata_meta,
+ Column("setID", ForeignKey("implantSets.ID"), index = True),
+ Column("implantID", ForeignKey("implants.ID"), primary_key = True))
+
mapper(Implant, implants_table)
diff --git a/eos/db/saveddata/implantSet.py b/eos/db/saveddata/implantSet.py
new file mode 100644
index 000000000..73036de91
--- /dev/null
+++ b/eos/db/saveddata/implantSet.py
@@ -0,0 +1,45 @@
+#===============================================================================
+# Copyright (C) 2016 Ryan Holmes
+#
+# 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 sqlalchemy import Table, Column, Integer, ForeignKey, String
+from sqlalchemy.orm import relation, mapper
+
+from eos.db import saveddata_meta
+from eos.db.saveddata.implant import implantsSetMap_table
+from eos.types import Implant, ImplantSet
+from eos.effectHandlerHelpers import HandledImplantBoosterList
+
+implant_set_table = Table("implantSets", saveddata_meta,
+ Column("ID", Integer, primary_key = True),
+ Column("name", String, nullable = False),
+)
+
+mapper(ImplantSet, implant_set_table,
+ properties = {
+ "_ImplantSet__implants": relation(
+ Implant,
+ collection_class = HandledImplantBoosterList,
+ cascade='all, delete, delete-orphan',
+ backref='set',
+ single_parent=True,
+ primaryjoin = implantsSetMap_table.c.setID == implant_set_table.c.ID,
+ secondaryjoin = implantsSetMap_table.c.implantID == Implant.ID,
+ secondary = implantsSetMap_table),
+ }
+)
diff --git a/eos/db/saveddata/queries.py b/eos/db/saveddata/queries.py
index a305994cd..5a6dd1bfc 100644
--- a/eos/db/saveddata/queries.py
+++ b/eos/db/saveddata/queries.py
@@ -20,7 +20,7 @@
from eos.db.util import processEager, processWhere
from eos.db import saveddata_session, sd_lock
-from eos.types import User, Character, Fit, Price, DamagePattern, Fleet, MiscData, Wing, Squad, TargetResists, Override, CrestChar
+from eos.types import *
from eos.db.saveddata.fleet import squadmembers_table
from eos.db.saveddata.fit import projectedFits_table
from sqlalchemy.sql import and_
@@ -154,7 +154,7 @@ def getCharacter(lookfor, eager=None):
elif isinstance(lookfor, basestring):
eager = processEager(eager)
with sd_lock:
- character = saveddata_session.query(Character).options(*eager).filter(Character.name == lookfor).first()
+ character = saveddata_session.query(Character).options(*eager).filter(Character.savedName == lookfor).first()
else:
raise TypeError("Need integer or string as argument")
return character
@@ -349,6 +349,12 @@ def getTargetResistsList(eager=None):
patterns = saveddata_session.query(TargetResists).options(*eager).all()
return patterns
+def getImplantSetList(eager=None):
+ eager = processEager(eager)
+ with sd_lock:
+ sets = saveddata_session.query(ImplantSet).options(*eager).all()
+ return sets
+
@cachedQuery(DamagePattern, 1, "lookfor")
def getDamagePattern(lookfor, eager=None):
if isinstance(lookfor, int):
@@ -385,6 +391,24 @@ def getTargetResists(lookfor, eager=None):
raise TypeError("Need integer or string as argument")
return pattern
+@cachedQuery(ImplantSet, 1, "lookfor")
+def getImplantSet(lookfor, eager=None):
+ if isinstance(lookfor, int):
+ if eager is None:
+ with sd_lock:
+ pattern = saveddata_session.query(ImplantSet).get(lookfor)
+ else:
+ eager = processEager(eager)
+ with sd_lock:
+ pattern = saveddata_session.query(ImplantSet).options(*eager).filter(TargetResists.ID == lookfor).first()
+ elif isinstance(lookfor, basestring):
+ eager = processEager(eager)
+ with sd_lock:
+ pattern = saveddata_session.query(ImplantSet).options(*eager).filter(TargetResists.name == lookfor).first()
+ else:
+ raise TypeError("Improper argument")
+ return pattern
+
def searchFits(nameLike, where=None, eager=None):
if not isinstance(nameLike, basestring):
raise TypeError("Need string as argument")
diff --git a/eos/effects/addtosignatureradius2.py b/eos/effects/addtosignatureradius2.py
index 01e6cf6c4..797729dff 100644
--- a/eos/effects/addtosignatureradius2.py
+++ b/eos/effects/addtosignatureradius2.py
@@ -2,7 +2,7 @@
#
# Used by:
# Modules from group: Missile Launcher Bomb (2 of 2)
-# Modules from group: Shield Extender (25 of 25)
+# Modules from group: Shield Extender (33 of 33)
type = "passive"
def handler(fit, module, context):
fit.ship.increaseItemAttr("signatureRadius", module.getModifiedItemAttr("signatureRadiusAdd"))
\ No newline at end of file
diff --git a/eos/effects/advanceddroneinterfacingmaxgroupdcuskilllevel.py b/eos/effects/advanceddroneinterfacingmaxgroupdcuskilllevel.py
index 59d80cabd..be2201717 100644
--- a/eos/effects/advanceddroneinterfacingmaxgroupdcuskilllevel.py
+++ b/eos/effects/advanceddroneinterfacingmaxgroupdcuskilllevel.py
@@ -4,5 +4,5 @@
# Skill: Advanced Drone Interfacing
type = "passive"
def handler(fit, skill, context):
- fit.modules.filteredItemIncrease(lambda mod: mod.item.group.name == "Drone Control Unit",
+ fit.modules.filteredItemIncrease(lambda mod: mod.item.group.name == "Fighter Support Unit",
"maxGroupActive", skill.level)
diff --git a/eos/effects/ammofallofmultiplier.py b/eos/effects/ammofallofmultiplier.py
index 9a10c953e..fb82e7f87 100644
--- a/eos/effects/ammofallofmultiplier.py
+++ b/eos/effects/ammofallofmultiplier.py
@@ -1,12 +1,12 @@
# ammoFallofMultiplier
#
# Used by:
-# Charges from group: Advanced Artillery Ammo (6 of 6)
-# Charges from group: Advanced Autocannon Ammo (6 of 6)
-# Charges from group: Advanced Beam Laser Crystal (6 of 6)
-# Charges from group: Advanced Blaster Charge (6 of 6)
-# Charges from group: Advanced Pulse Laser Crystal (6 of 6)
-# Charges from group: Advanced Railgun Charge (6 of 6)
+# Charges from group: Advanced Artillery Ammo (8 of 8)
+# Charges from group: Advanced Autocannon Ammo (8 of 8)
+# Charges from group: Advanced Beam Laser Crystal (8 of 8)
+# Charges from group: Advanced Blaster Charge (8 of 8)
+# Charges from group: Advanced Pulse Laser Crystal (8 of 8)
+# Charges from group: Advanced Railgun Charge (8 of 8)
type = "passive"
def handler(fit, module, context):
module.multiplyItemAttr("falloff", module.getModifiedChargeAttr("fallofMultiplier") or 1)
diff --git a/eos/effects/ammoinfluencecapneed.py b/eos/effects/ammoinfluencecapneed.py
index ea49d1f40..ee58865b7 100644
--- a/eos/effects/ammoinfluencecapneed.py
+++ b/eos/effects/ammoinfluencecapneed.py
@@ -1,7 +1,7 @@
# ammoInfluenceCapNeed
#
# Used by:
-# Items from category: Charge (458 of 851)
+# Items from category: Charge (465 of 884)
type = "passive"
def handler(fit, module, context):
# Dirty hack to work around cap charges setting cap booster
diff --git a/eos/effects/ammoinfluencerange.py b/eos/effects/ammoinfluencerange.py
index 8aae01faa..36a9494de 100644
--- a/eos/effects/ammoinfluencerange.py
+++ b/eos/effects/ammoinfluencerange.py
@@ -1,7 +1,7 @@
# ammoInfluenceRange
#
# Used by:
-# Items from category: Charge (559 of 851)
+# Items from category: Charge (571 of 884)
type = "passive"
def handler(fit, module, context):
module.multiplyItemAttr("maxRange", module.getModifiedChargeAttr("weaponRangeMultiplier"))
\ No newline at end of file
diff --git a/eos/effects/ammotrackingmultiplier.py b/eos/effects/ammotrackingmultiplier.py
index 426aa3e94..6dc7ab4bf 100644
--- a/eos/effects/ammotrackingmultiplier.py
+++ b/eos/effects/ammotrackingmultiplier.py
@@ -1,12 +1,12 @@
# ammoTrackingMultiplier
#
# Used by:
-# Charges from group: Advanced Artillery Ammo (6 of 6)
-# Charges from group: Advanced Autocannon Ammo (6 of 6)
-# Charges from group: Advanced Beam Laser Crystal (6 of 6)
-# Charges from group: Advanced Blaster Charge (6 of 6)
-# Charges from group: Advanced Pulse Laser Crystal (6 of 6)
-# Charges from group: Advanced Railgun Charge (6 of 6)
+# Charges from group: Advanced Artillery Ammo (8 of 8)
+# Charges from group: Advanced Autocannon Ammo (8 of 8)
+# Charges from group: Advanced Beam Laser Crystal (8 of 8)
+# Charges from group: Advanced Blaster Charge (8 of 8)
+# Charges from group: Advanced Pulse Laser Crystal (8 of 8)
+# Charges from group: Advanced Railgun Charge (8 of 8)
# Charges from group: Projectile Ammo (129 of 129)
type = "passive"
def handler(fit, module, context):
diff --git a/eos/effects/angelsetbonus.py b/eos/effects/angelsetbonus.py
index b2e5f449b..711d99c9d 100644
--- a/eos/effects/angelsetbonus.py
+++ b/eos/effects/angelsetbonus.py
@@ -5,7 +5,7 @@
runTime = "early"
type = "passive"
def handler(fit, implant, context):
- fit.implants.filteredItemMultiply(
+ fit.appliedImplants.filteredItemMultiply(
lambda implant: "signatureRadiusBonus" in implant.itemModifiedAttributes and "implantSetAngel" in implant.itemModifiedAttributes,
"signatureRadiusBonus",
implant.getModifiedItemAttr("implantSetAngel"))
\ No newline at end of file
diff --git a/eos/effects/armorhpbonusadd.py b/eos/effects/armorhpbonusadd.py
index a075cb025..51cbd8825 100644
--- a/eos/effects/armorhpbonusadd.py
+++ b/eos/effects/armorhpbonusadd.py
@@ -1,7 +1,7 @@
# armorHPBonusAdd
#
# Used by:
-# Modules from group: Armor Reinforcer (41 of 41)
+# Modules from group: Armor Reinforcer (48 of 48)
type = "passive"
def handler(fit, module, context):
fit.ship.increaseItemAttr("armorHP", module.getModifiedItemAttr("armorHPBonusAdd"))
\ No newline at end of file
diff --git a/eos/effects/armorreinforcermassadd.py b/eos/effects/armorreinforcermassadd.py
index 7a84a3f56..797901683 100644
--- a/eos/effects/armorreinforcermassadd.py
+++ b/eos/effects/armorreinforcermassadd.py
@@ -1,7 +1,7 @@
# armorReinforcerMassAdd
#
# Used by:
-# Modules from group: Armor Reinforcer (41 of 41)
+# Modules from group: Armor Reinforcer (48 of 48)
type = "passive"
def handler(fit, module, context):
fit.ship.increaseItemAttr("mass", module.getModifiedItemAttr("massAddition"))
\ No newline at end of file
diff --git a/eos/effects/armorrepair.py b/eos/effects/armorrepair.py
index 71011a063..02239d859 100644
--- a/eos/effects/armorrepair.py
+++ b/eos/effects/armorrepair.py
@@ -1,7 +1,7 @@
# armorRepair
#
# Used by:
-# Modules from group: Armor Repair Unit (100 of 100)
+# Modules from group: Armor Repair Unit (105 of 105)
runTime = "late"
type = "active"
def handler(fit, module, context):
diff --git a/eos/effects/caldarisetbonus3.py b/eos/effects/caldarisetbonus3.py
index 40aade2ac..a31e831e6 100644
--- a/eos/effects/caldarisetbonus3.py
+++ b/eos/effects/caldarisetbonus3.py
@@ -5,5 +5,5 @@
runTime = "early"
type = "passive"
def handler(fit, implant, context):
- fit.implants.filteredItemMultiply(lambda target: target.item.requiresSkill("Cybernetics"),
+ fit.appliedImplants.filteredItemMultiply(lambda target: target.item.requiresSkill("Cybernetics"),
"scanGravimetricStrengthPercent", implant.getModifiedItemAttr("implantSetCaldariNavy"))
diff --git a/eos/effects/caldarisetlgbonus.py b/eos/effects/caldarisetlgbonus.py
index abf7ecd8e..04d1c6f74 100644
--- a/eos/effects/caldarisetlgbonus.py
+++ b/eos/effects/caldarisetlgbonus.py
@@ -5,5 +5,5 @@
runTime = "early"
type = "passive"
def handler(fit, implant, context):
- fit.implants.filteredItemMultiply(lambda target: target.item.requiresSkill("Cybernetics"),
+ fit.appliedImplants.filteredItemMultiply(lambda target: target.item.requiresSkill("Cybernetics"),
"scanGravimetricStrengthModifier", implant.getModifiedItemAttr("implantSetLGCaldariNavy"))
diff --git a/eos/effects/capacitorcapacitybonus.py b/eos/effects/capacitorcapacitybonus.py
index a5f3846ae..69fd71ab7 100644
--- a/eos/effects/capacitorcapacitybonus.py
+++ b/eos/effects/capacitorcapacitybonus.py
@@ -1,7 +1,7 @@
# capacitorCapacityBonus
#
# Used by:
-# Modules from group: Capacitor Battery (22 of 22)
+# Modules from group: Capacitor Battery (27 of 27)
type = "passive"
def handler(fit, ship, context):
fit.ship.increaseItemAttr("capacitorCapacity", ship.getModifiedItemAttr("capacitorBonus"))
\ No newline at end of file
diff --git a/eos/effects/capacitorcapacitymultiply.py b/eos/effects/capacitorcapacitymultiply.py
index 03c560d55..415fe4abe 100644
--- a/eos/effects/capacitorcapacitymultiply.py
+++ b/eos/effects/capacitorcapacitymultiply.py
@@ -4,7 +4,7 @@
# Modules from group: Capacitor Flux Coil (6 of 6)
# Modules from group: Capacitor Power Relay (20 of 20)
# Modules from group: Power Diagnostic System (23 of 23)
-# Modules from group: Propulsion Module (114 of 114)
+# Modules from group: Propulsion Module (127 of 127)
# Modules from group: Reactor Control Unit (22 of 22)
type = "passive"
def handler(fit, module, context):
diff --git a/eos/effects/carrieramarrarmorenergytransferrange3.py b/eos/effects/carrieramarrarmorenergytransferrange3.py
index cfe150ded..f6d2b174a 100644
--- a/eos/effects/carrieramarrarmorenergytransferrange3.py
+++ b/eos/effects/carrieramarrarmorenergytransferrange3.py
@@ -8,4 +8,4 @@ def handler(fit, ship, context):
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Remote Armor Repair Systems"),
"maxRange", ship.getModifiedItemAttr("carrierAmarrBonus3"), skill="Amarr Carrier")
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Capacitor Emission Systems"),
- "powerTransferRange", ship.getModifiedItemAttr("carrierAmarrBonus3"), skill="Amarr Carrier")
+ "maxRange", ship.getModifiedItemAttr("carrierAmarrBonus3"), skill="Amarr Carrier")
diff --git a/eos/effects/carriercaldarishieldenergytransferrange3.py b/eos/effects/carriercaldarishieldenergytransferrange3.py
index 2e793f111..129c92916 100644
--- a/eos/effects/carriercaldarishieldenergytransferrange3.py
+++ b/eos/effects/carriercaldarishieldenergytransferrange3.py
@@ -9,4 +9,4 @@ def handler(fit, ship, context):
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Shield Emission Systems"),
"maxRange", ship.getModifiedItemAttr("carrierCaldariBonus3"), skill="Caldari Carrier")
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Capacitor Emission Systems"),
- "powerTransferRange", ship.getModifiedItemAttr("carrierCaldariBonus3"), skill="Caldari Carrier")
+ "maxRange", ship.getModifiedItemAttr("carrierCaldariBonus3"), skill="Caldari Carrier")
diff --git a/eos/effects/damagecontrol.py b/eos/effects/damagecontrol.py
index c1cccd267..8ebdda53e 100644
--- a/eos/effects/damagecontrol.py
+++ b/eos/effects/damagecontrol.py
@@ -1,7 +1,8 @@
# damageControl
#
# Used by:
-# Modules from group: Damage Control (17 of 17)
+# Variations of module: Damage Control I (16 of 16)
+# Module: Civilian Damage Control
type = "passive"
def handler(fit, module, context):
for layer, attrPrefix in (('shield', 'shield'), ('armor', 'armor'), ('hull', '')):
diff --git a/eos/effects/drawbackcpuoutput.py b/eos/effects/drawbackcpuoutput.py
index 07320a4d0..9395d7848 100644
--- a/eos/effects/drawbackcpuoutput.py
+++ b/eos/effects/drawbackcpuoutput.py
@@ -1,7 +1,7 @@
# drawbackCPUOutput
#
# Used by:
-# Modules from group: Rig Drones (64 of 64)
+# Modules from group: Rig Drones (58 of 64)
type = "passive"
def handler(fit, module, context):
fit.ship.boostItemAttr("cpuOutput", module.getModifiedItemAttr("drawback"))
\ No newline at end of file
diff --git a/eos/effects/dronedurabilityarmorhpbonus.py b/eos/effects/dronedurabilityarmorhpbonus.py
index 7ca639a8c..a11211e86 100644
--- a/eos/effects/dronedurabilityarmorhpbonus.py
+++ b/eos/effects/dronedurabilityarmorhpbonus.py
@@ -1,7 +1,7 @@
# droneDurabilityArmorHPBonus
#
# Used by:
-# Modules named like: Drone Durability Enhancer (8 of 8)
+# Modules named like: Drone Durability Enhancer (6 of 8)
type = "passive"
def handler(fit, module, context):
fit.drones.filteredItemBoost(lambda drone: drone.item.requiresSkill("Drones"),
diff --git a/eos/effects/dronedurabilityhpbonus.py b/eos/effects/dronedurabilityhpbonus.py
index 3e819288d..617873d03 100644
--- a/eos/effects/dronedurabilityhpbonus.py
+++ b/eos/effects/dronedurabilityhpbonus.py
@@ -1,8 +1,7 @@
# droneDurabilityHPBonus
#
# Used by:
-# Modules named like: Drone Durability Enhancer (8 of 8)
-# Skill: Drone Durability
+# Modules named like: Drone Durability Enhancer (6 of 8)
type = "passive"
def handler(fit, container, context):
level = container.level if "skill" in context else 1
diff --git a/eos/effects/dronedurabilityshieldcapbonus.py b/eos/effects/dronedurabilityshieldcapbonus.py
index 331c4f7ac..1691d8f4b 100644
--- a/eos/effects/dronedurabilityshieldcapbonus.py
+++ b/eos/effects/dronedurabilityshieldcapbonus.py
@@ -1,7 +1,7 @@
# droneDurabilityShieldCapBonus
#
# Used by:
-# Modules named like: Drone Durability Enhancer (8 of 8)
+# Modules named like: Drone Durability Enhancer (6 of 8)
type = "passive"
def handler(fit, module, context):
fit.drones.filteredItemBoost(lambda drone: drone.item.requiresSkill("Drones"),
diff --git a/eos/effects/dronemaxrangebonus.py b/eos/effects/dronemaxrangebonus.py
index 04321cfd3..be1ecde59 100644
--- a/eos/effects/dronemaxrangebonus.py
+++ b/eos/effects/dronemaxrangebonus.py
@@ -1,8 +1,7 @@
# droneMaxRangeBonus
#
# Used by:
-# Modules named like: Drone Scope Chip (8 of 8)
-# Skill: Drone Sharpshooting
+# Modules named like: Drone Scope Chip (6 of 8)
type = "passive"
def handler(fit, container, context):
level = container.level if "skill" in context else 1
diff --git a/eos/effects/dronemaxvelocitybonus.py b/eos/effects/dronemaxvelocitybonus.py
index 8ed627d9a..2e0f310bd 100644
--- a/eos/effects/dronemaxvelocitybonus.py
+++ b/eos/effects/dronemaxvelocitybonus.py
@@ -1,8 +1,7 @@
# droneMaxVelocityBonus
#
# Used by:
-# Modules named like: Drone Speed Augmentor (8 of 8)
-# Skill: Drone Navigation
+# Modules named like: Drone Speed Augmentor (6 of 8)
type = "passive"
def handler(fit, container, context):
level = container.level if "skill" in context else 1
diff --git a/eos/effects/elitebonuscommanddestroyermjfgspool2.py b/eos/effects/elitebonuscommanddestroyermjfgspool2.py
index 6d6fdb6a8..a2f7965a2 100644
--- a/eos/effects/elitebonuscommanddestroyermjfgspool2.py
+++ b/eos/effects/elitebonuscommanddestroyermjfgspool2.py
@@ -1,7 +1,7 @@
# eliteBonusCommandDestroyerMJFGspool2
#
# Used by:
-# Ships from group: Command Destroyers (4 of 4)
+# Ships from group: Command Destroyer (4 of 4)
type = "passive"
def handler(fit, src, context):
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Micro Jump Drive Operation"), "duration", src.getModifiedItemAttr("eliteBonusCommandDestroyer2"), skill="Command Destroyers")
diff --git a/eos/effects/energyneutralizerfalloff.py b/eos/effects/energyneutralizerfalloff.py
index 09d32a941..402f20333 100644
--- a/eos/effects/energyneutralizerfalloff.py
+++ b/eos/effects/energyneutralizerfalloff.py
@@ -1,7 +1,8 @@
# energyNeutralizerFalloff
#
# Used by:
-# Modules from group: Energy Neutralizer (45 of 45)
+# Drones from group: Energy Neutralizer Drone (3 of 3)
+# Modules from group: Energy Neutralizer (51 of 51)
from eos.types import State
type = "active", "projected"
def handler(fit, container, context):
diff --git a/eos/effects/energynosferatufalloff.py b/eos/effects/energynosferatufalloff.py
index f9348baa4..c2c3cecb7 100644
--- a/eos/effects/energynosferatufalloff.py
+++ b/eos/effects/energynosferatufalloff.py
@@ -1,7 +1,7 @@
# energyNosferatuFalloff
#
# Used by:
-# Modules from group: Energy Nosferatu (45 of 45)
+# Modules from group: Energy Nosferatu (51 of 51)
type = "active", "projected"
runTime = "late"
def handler(fit, module, context):
diff --git a/eos/effects/energytransferarraymaxrangebonus.py b/eos/effects/energytransferarraymaxrangebonus.py
index 3ec67bee9..3f1f61456 100644
--- a/eos/effects/energytransferarraymaxrangebonus.py
+++ b/eos/effects/energytransferarraymaxrangebonus.py
@@ -6,4 +6,4 @@
type = "passive"
def handler(fit, ship, context):
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Remote Capacitor Transmitter",
- "powerTransferRange", ship.getModifiedItemAttr("maxRangeBonus2"))
+ "maxRange", ship.getModifiedItemAttr("maxRangeBonus2"))
diff --git a/eos/effects/energyweapondamagemultiply.py b/eos/effects/energyweapondamagemultiply.py
index ab5ae1f9a..6e5c086eb 100644
--- a/eos/effects/energyweapondamagemultiply.py
+++ b/eos/effects/energyweapondamagemultiply.py
@@ -1,7 +1,7 @@
# energyWeaponDamageMultiply
#
# Used by:
-# Modules from group: Heat Sink (18 of 18)
+# Modules from group: Heat Sink (17 of 17)
# Modules named like: QA Multiship Module Players (4 of 4)
# Module: QA Damage Module
type = "passive"
diff --git a/eos/effects/energyweaponspeedmultiply.py b/eos/effects/energyweaponspeedmultiply.py
index da0f1c841..b4cb22ae2 100644
--- a/eos/effects/energyweaponspeedmultiply.py
+++ b/eos/effects/energyweaponspeedmultiply.py
@@ -1,7 +1,7 @@
# energyWeaponSpeedMultiply
#
# Used by:
-# Modules from group: Heat Sink (18 of 18)
+# Modules from group: Heat Sink (17 of 17)
type = "passive"
def handler(fit, module, context):
fit.modules.filteredItemMultiply(lambda mod: mod.item.group.name == "Energy Weapon",
diff --git a/eos/effects/entosisdurationmultiply.py b/eos/effects/entosisdurationmultiply.py
index 0918f2079..b89423f8d 100644
--- a/eos/effects/entosisdurationmultiply.py
+++ b/eos/effects/entosisdurationmultiply.py
@@ -1,11 +1,8 @@
# entosisDurationMultiply
#
# Used by:
-# Ships from group: Carrier (4 of 4)
-# Ships from group: Dreadnought (4 of 4)
# Ships from group: Supercarrier (5 of 5)
-# Ships from group: Titan (4 of 4)
-# Ship: Rorqual
+# Items from market group: Ships > Capital Ships (22 of 32)
type = "passive"
def handler(fit, ship, context):
fit.modules.filteredItemMultiply(lambda mod: mod.item.requiresSkill("Infomorph Psychology"),
diff --git a/eos/effects/ewgroupecmburstmaxrangebonus.py b/eos/effects/ewgroupecmburstmaxrangebonus.py
index 745485285..b41497d46 100644
--- a/eos/effects/ewgroupecmburstmaxrangebonus.py
+++ b/eos/effects/ewgroupecmburstmaxrangebonus.py
@@ -4,5 +4,5 @@
# Implants named like: grade Centurion (10 of 12)
type = "passive"
def handler(fit, implant, context):
- fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Remote ECM Burst",
+ fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Burst Projectors",
"maxRange", implant.getModifiedItemAttr("rangeSkillBonus"))
\ No newline at end of file
diff --git a/eos/effects/federationsetbonus3.py b/eos/effects/federationsetbonus3.py
index aa25dfcc4..b97317b82 100644
--- a/eos/effects/federationsetbonus3.py
+++ b/eos/effects/federationsetbonus3.py
@@ -5,5 +5,5 @@
type = "passive"
runTime = "early"
def handler(fit, implant, context):
- fit.implants.filteredItemMultiply(lambda target: target.item.requiresSkill("Cybernetics"),
+ fit.appliedImplants.filteredItemMultiply(lambda target: target.item.requiresSkill("Cybernetics"),
"scanMagnetometricStrengthPercent", implant.getModifiedItemAttr("implantSetFederationNavy"))
diff --git a/eos/effects/federationsetlgbonus.py b/eos/effects/federationsetlgbonus.py
index 27c320be9..4328417cd 100644
--- a/eos/effects/federationsetlgbonus.py
+++ b/eos/effects/federationsetlgbonus.py
@@ -5,5 +5,5 @@
type = "passive"
runTime = "early"
def handler(fit, implant, context):
- fit.implants.filteredItemMultiply(lambda target: target.item.requiresSkill("Cybernetics"),
+ fit.appliedImplants.filteredItemMultiply(lambda target: target.item.requiresSkill("Cybernetics"),
"scanMagnetometricStrengthModifier", implant.getModifiedItemAttr("implantSetLGFederationNavy"))
diff --git a/eos/effects/fighterabilityattackm.py b/eos/effects/fighterabilityattackm.py
new file mode 100644
index 000000000..dd41d77dc
--- /dev/null
+++ b/eos/effects/fighterabilityattackm.py
@@ -0,0 +1,14 @@
+"""
+Since fighter abilities do not have any sort of item entity in the EVE database, we must derive the abilities from the
+effects, and thus this effect file contains some custom information useful only to fighters.
+"""
+# User-friendly name for the ability
+displayName = "Turret Attack"
+
+# Attribute prefix that this ability targets
+prefix = "fighterAbilityAttackMissile"
+
+type = "active"
+
+def handler(fit, src, context):
+ pass
\ No newline at end of file
diff --git a/eos/effects/fighterabilityecm.py b/eos/effects/fighterabilityecm.py
new file mode 100644
index 000000000..10be84766
--- /dev/null
+++ b/eos/effects/fighterabilityecm.py
@@ -0,0 +1,18 @@
+"""
+Since fighter abilities do not have any sort of item entity in the EVE database, we must derive the abilities from the
+effects, and thus this effect file contains some custom information useful only to fighters.
+"""
+from eos.types import State
+
+# User-friendly name for the ability
+displayName = "ECM"
+
+prefix = "fighterAbilityECM"
+
+type = "projected", "active"
+def handler(fit, module, context):
+ if "projected" not in context: return
+ # jam formula: 1 - (1- (jammer str/ship str))^(# of jam mods with same str))
+ strModifier = 1 - module.getModifiedItemAttr("{}Srength{}".format(prefix, fit.scanType))/fit.scanStrength
+
+ fit.ecmProjectedStr *= strModifier
diff --git a/eos/effects/fighterabilityenergyneutralizer.py b/eos/effects/fighterabilityenergyneutralizer.py
new file mode 100644
index 000000000..2601bc535
--- /dev/null
+++ b/eos/effects/fighterabilityenergyneutralizer.py
@@ -0,0 +1,19 @@
+"""
+Since fighter abilities do not have any sort of item entity in the EVE database, we must derive the abilities from the
+effects, and thus this effect file contains some custom information useful only to fighters.
+"""
+from eos.types import State
+
+# User-friendly name for the ability
+displayName = "Energy Neutralizer"
+
+prefix = "fighterAbilityEnergyNeutralizer"
+
+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")):
+ multiplier = container.amountActive if hasattr(container, "amountActive") else 1
+ amount = container.getModifiedItemAttr("{}Amount".format(prefix))
+ time = container.getModifiedItemAttr("{}Duration".format(prefix))
+ fit.addDrain(time, amount * multiplier, 0)
\ No newline at end of file
diff --git a/eos/effects/fighterabilitylaunchbomb.py b/eos/effects/fighterabilitylaunchbomb.py
new file mode 100644
index 000000000..55e5eca15
--- /dev/null
+++ b/eos/effects/fighterabilitylaunchbomb.py
@@ -0,0 +1,14 @@
+"""
+Since fighter abilities do not have any sort of item entity in the EVE database, we must derive the abilities from the
+effects, and thus this effect file contains some custom information useful only to fighters.
+"""
+# User-friendly name for the ability
+displayName = "Bomb"
+
+# Attribute prefix that this ability targets
+prefix = "fighterAbilityLaunchBomb"
+
+type = "active"
+
+def handler(fit, src, context):
+ pass
\ No newline at end of file
diff --git a/eos/effects/fighterabilitymicrowarpdrive.py b/eos/effects/fighterabilitymicrowarpdrive.py
new file mode 100644
index 000000000..7d5bc13e6
--- /dev/null
+++ b/eos/effects/fighterabilitymicrowarpdrive.py
@@ -0,0 +1,15 @@
+"""
+Since fighter abilities do not have any sort of item entity in the EVE database, we must derive the abilities from the
+effects, and thus this effect file contains some custom information useful only to fighters.
+"""
+# User-friendly name for the ability
+displayName = "Microwarpdrive"
+
+# Is ability applied to the fighter squad as a whole, or per fighter?
+grouped = True
+
+type = "active"
+runTime = "late"
+def handler(fit, module, context):
+ module.boostItemAttr("maxVelocity", module.getModifiedItemAttr("fighterAbilityMicroWarpDriveSpeedBonus"))
+ module.boostItemAttr("signatureRadius", module.getModifiedItemAttr("fighterAbilityMicroWarpDriveSignatureRadiusBonus"), stackingPenalties = True)
\ No newline at end of file
diff --git a/eos/effects/fighterabilitymissiles.py b/eos/effects/fighterabilitymissiles.py
new file mode 100644
index 000000000..16e7ee8b2
--- /dev/null
+++ b/eos/effects/fighterabilitymissiles.py
@@ -0,0 +1,14 @@
+"""
+Since fighter abilities do not have any sort of item entity in the EVE database, we must derive the abilities from the
+effects, and thus this effect file contains some custom information useful only to fighters.
+"""
+# User-friendly name for the ability
+displayName = "Missile Attack"
+
+# Attribute prefix that this ability targets
+prefix = "fighterAbilityMissiles"
+
+type = "active"
+
+def handler(fit, src, context):
+ pass
\ No newline at end of file
diff --git a/eos/effects/fighterabilitystasiswebifier.py b/eos/effects/fighterabilitystasiswebifier.py
new file mode 100644
index 000000000..90da7a4eb
--- /dev/null
+++ b/eos/effects/fighterabilitystasiswebifier.py
@@ -0,0 +1,17 @@
+"""
+Since fighter abilities do not have any sort of item entity in the EVE database, we must derive the abilities from the
+effects, and thus this effect file contains some custom information useful only to fighters.
+"""
+from eos.types import State
+
+# User-friendly name for the ability
+displayName = "Stasis Webifier"
+
+prefix = "fighterAbilityStasisWebifier"
+
+type = "active", "projected"
+
+def handler(fit, src, context):
+ if "projected" not in context: return
+ multiplier = src.amountActive if hasattr(src, "amountActive") else 1
+ fit.ship.boostItemAttr("maxVelocity", src.getModifiedItemAttr("{}SpeedPenalty") * multiplier)
diff --git a/eos/effects/fighterabilitywarpdisruption.py b/eos/effects/fighterabilitywarpdisruption.py
new file mode 100644
index 000000000..8e74b35d7
--- /dev/null
+++ b/eos/effects/fighterabilitywarpdisruption.py
@@ -0,0 +1,16 @@
+"""
+Since fighter abilities do not have any sort of item entity in the EVE database, we must derive the abilities from the
+effects, and thus this effect file contains some custom information useful only to fighters.
+"""
+from eos.types import State
+
+# User-friendly name for the ability
+displayName = "Warp Disruption"
+
+prefix = "fighterAbilityWarpDisruption"
+
+type = "active", "projected"
+
+def handler(fit, src, context):
+ if "projected" not in context: return
+ fit.ship.increaseItemAttr("warpScrambleStatus", src.getModifiedItemAttr("{}PointStrength".format(prefix)))
\ No newline at end of file
diff --git a/eos/effects/fueledarmorrepair.py b/eos/effects/fueledarmorrepair.py
index 39c8bb377..0077e287d 100644
--- a/eos/effects/fueledarmorrepair.py
+++ b/eos/effects/fueledarmorrepair.py
@@ -1,7 +1,7 @@
# fueledArmorRepair
#
# Used by:
-# Modules from group: Fueled Armor Repairer (3 of 3)
+# Modules from group: Ancillary Armor Repairer (4 of 4)
runTime = "late"
type = "active"
def handler(fit, module, context):
diff --git a/eos/effects/fueledshieldboosting.py b/eos/effects/fueledshieldboosting.py
index 128afe13b..da058dfd6 100644
--- a/eos/effects/fueledshieldboosting.py
+++ b/eos/effects/fueledshieldboosting.py
@@ -1,7 +1,7 @@
# fueledShieldBoosting
#
# Used by:
-# Modules from group: Fueled Shield Booster (4 of 4)
+# Modules from group: Ancillary Shield Booster (5 of 5)
runTime = "late"
type = "active"
def handler(fit, module, context):
diff --git a/eos/effects/imperialsetbonus3.py b/eos/effects/imperialsetbonus3.py
index 7c764dcad..d239dcc35 100644
--- a/eos/effects/imperialsetbonus3.py
+++ b/eos/effects/imperialsetbonus3.py
@@ -5,5 +5,5 @@
type = "passive"
runTime = "early"
def handler(fit, implant, context):
- fit.implants.filteredItemMultiply(lambda target: target.item.requiresSkill("Cybernetics"),
+ fit.appliedImplants.filteredItemMultiply(lambda target: target.item.requiresSkill("Cybernetics"),
"scanRadarStrengthPercent", implant.getModifiedItemAttr("implantSetImperialNavy"))
diff --git a/eos/effects/imperialsetlgbonus.py b/eos/effects/imperialsetlgbonus.py
index 6495b9b81..56369bf22 100644
--- a/eos/effects/imperialsetlgbonus.py
+++ b/eos/effects/imperialsetlgbonus.py
@@ -5,5 +5,5 @@
type = "passive"
runTime = "early"
def handler(fit, implant, context):
- fit.implants.filteredItemMultiply(lambda target: target.item.requiresSkill("Cybernetics"),
+ fit.appliedImplants.filteredItemMultiply(lambda target: target.item.requiresSkill("Cybernetics"),
"scanRadarStrengthModifier", implant.getModifiedItemAttr("implantSetLGImperialNavy"))
diff --git a/eos/effects/implantsetwarpspeed.py b/eos/effects/implantsetwarpspeed.py
index a6410ed77..29fd50e49 100644
--- a/eos/effects/implantsetwarpspeed.py
+++ b/eos/effects/implantsetwarpspeed.py
@@ -5,5 +5,5 @@
runTime = "early"
type = "passive"
def handler(fit, implant, context):
- fit.implants.filteredItemMultiply(lambda mod: mod.item.group.name == "Cyberimplant",
+ fit.appliedImplants.filteredItemMultiply(lambda mod: mod.item.group.name == "Cyberimplant",
"WarpSBonus", implant.getModifiedItemAttr("implantSetWarpSpeed"))
diff --git a/eos/effects/industrialcoreeffect2.py b/eos/effects/industrialcoreeffect2.py
index 114f820a2..7bb0909f4 100644
--- a/eos/effects/industrialcoreeffect2.py
+++ b/eos/effects/industrialcoreeffect2.py
@@ -7,4 +7,4 @@ runTime = "early"
def handler(fit, module, context):
fit.extraAttributes["siege"] = True
fit.ship.boostItemAttr("maxVelocity", module.getModifiedItemAttr("speedFactor"))
- fit.ship.multiplyItemAttr("mass", module.getModifiedItemAttr("massMultiplier"))
+ fit.ship.multiplyItemAttr("mass", module.getModifiedItemAttr("siegeMassMultiplier"))
diff --git a/eos/effects/miningdroneoperationminingamountbonuspostpercentminingdroneamountpercentchar.py b/eos/effects/miningdroneoperationminingamountbonuspostpercentminingdroneamountpercentchar.py
index c9d34d4ad..c9074971e 100644
--- a/eos/effects/miningdroneoperationminingamountbonuspostpercentminingdroneamountpercentchar.py
+++ b/eos/effects/miningdroneoperationminingamountbonuspostpercentminingdroneamountpercentchar.py
@@ -2,7 +2,6 @@
#
# Used by:
# Modules named like: Drone Mining Augmentor (8 of 8)
-# Skill: Drone Interfacing
# Skill: Mining Drone Operation
type = "passive"
def handler(fit, container, context):
diff --git a/eos/effects/missileskillrapidlauncherrof.py b/eos/effects/missileskillrapidlauncherrof.py
index dc200dde2..7cba9d32a 100644
--- a/eos/effects/missileskillrapidlauncherrof.py
+++ b/eos/effects/missileskillrapidlauncherrof.py
@@ -1,8 +1,8 @@
# missileSkillRapidLauncherRoF
#
# Used by:
-# Implants named like: Cerebral Accelerator (3 of 3)
# Implants named like: Zainou 'Deadeye' Rapid Launch RL (6 of 6)
+# Implant: Standard Cerebral Accelerator
# Implant: Whelan Machorin's Ballistic Smartlink
# Skill: Missile Launcher Operation
# Skill: Rapid Launch
diff --git a/eos/effects/modifyactivearmorresonancepostpercent.py b/eos/effects/modifyactivearmorresonancepostpercent.py
index 11627846a..3af14f816 100644
--- a/eos/effects/modifyactivearmorresonancepostpercent.py
+++ b/eos/effects/modifyactivearmorresonancepostpercent.py
@@ -2,6 +2,7 @@
#
# Used by:
# Modules from group: Armor Hardener (156 of 156)
+# Modules from group: Flex Armor Hardener (4 of 4)
type = "active"
def handler(fit, module, context):
for damageType in ("kinetic", "thermal", "explosive", "em"):
diff --git a/eos/effects/modifyactiveshieldresonancepostpercent.py b/eos/effects/modifyactiveshieldresonancepostpercent.py
index e79a4e02b..8e78cc539 100644
--- a/eos/effects/modifyactiveshieldresonancepostpercent.py
+++ b/eos/effects/modifyactiveshieldresonancepostpercent.py
@@ -1,6 +1,7 @@
# modifyActiveShieldResonancePostPercent
#
# Used by:
+# Modules from group: Flex Shield Hardener (5 of 5)
# Modules from group: Shield Hardener (97 of 97)
type = "active"
def handler(fit, module, context):
diff --git a/eos/effects/modifyenergywarfareresistance.py b/eos/effects/modifyenergywarfareresistance.py
index c1aa2c7c9..e7aacdb74 100644
--- a/eos/effects/modifyenergywarfareresistance.py
+++ b/eos/effects/modifyenergywarfareresistance.py
@@ -1,7 +1,7 @@
# modifyEnergyWarfareResistance
#
# Used by:
-# Modules from group: Capacitor Battery (22 of 22)
+# Modules from group: Capacitor Battery (27 of 27)
type = "passive"
def handler(fit, module, context):
fit.ship.boostItemAttr("energyWarfareResistance",
diff --git a/eos/effects/modulebonusarmoredwarfarelinkdamagecontrol.py b/eos/effects/modulebonusarmoredwarfarelinkdamagecontrol.py
new file mode 100644
index 000000000..34423fd81
--- /dev/null
+++ b/eos/effects/modulebonusarmoredwarfarelinkdamagecontrol.py
@@ -0,0 +1,12 @@
+# moduleBonusArmoredWarfareLinkDamageControl
+#
+# Used by:
+# Variations of module: Armored Warfare Link - Damage Control I (2 of 2)
+type = "gang", "active"
+gangBoost = "armorRepairCapacitorNeed"
+runTime = "late"
+
+def handler(fit, module, context):
+ if "gang" not in context: return
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Repair Systems") or mod.item.requiresSkill("Remote Armor Repair Systems"),
+ "capacitorNeed", module.getModifiedItemAttr("commandBonus"))
diff --git a/eos/effects/modulebonusarmoredwarfarelinkpassivedefense.py b/eos/effects/modulebonusarmoredwarfarelinkpassivedefense.py
new file mode 100644
index 000000000..7b88f75f3
--- /dev/null
+++ b/eos/effects/modulebonusarmoredwarfarelinkpassivedefense.py
@@ -0,0 +1,14 @@
+# moduleBonusArmoredWarfareLinkPassiveDefense
+#
+# Used by:
+# Variations of module: Armored Warfare Link - Passive Defense I (2 of 2)
+type = "gang", "active"
+gangBoost = "armorResistance"
+runTime = "late"
+
+def handler(fit, module, context):
+ if "gang" not in context: return
+ for damageType in ("Em", "Thermal", "Explosive", "Kinetic"):
+ fit.ship.boostItemAttr("armor%sDamageResonance" % damageType,
+ module.getModifiedItemAttr("commandBonus"),
+ stackingPenalties = True)
diff --git a/eos/effects/modulebonusarmoredwarfarelinkrapidrepair.py b/eos/effects/modulebonusarmoredwarfarelinkrapidrepair.py
new file mode 100644
index 000000000..0817d2204
--- /dev/null
+++ b/eos/effects/modulebonusarmoredwarfarelinkrapidrepair.py
@@ -0,0 +1,12 @@
+# moduleBonusArmoredWarfareLinkRapidRepair
+#
+# Used by:
+# Variations of module: Armored Warfare Link - Rapid Repair I (2 of 2)
+type = "gang", "active"
+gangBoost = "armorRepairDuration"
+runTime = "late"
+
+def handler(fit, module, context):
+ if "gang" not in context: return
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Repair Systems") or mod.item.requiresSkill("Remote Armor Repair Systems"),
+ "duration", module.getModifiedItemAttr("commandBonus"))
diff --git a/eos/effects/modulebonusbastionmodule.py b/eos/effects/modulebonusbastionmodule.py
new file mode 100644
index 000000000..9151b73da
--- /dev/null
+++ b/eos/effects/modulebonusbastionmodule.py
@@ -0,0 +1,69 @@
+# moduleBonusBastionModule
+#
+# Used by:
+# Module: Bastion Module I
+type = "active"
+runTime = "early"
+def handler(fit, src, context):
+ # Resistances
+ for layer, attrPrefix in (('shield', 'shield'), ('armor', 'armor'), ('hull', '')):
+ for damageType in ('Kinetic', 'Thermal', 'Explosive', 'Em'):
+ bonus = "%s%sDamageResonance" % (attrPrefix, damageType)
+ bonus = "%s%s" % (bonus[0].lower(), bonus[1:])
+ booster = "%s%sDamageResonance" % (layer, damageType)
+ penalize = False if layer == 'hull' else True
+ fit.ship.multiplyItemAttr(bonus, src.getModifiedItemAttr(booster),
+ stackingPenalties=penalize, penaltyGroup="preMul")
+
+ # Turrets
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Large Energy Turret") or \
+ mod.item.requiresSkill("Large Hybrid Turret") or \
+ mod.item.requiresSkill("Large Projectile Turret"),
+ "maxRange", src.getModifiedItemAttr("maxRangeBonus"),
+ stackingPenalties=True)
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Large Energy Turret") or \
+ mod.item.requiresSkill("Large Hybrid Turret") or \
+ mod.item.requiresSkill("Large Projectile Turret"),
+ "falloff", src.getModifiedItemAttr("falloffBonus"),
+ stackingPenalties=True)
+
+ # Missiles
+ fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("Torpedoes") or \
+ mod.charge.requiresSkill("Cruise Missiles") or \
+ mod.charge.requiresSkill("Heavy Missiles"),
+ "maxVelocity", src.getModifiedItemAttr("missileVelocityBonus"))
+
+ # Tanking
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Repair Systems"),
+ "armorDamageAmount", src.getModifiedItemAttr("armorDamageAmountBonus"),
+ stackingPenalties=True)
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Shield Operation"),
+ "shieldBonus", src.getModifiedItemAttr("shieldBoostMultiplier"),
+ stackingPenalties=True)
+
+ # Speed penalty
+ fit.ship.boostItemAttr("maxVelocity", src.getModifiedItemAttr("speedFactor"))
+
+ # @todo: test these for April 2016 release
+ # Max locked targets
+ fit.ship.forceItemAttr("maxLockedTargets", src.getModifiedItemAttr("maxLockedTargets"))
+
+ # Block Hostile ewar
+ fit.ship.forceItemAttr("disallowOffensiveModifiers", src.getModifiedItemAttr("disallowOffensiveModifiers"))
+
+ # new with April 2016 release
+ for scanType in ('Magnetometric', 'Ladar', 'Gravimetric', 'Radar'):
+ fit.ship.boostItemAttr("scan{}Strength".format(scanType),
+ src.getModifiedItemAttr("scan{}StrengthPercent".format(scanType)),
+ stackingPenalties=True)
+
+ fit.ship.boostItemAttr("remoteRepairImpedance", src.getModifiedItemAttr("remoteRepairImpedanceBonus"))
+ fit.ship.boostItemAttr("remoteAssistanceImpedance", src.getModifiedItemAttr("remoteAssistanceImpedanceBonus"))
+ fit.ship.boostItemAttr("sensorDampenerResistance", src.getModifiedItemAttr("sensorDampenerResistanceBonus"))
+ fit.modules.filteredItemIncrease(lambda mod: mod.item.requiresSkill("Micro Jump Drive Operation"), "activationBlocked", src.getModifiedItemAttr("activationBlockedStrenght"))
+ fit.ship.boostItemAttr("targetPainterResistance", src.getModifiedItemAttr("targetPainterResistanceBonus"))
+ fit.ship.boostItemAttr("weaponDisruptionResistance", src.getModifiedItemAttr("weaponDisruptionResistanceBonus"))
+ fit.ship.increaseItemAttr("warpScrambleStatus", src.getModifiedItemAttr("siegeModeWarpStatus"))
+
+ fit.ship.forceItemAttr("disallowDocking", src.getModifiedItemAttr("disallowDocking"))
+ fit.ship.forceItemAttr("disallowTethering", src.getModifiedItemAttr("disallowTethering"))
diff --git a/eos/effects/modulebonuscapitaldronedurabilityenhancer.py b/eos/effects/modulebonuscapitaldronedurabilityenhancer.py
new file mode 100644
index 000000000..f8e4a8ab6
--- /dev/null
+++ b/eos/effects/modulebonuscapitaldronedurabilityenhancer.py
@@ -0,0 +1,11 @@
+# moduleBonusCapitalDroneDurabilityEnhancer
+#
+# Used by:
+# Variations of module: Capital Drone Durability Enhancer I (2 of 2)
+type = "passive"
+def handler(fit, src, context):
+ fit.drones.filteredItemBoost(lambda mod: mod.item.requiresSkill("Drones"), "armorHP", src.getModifiedItemAttr("hullHpBonus"))
+ fit.drones.filteredItemBoost(lambda mod: mod.item.requiresSkill("Drones"), "hp", src.getModifiedItemAttr("hullHpBonus"))
+ fit.drones.filteredItemBoost(lambda mod: mod.item.requiresSkill("Drones"), "shieldCapacity", src.getModifiedItemAttr("hullHpBonus"))
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "shieldCapacity", src.getModifiedItemAttr("hullHpBonus"))
+ fit.ship.boostItemAttr("cpuOutput", src.getModifiedItemAttr("drawback"))
diff --git a/eos/effects/modulebonuscapitaldronescopechip.py b/eos/effects/modulebonuscapitaldronescopechip.py
new file mode 100644
index 000000000..03337760f
--- /dev/null
+++ b/eos/effects/modulebonuscapitaldronescopechip.py
@@ -0,0 +1,11 @@
+# moduleBonusCapitalDroneScopeChip
+#
+# Used by:
+# Variations of module: Capital Drone Scope Chip I (2 of 2)
+type = "passive"
+def handler(fit, src, context):
+ fit.drones.filteredItemBoost(lambda mod: mod.item.requiresSkill("Drones"), "maxRange", src.getModifiedItemAttr("rangeSkillBonus"), stackingPenalties=True)
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityMissilesRange", src.getModifiedItemAttr("rangeSkillBonus"), stackingPenalties=True)
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackTurretRangeOptimal", src.getModifiedItemAttr("rangeSkillBonus"), stackingPenalties=True)
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackMissileRangeOptimal", src.getModifiedItemAttr("rangeSkillBonus"), stackingPenalties=True)
+ fit.ship.boostItemAttr("cpuOutput", src.getModifiedItemAttr("drawback"))
diff --git a/eos/effects/modulebonuscapitaldronespeedaugmentor.py b/eos/effects/modulebonuscapitaldronespeedaugmentor.py
new file mode 100644
index 000000000..1fb64a671
--- /dev/null
+++ b/eos/effects/modulebonuscapitaldronespeedaugmentor.py
@@ -0,0 +1,9 @@
+# moduleBonusCapitalDroneSpeedAugmentor
+#
+# Used by:
+# Variations of module: Capital Drone Speed Augmentor I (2 of 2)
+type = "passive"
+def handler(fit, src, context):
+ fit.drones.filteredItemBoost(lambda mod: mod.item.requiresSkill("Drones"), "maxVelocity", src.getModifiedItemAttr("droneMaxVelocityBonus"), stackingPenalties=True)
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "maxVelocity", src.getModifiedItemAttr("droneMaxVelocityBonus"), stackingPenalties=True)
+ fit.ship.boostItemAttr("cpuOutput", src.getModifiedItemAttr("drawback"))
diff --git a/eos/effects/modulebonusdronedamageamplifier.py b/eos/effects/modulebonusdronedamageamplifier.py
new file mode 100644
index 000000000..8d5f03de1
--- /dev/null
+++ b/eos/effects/modulebonusdronedamageamplifier.py
@@ -0,0 +1,10 @@
+# moduleBonusDroneDamageAmplifier
+#
+# Used by:
+# Modules from group: Drone Damage Modules (11 of 11)
+type = "passive"
+def handler(fit, src, context):
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityMissilesDamageMultiplier", src.getModifiedItemAttr("droneDamageBonus"))
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackTurretDamageMultiplier", src.getModifiedItemAttr("droneDamageBonus"))
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackMissileDamageMultiplier", src.getModifiedItemAttr("droneDamageBonus"))
+ fit.drones.filteredItemBoost(lambda mod: mod.item.requiresSkill("Drones"), "damageMultiplier", src.getModifiedItemAttr("droneDamageBonus"), stackingPenalties=True)
diff --git a/eos/effects/modulebonusdronenavigationcomputer.py b/eos/effects/modulebonusdronenavigationcomputer.py
new file mode 100644
index 000000000..6cf0e7122
--- /dev/null
+++ b/eos/effects/modulebonusdronenavigationcomputer.py
@@ -0,0 +1,8 @@
+# moduleBonusDroneNavigationComputer
+#
+# Used by:
+# Modules from group: Drone Navigation Computer (8 of 8)
+type = "passive"
+def handler(fit, src, context):
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "maxVelocity", src.getModifiedItemAttr("speedFactor"), stackingPenalties=True)
+ fit.drones.filteredItemBoost(lambda mod: mod.item.requiresSkill("Drones"), "maxVelocity", src.getModifiedItemAttr("speedFactor"), stackingPenalties=True)
diff --git a/eos/effects/modulebonusfightersupportunit.py b/eos/effects/modulebonusfightersupportunit.py
new file mode 100644
index 000000000..2e1de22d0
--- /dev/null
+++ b/eos/effects/modulebonusfightersupportunit.py
@@ -0,0 +1,12 @@
+# moduleBonusFighterSupportUnit
+#
+# Used by:
+# Modules from group: Fighter Support Unit (8 of 8)
+type = "passive"
+def handler(fit, src, context):
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackMissileDuration", src.getModifiedItemAttr("fighterBonusROFPercent"))
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "shieldRechargeRate", src.getModifiedItemAttr("fighterBonusShieldRechargePercent"))
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityMissilesDuration", src.getModifiedItemAttr("fighterBonusROFPercent"))
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "shieldCapacity", src.getModifiedItemAttr("fighterBonusShieldCapacityPercent"))
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "maxVelocity", src.getModifiedItemAttr("fighterBonusVelocityPercent"), stackingPenalties=True)
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackTurretDuration", src.getModifiedItemAttr("fighterBonusROFPercent"))
diff --git a/eos/effects/modulebonusinformationwarfarelinkelectronicsuperiority.py b/eos/effects/modulebonusinformationwarfarelinkelectronicsuperiority.py
new file mode 100644
index 000000000..1c99889aa
--- /dev/null
+++ b/eos/effects/modulebonusinformationwarfarelinkelectronicsuperiority.py
@@ -0,0 +1,11 @@
+# moduleBonusInformationWarfareLinkElectronicSuperiority
+#
+# Used by:
+# Variations of module: Information Warfare Link - Electronic Superiority I (2 of 2)
+type = "active"
+
+def handler(fit, module, context):
+ module.multiplyItemAttr("commandBonusTD", module.getModifiedItemAttr("commandBonusHidden"))
+ module.multiplyItemAttr("commandBonusECM", module.getModifiedItemAttr("commandBonusHidden"))
+ module.multiplyItemAttr("commandBonusRSD", module.getModifiedItemAttr("commandBonusHidden"))
+ module.multiplyItemAttr("commandBonusTP", module.getModifiedItemAttr("commandBonusHidden"))
diff --git a/eos/effects/modulebonusinformationwarfarelinkreconoperation.py b/eos/effects/modulebonusinformationwarfarelinkreconoperation.py
new file mode 100644
index 000000000..98c23a7f2
--- /dev/null
+++ b/eos/effects/modulebonusinformationwarfarelinkreconoperation.py
@@ -0,0 +1,14 @@
+# moduleBonusInformationWarfareLinkReconOperation
+#
+# Used by:
+# Variations of module: Information Warfare Link - Recon Operation I (2 of 2)
+type = "gang", "active"
+gangBoost = "electronicMaxRange"
+runTime = "late"
+
+def handler(fit, module, context):
+ if "gang" not in context: return
+ groups = ("Target Painter", "Weapon Disruptor", "Sensor Dampener", "ECM", "Burst Jammer")
+ fit.modules.filteredItemBoost(lambda mod: mod.item.group.name in groups,
+ "maxRange", module.getModifiedItemAttr("commandBonus"),
+ stackingPenalties = True)
diff --git a/eos/effects/modulebonusinformationwarfarelinksensorintegrity.py b/eos/effects/modulebonusinformationwarfarelinksensorintegrity.py
new file mode 100644
index 000000000..e85db5c3d
--- /dev/null
+++ b/eos/effects/modulebonusinformationwarfarelinksensorintegrity.py
@@ -0,0 +1,17 @@
+# moduleBonusInformationWarfareLinkSensorIntegrity
+#
+# Used by:
+# Variations of module: Information Warfare Link - Sensor Integrity I (2 of 2)
+type = "gang", "active"
+gangBoost = "maxTargetRange"
+gangBonus = "commandBonus"
+runTime = "late"
+
+def handler(fit, module, context):
+ if "gang" not in context: return
+ fit.ship.boostItemAttr("maxTargetRange", module.getModifiedItemAttr("commandBonus"),
+ stackingPenalties = True)
+ for scanType in ("Gravimetric", "Radar", "Ladar", "Magnetometric"):
+ fit.ship.boostItemAttr("scan%sStrength" % scanType,
+ module.getModifiedItemAttr("commandBonus"),
+ stackingPenalties = True)
diff --git a/eos/effects/modulebonusminingforemanlinkharvestercapacitorefficiency.py b/eos/effects/modulebonusminingforemanlinkharvestercapacitorefficiency.py
new file mode 100644
index 000000000..d86fbfc35
--- /dev/null
+++ b/eos/effects/modulebonusminingforemanlinkharvestercapacitorefficiency.py
@@ -0,0 +1,13 @@
+# moduleBonusMiningForemanLinkHarvesterCapacitorEfficiency
+#
+# Used by:
+# Variations of module: Mining Foreman Link - Harvester Capacitor Efficiency I (2 of 2)
+type = "gang", "active"
+gangBoost = "miningCapacitorNeed"
+def handler(fit, module, context):
+ if "gang" not in context: return
+ groups = ("Mining Laser", "Strip Miner", "Frequency Mining Laser",
+ "Ice Harvester", "Gas Cloud Harvester")
+ fit.modules.filteredItemBoost(lambda mod: mod.item.group.name in groups,
+ "capacitorNeed", module.getModifiedItemAttr("commandBonus"),
+ stackingPenalties = True)
diff --git a/eos/effects/modulebonusminingforemanlinklaseroptimization.py b/eos/effects/modulebonusminingforemanlinklaseroptimization.py
new file mode 100644
index 000000000..a1eb89913
--- /dev/null
+++ b/eos/effects/modulebonusminingforemanlinklaseroptimization.py
@@ -0,0 +1,13 @@
+# moduleBonusMiningForemanLinkLaserOptimization
+#
+# Used by:
+# Variations of module: Mining Foreman Link - Laser Optimization I (2 of 2)
+type = "gang", "active"
+gangBoost = "miningDuration"
+def handler(fit, module, context):
+ if "gang" not in context: return
+ groups = ("Mining Laser", "Strip Miner", "Frequency Mining Laser",
+ "Ice Harvester", "Gas Cloud Harvester")
+ fit.modules.filteredItemBoost(lambda mod: mod.item.group.name in groups,
+ "duration", module.getModifiedItemAttr("commandBonus"),
+ stackingPenalties = True)
diff --git a/eos/effects/modulebonusminingforemanlinkmininglaserfieldenhancement.py b/eos/effects/modulebonusminingforemanlinkmininglaserfieldenhancement.py
new file mode 100644
index 000000000..8d47866bd
--- /dev/null
+++ b/eos/effects/modulebonusminingforemanlinkmininglaserfieldenhancement.py
@@ -0,0 +1,13 @@
+# moduleBonusMiningForemanLinkMiningLaserFieldEnhancement
+#
+# Used by:
+# Variations of module: Mining Foreman Link - Mining Laser Field Enhancement I (2 of 2)
+type = "gang", "active"
+gangBoost = "miningMaxRange"
+def handler(fit, module, context):
+ if "gang" not in context: return
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Gas Cloud Harvesting") or mod.item.requiresSkill("Ice Harvesting") or mod.item.requiresSkill("Mining"),
+ "maxRange", module.getModifiedItemAttr("commandBonus"),
+ stackingPenalties = True)
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("CPU Management"),
+ "surveyScanRange", module.getModifiedItemAttr("commandBonus"))
diff --git a/eos/effects/modulebonusnetworkedsensorarray.py b/eos/effects/modulebonusnetworkedsensorarray.py
new file mode 100644
index 000000000..236b6e6b7
--- /dev/null
+++ b/eos/effects/modulebonusnetworkedsensorarray.py
@@ -0,0 +1,28 @@
+# moduleBonusNetworkedSensorArray
+#
+# Used by:
+# Module: Networked Sensor Array
+type = "active"
+def handler(fit, src, context):
+ fit.ship.increaseItemAttr("maxLockedTargets", src.getModifiedItemAttr("maxLockedTargetsBonus"))
+ fit.ship.multiplyItemAttr("maxTargetRange", src.getModifiedItemAttr("maxTargetRangeMultiplier"), stackingPenalties=True, penaltyGroup="postMul")
+ fit.ship.multiplyItemAttr("scanResolution", src.getModifiedItemAttr("scanResolutionMultiplier"), stackingPenalties=True)
+
+ for scanType in ('Magnetometric', 'Ladar', 'Gravimetric', 'Radar'):
+ fit.ship.boostItemAttr("scan{}Strength".format(scanType),
+ src.getModifiedItemAttr("scan{}StrengthPercent".format(scanType)),
+ stackingPenalties=True)
+
+ # EW cap need increase
+ groups = [
+ 'Burst Jammer',
+ 'Weapon Disruptor',
+ 'ECM',
+ 'Sensor Dampener',
+ 'Target Painter']
+
+ fit.modules.filteredItemBoost(lambda mod: mod.item.group.name in groups or
+ mod.item.requiresSkill("Propulsion Jamming"),
+ "capacitorNeed", src.getModifiedItemAttr("ewCapacitorNeedBonus"))
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Propulsion Jamming"),
+ "capacitorNeed", src.getModifiedItemAttr("ewCapacitorNeedBonus"))
diff --git a/eos/effects/modulebonusomnidirectionaltrackingenhancer.py b/eos/effects/modulebonusomnidirectionaltrackingenhancer.py
new file mode 100644
index 000000000..584de14bf
--- /dev/null
+++ b/eos/effects/modulebonusomnidirectionaltrackingenhancer.py
@@ -0,0 +1,19 @@
+# moduleBonusOmnidirectionalTrackingEnhancer
+#
+# Used by:
+# Modules from group: Drone Tracking Enhancer (10 of 10)
+type = "passive"
+def handler(fit, src, context):
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackMissileExplosionRadius", src.getModifiedItemAttr("aoeCloudSizeBonus"))
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackMissileRangeOptimal", src.getModifiedItemAttr("maxRangeBonus"))
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackTurretRangeFalloff", src.getModifiedItemAttr("falloffBonus"))
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityMissilesExplosionRadius", src.getModifiedItemAttr("aoeCloudSizeBonus"))
+ fit.drones.filteredItemBoost(lambda mod: mod.item.requiresSkill("Drones"), "falloff", src.getModifiedItemAttr("falloffBonus"), stackingPenalties=True)
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackMissileRangeFalloff", src.getModifiedItemAttr("falloffBonus"))
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackTurretTrackingSpeed", src.getModifiedItemAttr("trackingSpeedBonus"))
+ fit.drones.filteredItemBoost(lambda mod: mod.item.requiresSkill("Drones"), "maxRange", src.getModifiedItemAttr("maxRangeBonus"), stackingPenalties=True)
+ fit.drones.filteredItemBoost(lambda mod: mod.item.requiresSkill("Drones"), "trackingSpeed", src.getModifiedItemAttr("trackingSpeedBonus"), stackingPenalties=True)
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackTurretRangeOptimal", src.getModifiedItemAttr("maxRangeBonus"))
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityMissilesExplosionVelocity", src.getModifiedItemAttr("aoeVelocityBonus"))
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackMissileExplosionVelocity", src.getModifiedItemAttr("aoeVelocityBonus"))
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityMissilesRange", src.getModifiedItemAttr("maxRangeBonus"))
diff --git a/eos/effects/modulebonusomnidirectionaltrackinglink.py b/eos/effects/modulebonusomnidirectionaltrackinglink.py
new file mode 100644
index 000000000..c01a82776
--- /dev/null
+++ b/eos/effects/modulebonusomnidirectionaltrackinglink.py
@@ -0,0 +1,19 @@
+# moduleBonusOmnidirectionalTrackingLink
+#
+# Used by:
+# Modules from group: Drone Tracking Modules (10 of 10)
+type = "passive"
+def handler(fit, src, context):
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackTurretRangeFalloff", src.getModifiedItemAttr("falloffBonus"))
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityMissilesExplosionVelocity", src.getModifiedItemAttr("aoeVelocityBonus"))
+ fit.drones.filteredItemBoost(lambda mod: mod.item.requiresSkill("Drones"), "trackingSpeed", src.getModifiedItemAttr("trackingSpeedBonus"), stackingPenalties=True)
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackMissileExplosionRadius", src.getModifiedItemAttr("aoeCloudSizeBonus"))
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackTurretTrackingSpeed", src.getModifiedItemAttr("trackingSpeedBonus"))
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityMissilesExplosionRadius", src.getModifiedItemAttr("aoeCloudSizeBonus"))
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityMissilesRange", src.getModifiedItemAttr("maxRangeBonus"))
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackMissileRangeOptimal", src.getModifiedItemAttr("maxRangeBonus"))
+ fit.drones.filteredItemBoost(lambda mod: mod.item.requiresSkill("Drones"), "falloff", src.getModifiedItemAttr("falloffBonus"), stackingPenalties=True)
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackMissileExplosionVelocity", src.getModifiedItemAttr("aoeVelocityBonus"))
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackMissileRangeFalloff", src.getModifiedItemAttr("falloffBonus"))
+ fit.drones.filteredItemBoost(lambda mod: mod.item.requiresSkill("Drones"), "maxRange", src.getModifiedItemAttr("maxRangeBonus"), stackingPenalties=True)
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackTurretRangeOptimal", src.getModifiedItemAttr("maxRangeBonus"))
diff --git a/eos/effects/modulebonusomnidirectionaltrackinglinkoverload.py b/eos/effects/modulebonusomnidirectionaltrackinglinkoverload.py
new file mode 100644
index 000000000..40cef1df4
--- /dev/null
+++ b/eos/effects/modulebonusomnidirectionaltrackinglinkoverload.py
@@ -0,0 +1,9 @@
+# moduleBonusOmnidirectionalTrackingLinkOverload
+#
+# Used by:
+# Modules from group: Drone Tracking Modules (10 of 10)
+type = "overheat"
+def handler(fit, module, context):
+ module.boostItemAttr("maxRangeBonus", module.getModifiedItemAttr("overloadTrackingModuleStrengthBonus"))
+ module.boostItemAttr("falloffBonus", module.getModifiedItemAttr("overloadTrackingModuleStrengthBonus"))
+ module.boostItemAttr("trackingSpeedBonus", module.getModifiedItemAttr("overloadTrackingModuleStrengthBonus"))
diff --git a/eos/effects/modulebonussiegemodule.py b/eos/effects/modulebonussiegemodule.py
new file mode 100644
index 000000000..b51553ff7
--- /dev/null
+++ b/eos/effects/modulebonussiegemodule.py
@@ -0,0 +1,65 @@
+# moduleBonusSiegeModule
+#
+# Used by:
+# Variations of module: Siege Module I (2 of 2)
+type = "active"
+runTime = "early"
+def handler(fit, src, context):
+ #Turrets
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Energy Turret") or \
+ mod.item.requiresSkill("Capital Hybrid Turret") or \
+ mod.item.requiresSkill("Capital Projectile Turret"),
+ "damageMultiplier", src.getModifiedItemAttr("siegeTurretDamageBonus"))
+
+ #Missiles
+ for type in ("kinetic", "thermal", "explosive", "em"):
+ fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("XL Torpedoes") or \
+ mod.charge.requiresSkill("XL Cruise Missiles") or \
+ mod.charge.requiresSkill("Torpedoes"),
+ "%sDamage" % type, src.getModifiedItemAttr("siegeMissileDamageBonus"))
+
+ # Reppers
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Shield Operation") or \
+ mod.item.requiresSkill("Capital Repair Systems"),
+ "duration", src.getModifiedItemAttr("siegeLocalLogisticsDurationBonus"))
+
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Shield Operation"),
+ "shieldBonus", src.getModifiedItemAttr("siegeLocalLogisticsAmountBonus"),
+ stackingPenalties=True)
+
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Repair Systems"),
+ "armorDamageAmount", src.getModifiedItemAttr("siegeLocalLogisticsAmountBonus"),
+ stackingPenalties=True)
+
+ #Speed penalty
+ fit.ship.boostItemAttr("maxVelocity", src.getModifiedItemAttr("speedFactor"))
+
+ #Mass
+ fit.ship.multiplyItemAttr("mass", src.getModifiedItemAttr("siegeMassMultiplier"),
+ stackingPenalties=True, penaltyGroup="postMul")
+
+ # @ todo: test for April 2016 release
+ #Block Hostile EWAR and friendly effects
+ fit.ship.forceItemAttr("disallowOffensiveModifiers", src.getModifiedItemAttr("disallowOffensiveModifiers"))
+ fit.ship.forceItemAttr("disallowAssistance", src.getModifiedItemAttr("disallowAssistance"))
+
+ # new in April 2016 release
+ for scanType in ('Magnetometric', 'Ladar', 'Gravimetric', 'Radar'):
+ fit.ship.boostItemAttr("scan{}Strength".format(scanType),
+ src.getModifiedItemAttr("scan{}StrengthPercent".format(scanType)),
+ stackingPenalties=True)
+
+ # missile ROF bonus
+ for group in ("Missile Launcher XL Torpedo", "Missile Launcher Rapid Torpedo", "Missile Launcher XL Cruise"):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == group, "speed", src.getModifiedItemAttr("siegeLauncherROFBonus"), stackingPenalties=True)
+
+ fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("Torpedoes"), "maxVelocity", src.getModifiedItemAttr("siegeTorpedoVelocityBonus"), stackingPenalties=True)
+
+ fit.ship.increaseItemAttr("warpScrambleStatus", src.getModifiedItemAttr("siegeModeWarpStatus"))
+ fit.ship.boostItemAttr("remoteRepairImpedance", src.getModifiedItemAttr("remoteRepairImpedanceBonus"))
+ fit.ship.boostItemAttr("sensorDampenerResistance", src.getModifiedItemAttr("sensorDampenerResistanceBonus"))
+ fit.ship.boostItemAttr("remoteAssistanceImpedance", src.getModifiedItemAttr("remoteAssistanceImpedanceBonus"))
+ fit.ship.boostItemAttr("weaponDisruptionResistance", src.getModifiedItemAttr("weaponDisruptionResistanceBonus"))
+
+ fit.ship.forceItemAttr("disallowDocking", src.getModifiedItemAttr("disallowDocking"))
+ fit.ship.forceItemAttr("disallowTethering", src.getModifiedItemAttr("disallowTethering"))
diff --git a/eos/effects/modulebonussiegewarfarelinkactiveshielding.py b/eos/effects/modulebonussiegewarfarelinkactiveshielding.py
new file mode 100644
index 000000000..0719d3c71
--- /dev/null
+++ b/eos/effects/modulebonussiegewarfarelinkactiveshielding.py
@@ -0,0 +1,12 @@
+# moduleBonusSiegeWarfareLinkActiveShielding
+#
+# Used by:
+# Variations of module: Siege Warfare Link - Active Shielding I (2 of 2)
+type = "gang", "active"
+gangBoost = "shieldRepairDuration"
+runTime = "late"
+
+def handler(fit, module, context):
+ if "gang" not in context: return
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Shield Operation") or mod.item.requiresSkill("Shield Emission Systems"),
+ "duration", module.getModifiedItemAttr("commandBonus"))
diff --git a/eos/effects/modulebonussiegewarfarelinkshieldefficiency.py b/eos/effects/modulebonussiegewarfarelinkshieldefficiency.py
new file mode 100644
index 000000000..adc1f6e08
--- /dev/null
+++ b/eos/effects/modulebonussiegewarfarelinkshieldefficiency.py
@@ -0,0 +1,14 @@
+# moduleBonusSiegeWarfareLinkShieldEfficiency
+#
+# Used by:
+# Variations of module: Siege Warfare Link - Shield Efficiency I (2 of 2)
+type = "gang", "active"
+gangBoost = "shieldResistance"
+runTime = "late"
+
+def handler(fit, module, context):
+ if "gang" not in context: return
+ for damageType in ("Em", "Explosive", "Thermal", "Kinetic"):
+ fit.ship.boostItemAttr("shield%sDamageResonance" % damageType,
+ module.getModifiedItemAttr("commandBonus"),
+ stackingPenalties = True)
diff --git a/eos/effects/modulebonussiegewarfarelinkshieldharmonizing.py b/eos/effects/modulebonussiegewarfarelinkshieldharmonizing.py
new file mode 100644
index 000000000..229431f8b
--- /dev/null
+++ b/eos/effects/modulebonussiegewarfarelinkshieldharmonizing.py
@@ -0,0 +1,12 @@
+# moduleBonusSiegeWarfareLinkShieldHarmonizing
+#
+# Used by:
+# Variations of module: Siege Warfare Link - Shield Harmonizing I (2 of 2)
+type = "gang", "active"
+gangBoost = "shieldRepairCapacitorNeed"
+runTime = "late"
+
+def handler(fit, module, context):
+ if "gang" not in context: return
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Shield Operation") or mod.item.requiresSkill("Shield Emission Systems"),
+ "capacitorNeed", module.getModifiedItemAttr("commandBonus"))
diff --git a/eos/effects/modulebonusskirmishwarfarelinkevasivemaneuvers.py b/eos/effects/modulebonusskirmishwarfarelinkevasivemaneuvers.py
new file mode 100644
index 000000000..8e93481a8
--- /dev/null
+++ b/eos/effects/modulebonusskirmishwarfarelinkevasivemaneuvers.py
@@ -0,0 +1,12 @@
+# moduleBonusSkirmishWarfareLinkEvasiveManeuvers
+#
+# Used by:
+# Variations of module: Skirmish Warfare Link - Evasive Maneuvers I (2 of 2)
+type = "gang", "active"
+gangBoost = "signatureRadius"
+runTime = "late"
+
+def handler(fit, module, context):
+ if "gang" not in context: return
+ fit.ship.boostItemAttr("signatureRadius", module.getModifiedItemAttr("commandBonus"),
+ stackingPenalties = True)
diff --git a/eos/effects/modulebonusskirmishwarfarelinkinterdictionmaneuvers.py b/eos/effects/modulebonusskirmishwarfarelinkinterdictionmaneuvers.py
new file mode 100644
index 000000000..60c868d56
--- /dev/null
+++ b/eos/effects/modulebonusskirmishwarfarelinkinterdictionmaneuvers.py
@@ -0,0 +1,14 @@
+# moduleBonusSkirmishWarfareLinkInterdictionManeuvers
+#
+# Used by:
+# Variations of module: Skirmish Warfare Link - Interdiction Maneuvers I (2 of 2)
+type = "gang", "active"
+gangBoost = "interdictionMaxRange"
+runTime = "late"
+
+def handler(fit, module, context):
+ if "gang" not in context: return
+ groups = ("Stasis Web", "Warp Scrambler")
+ fit.modules.filteredItemBoost(lambda mod: mod.item.group.name in groups,
+ "maxRange", module.getModifiedItemAttr("commandBonus"),
+ stackingPenalties = True)
diff --git a/eos/effects/modulebonusskirmishwarfarelinkrapiddeployment.py b/eos/effects/modulebonusskirmishwarfarelinkrapiddeployment.py
new file mode 100644
index 000000000..aae691cd6
--- /dev/null
+++ b/eos/effects/modulebonusskirmishwarfarelinkrapiddeployment.py
@@ -0,0 +1,13 @@
+# moduleBonusSkirmishWarfareLinkRapidDeployment
+#
+# Used by:
+# Variations of module: Skirmish Warfare Link - Rapid Deployment I (2 of 2)
+type = "gang", "active"
+gangBoost = "speedFactor"
+runTime = "late"
+
+def handler(fit, module, context):
+ if "gang" not in context: return
+ fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Propulsion Module",
+ "speedFactor", module.getModifiedItemAttr("commandBonus"),
+ stackingPenalties=True)
diff --git a/eos/effects/modulebonustriagemodule.py b/eos/effects/modulebonustriagemodule.py
new file mode 100644
index 000000000..704348e25
--- /dev/null
+++ b/eos/effects/modulebonustriagemodule.py
@@ -0,0 +1,74 @@
+# moduleBonusTriageModule
+#
+# Used by:
+# Variations of module: Triage Module I (2 of 2)
+type = "active"
+runTime = "early"
+def handler(fit, src, context):
+ # Remote effect bonuses (duration / amount / range / fallout)
+ for skill, amtAttr, stack in (
+ ("Capital Remote Armor Repair Systems", "armorDamageAmount", True),
+ ("Capital Shield Emission Systems", "shieldBonus", True),
+ ("Capital Capacitor Emission Systems", "powerTransferAmount", False),
+ ("Capital Remote Hull Repair Systems", "structureDamageAmount", False)):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill(skill), "duration", src.getModifiedItemAttr("siegeRemoteLogisticsDurationBonus"))
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill(skill), amtAttr, src.getModifiedItemAttr("siegeRemoteLogisticsAmountBonus"), stackingPenalties=stack)
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill(skill), "maxRange", src.getModifiedItemAttr("siegeRemoteLogisticsRangeBonus"), stackingPenalties=True)
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill(skill), "falloffEffectiveness", src.getModifiedItemAttr("siegeRemoteLogisticsRangeBonus"), stackingPenalties=True)
+
+ # Local armor/shield rep effects (duration / amoutn)
+ for skill, amtAttr in (
+ ("Capital Shield Operation", "shieldBonus"),
+ ("Capital Repair Systems", "armorDamageAmount")):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill(skill), "duration", src.getModifiedItemAttr("siegeLocalLogisticsDurationBonus"))
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill(skill), amtAttr, src.getModifiedItemAttr("siegeLocalLogisticsAmountBonus"))
+
+
+ # Speed bonus
+ fit.ship.boostItemAttr("maxVelocity", src.getModifiedItemAttr("speedFactor"), stackingPenalties=True)
+
+ # Scan resolution multiplier
+ fit.ship.multiplyItemAttr("scanResolution", src.getModifiedItemAttr("scanResolutionMultiplier"), stackingPenalties=True)
+
+ # Mass multiplier
+ fit.ship.multiplyItemAttr("mass", src.getModifiedItemAttr("siegeMassMultiplier"), stackingPenalties=True)
+
+ # Max locked targets
+ fit.ship.increaseItemAttr("maxLockedTargets", src.getModifiedItemAttr("maxLockedTargetsBonus"))
+
+
+ # EW cap need increase
+ groups = [
+ 'Burst Jammer',
+ 'Weapon Disruptor',
+ 'ECM',
+ 'Sensor Dampener',
+ 'Target Painter']
+
+ fit.modules.filteredItemBoost(lambda mod: mod.item.group.name in groups or
+ mod.item.requiresSkill("Propulsion Jamming"),
+ "capacitorNeed", src.getModifiedItemAttr("ewCapacitorNeedBonus"))
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Propulsion Jamming"),
+ "capacitorNeed", src.getModifiedItemAttr("ewCapacitorNeedBonus"))
+
+ # todo: test for April 2016 release
+ # Block EWAR & projected effects
+ fit.ship.forceItemAttr("disallowOffensiveModifiers", src.getModifiedItemAttr("disallowOffensiveModifiers"))
+ fit.ship.forceItemAttr("disallowAssistance", src.getModifiedItemAttr("disallowAssistance"))
+
+ # new in April 2016 release
+
+ for scanType in ('Magnetometric', 'Ladar', 'Gravimetric', 'Radar'):
+ fit.ship.boostItemAttr("scan{}Strength".format(scanType),
+ src.getModifiedItemAttr("scan{}StrengthPercent".format(scanType)),
+ stackingPenalties=True)
+
+ fit.drones.filteredItemBoost(lambda mod: mod.item.requiresSkill("Drones"), "damageMultiplier", src.getModifiedItemAttr("droneDamageBonus"), stackingPenalties=True)
+
+ fit.ship.increaseItemAttr("warpScrambleStatus", src.getModifiedItemAttr("siegeModeWarpStatus"))
+ fit.ship.boostItemAttr("sensorDampenerResistance", src.getModifiedItemAttr("sensorDampenerResistanceBonus"))
+ fit.ship.boostItemAttr("remoteAssistanceImpedance", src.getModifiedItemAttr("remoteAssistanceImpedanceBonus"))
+ fit.ship.boostItemAttr("remoteRepairImpedance", src.getModifiedItemAttr("remoteRepairImpedanceBonus"))
+
+ fit.ship.forceItemAttr("disallowTethering", src.getModifiedItemAttr("disallowTethering"))
+ fit.ship.forceItemAttr("disallowDocking", src.getModifiedItemAttr("disallowDocking"))
diff --git a/eos/effects/mwdsignatureradiusrolebonus.py b/eos/effects/mwdsignatureradiusrolebonus.py
index b160c5b28..ff3fd7530 100644
--- a/eos/effects/mwdsignatureradiusrolebonus.py
+++ b/eos/effects/mwdsignatureradiusrolebonus.py
@@ -2,6 +2,7 @@
#
# Used by:
# Ships from group: Assault Frigate (8 of 12)
+# Ships from group: Command Destroyer (4 of 4)
# Ships from group: Heavy Assault Cruiser (8 of 11)
type = "passive"
def handler(fit, ship, context):
diff --git a/eos/effects/overloadrofbonus.py b/eos/effects/overloadrofbonus.py
index fd8623e2b..8da5776ab 100644
--- a/eos/effects/overloadrofbonus.py
+++ b/eos/effects/overloadrofbonus.py
@@ -2,7 +2,7 @@
#
# Used by:
# Modules from group: Missile Launcher Torpedo (22 of 22)
-# Items from market group: Ship Equipment > Turrets & Bays (397 of 767)
+# Items from market group: Ship Equipment > Turrets & Bays (428 of 848)
# Module: Interdiction Sphere Launcher I
type = "overheat"
def handler(fit, module, context):
diff --git a/eos/effects/overloadselfarmordamageamountdurationbonus.py b/eos/effects/overloadselfarmordamageamountdurationbonus.py
index 94bad3995..edf684b56 100644
--- a/eos/effects/overloadselfarmordamageamountdurationbonus.py
+++ b/eos/effects/overloadselfarmordamageamountdurationbonus.py
@@ -1,8 +1,8 @@
# overloadSelfArmorDamageAmountDurationBonus
#
# Used by:
-# Modules from group: Armor Repair Unit (100 of 100)
-# Modules from group: Fueled Armor Repairer (3 of 3)
+# Modules from group: Ancillary Armor Repairer (4 of 4)
+# Modules from group: Armor Repair Unit (105 of 105)
type = "overheat"
def handler(fit, module, context):
module.boostItemAttr("duration", module.getModifiedItemAttr("overloadSelfDurationBonus"))
diff --git a/eos/effects/overloadselfdamagebonus.py b/eos/effects/overloadselfdamagebonus.py
index 2e46fe1ec..305e9d3d5 100644
--- a/eos/effects/overloadselfdamagebonus.py
+++ b/eos/effects/overloadselfdamagebonus.py
@@ -1,9 +1,9 @@
# overloadSelfDamageBonus
#
# Used by:
-# Modules from group: Energy Weapon (86 of 187)
-# Modules from group: Hybrid Weapon (92 of 202)
-# Modules from group: Projectile Weapon (86 of 146)
+# Modules from group: Energy Weapon (102 of 209)
+# Modules from group: Hybrid Weapon (106 of 221)
+# Modules from group: Projectile Weapon (100 of 165)
type = "overheat"
def handler(fit, module, context):
module.boostItemAttr("damageMultiplier", module.getModifiedItemAttr("overloadDamageModifier"))
\ No newline at end of file
diff --git a/eos/effects/overloadselfdurationbonus.py b/eos/effects/overloadselfdurationbonus.py
index 984b06639..e9ddd0596 100644
--- a/eos/effects/overloadselfdurationbonus.py
+++ b/eos/effects/overloadselfdurationbonus.py
@@ -1,15 +1,16 @@
# overloadSelfDurationBonus
#
# Used by:
-# Modules from group: Capacitor Booster (54 of 54)
-# Modules from group: Energy Neutralizer (45 of 45)
-# Modules from group: Energy Nosferatu (45 of 45)
-# Modules from group: Hull Repair Unit (21 of 21)
-# Modules from group: Remote Armor Repairer (33 of 33)
-# Modules from group: Remote Capacitor Transmitter (38 of 38)
-# Modules from group: Remote Shield Booster (31 of 31)
+# Modules from group: Capacitor Booster (59 of 59)
+# Modules from group: Energy Neutralizer (51 of 51)
+# Modules from group: Energy Nosferatu (51 of 51)
+# Modules from group: Hull Repair Unit (25 of 25)
+# Modules from group: Remote Armor Repairer (39 of 39)
+# Modules from group: Remote Capacitor Transmitter (41 of 41)
+# Modules from group: Remote Shield Booster (38 of 38)
# Modules from group: Smart Bomb (118 of 118)
# Modules from group: Warp Disrupt Field Generator (7 of 7)
+# Modules named like: Ancillary Remote (8 of 8)
# Module: QA Remote Armor Repair System - 5 Players
# Module: QA Shield Transporter - 5 Players
# Module: Reactive Armor Hardener
diff --git a/eos/effects/overloadselfhardeninginvulnerabilitybonus.py b/eos/effects/overloadselfhardeninginvulnerabilitybonus.py
index 6251f1fa2..c044987b2 100644
--- a/eos/effects/overloadselfhardeninginvulnerabilitybonus.py
+++ b/eos/effects/overloadselfhardeninginvulnerabilitybonus.py
@@ -1,6 +1,7 @@
# overloadSelfHardeningInvulnerabilityBonus
#
# Used by:
+# Modules named like: Capital Flex Hardener (9 of 9)
# Variations of module: Adaptive Invulnerability Field I (17 of 17)
type = "overheat"
def handler(fit, module, context):
diff --git a/eos/effects/overloadselfrangebonus.py b/eos/effects/overloadselfrangebonus.py
index 9250b48c0..eb2b4e370 100644
--- a/eos/effects/overloadselfrangebonus.py
+++ b/eos/effects/overloadselfrangebonus.py
@@ -3,7 +3,7 @@
# Used by:
# Modules from group: Stasis Grappler (7 of 7)
# Modules from group: Stasis Web (18 of 18)
-# Modules from group: Warp Scrambler (38 of 39)
+# Modules from group: Warp Scrambler (52 of 53)
type = "overheat"
def handler(fit, module, context):
module.boostItemAttr("maxRange", module.getModifiedItemAttr("overloadRangeBonus"),
diff --git a/eos/effects/overloadselfshieldbonusdurationbonus.py b/eos/effects/overloadselfshieldbonusdurationbonus.py
index daf8ebbc1..05d89029d 100644
--- a/eos/effects/overloadselfshieldbonusdurationbonus.py
+++ b/eos/effects/overloadselfshieldbonusdurationbonus.py
@@ -1,8 +1,8 @@
# overloadSelfShieldBonusDurationBonus
#
# Used by:
-# Modules from group: Fueled Shield Booster (4 of 4)
-# Modules from group: Shield Booster (87 of 87)
+# Modules from group: Ancillary Shield Booster (5 of 5)
+# Modules from group: Shield Booster (93 of 93)
type = "overheat"
def handler(fit, module, context):
module.boostItemAttr("duration", module.getModifiedItemAttr("overloadSelfDurationBonus"))
diff --git a/eos/effects/overloadselfspeedbonus.py b/eos/effects/overloadselfspeedbonus.py
index 53d17411a..7b5d7bb5a 100644
--- a/eos/effects/overloadselfspeedbonus.py
+++ b/eos/effects/overloadselfspeedbonus.py
@@ -1,7 +1,7 @@
# overloadSelfSpeedBonus
#
# Used by:
-# Modules from group: Propulsion Module (114 of 114)
+# Modules from group: Propulsion Module (127 of 127)
type = "overheat"
def handler(fit, module, context):
module.boostItemAttr("speedFactor", module.getModifiedItemAttr("overloadSpeedFactorBonus"),
diff --git a/eos/effects/overloadselftrackingmodulebonus.py b/eos/effects/overloadselftrackingmodulebonus.py
index 8269d377f..bb7c7481b 100644
--- a/eos/effects/overloadselftrackingmodulebonus.py
+++ b/eos/effects/overloadselftrackingmodulebonus.py
@@ -1,7 +1,6 @@
# overloadSelfTrackingModuleBonus
#
# Used by:
-# Modules from group: Drone Tracking Modules (10 of 10)
# Modules named like: Tracking Computer (19 of 19)
# Variations of module: Tracking Disruptor I (6 of 6)
type = "overheat"
diff --git a/eos/effects/powerbooster.py b/eos/effects/powerbooster.py
index e296461ba..6f23f7df3 100644
--- a/eos/effects/powerbooster.py
+++ b/eos/effects/powerbooster.py
@@ -1,7 +1,7 @@
# powerBooster
#
# Used by:
-# Modules from group: Capacitor Booster (54 of 54)
+# Modules from group: Capacitor Booster (59 of 59)
type = "active"
def handler(fit, module, context):
# Set reload time to 10 seconds
diff --git a/eos/effects/projectilefired.py b/eos/effects/projectilefired.py
index 63c4927a7..0de9601c2 100644
--- a/eos/effects/projectilefired.py
+++ b/eos/effects/projectilefired.py
@@ -1,8 +1,8 @@
# projectileFired
#
# Used by:
-# Modules from group: Hybrid Weapon (202 of 202)
-# Modules from group: Projectile Weapon (146 of 146)
+# Modules from group: Hybrid Weapon (221 of 221)
+# Modules from group: Projectile Weapon (165 of 165)
type = 'active'
def handler(fit, module, context):
rt = module.getModifiedItemAttr("reloadTime")
diff --git a/eos/effects/remotearmorrepairfalloff.py b/eos/effects/remotearmorrepairfalloff.py
index ed5b38969..01ebfd10f 100644
--- a/eos/effects/remotearmorrepairfalloff.py
+++ b/eos/effects/remotearmorrepairfalloff.py
@@ -1,7 +1,8 @@
# remoteArmorRepairFalloff
#
# Used by:
-# Modules from group: Remote Armor Repairer (33 of 33)
+# Modules from group: Remote Armor Repairer (39 of 39)
+# Drones named like: Armor Maintenance Bot (6 of 6)
type = "projected", "active"
def handler(fit, container, context):
if "projected" in context:
diff --git a/eos/effects/remoteecmburst.py b/eos/effects/remoteecmburst.py
index ac25f0e7d..cd54b4cbc 100644
--- a/eos/effects/remoteecmburst.py
+++ b/eos/effects/remoteecmburst.py
@@ -1,7 +1,7 @@
# remoteEcmBurst
#
# Used by:
-# Module: Remote ECM Burst I
+# Module: ECM Jammer Burst Projector
type = 'active'
def handler(fit, module, context):
pass
diff --git a/eos/effects/remoteenergytransferfalloff.py b/eos/effects/remoteenergytransferfalloff.py
new file mode 100644
index 000000000..abdece325
--- /dev/null
+++ b/eos/effects/remoteenergytransferfalloff.py
@@ -0,0 +1,10 @@
+# remoteEnergyTransferFalloff
+#
+# Used by:
+# Modules from group: Remote Capacitor Transmitter (41 of 41)
+type = "projected", "active"
+def handler(fit, module, context):
+ if "projected" in context:
+ amount = module.getModifiedItemAttr("maxRange")
+ duration = module.getModifiedItemAttr("duration")
+ fit.addDrain(duration, -amount, 0)
diff --git a/eos/effects/remotehullrepairfalloff.py b/eos/effects/remotehullrepairfalloff.py
index 99b1adc55..41ccddae1 100644
--- a/eos/effects/remotehullrepairfalloff.py
+++ b/eos/effects/remotehullrepairfalloff.py
@@ -1,7 +1,8 @@
# remoteHullRepairFalloff
#
# Used by:
-# Modules from group: Remote Hull Repairer (7 of 7)
+# Modules from group: Remote Hull Repairer (8 of 8)
+# Drones named like: Hull Maintenance Bot (6 of 6)
type = "projected", "active"
runTime = "late"
def handler(fit, module, context):
diff --git a/eos/effects/remotesensordampfalloff.py b/eos/effects/remotesensordampfalloff.py
index a1ac27bd9..aa944bb19 100644
--- a/eos/effects/remotesensordampfalloff.py
+++ b/eos/effects/remotesensordampfalloff.py
@@ -2,6 +2,7 @@
#
# Used by:
# Modules from group: Sensor Dampener (6 of 6)
+# Drones named like: SD (3 of 3)
type= "projected", "active"
def handler(fit, module, context):
if "projected" not in context:
diff --git a/eos/effects/remoteshieldtransferfalloff.py b/eos/effects/remoteshieldtransferfalloff.py
index 2bf11e9d6..883341859 100644
--- a/eos/effects/remoteshieldtransferfalloff.py
+++ b/eos/effects/remoteshieldtransferfalloff.py
@@ -1,7 +1,8 @@
# remoteShieldTransferFalloff
#
# Used by:
-# Modules from group: Remote Shield Booster (31 of 31)
+# Modules from group: Remote Shield Booster (38 of 38)
+# Drones named like: Shield Maintenance Bot (6 of 6)
type = "projected", "active"
def handler(fit, container, context):
if "projected" in context:
diff --git a/eos/effects/remotetargetpaintfalloff.py b/eos/effects/remotetargetpaintfalloff.py
index 9d4e31a4a..feb722b42 100644
--- a/eos/effects/remotetargetpaintfalloff.py
+++ b/eos/effects/remotetargetpaintfalloff.py
@@ -2,6 +2,7 @@
#
# Used by:
# Modules from group: Target Painter (8 of 8)
+# Drones named like: TP (3 of 3)
type = "projected", "active"
def handler(fit, container, context):
if "projected" in context:
diff --git a/eos/effects/remotetrackingdisruptfalloff.py b/eos/effects/remotetrackingdisruptfalloff.py
index 25c507841..05e193603 100644
--- a/eos/effects/remotetrackingdisruptfalloff.py
+++ b/eos/effects/remotetrackingdisruptfalloff.py
@@ -1,6 +1,7 @@
# remoteTrackingDisruptFalloff
#
# Used by:
+# Drones named like: TD (3 of 3)
# Variations of module: Tracking Disruptor I (6 of 6)
type= "projected", "active"
def handler(fit, module, context):
diff --git a/eos/effects/remotewebifierfalloff.py b/eos/effects/remotewebifierfalloff.py
index a2e3e9cda..76d932c70 100644
--- a/eos/effects/remotewebifierfalloff.py
+++ b/eos/effects/remotewebifierfalloff.py
@@ -1,6 +1,7 @@
# remoteWebifierFalloff
#
# Used by:
+# Drones from group: Stasis Webifying Drone (3 of 3)
# Modules from group: Stasis Grappler (7 of 7)
# Modules from group: Stasis Web (18 of 18)
type = "active", "projected"
diff --git a/eos/effects/republicsetbonus3.py b/eos/effects/republicsetbonus3.py
index 1f3cad903..5709959ae 100644
--- a/eos/effects/republicsetbonus3.py
+++ b/eos/effects/republicsetbonus3.py
@@ -5,5 +5,5 @@
runTime = "early"
type = "passive"
def handler(fit, implant, context):
- fit.implants.filteredItemMultiply(lambda target: target.item.requiresSkill("Cybernetics"),
+ fit.appliedImplants.filteredItemMultiply(lambda target: target.item.requiresSkill("Cybernetics"),
"scanLadarStrengthPercent", implant.getModifiedItemAttr("implantSetRepublicFleet"))
diff --git a/eos/effects/republicsetlgbonus.py b/eos/effects/republicsetlgbonus.py
index a80ae38e7..bf79499ea 100644
--- a/eos/effects/republicsetlgbonus.py
+++ b/eos/effects/republicsetlgbonus.py
@@ -5,5 +5,5 @@
runTime = "early"
type = "passive"
def handler(fit, implant, context):
- fit.implants.filteredItemMultiply(lambda target: target.item.requiresSkill("Cybernetics"),
+ fit.appliedImplants.filteredItemMultiply(lambda target: target.item.requiresSkill("Cybernetics"),
"scanLadarStrengthModifier", implant.getModifiedItemAttr("implantSetLGRepublicFleet"))
diff --git a/eos/effects/rolebonuscdlinkspgreduction.py b/eos/effects/rolebonuscdlinkspgreduction.py
index bfbc05f26..423f28aa2 100644
--- a/eos/effects/rolebonuscdlinkspgreduction.py
+++ b/eos/effects/rolebonuscdlinkspgreduction.py
@@ -1,7 +1,7 @@
# roleBonusCDLinksPGReduction
#
# Used by:
-# Ships from group: Command Destroyers (4 of 4)
+# Ships from group: Command Destroyer (4 of 4)
type = "passive"
def handler(fit, src, context):
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Leadership"), "power", src.getModifiedItemAttr("roleBonusCD"))
diff --git a/eos/effects/scriptmissileguidancecomputeraoecloudsizebonusbonus.py b/eos/effects/scriptmissileguidancecomputeraoecloudsizebonusbonus.py
index c97e060f7..e8b09cedb 100644
--- a/eos/effects/scriptmissileguidancecomputeraoecloudsizebonusbonus.py
+++ b/eos/effects/scriptmissileguidancecomputeraoecloudsizebonusbonus.py
@@ -1,6 +1,7 @@
# scriptMissileGuidanceComputerAOECloudSizeBonusBonus
#
# Used by:
+# Charges from group: Tracking Script (2 of 2)
# Charges named like: Missile Script (4 of 4)
type = "passive"
def handler(fit, module, context):
diff --git a/eos/effects/scriptmissileguidancecomputeraoevelocitybonusbonus.py b/eos/effects/scriptmissileguidancecomputeraoevelocitybonusbonus.py
index 0f7d96734..514cc0077 100644
--- a/eos/effects/scriptmissileguidancecomputeraoevelocitybonusbonus.py
+++ b/eos/effects/scriptmissileguidancecomputeraoevelocitybonusbonus.py
@@ -1,6 +1,7 @@
# scriptMissileGuidanceComputerAOEVelocityBonusBonus
#
# Used by:
+# Charges from group: Tracking Script (2 of 2)
# Charges named like: Missile Script (4 of 4)
type = "passive"
def handler(fit, module, context):
diff --git a/eos/effects/scriptresistancebonusbonus.py b/eos/effects/scriptresistancebonusbonus.py
new file mode 100644
index 000000000..1698579fc
--- /dev/null
+++ b/eos/effects/scriptresistancebonusbonus.py
@@ -0,0 +1,10 @@
+# scriptResistanceBonusBonus
+#
+# Used by:
+# Charges named like: Resistance Script (8 of 8)
+type = "passive"
+def handler(fit, src, context):
+ src.boostItemAttr("emDamageResistanceBonus", src.getModifiedChargeAttr("emDamageResistanceBonusBonus"))
+ src.boostItemAttr("explosiveDamageResistanceBonus", src.getModifiedChargeAttr("explosiveDamageResistanceBonusBonus"))
+ src.boostItemAttr("kineticDamageResistanceBonus", src.getModifiedChargeAttr("kineticDamageResistanceBonusBonus"))
+ src.boostItemAttr("thermalDamageResistanceBonus", src.getModifiedChargeAttr("thermalDamageResistanceBonusBonus"))
diff --git a/eos/effects/selfrof.py b/eos/effects/selfrof.py
index e2fa162cb..58334e09d 100644
--- a/eos/effects/selfrof.py
+++ b/eos/effects/selfrof.py
@@ -1,7 +1,7 @@
# selfRof
#
# Used by:
-# Skills named like: Missile Specialization (4 of 4)
+# Skills named like: Missile Specialization (4 of 5)
# Skill: Rocket Specialization
# Skill: Torpedo Specialization
type = "passive"
diff --git a/eos/effects/setbonusbloodraider.py b/eos/effects/setbonusbloodraider.py
index 718be78e6..73fb305ec 100644
--- a/eos/effects/setbonusbloodraider.py
+++ b/eos/effects/setbonusbloodraider.py
@@ -5,5 +5,5 @@
runTime = "early"
type = "passive"
def handler(fit, implant, context):
- fit.implants.filteredItemMultiply(lambda mod: mod.item.group.name == "Cyberimplant",
+ fit.appliedImplants.filteredItemMultiply(lambda mod: mod.item.group.name == "Cyberimplant",
"durationBonus", implant.getModifiedItemAttr("implantSetBloodraider"))
diff --git a/eos/effects/setbonuschristmasagilitybonus.py b/eos/effects/setbonuschristmasagilitybonus.py
index 857cad355..f0ca5c03f 100644
--- a/eos/effects/setbonuschristmasagilitybonus.py
+++ b/eos/effects/setbonuschristmasagilitybonus.py
@@ -5,5 +5,5 @@
runTime = "early"
type = "passive"
def handler(fit, implant, context):
- fit.implants.filteredItemMultiply(lambda mod: mod.item.group.name == "Cyberimplant",
+ fit.appliedImplants.filteredItemMultiply(lambda mod: mod.item.group.name == "Cyberimplant",
"agilityBonus", implant.getModifiedItemAttr("implantSetChristmas"))
diff --git a/eos/effects/setbonuschristmasarmorhpbonus2.py b/eos/effects/setbonuschristmasarmorhpbonus2.py
index 971644d02..9f5c52fd4 100644
--- a/eos/effects/setbonuschristmasarmorhpbonus2.py
+++ b/eos/effects/setbonuschristmasarmorhpbonus2.py
@@ -5,5 +5,5 @@
runTime = "early"
type = "passive"
def handler(fit, implant, context):
- fit.implants.filteredItemMultiply(lambda mod: mod.item.group.name == "Cyberimplant",
+ fit.appliedImplants.filteredItemMultiply(lambda mod: mod.item.group.name == "Cyberimplant",
"armorHpBonus2", implant.getModifiedItemAttr("implantSetChristmas"))
diff --git a/eos/effects/setbonuschristmasbonusvelocity.py b/eos/effects/setbonuschristmasbonusvelocity.py
index 1a0d7ffcd..09b1ef21f 100644
--- a/eos/effects/setbonuschristmasbonusvelocity.py
+++ b/eos/effects/setbonuschristmasbonusvelocity.py
@@ -5,5 +5,5 @@
runTime = "early"
type = "passive"
def handler(fit, implant, context):
- fit.implants.filteredItemMultiply(lambda mod: mod.item.group.name == "Cyberimplant",
+ fit.appliedImplants.filteredItemMultiply(lambda mod: mod.item.group.name == "Cyberimplant",
"implantBonusVelocity", implant.getModifiedItemAttr("implantSetChristmas"))
diff --git a/eos/effects/setbonuschristmascapacitorcapacity.py b/eos/effects/setbonuschristmascapacitorcapacity.py
index a0ba4bdd0..cc949b255 100644
--- a/eos/effects/setbonuschristmascapacitorcapacity.py
+++ b/eos/effects/setbonuschristmascapacitorcapacity.py
@@ -5,5 +5,5 @@
runTime = "early"
type = "passive"
def handler(fit, implant, context):
- fit.implants.filteredItemMultiply(lambda mod: mod.item.group.name == "Cyberimplant",
+ fit.appliedImplants.filteredItemMultiply(lambda mod: mod.item.group.name == "Cyberimplant",
"capacitorCapacityBonus", implant.getModifiedItemAttr("implantSetChristmas"))
diff --git a/eos/effects/setbonuschristmascapacitorrecharge2.py b/eos/effects/setbonuschristmascapacitorrecharge2.py
index 7f31e1818..a526176e4 100644
--- a/eos/effects/setbonuschristmascapacitorrecharge2.py
+++ b/eos/effects/setbonuschristmascapacitorrecharge2.py
@@ -5,5 +5,5 @@
runTime = "early"
type = "passive"
def handler(fit, implant, context):
- fit.implants.filteredItemMultiply(lambda mod: mod.item.group.name == "Cyberimplant",
+ fit.appliedImplants.filteredItemMultiply(lambda mod: mod.item.group.name == "Cyberimplant",
"capRechargeBonus", implant.getModifiedItemAttr("implantSetChristmas"))
diff --git a/eos/effects/setbonuschristmascpuoutput.py b/eos/effects/setbonuschristmascpuoutput.py
index 5ba1d538a..e264c8dd5 100644
--- a/eos/effects/setbonuschristmascpuoutput.py
+++ b/eos/effects/setbonuschristmascpuoutput.py
@@ -5,5 +5,5 @@
runTime = "early"
type = "passive"
def handler(fit, implant, context):
- fit.implants.filteredItemMultiply(lambda mod: mod.item.group.name == "Cyberimplant",
+ fit.appliedImplants.filteredItemMultiply(lambda mod: mod.item.group.name == "Cyberimplant",
"cpuOutputBonus2", implant.getModifiedItemAttr("implantSetChristmas"))
diff --git a/eos/effects/setbonuschristmaspowergrid.py b/eos/effects/setbonuschristmaspowergrid.py
index b0fc46366..9c39919be 100644
--- a/eos/effects/setbonuschristmaspowergrid.py
+++ b/eos/effects/setbonuschristmaspowergrid.py
@@ -5,5 +5,5 @@
runTime = "early"
type = "passive"
def handler(fit, implant, context):
- fit.implants.filteredItemMultiply(lambda mod: mod.item.group.name == "Cyberimplant",
+ fit.appliedImplants.filteredItemMultiply(lambda mod: mod.item.group.name == "Cyberimplant",
"powerEngineeringOutputBonus", implant.getModifiedItemAttr("implantSetChristmas"))
diff --git a/eos/effects/setbonuschristmasshieldcapacitybonus.py b/eos/effects/setbonuschristmasshieldcapacitybonus.py
index 5841a565e..c604d0281 100644
--- a/eos/effects/setbonuschristmasshieldcapacitybonus.py
+++ b/eos/effects/setbonuschristmasshieldcapacitybonus.py
@@ -5,5 +5,5 @@
runTime = "early"
type = "passive"
def handler(fit, implant, context):
- fit.implants.filteredItemMultiply(lambda mod: mod.item.group.name == "Cyberimplant",
+ fit.appliedImplants.filteredItemMultiply(lambda mod: mod.item.group.name == "Cyberimplant",
"shieldCapacityBonus", implant.getModifiedItemAttr("implantSetChristmas"))
diff --git a/eos/effects/setbonusguristas.py b/eos/effects/setbonusguristas.py
index e0e6a14bf..34bbfacc2 100644
--- a/eos/effects/setbonusguristas.py
+++ b/eos/effects/setbonusguristas.py
@@ -5,5 +5,5 @@
runTime = "early"
type = "passive"
def handler(fit, implant, context):
- fit.implants.filteredItemMultiply(lambda mod: mod.item.group.name == "Cyberimplant",
+ fit.appliedImplants.filteredItemMultiply(lambda mod: mod.item.group.name == "Cyberimplant",
"shieldBoostMultiplier", implant.getModifiedItemAttr("implantSetGuristas"))
diff --git a/eos/effects/setbonusmordus.py b/eos/effects/setbonusmordus.py
index 3bcdb2c07..eef3675f9 100644
--- a/eos/effects/setbonusmordus.py
+++ b/eos/effects/setbonusmordus.py
@@ -5,5 +5,5 @@
runTime = "early"
type = "passive"
def handler(fit, implant, context):
- fit.implants.filteredItemMultiply(lambda mod: mod.item.group.name == "Cyberimplant",
+ fit.appliedImplants.filteredItemMultiply(lambda mod: mod.item.group.name == "Cyberimplant",
"rangeSkillBonus", implant.getModifiedItemAttr("implantSetMordus"))
diff --git a/eos/effects/setbonusore.py b/eos/effects/setbonusore.py
index 8e540b81c..a7342a8fa 100644
--- a/eos/effects/setbonusore.py
+++ b/eos/effects/setbonusore.py
@@ -5,5 +5,5 @@
runTime = "early"
type = "passive"
def handler(fit, implant, context):
- fit.implants.filteredItemMultiply(lambda mod: mod.item.group.name == "Cyberimplant",
+ fit.appliedImplants.filteredItemMultiply(lambda mod: mod.item.group.name == "Cyberimplant",
"maxRangeBonus", implant.getModifiedItemAttr("implantSetORE"))
diff --git a/eos/effects/setbonussansha.py b/eos/effects/setbonussansha.py
index e7e0d261c..df7ae7be3 100644
--- a/eos/effects/setbonussansha.py
+++ b/eos/effects/setbonussansha.py
@@ -6,5 +6,5 @@
runTime = "early"
type = "passive"
def handler(fit, implant, context):
- fit.implants.filteredItemMultiply(lambda target: target.item.requiresSkill("Cybernetics"),
+ fit.appliedImplants.filteredItemMultiply(lambda target: target.item.requiresSkill("Cybernetics"),
"armorHpBonus", implant.getModifiedItemAttr("implantSetSansha") or 1)
diff --git a/eos/effects/setbonusserpentis.py b/eos/effects/setbonusserpentis.py
index 4775993c0..f4de04dcc 100644
--- a/eos/effects/setbonusserpentis.py
+++ b/eos/effects/setbonusserpentis.py
@@ -5,5 +5,5 @@
runTime = "early"
type = "passive"
def handler(fit, implant, context):
- fit.implants.filteredItemMultiply(lambda mod: mod.item.group.name == "Cyberimplant",
+ fit.appliedImplants.filteredItemMultiply(lambda mod: mod.item.group.name == "Cyberimplant",
"velocityBonus", implant.getModifiedItemAttr("implantSetSerpentis"))
diff --git a/eos/effects/setbonussisters.py b/eos/effects/setbonussisters.py
index cf67fda48..a43478d52 100644
--- a/eos/effects/setbonussisters.py
+++ b/eos/effects/setbonussisters.py
@@ -5,5 +5,5 @@
runTime = "early"
type = "passive"
def handler(fit, implant, context):
- fit.implants.filteredItemMultiply(lambda mod: mod.item.group.name == "Cyberimplant",
+ fit.appliedImplants.filteredItemMultiply(lambda mod: mod.item.group.name == "Cyberimplant",
"scanStrengthBonus", implant.getModifiedItemAttr("implantSetSisters"))
diff --git a/eos/effects/setbonussyndicate.py b/eos/effects/setbonussyndicate.py
index 594c4e90a..61fc59591 100644
--- a/eos/effects/setbonussyndicate.py
+++ b/eos/effects/setbonussyndicate.py
@@ -5,5 +5,5 @@
runTime = "early"
type = "passive"
def handler(fit, implant, context):
- fit.implants.filteredItemMultiply(lambda mod: mod.item.group.name == "Cyberimplant",
+ fit.appliedImplants.filteredItemMultiply(lambda mod: mod.item.group.name == "Cyberimplant",
"boosterAttributeModifier", implant.getModifiedItemAttr("implantSetSyndicate"))
diff --git a/eos/effects/setbonusthukker.py b/eos/effects/setbonusthukker.py
index 073b46c96..8594ddcfe 100644
--- a/eos/effects/setbonusthukker.py
+++ b/eos/effects/setbonusthukker.py
@@ -5,5 +5,5 @@
runTime = "early"
type = "passive"
def handler(fit, implant, context):
- fit.implants.filteredItemMultiply(lambda mod: mod.item.group.name == "Cyberimplant",
+ fit.appliedImplants.filteredItemMultiply(lambda mod: mod.item.group.name == "Cyberimplant",
"agilityBonus", implant.getModifiedItemAttr("implantSetThukker"))
diff --git a/eos/effects/shieldboosting.py b/eos/effects/shieldboosting.py
index 657fb9e19..70e49fa8b 100644
--- a/eos/effects/shieldboosting.py
+++ b/eos/effects/shieldboosting.py
@@ -1,7 +1,7 @@
# shieldBoosting
#
# Used by:
-# Modules from group: Shield Booster (87 of 87)
+# Modules from group: Shield Booster (93 of 93)
runTime = "late"
type = "active"
def handler(fit, module, context):
diff --git a/eos/effects/shieldcapacitybonusonline.py b/eos/effects/shieldcapacitybonusonline.py
index caf100297..2c4794eda 100644
--- a/eos/effects/shieldcapacitybonusonline.py
+++ b/eos/effects/shieldcapacitybonusonline.py
@@ -2,7 +2,7 @@
#
# Used by:
# Modules from group: Shield Amplifier (88 of 88)
-# Modules from group: Shield Extender (25 of 25)
+# Modules from group: Shield Extender (33 of 33)
type = "passive"
def handler(fit, module, context):
fit.ship.increaseItemAttr("shieldCapacity", module.getModifiedItemAttr("capacityBonus"))
\ No newline at end of file
diff --git a/eos/effects/shieldtransfer.py b/eos/effects/shieldtransfer.py
index c5a95088e..a06ea9e4c 100644
--- a/eos/effects/shieldtransfer.py
+++ b/eos/effects/shieldtransfer.py
@@ -1,7 +1,6 @@
# shieldTransfer
#
# Used by:
-# Drones named like: Shield Maintenance Bot (6 of 6)
# Module: QA Shield Transporter - 5 Players
type = "projected", "active"
def handler(fit, container, context):
diff --git a/eos/effects/shipadvancedspaceshipcommandagilitybonus.py b/eos/effects/shipadvancedspaceshipcommandagilitybonus.py
index 081daa2f7..cad85700a 100644
--- a/eos/effects/shipadvancedspaceshipcommandagilitybonus.py
+++ b/eos/effects/shipadvancedspaceshipcommandagilitybonus.py
@@ -1,7 +1,7 @@
# shipAdvancedSpaceshipCommandAgilityBonus
#
# Used by:
-# Items from market group: Ships > Capital Ships (27 of 28)
+# Items from market group: Ships > Capital Ships (31 of 32)
type = "passive"
def handler(fit, ship, context):
skillName = "Advanced Spaceship Command"
diff --git a/eos/effects/shipbonuscarriera1armorresists.py b/eos/effects/shipbonuscarriera1armorresists.py
new file mode 100644
index 000000000..2e90ea373
--- /dev/null
+++ b/eos/effects/shipbonuscarriera1armorresists.py
@@ -0,0 +1,10 @@
+# shipBonusCarrierA1ArmorResists
+#
+# Used by:
+# Ship: Archon
+type = "passive"
+def handler(fit, src, context):
+ fit.ship.boostItemAttr("armorKineticDamageResonance", src.getModifiedItemAttr("shipBonusCarrierA1"), skill="Amarr Carrier")
+ fit.ship.boostItemAttr("armorEmDamageResonance", src.getModifiedItemAttr("shipBonusCarrierA1"), skill="Amarr Carrier")
+ fit.ship.boostItemAttr("armorExplosiveDamageResonance", src.getModifiedItemAttr("shipBonusCarrierA1"), skill="Amarr Carrier")
+ fit.ship.boostItemAttr("armorThermalDamageResonance", src.getModifiedItemAttr("shipBonusCarrierA1"), skill="Amarr Carrier")
diff --git a/eos/effects/shipbonuscarriera2supportfighterbonus.py b/eos/effects/shipbonuscarriera2supportfighterbonus.py
new file mode 100644
index 000000000..c226a07e5
--- /dev/null
+++ b/eos/effects/shipbonuscarriera2supportfighterbonus.py
@@ -0,0 +1,8 @@
+# shipBonusCarrierA2SupportFighterBonus
+#
+# Used by:
+# Ship: Archon
+type = "passive"
+def handler(fit, src, context):
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Support Fighters"), "fighterSquadronOrbitRange", src.getModifiedItemAttr("shipBonusCarrierA2"), skill="Amarr Carrier")
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Support Fighters"), "fighterAbilityEnergyNeutralizerOptimalRange", src.getModifiedItemAttr("shipBonusCarrierA2"), skill="Amarr Carrier")
diff --git a/eos/effects/shipbonuscarriera4warfarelinksbonus.py b/eos/effects/shipbonuscarriera4warfarelinksbonus.py
new file mode 100644
index 000000000..96716c37f
--- /dev/null
+++ b/eos/effects/shipbonuscarriera4warfarelinksbonus.py
@@ -0,0 +1,8 @@
+# shipBonusCarrierA4WarfareLinksBonus
+#
+# Used by:
+# Ship: Archon
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Information Warfare Specialist"), "commandBonus", src.getModifiedItemAttr("shipBonusCarrierA4"), skill="Amarr Carrier")
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Armored Warfare Specialist"), "commandBonus", src.getModifiedItemAttr("shipBonusCarrierA4"), skill="Amarr Carrier")
diff --git a/eos/effects/shipbonuscarrierc1shieldresists.py b/eos/effects/shipbonuscarrierc1shieldresists.py
new file mode 100644
index 000000000..195b1a2af
--- /dev/null
+++ b/eos/effects/shipbonuscarrierc1shieldresists.py
@@ -0,0 +1,10 @@
+# shipBonusCarrierC1ShieldResists
+#
+# Used by:
+# Ship: Chimera
+type = "passive"
+def handler(fit, src, context):
+ fit.ship.boostItemAttr("shieldThermalDamageResonance", src.getModifiedItemAttr("shipBonusCarrierC1"), skill="Caldari Carrier")
+ fit.ship.boostItemAttr("shieldEmDamageResonance", src.getModifiedItemAttr("shipBonusCarrierC1"), skill="Caldari Carrier")
+ fit.ship.boostItemAttr("shieldKineticDamageResonance", src.getModifiedItemAttr("shipBonusCarrierC1"), skill="Caldari Carrier")
+ fit.ship.boostItemAttr("shieldExplosiveDamageResonance", src.getModifiedItemAttr("shipBonusCarrierC1"), skill="Caldari Carrier")
diff --git a/eos/effects/shipbonuscarrierc2supportfighterbonus.py b/eos/effects/shipbonuscarrierc2supportfighterbonus.py
new file mode 100644
index 000000000..96ae4beb0
--- /dev/null
+++ b/eos/effects/shipbonuscarrierc2supportfighterbonus.py
@@ -0,0 +1,8 @@
+# shipBonusCarrierC2SupportFighterBonus
+#
+# Used by:
+# Ship: Chimera
+type = "passive"
+def handler(fit, src, context):
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Support Fighters"), "fighterSquadronOrbitRange", src.getModifiedItemAttr("shipBonusCarrierC2"), skill="Caldari Carrier")
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Support Fighters"), "fighterAbilityECMRangeOptimal", src.getModifiedItemAttr("shipBonusCarrierC2"), skill="Caldari Carrier")
diff --git a/eos/effects/shipbonuscarrierc4warfarelinksbonus.py b/eos/effects/shipbonuscarrierc4warfarelinksbonus.py
new file mode 100644
index 000000000..b47c3eaab
--- /dev/null
+++ b/eos/effects/shipbonuscarrierc4warfarelinksbonus.py
@@ -0,0 +1,8 @@
+# shipBonusCarrierC4WarfareLinksBonus
+#
+# Used by:
+# Ship: Chimera
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Siege Warfare Specialist"), "commandBonus", src.getModifiedItemAttr("shipBonusCarrierC4"), skill="Caldari Carrier")
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Information Warfare Specialist"), "commandBonus", src.getModifiedItemAttr("shipBonusCarrierC4"), skill="Caldari Carrier")
diff --git a/eos/effects/shipbonuscarrierg1fighterdamage.py b/eos/effects/shipbonuscarrierg1fighterdamage.py
new file mode 100644
index 000000000..dbd2ef63b
--- /dev/null
+++ b/eos/effects/shipbonuscarrierg1fighterdamage.py
@@ -0,0 +1,9 @@
+# shipBonusCarrierG1FighterDamage
+#
+# Used by:
+# Ship: Thanatos
+type = "passive"
+def handler(fit, src, context):
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityMissilesDamageMultiplier", src.getModifiedItemAttr("shipBonusCarrierG1"), skill="Gallente Carrier")
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackTurretDamageMultiplier", src.getModifiedItemAttr("shipBonusCarrierG1"), skill="Gallente Carrier")
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackMissileDamageMultiplier", src.getModifiedItemAttr("shipBonusCarrierG1"), skill="Gallente Carrier")
diff --git a/eos/effects/shipbonuscarrierg1fighterdamageandhitpoints.py b/eos/effects/shipbonuscarrierg1fighterdamageandhitpoints.py
new file mode 100644
index 000000000..df81f47ac
--- /dev/null
+++ b/eos/effects/shipbonuscarrierg1fighterdamageandhitpoints.py
@@ -0,0 +1,10 @@
+# shipBonusCarrierG1FighterDamageAndHitpoints
+#
+# Used by:
+# Ship: Thanatos
+type = "passive"
+def handler(fit, src, context):
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityMissilesDamageMultiplier", src.getModifiedItemAttr("shipBonusCarrierG1"), skill="Gallente Carrier")
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackTurretDamageMultiplier", src.getModifiedItemAttr("shipBonusCarrierG1"), skill="Gallente Carrier")
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "shieldCapacity", src.getModifiedItemAttr("shipBonusCarrierG1"), skill="Gallente Carrier")
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackMissileDamageMultiplier", src.getModifiedItemAttr("shipBonusCarrierG1"), skill="Gallente Carrier")
diff --git a/eos/effects/shipbonuscarrierg2supportfighterbonus.py b/eos/effects/shipbonuscarrierg2supportfighterbonus.py
new file mode 100644
index 000000000..05ba1172d
--- /dev/null
+++ b/eos/effects/shipbonuscarrierg2supportfighterbonus.py
@@ -0,0 +1,8 @@
+# shipBonusCarrierG2SupportFighterBonus
+#
+# Used by:
+# Ship: Thanatos
+type = "passive"
+def handler(fit, src, context):
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Support Fighters"), "fighterSquadronOrbitRange", src.getModifiedItemAttr("shipBonusCarrierG2"), skill="Gallente Carrier")
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Support Fighters"), "fighterAbilityWarpDisruptionRange", src.getModifiedItemAttr("shipBonusCarrierG2"), skill="Gallente Carrier")
diff --git a/eos/effects/shipbonuscarrierg3fighterhitpoints.py b/eos/effects/shipbonuscarrierg3fighterhitpoints.py
new file mode 100644
index 000000000..40b568fb3
--- /dev/null
+++ b/eos/effects/shipbonuscarrierg3fighterhitpoints.py
@@ -0,0 +1,7 @@
+# shipBonusCarrierG3FighterHitpoints
+#
+# Used by:
+# Ship: Thanatos
+type = "passive"
+def handler(fit, src, context):
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "shieldCapacity", src.getModifiedItemAttr("shipBonusCarrierG3"), skill="Gallente Carrier")
diff --git a/eos/effects/shipbonuscarrierg4warfarelinksbonus.py b/eos/effects/shipbonuscarrierg4warfarelinksbonus.py
new file mode 100644
index 000000000..d7518eb28
--- /dev/null
+++ b/eos/effects/shipbonuscarrierg4warfarelinksbonus.py
@@ -0,0 +1,8 @@
+# shipBonusCarrierG4WarfareLinksBonus
+#
+# Used by:
+# Ship: Thanatos
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Armored Warfare Specialist"), "commandBonus", src.getModifiedItemAttr("shipBonusCarrierG4"), skill="Gallente Carrier")
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Skirmish Warfare Specialist"), "commandBonus", src.getModifiedItemAttr("shipBonusCarrierG4"), skill="Gallente Carrier")
diff --git a/eos/effects/shipbonuscarrierm1fighterdamage.py b/eos/effects/shipbonuscarrierm1fighterdamage.py
new file mode 100644
index 000000000..954d783fb
--- /dev/null
+++ b/eos/effects/shipbonuscarrierm1fighterdamage.py
@@ -0,0 +1,9 @@
+# shipBonusCarrierM1FighterDamage
+#
+# Used by:
+# Ship: Nidhoggur
+type = "passive"
+def handler(fit, src, context):
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackMissileDamageMultiplier", src.getModifiedItemAttr("shipBonusCarrierM1"), skill="Minmatar Carrier")
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityMissilesDamageMultiplier", src.getModifiedItemAttr("shipBonusCarrierM1"), skill="Minmatar Carrier")
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackTurretDamageMultiplier", src.getModifiedItemAttr("shipBonusCarrierM1"), skill="Minmatar Carrier")
diff --git a/eos/effects/shipbonuscarrierm1fighterdamageandvelocity.py b/eos/effects/shipbonuscarrierm1fighterdamageandvelocity.py
new file mode 100644
index 000000000..fbd629a73
--- /dev/null
+++ b/eos/effects/shipbonuscarrierm1fighterdamageandvelocity.py
@@ -0,0 +1,10 @@
+# shipBonusCarrierM1FighterDamageAndVelocity
+#
+# Used by:
+# Ship: Nidhoggur
+type = "passive"
+def handler(fit, src, context):
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "maxVelocity", src.getModifiedItemAttr("shipBonusCarrierM1"), skill="Minmatar Carrier")
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityMissilesDamageMultiplier", src.getModifiedItemAttr("shipBonusCarrierM1"), skill="Minmatar Carrier")
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackTurretDamageMultiplier", src.getModifiedItemAttr("shipBonusCarrierM1"), skill="Minmatar Carrier")
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackMissileDamageMultiplier", src.getModifiedItemAttr("shipBonusCarrierM1"), skill="Minmatar Carrier")
diff --git a/eos/effects/shipbonuscarrierm2supportfighterbonus.py b/eos/effects/shipbonuscarrierm2supportfighterbonus.py
new file mode 100644
index 000000000..6dd2c8518
--- /dev/null
+++ b/eos/effects/shipbonuscarrierm2supportfighterbonus.py
@@ -0,0 +1,8 @@
+# shipBonusCarrierM2SupportFighterBonus
+#
+# Used by:
+# Ship: Nidhoggur
+type = "passive"
+def handler(fit, src, context):
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Support Fighters"), "fighterSquadronOrbitRange", src.getModifiedItemAttr("shipBonusCarrierM2"), skill="Minmatar Carrier")
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Support Fighters"), "fighterAbilityStasisWebifierOptimalRange", src.getModifiedItemAttr("shipBonusCarrierM2"), skill="Minmatar Carrier")
diff --git a/eos/effects/shipbonuscarrierm3fightervelocity.py b/eos/effects/shipbonuscarrierm3fightervelocity.py
new file mode 100644
index 000000000..a880ddcdf
--- /dev/null
+++ b/eos/effects/shipbonuscarrierm3fightervelocity.py
@@ -0,0 +1,7 @@
+# shipBonusCarrierM3FighterVelocity
+#
+# Used by:
+# Ship: Nidhoggur
+type = "passive"
+def handler(fit, src, context):
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "maxVelocity", src.getModifiedItemAttr("shipBonusCarrierM3"), skill="Minmatar Carrier")
diff --git a/eos/effects/shipbonuscarrierm4warfarelinksbonus.py b/eos/effects/shipbonuscarrierm4warfarelinksbonus.py
new file mode 100644
index 000000000..4f47e8954
--- /dev/null
+++ b/eos/effects/shipbonuscarrierm4warfarelinksbonus.py
@@ -0,0 +1,8 @@
+# shipBonusCarrierM4WarfareLinksBonus
+#
+# Used by:
+# Ship: Nidhoggur
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Skirmish Warfare Specialist"), "commandBonus", src.getModifiedItemAttr("shipBonusCarrierM4"), skill="Minmatar Carrier")
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Siege Warfare Specialist"), "commandBonus", src.getModifiedItemAttr("shipBonusCarrierM4"), skill="Minmatar Carrier")
diff --git a/eos/effects/shipbonuscarrierrole1numwarfarelinks.py b/eos/effects/shipbonuscarrierrole1numwarfarelinks.py
new file mode 100644
index 000000000..e2fde5322
--- /dev/null
+++ b/eos/effects/shipbonuscarrierrole1numwarfarelinks.py
@@ -0,0 +1,7 @@
+# shipBonusCarrierRole1NumWarfareLinks
+#
+# Used by:
+# Ships from group: Carrier (4 of 4)
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemIncrease(lambda mod: mod.item.requiresSkill("Leadership"), "maxGroupActive", src.getModifiedItemAttr("shipBonusRole1"))
diff --git a/eos/effects/shipbonusdreadnoughta1damagebonus.py b/eos/effects/shipbonusdreadnoughta1damagebonus.py
new file mode 100644
index 000000000..03dff96c9
--- /dev/null
+++ b/eos/effects/shipbonusdreadnoughta1damagebonus.py
@@ -0,0 +1,7 @@
+# shipBonusDreadnoughtA1DamageBonus
+#
+# Used by:
+# Ship: Revelation
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Energy Turret"), "damageMultiplier", src.getModifiedItemAttr("shipBonusDreadnoughtA1"), skill="Amarr Dreadnought")
diff --git a/eos/effects/shipbonusdreadnoughta2armorresists.py b/eos/effects/shipbonusdreadnoughta2armorresists.py
new file mode 100644
index 000000000..b1fbada09
--- /dev/null
+++ b/eos/effects/shipbonusdreadnoughta2armorresists.py
@@ -0,0 +1,10 @@
+# shipBonusDreadnoughtA2ArmorResists
+#
+# Used by:
+# Ship: Revelation
+type = "passive"
+def handler(fit, src, context):
+ fit.ship.boostItemAttr("armorExplosiveDamageResonance", src.getModifiedItemAttr("shipBonusDreadnoughtA2"), skill="Amarr Dreadnought")
+ fit.ship.boostItemAttr("armorEmDamageResonance", src.getModifiedItemAttr("shipBonusDreadnoughtA2"), skill="Amarr Dreadnought")
+ fit.ship.boostItemAttr("armorThermalDamageResonance", src.getModifiedItemAttr("shipBonusDreadnoughtA2"), skill="Amarr Dreadnought")
+ fit.ship.boostItemAttr("armorKineticDamageResonance", src.getModifiedItemAttr("shipBonusDreadnoughtA2"), skill="Amarr Dreadnought")
diff --git a/eos/effects/shipbonusdreadnoughta3capneed.py b/eos/effects/shipbonusdreadnoughta3capneed.py
new file mode 100644
index 000000000..515c7e026
--- /dev/null
+++ b/eos/effects/shipbonusdreadnoughta3capneed.py
@@ -0,0 +1,7 @@
+# shipBonusDreadnoughtA3CapNeed
+#
+# Used by:
+# Ship: Revelation
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Energy Turret"), "capacitorNeed", src.getModifiedItemAttr("shipBonusDreadnoughtA3"), skill="Amarr Dreadnought")
diff --git a/eos/effects/shipbonusdreadnoughtc1damagebonus.py b/eos/effects/shipbonusdreadnoughtc1damagebonus.py
new file mode 100644
index 000000000..0fb110a9e
--- /dev/null
+++ b/eos/effects/shipbonusdreadnoughtc1damagebonus.py
@@ -0,0 +1,18 @@
+# shipBonusDreadnoughtC1DamageBonus
+#
+# Used by:
+# Ship: Phoenix
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("XL Torpedoes"), "thermalDamage", src.getModifiedItemAttr("shipBonusDreadnoughtC1"), skill="Caldari Dreadnought")
+ fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("XL Cruise Missiles"), "kineticDamage", src.getModifiedItemAttr("shipBonusDreadnoughtC1"), skill="Caldari Dreadnought")
+ fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("Torpedoes"), "emDamage", src.getModifiedItemAttr("shipBonusDreadnoughtC1"), skill="Caldari Dreadnought")
+ fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("Torpedoes"), "explosiveDamage", src.getModifiedItemAttr("shipBonusDreadnoughtC1"), skill="Caldari Dreadnought")
+ fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("XL Cruise Missiles"), "explosiveDamage", src.getModifiedItemAttr("shipBonusDreadnoughtC1"), skill="Caldari Dreadnought")
+ fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("XL Cruise Missiles"), "thermalDamage", src.getModifiedItemAttr("shipBonusDreadnoughtC1"), skill="Caldari Dreadnought")
+ fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("Torpedoes"), "thermalDamage", src.getModifiedItemAttr("shipBonusDreadnoughtC1"), skill="Caldari Dreadnought")
+ fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("XL Torpedoes"), "emDamage", src.getModifiedItemAttr("shipBonusDreadnoughtC1"), skill="Caldari Dreadnought")
+ fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("Torpedoes"), "kineticDamage", src.getModifiedItemAttr("shipBonusDreadnoughtC1"), skill="Caldari Dreadnought")
+ fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("XL Torpedoes"), "kineticDamage", src.getModifiedItemAttr("shipBonusDreadnoughtC1"), skill="Caldari Dreadnought")
+ fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("XL Torpedoes"), "explosiveDamage", src.getModifiedItemAttr("shipBonusDreadnoughtC1"), skill="Caldari Dreadnought")
+ fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("XL Cruise Missiles"), "emDamage", src.getModifiedItemAttr("shipBonusDreadnoughtC1"), skill="Caldari Dreadnought")
diff --git a/eos/effects/shipbonusdreadnoughtc2shieldresists.py b/eos/effects/shipbonusdreadnoughtc2shieldresists.py
new file mode 100644
index 000000000..f8704bc73
--- /dev/null
+++ b/eos/effects/shipbonusdreadnoughtc2shieldresists.py
@@ -0,0 +1,10 @@
+# shipBonusDreadnoughtC2ShieldResists
+#
+# Used by:
+# Ship: Phoenix
+type = "passive"
+def handler(fit, src, context):
+ fit.ship.boostItemAttr("shieldThermalDamageResonance", src.getModifiedItemAttr("shipBonusDreadnoughtC2"), skill="Caldari Dreadnought")
+ fit.ship.boostItemAttr("shieldKineticDamageResonance", src.getModifiedItemAttr("shipBonusDreadnoughtC2"), skill="Caldari Dreadnought")
+ fit.ship.boostItemAttr("shieldEmDamageResonance", src.getModifiedItemAttr("shipBonusDreadnoughtC2"), skill="Caldari Dreadnought")
+ fit.ship.boostItemAttr("shieldExplosiveDamageResonance", src.getModifiedItemAttr("shipBonusDreadnoughtC2"), skill="Caldari Dreadnought")
diff --git a/eos/effects/shipbonusdreadnoughtc3reloadbonus.py b/eos/effects/shipbonusdreadnoughtc3reloadbonus.py
new file mode 100644
index 000000000..71d7353cf
--- /dev/null
+++ b/eos/effects/shipbonusdreadnoughtc3reloadbonus.py
@@ -0,0 +1,7 @@
+# shipBonusDreadnoughtC3ReloadBonus
+#
+# Used by:
+# Ship: Phoenix
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Missile Launcher Operation"), "reloadTime", src.getModifiedItemAttr("shipBonusDreadnoughtC3"), skill="Caldari Dreadnought")
diff --git a/eos/effects/shipbonusdreadnoughtg1damagebonus.py b/eos/effects/shipbonusdreadnoughtg1damagebonus.py
new file mode 100644
index 000000000..343616f66
--- /dev/null
+++ b/eos/effects/shipbonusdreadnoughtg1damagebonus.py
@@ -0,0 +1,7 @@
+# shipBonusDreadnoughtG1DamageBonus
+#
+# Used by:
+# Ship: Moros
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Hybrid Turret"), "damageMultiplier", src.getModifiedItemAttr("shipBonusDreadnoughtG1"), skill="Gallente Dreadnought")
diff --git a/eos/effects/shipbonusdreadnoughtg2rofbonus.py b/eos/effects/shipbonusdreadnoughtg2rofbonus.py
new file mode 100644
index 000000000..f6f39b89e
--- /dev/null
+++ b/eos/effects/shipbonusdreadnoughtg2rofbonus.py
@@ -0,0 +1,7 @@
+# shipBonusDreadnoughtG2ROFBonus
+#
+# Used by:
+# Ship: Moros
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Hybrid Turret"), "speed", src.getModifiedItemAttr("shipBonusDreadnoughtG2"), skill="Gallente Dreadnought")
diff --git a/eos/effects/shipbonusdreadnoughtg3repairtime.py b/eos/effects/shipbonusdreadnoughtg3repairtime.py
new file mode 100644
index 000000000..9b764ccf7
--- /dev/null
+++ b/eos/effects/shipbonusdreadnoughtg3repairtime.py
@@ -0,0 +1,7 @@
+# shipBonusDreadnoughtG3RepairTime
+#
+# Used by:
+# Ship: Moros
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Repair Systems"), "duration", src.getModifiedItemAttr("shipBonusDreadnoughtG3"), skill="Gallente Dreadnought")
diff --git a/eos/effects/shipbonusdreadnoughtm1damagebonus.py b/eos/effects/shipbonusdreadnoughtm1damagebonus.py
new file mode 100644
index 000000000..1117b294c
--- /dev/null
+++ b/eos/effects/shipbonusdreadnoughtm1damagebonus.py
@@ -0,0 +1,7 @@
+# shipBonusDreadnoughtM1DamageBonus
+#
+# Used by:
+# Ship: Naglfar
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Projectile Turret"), "damageMultiplier", src.getModifiedItemAttr("shipBonusDreadnoughtM1"), skill="Minmatar Dreadnought")
diff --git a/eos/effects/shipbonusdreadnoughtm2rofbonus.py b/eos/effects/shipbonusdreadnoughtm2rofbonus.py
new file mode 100644
index 000000000..a92dea0a3
--- /dev/null
+++ b/eos/effects/shipbonusdreadnoughtm2rofbonus.py
@@ -0,0 +1,7 @@
+# shipBonusDreadnoughtM2ROFBonus
+#
+# Used by:
+# Ship: Naglfar
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Projectile Turret"), "speed", src.getModifiedItemAttr("shipBonusDreadnoughtM2"), skill="Minmatar Dreadnought")
diff --git a/eos/effects/shipbonusdreadnoughtm3repairtime.py b/eos/effects/shipbonusdreadnoughtm3repairtime.py
new file mode 100644
index 000000000..dab9cd5fb
--- /dev/null
+++ b/eos/effects/shipbonusdreadnoughtm3repairtime.py
@@ -0,0 +1,7 @@
+# shipBonusDreadnoughtM3RepairTime
+#
+# Used by:
+# Ship: Naglfar
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Shield Operation"), "duration", src.getModifiedItemAttr("shipBonusDreadnoughtM2"), skill="Minmatar Dreadnought")
diff --git a/eos/effects/shipbonusdreadnoughtrole1damagebonus.py b/eos/effects/shipbonusdreadnoughtrole1damagebonus.py
new file mode 100644
index 000000000..c7fd5b85b
--- /dev/null
+++ b/eos/effects/shipbonusdreadnoughtrole1damagebonus.py
@@ -0,0 +1,7 @@
+# shipBonusDreadnoughtRole1DamageBonus
+#
+# Used by:
+# Ship: Naglfar
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Projectile Turret"), "damageMultiplier", src.getModifiedItemAttr("shipBonusRole1"))
diff --git a/eos/effects/shipbonusenergyvampirerangead2.py b/eos/effects/shipbonusenergyvampirerangead2.py
index a71170696..90f055473 100644
--- a/eos/effects/shipbonusenergyvampirerangead2.py
+++ b/eos/effects/shipbonusenergyvampirerangead2.py
@@ -5,4 +5,4 @@
type = "passive"
def handler(fit, ship, context):
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Energy Nosferatu",
- "powerTransferRange", ship.getModifiedItemAttr("shipBonusAD2"), skill="Amarr Destroyer")
+ "maxRange", ship.getModifiedItemAttr("shipBonusAD2"), skill="Amarr Destroyer")
diff --git a/eos/effects/shipbonusforceauxiliarya1remoterepairandcapamount.py b/eos/effects/shipbonusforceauxiliarya1remoterepairandcapamount.py
new file mode 100644
index 000000000..2a9e8bfba
--- /dev/null
+++ b/eos/effects/shipbonusforceauxiliarya1remoterepairandcapamount.py
@@ -0,0 +1,8 @@
+# shipBonusForceAuxiliaryA1RemoteRepairAndCapAmount
+#
+# Used by:
+# Ship: Apostle
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Capacitor Emission Systems"), "powerTransferAmount", src.getModifiedItemAttr("shipBonusForceAuxiliaryA1"), skill="Amarr Carrier")
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Remote Armor Repair Systems"), "armorDamageAmount", src.getModifiedItemAttr("shipBonusForceAuxiliaryA1"), skill="Amarr Carrier")
diff --git a/eos/effects/shipbonusforceauxiliarya2armorresists.py b/eos/effects/shipbonusforceauxiliarya2armorresists.py
new file mode 100644
index 000000000..071d51184
--- /dev/null
+++ b/eos/effects/shipbonusforceauxiliarya2armorresists.py
@@ -0,0 +1,10 @@
+# shipBonusForceAuxiliaryA2ArmorResists
+#
+# Used by:
+# Ship: Apostle
+type = "passive"
+def handler(fit, src, context):
+ fit.ship.boostItemAttr("armorKineticDamageResonance", src.getModifiedItemAttr("shipBonusForceAuxiliaryA2"), skill="Amarr Carrier")
+ fit.ship.boostItemAttr("armorExplosiveDamageResonance", src.getModifiedItemAttr("shipBonusForceAuxiliaryA2"), skill="Amarr Carrier")
+ fit.ship.boostItemAttr("armorEmDamageResonance", src.getModifiedItemAttr("shipBonusForceAuxiliaryA2"), skill="Amarr Carrier")
+ fit.ship.boostItemAttr("armorThermalDamageResonance", src.getModifiedItemAttr("shipBonusForceAuxiliaryA2"), skill="Amarr Carrier")
diff --git a/eos/effects/shipbonusforceauxiliarya3capcapacity.py b/eos/effects/shipbonusforceauxiliarya3capcapacity.py
new file mode 100644
index 000000000..8ee87d878
--- /dev/null
+++ b/eos/effects/shipbonusforceauxiliarya3capcapacity.py
@@ -0,0 +1,7 @@
+# shipBonusForceAuxiliaryA3CapCapacity
+#
+# Used by:
+# Ship: Apostle
+type = "passive"
+def handler(fit, src, context):
+ fit.ship.boostItemAttr("capacitorCapacity", src.getModifiedItemAttr("shipBonusForceAuxiliaryA3"), skill="Amarr Carrier")
diff --git a/eos/effects/shipbonusforceauxiliarya4warfarelinksbonus.py b/eos/effects/shipbonusforceauxiliarya4warfarelinksbonus.py
new file mode 100644
index 000000000..ed7b9cf3d
--- /dev/null
+++ b/eos/effects/shipbonusforceauxiliarya4warfarelinksbonus.py
@@ -0,0 +1,8 @@
+# shipBonusForceAuxiliaryA4WarfareLinksBonus
+#
+# Used by:
+# Ship: Apostle
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Armored Warfare Specialist"), "commandBonus", src.getModifiedItemAttr("shipBonusForceAuxiliaryA4"), skill="Amarr Carrier")
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Information Warfare Specialist"), "commandBonus", src.getModifiedItemAttr("shipBonusForceAuxiliaryA4"), skill="Amarr Carrier")
diff --git a/eos/effects/shipbonusforceauxiliaryc1remoteboostandcapamount.py b/eos/effects/shipbonusforceauxiliaryc1remoteboostandcapamount.py
new file mode 100644
index 000000000..1b0b75d4d
--- /dev/null
+++ b/eos/effects/shipbonusforceauxiliaryc1remoteboostandcapamount.py
@@ -0,0 +1,8 @@
+# shipBonusForceAuxiliaryC1RemoteBoostAndCapAmount
+#
+# Used by:
+# Ship: Minokawa
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Capacitor Emission Systems"), "powerTransferAmount", src.getModifiedItemAttr("shipBonusForceAuxiliaryC1"), skill="Caldari Carrier")
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Shield Emission Systems"), "shieldBonus", src.getModifiedItemAttr("shipBonusForceAuxiliaryC1"), skill="Caldari Carrier")
diff --git a/eos/effects/shipbonusforceauxiliaryc2shieldresists.py b/eos/effects/shipbonusforceauxiliaryc2shieldresists.py
new file mode 100644
index 000000000..96cfae084
--- /dev/null
+++ b/eos/effects/shipbonusforceauxiliaryc2shieldresists.py
@@ -0,0 +1,10 @@
+# shipBonusForceAuxiliaryC2ShieldResists
+#
+# Used by:
+# Ship: Minokawa
+type = "passive"
+def handler(fit, src, context):
+ fit.ship.boostItemAttr("shieldEmDamageResonance", src.getModifiedItemAttr("shipBonusForceAuxiliaryC2"), skill="Caldari Carrier")
+ fit.ship.boostItemAttr("shieldExplosiveDamageResonance", src.getModifiedItemAttr("shipBonusForceAuxiliaryC2"), skill="Caldari Carrier")
+ fit.ship.boostItemAttr("shieldKineticDamageResonance", src.getModifiedItemAttr("shipBonusForceAuxiliaryC2"), skill="Caldari Carrier")
+ fit.ship.boostItemAttr("shieldThermalDamageResonance", src.getModifiedItemAttr("shipBonusForceAuxiliaryC2"), skill="Caldari Carrier")
diff --git a/eos/effects/shipbonusforceauxiliaryc3capcapacity.py b/eos/effects/shipbonusforceauxiliaryc3capcapacity.py
new file mode 100644
index 000000000..3e1cf41d4
--- /dev/null
+++ b/eos/effects/shipbonusforceauxiliaryc3capcapacity.py
@@ -0,0 +1,7 @@
+# shipBonusForceAuxiliaryC3CapCapacity
+#
+# Used by:
+# Ship: Minokawa
+type = "passive"
+def handler(fit, src, context):
+ fit.ship.boostItemAttr("capacitorCapacity", src.getModifiedItemAttr("shipBonusForceAuxiliaryC3"), skill="Caldari Carrier")
diff --git a/eos/effects/shipbonusforceauxiliaryc4warfarelinksbonus.py b/eos/effects/shipbonusforceauxiliaryc4warfarelinksbonus.py
new file mode 100644
index 000000000..d724e8bda
--- /dev/null
+++ b/eos/effects/shipbonusforceauxiliaryc4warfarelinksbonus.py
@@ -0,0 +1,8 @@
+# shipBonusForceAuxiliaryC4WarfareLinksBonus
+#
+# Used by:
+# Ship: Minokawa
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Siege Warfare Specialist"), "commandBonus", src.getModifiedItemAttr("shipBonusForceAuxiliaryC4"), skill="Caldari Carrier")
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Information Warfare Specialist"), "commandBonus", src.getModifiedItemAttr("shipBonusForceAuxiliaryC4"), skill="Caldari Carrier")
diff --git a/eos/effects/shipbonusforceauxiliaryg1remotecycletime.py b/eos/effects/shipbonusforceauxiliaryg1remotecycletime.py
new file mode 100644
index 000000000..f73fe5bd8
--- /dev/null
+++ b/eos/effects/shipbonusforceauxiliaryg1remotecycletime.py
@@ -0,0 +1,10 @@
+# shipBonusForceAuxiliaryG1RemoteCycleTime
+#
+# Used by:
+# Ship: Ninazu
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Remote Armor Repair Systems"), "duration", src.getModifiedItemAttr("shipBonusForceAuxiliaryG1"), skill="Gallente Carrier")
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Shield Emission Systems"), "duration", src.getModifiedItemAttr("shipBonusForceAuxiliaryG1"), skill="Gallente Carrier")
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Shield Emission Systems"), "duration", src.getModifiedItemAttr("shipBonusForceAuxiliaryG1"), skill="Gallente Carrier")
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems"), "duration", src.getModifiedItemAttr("shipBonusForceAuxiliaryG1"), skill="Gallente Carrier")
diff --git a/eos/effects/shipbonusforceauxiliaryg2localrepairamount.py b/eos/effects/shipbonusforceauxiliaryg2localrepairamount.py
new file mode 100644
index 000000000..b93057e97
--- /dev/null
+++ b/eos/effects/shipbonusforceauxiliaryg2localrepairamount.py
@@ -0,0 +1,8 @@
+# shipBonusForceAuxiliaryG2LocalRepairAmount
+#
+# Used by:
+# Ship: Ninazu
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Repair Systems"), "armorDamageAmount", src.getModifiedItemAttr("shipBonusForceAuxiliaryG2"), skill="Gallente Carrier")
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Repair Systems"), "armorDamageAmount", src.getModifiedItemAttr("shipBonusForceAuxiliaryG2"), skill="Gallente Carrier")
diff --git a/eos/effects/shipbonusforceauxiliaryg3capboosterstrength.py b/eos/effects/shipbonusforceauxiliaryg3capboosterstrength.py
new file mode 100644
index 000000000..dffacb74a
--- /dev/null
+++ b/eos/effects/shipbonusforceauxiliaryg3capboosterstrength.py
@@ -0,0 +1,7 @@
+# shipBonusForceAuxiliaryG3CapBoosterStrength
+#
+# Used by:
+# Ship: Ninazu
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredChargeBoost(lambda mod: mod.charge.group.name == "Capacitor Booster Charge", "capacitorBonus", src.getModifiedItemAttr("shipBonusForceAuxiliaryG3"), skill="Gallente Carrier")
diff --git a/eos/effects/shipbonusforceauxiliaryg4warfarelinksbonus.py b/eos/effects/shipbonusforceauxiliaryg4warfarelinksbonus.py
new file mode 100644
index 000000000..5e933d9a5
--- /dev/null
+++ b/eos/effects/shipbonusforceauxiliaryg4warfarelinksbonus.py
@@ -0,0 +1,8 @@
+# shipBonusForceAuxiliaryG4WarfareLinksBonus
+#
+# Used by:
+# Ship: Ninazu
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Skirmish Warfare Specialist"), "commandBonus", src.getModifiedItemAttr("shipBonusForceAuxiliaryG4"), skill="Gallente Carrier")
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Armored Warfare Specialist"), "commandBonus", src.getModifiedItemAttr("shipBonusForceAuxiliaryG4"), skill="Gallente Carrier")
diff --git a/eos/effects/shipbonusforceauxiliarym1remotecycletime.py b/eos/effects/shipbonusforceauxiliarym1remotecycletime.py
new file mode 100644
index 000000000..f553f578e
--- /dev/null
+++ b/eos/effects/shipbonusforceauxiliarym1remotecycletime.py
@@ -0,0 +1,10 @@
+# shipBonusForceAuxiliaryM1RemoteCycleTime
+#
+# Used by:
+# Ship: Lif
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Shield Emission Systems"), "duration", src.getModifiedItemAttr("shipBonusForceAuxiliaryM1"), skill="Minmatar Carrier")
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Shield Emission Systems"), "duration", src.getModifiedItemAttr("shipBonusForceAuxiliaryM1"), skill="Minmatar Carrier")
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems"), "duration", src.getModifiedItemAttr("shipBonusForceAuxiliaryM1"), skill="Minmatar Carrier")
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Remote Armor Repair Systems"), "duration", src.getModifiedItemAttr("shipBonusForceAuxiliaryM1"), skill="Minmatar Carrier")
diff --git a/eos/effects/shipbonusforceauxiliarym2localboostamount.py b/eos/effects/shipbonusforceauxiliarym2localboostamount.py
new file mode 100644
index 000000000..8fe11a235
--- /dev/null
+++ b/eos/effects/shipbonusforceauxiliarym2localboostamount.py
@@ -0,0 +1,8 @@
+# shipBonusForceAuxiliaryM2LocalBoostAmount
+#
+# Used by:
+# Ship: Lif
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Shield Operation"), "shieldBonus", src.getModifiedItemAttr("shipBonusForceAuxiliaryM2"), skill="Minmatar Carrier")
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Shield Operation"), "shieldBonus", src.getModifiedItemAttr("shipBonusForceAuxiliaryM2"), skill="Minmatar Carrier")
diff --git a/eos/effects/shipbonusforceauxiliarym3capboosterstrength.py b/eos/effects/shipbonusforceauxiliarym3capboosterstrength.py
new file mode 100644
index 000000000..401b0530f
--- /dev/null
+++ b/eos/effects/shipbonusforceauxiliarym3capboosterstrength.py
@@ -0,0 +1,7 @@
+# shipBonusForceAuxiliaryM3CapBoosterStrength
+#
+# Used by:
+# Ship: Lif
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredChargeBoost(lambda mod: mod.charge.group.name == "Capacitor Booster Charge", "capacitorBonus", src.getModifiedItemAttr("shipBonusForceAuxiliaryM3"), skill="Minmatar Carrier")
diff --git a/eos/effects/shipbonusforceauxiliarym4warfarelinksbonus.py b/eos/effects/shipbonusforceauxiliarym4warfarelinksbonus.py
new file mode 100644
index 000000000..afbb2c09a
--- /dev/null
+++ b/eos/effects/shipbonusforceauxiliarym4warfarelinksbonus.py
@@ -0,0 +1,8 @@
+# shipBonusForceAuxiliaryM4WarfareLinksBonus
+#
+# Used by:
+# Ship: Lif
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Skirmish Warfare Specialist"), "commandBonus", src.getModifiedItemAttr("shipBonusForceAuxiliaryM4"), skill="Minmatar Carrier")
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Siege Warfare Specialist"), "commandBonus", src.getModifiedItemAttr("shipBonusForceAuxiliaryM4"), skill="Minmatar Carrier")
diff --git a/eos/effects/shipbonusforceauxiliaryrole1cpubonus.py b/eos/effects/shipbonusforceauxiliaryrole1cpubonus.py
new file mode 100644
index 000000000..41f57ed82
--- /dev/null
+++ b/eos/effects/shipbonusforceauxiliaryrole1cpubonus.py
@@ -0,0 +1,7 @@
+# shipBonusForceAuxiliaryRole1CPUBonus
+#
+# Used by:
+# Ships from group: Force Auxiliary (4 of 4)
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Leadership"), "cpu", src.getModifiedItemAttr("shipBonusRole1"))
diff --git a/eos/effects/shipbonusforceauxiliaryrole2logisticdronebonus.py b/eos/effects/shipbonusforceauxiliaryrole2logisticdronebonus.py
new file mode 100644
index 000000000..a401ef2a0
--- /dev/null
+++ b/eos/effects/shipbonusforceauxiliaryrole2logisticdronebonus.py
@@ -0,0 +1,9 @@
+# shipBonusForceAuxiliaryRole2LogisticDroneBonus
+#
+# Used by:
+# Ships from group: Force Auxiliary (4 of 4)
+type = "passive"
+def handler(fit, src, context):
+ fit.drones.filteredItemBoost(lambda mod: mod.item.requiresSkill("Repair Drone Operation"), "structureDamageAmount", src.getModifiedItemAttr("shipBonusRole2"))
+ fit.drones.filteredItemBoost(lambda mod: mod.item.requiresSkill("Repair Drone Operation"), "armorDamageAmount", src.getModifiedItemAttr("shipBonusRole2"))
+ fit.drones.filteredItemBoost(lambda mod: mod.item.requiresSkill("Repair Drone Operation"), "shieldBonus", src.getModifiedItemAttr("shipBonusRole2"))
diff --git a/eos/effects/shipbonusforceauxiliaryrole3numwarfarelinks.py b/eos/effects/shipbonusforceauxiliaryrole3numwarfarelinks.py
new file mode 100644
index 000000000..b44ffb8f0
--- /dev/null
+++ b/eos/effects/shipbonusforceauxiliaryrole3numwarfarelinks.py
@@ -0,0 +1,7 @@
+# shipBonusForceAuxiliaryRole3NumWarfareLinks
+#
+# Used by:
+# Ships from group: Force Auxiliary (4 of 4)
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemIncrease(lambda mod: mod.item.requiresSkill("Leadership"), "maxGroupActive", src.getModifiedItemAttr("shipBonusRole3"))
diff --git a/eos/effects/shipbonussupercarriera1fighterdamage.py b/eos/effects/shipbonussupercarriera1fighterdamage.py
new file mode 100644
index 000000000..a093c63aa
--- /dev/null
+++ b/eos/effects/shipbonussupercarriera1fighterdamage.py
@@ -0,0 +1,10 @@
+# shipBonusSupercarrierA1FighterDamage
+#
+# Used by:
+# Ship: Aeon
+# Ship: Revenant
+type = "passive"
+def handler(fit, src, context):
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityMissilesDamageMultiplier", src.getModifiedItemAttr("shipBonusSupercarrierA1"), skill="Amarr Carrier")
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackMissileDamageMultiplier", src.getModifiedItemAttr("shipBonusSupercarrierA1"), skill="Amarr Carrier")
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackTurretDamageMultiplier", src.getModifiedItemAttr("shipBonusSupercarrierA1"), skill="Amarr Carrier")
diff --git a/eos/effects/shipbonussupercarriera2armorresists.py b/eos/effects/shipbonussupercarriera2armorresists.py
new file mode 100644
index 000000000..3fb12647b
--- /dev/null
+++ b/eos/effects/shipbonussupercarriera2armorresists.py
@@ -0,0 +1,10 @@
+# shipBonusSupercarrierA2ArmorResists
+#
+# Used by:
+# Ship: Aeon
+type = "passive"
+def handler(fit, src, context):
+ fit.ship.boostItemAttr("armorExplosiveDamageResonance", src.getModifiedItemAttr("shipBonusSupercarrierA2"), skill="Amarr Carrier")
+ fit.ship.boostItemAttr("armorEmDamageResonance", src.getModifiedItemAttr("shipBonusSupercarrierA2"), skill="Amarr Carrier")
+ fit.ship.boostItemAttr("armorThermalDamageResonance", src.getModifiedItemAttr("shipBonusSupercarrierA2"), skill="Amarr Carrier")
+ fit.ship.boostItemAttr("armorKineticDamageResonance", src.getModifiedItemAttr("shipBonusSupercarrierA2"), skill="Amarr Carrier")
diff --git a/eos/effects/shipbonussupercarriera2fighterapplicationbonus.py b/eos/effects/shipbonussupercarriera2fighterapplicationbonus.py
new file mode 100644
index 000000000..c8567faf7
--- /dev/null
+++ b/eos/effects/shipbonussupercarriera2fighterapplicationbonus.py
@@ -0,0 +1,8 @@
+# shipBonusSupercarrierA2FighterApplicationBonus
+#
+# Used by:
+# Ship: Revenant
+type = "passive"
+def handler(fit, src, context):
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityMissilesExplosionVelocity", src.getModifiedItemAttr("shipBonusSupercarrierA2"), skill="Amarr Carrier")
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackMissileExplosionVelocity", src.getModifiedItemAttr("shipBonusSupercarrierA2"), skill="Amarr Carrier")
diff --git a/eos/effects/shipbonussupercarriera3warpstrength.py b/eos/effects/shipbonussupercarriera3warpstrength.py
new file mode 100644
index 000000000..13c8b0160
--- /dev/null
+++ b/eos/effects/shipbonussupercarriera3warpstrength.py
@@ -0,0 +1,8 @@
+# shipBonusSupercarrierA3WarpStrength
+#
+# Used by:
+# Ship: Aeon
+# Ship: Revenant
+type = "passive"
+def handler(fit, src, context):
+ fit.ship.increaseItemAttr("warpScrambleStatus", src.getModifiedItemAttr("shipBonusSupercarrierA3"), skill="Amarr Carrier")
diff --git a/eos/effects/shipbonussupercarriera4burstprojectorbonus.py b/eos/effects/shipbonussupercarriera4burstprojectorbonus.py
new file mode 100644
index 000000000..e4ad92cdc
--- /dev/null
+++ b/eos/effects/shipbonussupercarriera4burstprojectorbonus.py
@@ -0,0 +1,7 @@
+# shipBonusSupercarrierA4BurstProjectorBonus
+#
+# Used by:
+# Ship: Aeon
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Burst Projector Operation"), "durationWeaponDisruptionBurstProjector", src.getModifiedItemAttr("shipBonusSupercarrierA4"), skill="Amarr Carrier")
diff --git a/eos/effects/shipbonussupercarriera4fighterapplicationbonus.py b/eos/effects/shipbonussupercarriera4fighterapplicationbonus.py
new file mode 100644
index 000000000..4a28f6b5f
--- /dev/null
+++ b/eos/effects/shipbonussupercarriera4fighterapplicationbonus.py
@@ -0,0 +1,8 @@
+# shipBonusSupercarrierA4FighterApplicationBonus
+#
+# Used by:
+# Ship: Revenant
+type = "passive"
+def handler(fit, src, context):
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityMissilesExplosionRadius", src.getModifiedItemAttr("shipBonusSupercarrierA4"), skill="Amarr Carrier")
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackMissileExplosionRadius", src.getModifiedItemAttr("shipBonusSupercarrierA4"), skill="Amarr Carrier")
diff --git a/eos/effects/shipbonussupercarriera5warfarelinksbonus.py b/eos/effects/shipbonussupercarriera5warfarelinksbonus.py
new file mode 100644
index 000000000..eb48a0191
--- /dev/null
+++ b/eos/effects/shipbonussupercarriera5warfarelinksbonus.py
@@ -0,0 +1,8 @@
+# shipBonusSupercarrierA5WarfareLinksBonus
+#
+# Used by:
+# Ship: Aeon
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Information Warfare Specialist"), "commandBonus", src.getModifiedItemAttr("shipBonusSupercarrierA5"), skill="Amarr Carrier")
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Armored Warfare Specialist"), "commandBonus", src.getModifiedItemAttr("shipBonusSupercarrierA5"), skill="Amarr Carrier")
diff --git a/eos/effects/shipbonussupercarrierc1fighterdamage.py b/eos/effects/shipbonussupercarrierc1fighterdamage.py
new file mode 100644
index 000000000..b96d89ad7
--- /dev/null
+++ b/eos/effects/shipbonussupercarrierc1fighterdamage.py
@@ -0,0 +1,10 @@
+# shipBonusSupercarrierC1FighterDamage
+#
+# Used by:
+# Ship: Revenant
+# Ship: Wyvern
+type = "passive"
+def handler(fit, src, context):
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityMissilesDamageMultiplier", src.getModifiedItemAttr("shipBonusSupercarrierC1"), skill="Caldari Carrier")
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackTurretDamageMultiplier", src.getModifiedItemAttr("shipBonusSupercarrierC1"), skill="Caldari Carrier")
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackMissileDamageMultiplier", src.getModifiedItemAttr("shipBonusSupercarrierC1"), skill="Caldari Carrier")
diff --git a/eos/effects/shipbonussupercarrierc2afterburnerbonus.py b/eos/effects/shipbonussupercarrierc2afterburnerbonus.py
new file mode 100644
index 000000000..4ec867087
--- /dev/null
+++ b/eos/effects/shipbonussupercarrierc2afterburnerbonus.py
@@ -0,0 +1,7 @@
+# shipBonusSupercarrierC2AfterburnerBonus
+#
+# Used by:
+# Ship: Revenant
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Afterburner"), "speedFactor", src.getModifiedItemAttr("shipBonusSupercarrierC2"), skill="Caldari Carrier")
diff --git a/eos/effects/shipbonussupercarrierc2shieldresists.py b/eos/effects/shipbonussupercarrierc2shieldresists.py
new file mode 100644
index 000000000..f8334921b
--- /dev/null
+++ b/eos/effects/shipbonussupercarrierc2shieldresists.py
@@ -0,0 +1,10 @@
+# shipBonusSupercarrierC2ShieldResists
+#
+# Used by:
+# Ship: Wyvern
+type = "passive"
+def handler(fit, src, context):
+ fit.ship.boostItemAttr("shieldThermalDamageResonance", src.getModifiedItemAttr("shipBonusSupercarrierC2"), skill="Caldari Carrier")
+ fit.ship.boostItemAttr("shieldEmDamageResonance", src.getModifiedItemAttr("shipBonusSupercarrierC2"), skill="Caldari Carrier")
+ fit.ship.boostItemAttr("shieldKineticDamageResonance", src.getModifiedItemAttr("shipBonusSupercarrierC2"), skill="Caldari Carrier")
+ fit.ship.boostItemAttr("shieldExplosiveDamageResonance", src.getModifiedItemAttr("shipBonusSupercarrierC2"), skill="Caldari Carrier")
diff --git a/eos/effects/shipbonussupercarrierc3warpstrength.py b/eos/effects/shipbonussupercarrierc3warpstrength.py
new file mode 100644
index 000000000..d61a96370
--- /dev/null
+++ b/eos/effects/shipbonussupercarrierc3warpstrength.py
@@ -0,0 +1,8 @@
+# shipBonusSupercarrierC3WarpStrength
+#
+# Used by:
+# Ship: Revenant
+# Ship: Wyvern
+type = "passive"
+def handler(fit, src, context):
+ fit.ship.increaseItemAttr("warpScrambleStatus", src.getModifiedItemAttr("shipBonusSupercarrierC3"), skill="Caldari Carrier")
diff --git a/eos/effects/shipbonussupercarrierc4burstprojectorbonus.py b/eos/effects/shipbonussupercarrierc4burstprojectorbonus.py
new file mode 100644
index 000000000..e26358a72
--- /dev/null
+++ b/eos/effects/shipbonussupercarrierc4burstprojectorbonus.py
@@ -0,0 +1,7 @@
+# shipBonusSupercarrierC4BurstProjectorBonus
+#
+# Used by:
+# Ship: Wyvern
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Burst Projector Operation"), "durationECMJammerBurstProjector", src.getModifiedItemAttr("shipBonusSupercarrierC4"), skill="Caldari Carrier")
diff --git a/eos/effects/shipbonussupercarrierc5warfarelinksbonus.py b/eos/effects/shipbonussupercarrierc5warfarelinksbonus.py
new file mode 100644
index 000000000..ef76d206b
--- /dev/null
+++ b/eos/effects/shipbonussupercarrierc5warfarelinksbonus.py
@@ -0,0 +1,8 @@
+# shipBonusSupercarrierC5WarfareLinksBonus
+#
+# Used by:
+# Ship: Wyvern
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Information Warfare Specialist"), "commandBonus", src.getModifiedItemAttr("shipBonusSupercarrierC5"), skill="Caldari Carrier")
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Siege Warfare Specialist"), "commandBonus", src.getModifiedItemAttr("shipBonusSupercarrierC5"), skill="Caldari Carrier")
diff --git a/eos/effects/shipbonussupercarrierg1fighterdamage.py b/eos/effects/shipbonussupercarrierg1fighterdamage.py
new file mode 100644
index 000000000..366387ccd
--- /dev/null
+++ b/eos/effects/shipbonussupercarrierg1fighterdamage.py
@@ -0,0 +1,9 @@
+# shipBonusSupercarrierG1FighterDamage
+#
+# Used by:
+# Ship: Nyx
+type = "passive"
+def handler(fit, src, context):
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackTurretDamageMultiplier", src.getModifiedItemAttr("shipBonusSupercarrierG1"), skill="Gallente Carrier")
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityMissilesDamageMultiplier", src.getModifiedItemAttr("shipBonusSupercarrierG1"), skill="Gallente Carrier")
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackMissileDamageMultiplier", src.getModifiedItemAttr("shipBonusSupercarrierG1"), skill="Gallente Carrier")
diff --git a/eos/effects/shipbonussupercarrierg2fighterhitpoints.py b/eos/effects/shipbonussupercarrierg2fighterhitpoints.py
new file mode 100644
index 000000000..f18351da2
--- /dev/null
+++ b/eos/effects/shipbonussupercarrierg2fighterhitpoints.py
@@ -0,0 +1,7 @@
+# shipBonusSupercarrierG2FighterHitpoints
+#
+# Used by:
+# Ship: Nyx
+type = "passive"
+def handler(fit, src, context):
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "shieldCapacity", src.getModifiedItemAttr("shipBonusSupercarrierG2"), skill="Gallente Carrier")
diff --git a/eos/effects/shipbonussupercarrierg3warpstrength.py b/eos/effects/shipbonussupercarrierg3warpstrength.py
new file mode 100644
index 000000000..4d9ff26f1
--- /dev/null
+++ b/eos/effects/shipbonussupercarrierg3warpstrength.py
@@ -0,0 +1,7 @@
+# shipBonusSupercarrierG3WarpStrength
+#
+# Used by:
+# Ship: Nyx
+type = "passive"
+def handler(fit, src, context):
+ fit.ship.increaseItemAttr("warpScrambleStatus", src.getModifiedItemAttr("shipBonusSupercarrierG3"), skill="Gallente Carrier")
diff --git a/eos/effects/shipbonussupercarrierg4burstprojectorbonus.py b/eos/effects/shipbonussupercarrierg4burstprojectorbonus.py
new file mode 100644
index 000000000..d3f3cd7a2
--- /dev/null
+++ b/eos/effects/shipbonussupercarrierg4burstprojectorbonus.py
@@ -0,0 +1,7 @@
+# shipBonusSupercarrierG4BurstProjectorBonus
+#
+# Used by:
+# Ship: Nyx
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Burst Projector Operation"), "durationSensorDampeningBurstProjector", src.getModifiedItemAttr("shipBonusSupercarrierG4"), skill="Gallente Carrier")
diff --git a/eos/effects/shipbonussupercarrierg5warfarelinksbonus.py b/eos/effects/shipbonussupercarrierg5warfarelinksbonus.py
new file mode 100644
index 000000000..b1d975523
--- /dev/null
+++ b/eos/effects/shipbonussupercarrierg5warfarelinksbonus.py
@@ -0,0 +1,8 @@
+# shipBonusSupercarrierG5WarfareLinksBonus
+#
+# Used by:
+# Ship: Nyx
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Armored Warfare Specialist"), "commandBonus", src.getModifiedItemAttr("shipBonusSupercarrierG5"), skill="Gallente Carrier")
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Skirmish Warfare Specialist"), "commandBonus", src.getModifiedItemAttr("shipBonusSupercarrierG5"), skill="Gallente Carrier")
diff --git a/eos/effects/shipbonussupercarrierm1fighterdamage.py b/eos/effects/shipbonussupercarrierm1fighterdamage.py
new file mode 100644
index 000000000..5d1f73613
--- /dev/null
+++ b/eos/effects/shipbonussupercarrierm1fighterdamage.py
@@ -0,0 +1,9 @@
+# shipBonusSupercarrierM1FighterDamage
+#
+# Used by:
+# Ship: Hel
+type = "passive"
+def handler(fit, src, context):
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackMissileDamageMultiplier", src.getModifiedItemAttr("shipBonusSupercarrierM1"), skill="Minmatar Carrier")
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityMissilesDamageMultiplier", src.getModifiedItemAttr("shipBonusSupercarrierM1"), skill="Minmatar Carrier")
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackTurretDamageMultiplier", src.getModifiedItemAttr("shipBonusSupercarrierM1"), skill="Minmatar Carrier")
diff --git a/eos/effects/shipbonussupercarrierm2fightervelocity.py b/eos/effects/shipbonussupercarrierm2fightervelocity.py
new file mode 100644
index 000000000..123afebb8
--- /dev/null
+++ b/eos/effects/shipbonussupercarrierm2fightervelocity.py
@@ -0,0 +1,7 @@
+# shipBonusSupercarrierM2FighterVelocity
+#
+# Used by:
+# Ship: Hel
+type = "passive"
+def handler(fit, src, context):
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "maxVelocity", src.getModifiedItemAttr("shipBonusSupercarrierM2"), skill="Minmatar Carrier")
diff --git a/eos/effects/shipbonussupercarrierm3warpstrength.py b/eos/effects/shipbonussupercarrierm3warpstrength.py
new file mode 100644
index 000000000..7219ca9b2
--- /dev/null
+++ b/eos/effects/shipbonussupercarrierm3warpstrength.py
@@ -0,0 +1,7 @@
+# shipBonusSupercarrierM3WarpStrength
+#
+# Used by:
+# Ship: Hel
+type = "passive"
+def handler(fit, src, context):
+ fit.ship.increaseItemAttr("warpScrambleStatus", src.getModifiedItemAttr("shipBonusSupercarrierM3"), skill="Minmatar Carrier")
diff --git a/eos/effects/shipbonussupercarrierm4burstprojectorbonus.py b/eos/effects/shipbonussupercarrierm4burstprojectorbonus.py
new file mode 100644
index 000000000..bc5a9972a
--- /dev/null
+++ b/eos/effects/shipbonussupercarrierm4burstprojectorbonus.py
@@ -0,0 +1,7 @@
+# shipBonusSupercarrierM4BurstProjectorBonus
+#
+# Used by:
+# Ship: Hel
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Burst Projector Operation"), "durationTargetIlluminationBurstProjector", src.getModifiedItemAttr("shipBonusSupercarrierM4"), skill="Minmatar Carrier")
diff --git a/eos/effects/shipbonussupercarrierm5warfarelinksbonus.py b/eos/effects/shipbonussupercarrierm5warfarelinksbonus.py
new file mode 100644
index 000000000..f742dd710
--- /dev/null
+++ b/eos/effects/shipbonussupercarrierm5warfarelinksbonus.py
@@ -0,0 +1,8 @@
+# shipBonusSupercarrierM5WarfareLinksBonus
+#
+# Used by:
+# Ship: Hel
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Skirmish Warfare Specialist"), "commandBonus", src.getModifiedItemAttr("shipBonusSupercarrierM5"), skill="Minmatar Carrier")
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Siege Warfare Specialist"), "commandBonus", src.getModifiedItemAttr("shipBonusSupercarrierM5"), skill="Minmatar Carrier")
diff --git a/eos/effects/shipbonussupercarrierrole1numwarfarelinks.py b/eos/effects/shipbonussupercarrierrole1numwarfarelinks.py
new file mode 100644
index 000000000..ae8f4992c
--- /dev/null
+++ b/eos/effects/shipbonussupercarrierrole1numwarfarelinks.py
@@ -0,0 +1,7 @@
+# shipBonusSupercarrierRole1NumWarfareLinks
+#
+# Used by:
+# Ships from group: Supercarrier (5 of 5)
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemIncrease(lambda mod: mod.item.requiresSkill("Leadership"), "maxGroupActive", src.getModifiedItemAttr("shipBonusRole1"))
diff --git a/eos/effects/shipbonussupercarrierrole2armorshieldmodulebonus.py b/eos/effects/shipbonussupercarrierrole2armorshieldmodulebonus.py
new file mode 100644
index 000000000..3e9e5045a
--- /dev/null
+++ b/eos/effects/shipbonussupercarrierrole2armorshieldmodulebonus.py
@@ -0,0 +1,8 @@
+# shipBonusSupercarrierRole2ArmorShieldModuleBonus
+#
+# Used by:
+# Ships from group: Supercarrier (5 of 5)
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Hull Upgrades"), "armorHPBonusAdd", src.getModifiedItemAttr("shipBonusRole2"))
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Shield Upgrades"), "capacityBonus", src.getModifiedItemAttr("shipBonusRole2"))
diff --git a/eos/effects/shipbonustitana1damagebonus.py b/eos/effects/shipbonustitana1damagebonus.py
new file mode 100644
index 000000000..17f727696
--- /dev/null
+++ b/eos/effects/shipbonustitana1damagebonus.py
@@ -0,0 +1,7 @@
+# shipBonusTitanA1DamageBonus
+#
+# Used by:
+# Ship: Avatar
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Energy Turret"), "damageMultiplier", src.getModifiedItemAttr("shipBonusTitanA1"), skill="Amarr Titan")
diff --git a/eos/effects/shipbonustitana2capneed.py b/eos/effects/shipbonustitana2capneed.py
new file mode 100644
index 000000000..bec69b616
--- /dev/null
+++ b/eos/effects/shipbonustitana2capneed.py
@@ -0,0 +1,7 @@
+# shipBonusTitanA2CapNeed
+#
+# Used by:
+# Ship: Avatar
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Energy Turret"), "capacitorNeed", src.getModifiedItemAttr("shipBonusTitanA2"), skill="Amarr Titan")
diff --git a/eos/effects/shipbonustitana3warpstrength.py b/eos/effects/shipbonustitana3warpstrength.py
new file mode 100644
index 000000000..a496c1bfd
--- /dev/null
+++ b/eos/effects/shipbonustitana3warpstrength.py
@@ -0,0 +1,7 @@
+# shipBonusTitanA3WarpStrength
+#
+# Used by:
+# Ship: Avatar
+type = "passive"
+def handler(fit, src, context):
+ fit.ship.increaseItemAttr("warpScrambleStatus", src.getModifiedItemAttr("shipBonusTitanA3"), skill="Amarr Titan")
diff --git a/eos/effects/shipbonustitana4fleetbonus.py b/eos/effects/shipbonustitana4fleetbonus.py
new file mode 100644
index 000000000..b169eedf2
--- /dev/null
+++ b/eos/effects/shipbonustitana4fleetbonus.py
@@ -0,0 +1,13 @@
+# shipBonusTitanA4FleetBonus
+#
+# Used by:
+# Ship: Avatar
+type = "gang"
+gangBoost = "rechargeRate"
+gangBonus = "shipBonusTitanA4"
+runTime = "late"
+
+def handler(fit, src, context):
+ if "gang" not in context: return
+ fit.ship.boostItemAttr(gangBoost, src.getModifiedItemAttr(gangBonus) * src.parent.character.getSkill("Amarr Titan").level)
+
diff --git a/eos/effects/shipbonustitanc1kindamagebonus.py b/eos/effects/shipbonustitanc1kindamagebonus.py
new file mode 100644
index 000000000..0ca0dd671
--- /dev/null
+++ b/eos/effects/shipbonustitanc1kindamagebonus.py
@@ -0,0 +1,9 @@
+# shipBonusTitanC1KinDamageBonus
+#
+# Used by:
+# Ship: Leviathan
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("XL Torpedoes"), "kineticDamage", src.getModifiedItemAttr("shipBonusTitanC1"), skill="Caldari Titan")
+ fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("XL Cruise Missiles"), "kineticDamage", src.getModifiedItemAttr("shipBonusTitanC1"), skill="Caldari Titan")
+ fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("Torpedoes"), "kineticDamage", src.getModifiedItemAttr("shipBonusTitanC1"), skill="Caldari Titan")
diff --git a/eos/effects/shipbonustitanc2rofbonus.py b/eos/effects/shipbonustitanc2rofbonus.py
new file mode 100644
index 000000000..cd131d5d6
--- /dev/null
+++ b/eos/effects/shipbonustitanc2rofbonus.py
@@ -0,0 +1,9 @@
+# shipBonusTitanC2ROFBonus
+#
+# Used by:
+# Ship: Leviathan
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Missile Launcher XL Cruise", "speed", src.getModifiedItemAttr("shipBonusTitanC2"), skill="Caldari Titan")
+ fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Missile Launcher Rapid Torpedo", "speed", src.getModifiedItemAttr("shipBonusTitanC2"), skill="Caldari Titan")
+ fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Missile Launcher XL Torpedo", "speed", src.getModifiedItemAttr("shipBonusTitanC2"), skill="Caldari Titan")
diff --git a/eos/effects/shipbonustitanc3warpstrength.py b/eos/effects/shipbonustitanc3warpstrength.py
new file mode 100644
index 000000000..2cfdc56c4
--- /dev/null
+++ b/eos/effects/shipbonustitanc3warpstrength.py
@@ -0,0 +1,7 @@
+# shipBonusTitanC3WarpStrength
+#
+# Used by:
+# Ship: Leviathan
+type = "passive"
+def handler(fit, src, context):
+ fit.ship.increaseItemAttr("warpScrambleStatus", src.getModifiedItemAttr("shipBonusTitanC3"), skill="Caldari Titan")
diff --git a/eos/effects/shipbonustitanc4fleetbonus.py b/eos/effects/shipbonustitanc4fleetbonus.py
new file mode 100644
index 000000000..d5e909333
--- /dev/null
+++ b/eos/effects/shipbonustitanc4fleetbonus.py
@@ -0,0 +1,13 @@
+# shipBonusTitanC4FleetBonus
+#
+# Used by:
+# Ship: Leviathan
+type = "gang"
+gangBoost = "shieldCapacity"
+gangBonus = "shipBonusTitanC4"
+runTime = "late"
+
+def handler(fit, src, context):
+ if "gang" not in context: return
+ fit.ship.boostItemAttr(gangBoost, src.getModifiedItemAttr(gangBonus) * src.parent.character.getSkill("Caldari Titan").level)
+
diff --git a/eos/effects/shipbonustitanc5alldamagebonus.py b/eos/effects/shipbonustitanc5alldamagebonus.py
new file mode 100644
index 000000000..49e1a4651
--- /dev/null
+++ b/eos/effects/shipbonustitanc5alldamagebonus.py
@@ -0,0 +1,15 @@
+# shipBonusTitanC5AllDamageBonus
+#
+# Used by:
+# Ship: Leviathan
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("Torpedoes"), "emDamage", src.getModifiedItemAttr("shipBonusTitanC5"), skill="Caldari Titan")
+ fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("Torpedoes"), "explosiveDamage", src.getModifiedItemAttr("shipBonusTitanC5"), skill="Caldari Titan")
+ fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("Torpedoes"), "thermalDamage", src.getModifiedItemAttr("shipBonusTitanC5"), skill="Caldari Titan")
+ fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("XL Cruise Missiles"), "explosiveDamage", src.getModifiedItemAttr("shipBonusTitanC5"), skill="Caldari Titan")
+ fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("XL Cruise Missiles"), "thermalDamage", src.getModifiedItemAttr("shipBonusTitanC5"), skill="Caldari Titan")
+ fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("XL Cruise Missiles"), "emDamage", src.getModifiedItemAttr("shipBonusTitanC5"), skill="Caldari Titan")
+ fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("XL Torpedoes"), "thermalDamage", src.getModifiedItemAttr("shipBonusTitanC5"), skill="Caldari Titan")
+ fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("XL Torpedoes"), "emDamage", src.getModifiedItemAttr("shipBonusTitanC5"), skill="Caldari Titan")
+ fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("XL Torpedoes"), "explosiveDamage", src.getModifiedItemAttr("shipBonusTitanC5"), skill="Caldari Titan")
diff --git a/eos/effects/shipbonustitang1damagebonus.py b/eos/effects/shipbonustitang1damagebonus.py
new file mode 100644
index 000000000..065bb43fb
--- /dev/null
+++ b/eos/effects/shipbonustitang1damagebonus.py
@@ -0,0 +1,7 @@
+# shipBonusTitanG1DamageBonus
+#
+# Used by:
+# Ship: Erebus
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Hybrid Turret"), "damageMultiplier", src.getModifiedItemAttr("shipBonusTitanG1"), skill="Gallente Titan")
diff --git a/eos/effects/shipbonustitang2rofbonus.py b/eos/effects/shipbonustitang2rofbonus.py
new file mode 100644
index 000000000..2c713f32f
--- /dev/null
+++ b/eos/effects/shipbonustitang2rofbonus.py
@@ -0,0 +1,7 @@
+# shipBonusTitanG2ROFBonus
+#
+# Used by:
+# Ship: Erebus
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Hybrid Turret"), "speed", src.getModifiedItemAttr("shipBonusTitanG2"), skill="Gallente Titan")
diff --git a/eos/effects/shipbonustitang3warpstrength.py b/eos/effects/shipbonustitang3warpstrength.py
new file mode 100644
index 000000000..afe99bb65
--- /dev/null
+++ b/eos/effects/shipbonustitang3warpstrength.py
@@ -0,0 +1,7 @@
+# shipBonusTitanG3WarpStrength
+#
+# Used by:
+# Ship: Erebus
+type = "passive"
+def handler(fit, src, context):
+ fit.ship.increaseItemAttr("warpScrambleStatus", src.getModifiedItemAttr("shipBonusTitanG3"), skill="Gallente Titan")
diff --git a/eos/effects/shipbonustitang4fleetbonus.py b/eos/effects/shipbonustitang4fleetbonus.py
new file mode 100644
index 000000000..69b16ed03
--- /dev/null
+++ b/eos/effects/shipbonustitang4fleetbonus.py
@@ -0,0 +1,13 @@
+# shipBonusTitanG4FleetBonus
+#
+# Used by:
+# Ship: Erebus
+type = "gang"
+gangBoost = "armorHP"
+gangBonus = "shipBonusTitanG4"
+runTime = "late"
+
+def handler(fit, src, context):
+ if "gang" not in context: return
+ fit.ship.boostItemAttr(gangBoost, src.getModifiedItemAttr(gangBonus) * src.parent.character.getSkill("Gallente Titan").level)
+
diff --git a/eos/effects/shipbonustitanm1damagebonus.py b/eos/effects/shipbonustitanm1damagebonus.py
new file mode 100644
index 000000000..f011547f2
--- /dev/null
+++ b/eos/effects/shipbonustitanm1damagebonus.py
@@ -0,0 +1,7 @@
+# shipBonusTitanM1DamageBonus
+#
+# Used by:
+# Ship: Ragnarok
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Projectile Turret"), "damageMultiplier", src.getModifiedItemAttr("shipBonusTitanM1"), skill="Minmatar Titan")
diff --git a/eos/effects/shipbonustitanm2rofbonus.py b/eos/effects/shipbonustitanm2rofbonus.py
new file mode 100644
index 000000000..ba663cf9f
--- /dev/null
+++ b/eos/effects/shipbonustitanm2rofbonus.py
@@ -0,0 +1,7 @@
+# shipBonusTitanM2ROFBonus
+#
+# Used by:
+# Ship: Ragnarok
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Projectile Turret"), "speed", src.getModifiedItemAttr("shipBonusTitanM2"), skill="Minmatar Titan")
diff --git a/eos/effects/shipbonustitanm3warpstrength.py b/eos/effects/shipbonustitanm3warpstrength.py
new file mode 100644
index 000000000..fc3969e07
--- /dev/null
+++ b/eos/effects/shipbonustitanm3warpstrength.py
@@ -0,0 +1,7 @@
+# shipBonusTitanM3WarpStrength
+#
+# Used by:
+# Ship: Ragnarok
+type = "passive"
+def handler(fit, src, context):
+ fit.ship.increaseItemAttr("warpScrambleStatus", src.getModifiedItemAttr("shipBonusTitanM3"), skill="Minmatar Titan")
diff --git a/eos/effects/shipbonustitanm4fleetbonus.py b/eos/effects/shipbonustitanm4fleetbonus.py
new file mode 100644
index 000000000..4fc14259e
--- /dev/null
+++ b/eos/effects/shipbonustitanm4fleetbonus.py
@@ -0,0 +1,13 @@
+# shipBonusTitanM4FleetBonus
+#
+# Used by:
+# Ship: Ragnarok
+type = "gang"
+gangBoost = "signatureRadius"
+gangBonus = "shipBonusTitanM4"
+runTime = "late"
+
+def handler(fit, src, context):
+ if "gang" not in context: return
+ fit.ship.boostItemAttr(gangBoost, src.getModifiedItemAttr(gangBonus) * src.parent.character.getSkill("Minmatar Titan").level)
+
diff --git a/eos/effects/shipbonustitanrole1numwarfarelinks.py b/eos/effects/shipbonustitanrole1numwarfarelinks.py
new file mode 100644
index 000000000..94033c2ec
--- /dev/null
+++ b/eos/effects/shipbonustitanrole1numwarfarelinks.py
@@ -0,0 +1,7 @@
+# shipBonusTitanRole1NumWarfareLinks
+#
+# Used by:
+# Ships from group: Titan (4 of 4)
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemIncrease(lambda mod: mod.item.requiresSkill("Leadership"), "maxGroupActive", src.getModifiedItemAttr("shipBonusRole1"))
diff --git a/eos/effects/shipbonustitanrole2armorshieldmodulebonus.py b/eos/effects/shipbonustitanrole2armorshieldmodulebonus.py
new file mode 100644
index 000000000..4a709be5f
--- /dev/null
+++ b/eos/effects/shipbonustitanrole2armorshieldmodulebonus.py
@@ -0,0 +1,8 @@
+# shipBonusTitanRole2ArmorShieldModuleBonus
+#
+# Used by:
+# Ships from group: Titan (4 of 4)
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Hull Upgrades"), "armorHPBonusAdd", src.getModifiedItemAttr("shipBonusRole2"))
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Shield Upgrades"), "capacityBonus", src.getModifiedItemAttr("shipBonusRole2"))
diff --git a/eos/effects/shipbonustitanrole3torpdeovelocitybonus.py b/eos/effects/shipbonustitanrole3torpdeovelocitybonus.py
new file mode 100644
index 000000000..75d2a4cdd
--- /dev/null
+++ b/eos/effects/shipbonustitanrole3torpdeovelocitybonus.py
@@ -0,0 +1,7 @@
+# shipBonusTitanRole3TorpdeoVelocityBonus
+#
+# Used by:
+# Ship: Leviathan
+type = "passive"
+def handler(fit, src, context):
+ fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("Torpedoes"), "maxVelocity", src.getModifiedItemAttr("shipBonusRole3"))
diff --git a/eos/effects/shipcapitalagilitybonus.py b/eos/effects/shipcapitalagilitybonus.py
new file mode 100644
index 000000000..2eaf6d370
--- /dev/null
+++ b/eos/effects/shipcapitalagilitybonus.py
@@ -0,0 +1,8 @@
+# shipCapitalAgilityBonus
+#
+# Used by:
+# Ships from group: Supercarrier (5 of 5)
+# Items from market group: Ships > Capital Ships (22 of 32)
+type = "passive"
+def handler(fit, src, context):
+ fit.ship.multiplyItemAttr("agility", src.getModifiedItemAttr("advancedCapitalAgility"), stackingPenalties=True)
diff --git a/eos/effects/shipenergytransferrange1.py b/eos/effects/shipenergytransferrange1.py
index 193af0dbb..7a8182c86 100644
--- a/eos/effects/shipenergytransferrange1.py
+++ b/eos/effects/shipenergytransferrange1.py
@@ -5,4 +5,4 @@
type = "passive"
def handler(fit, ship, context):
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Remote Capacitor Transmitter",
- "powerTransferRange", ship.getModifiedItemAttr("shipBonusAC"), skill="Amarr Cruiser")
+ "maxRange", ship.getModifiedItemAttr("shipBonusAC"), skill="Amarr Cruiser")
diff --git a/eos/effects/shipenergytransferrange2.py b/eos/effects/shipenergytransferrange2.py
index adac10fcc..a80259cb2 100644
--- a/eos/effects/shipenergytransferrange2.py
+++ b/eos/effects/shipenergytransferrange2.py
@@ -6,4 +6,4 @@
type = "passive"
def handler(fit, ship, context):
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Remote Capacitor Transmitter",
- "powerTransferRange", ship.getModifiedItemAttr("shipBonusCC2"), skill="Caldari Cruiser")
+ "maxRange", ship.getModifiedItemAttr("shipBonusCC2"), skill="Caldari Cruiser")
diff --git a/eos/effects/siegemodeeffect6.py b/eos/effects/siegemodeeffect6.py
index f94a2b25d..8b27e7809 100644
--- a/eos/effects/siegemodeeffect6.py
+++ b/eos/effects/siegemodeeffect6.py
@@ -46,7 +46,7 @@ def handler(fit, module, context):
fit.ship.boostItemAttr("maxVelocity", module.getModifiedItemAttr("speedFactor"))
#Mass
- fit.ship.multiplyItemAttr("mass", module.getModifiedItemAttr("massMultiplier"))
+ fit.ship.multiplyItemAttr("mass", module.getModifiedItemAttr("siegeMassMultiplier"))
#Scan resolution
fit.ship.multiplyItemAttr("scanResolution", module.getModifiedItemAttr("scanResolutionMultiplier"),
diff --git a/eos/effects/skillbonuscapitalartilleryspecialization.py b/eos/effects/skillbonuscapitalartilleryspecialization.py
new file mode 100644
index 000000000..521c6e8d2
--- /dev/null
+++ b/eos/effects/skillbonuscapitalartilleryspecialization.py
@@ -0,0 +1,8 @@
+# skillBonusCapitalArtillerySpecialization
+#
+# Used by:
+# Skill: Capital Artillery Specialization
+type = "passive"
+def handler(fit, src, context):
+ lvl = src.level
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Artillery Specialization"), "damageMultiplier", src.getModifiedItemAttr("damageMultiplierBonus") * lvl)
diff --git a/eos/effects/skillbonuscapitalautocannonspecialization.py b/eos/effects/skillbonuscapitalautocannonspecialization.py
new file mode 100644
index 000000000..d4fda1400
--- /dev/null
+++ b/eos/effects/skillbonuscapitalautocannonspecialization.py
@@ -0,0 +1,8 @@
+# skillBonusCapitalAutocannonSpecialization
+#
+# Used by:
+# Skill: Capital Autocannon Specialization
+type = "passive"
+def handler(fit, src, context):
+ lvl = src.level
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Autocannon Specialization"), "damageMultiplier", src.getModifiedItemAttr("damageMultiplierBonus") * lvl)
diff --git a/eos/effects/skillbonuscapitalbeamlaserspecialization.py b/eos/effects/skillbonuscapitalbeamlaserspecialization.py
new file mode 100644
index 000000000..6fcecf510
--- /dev/null
+++ b/eos/effects/skillbonuscapitalbeamlaserspecialization.py
@@ -0,0 +1,8 @@
+# skillBonusCapitalBeamLaserSpecialization
+#
+# Used by:
+# Skill: Capital Beam Laser Specialization
+type = "passive"
+def handler(fit, src, context):
+ lvl = src.level
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Beam Laser Specialization"), "damageMultiplier", src.getModifiedItemAttr("damageMultiplierBonus") * lvl)
diff --git a/eos/effects/skillbonuscapitalblasterspecialization.py b/eos/effects/skillbonuscapitalblasterspecialization.py
new file mode 100644
index 000000000..93f0c5624
--- /dev/null
+++ b/eos/effects/skillbonuscapitalblasterspecialization.py
@@ -0,0 +1,8 @@
+# skillBonusCapitalBlasterSpecialization
+#
+# Used by:
+# Skill: Capital Blaster Specialization
+type = "passive"
+def handler(fit, src, context):
+ lvl = src.level
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Blaster Specialization"), "damageMultiplier", src.getModifiedItemAttr("damageMultiplierBonus") * lvl)
diff --git a/eos/effects/skillbonuscapitalpulselaserspecialization.py b/eos/effects/skillbonuscapitalpulselaserspecialization.py
new file mode 100644
index 000000000..d658a3ce1
--- /dev/null
+++ b/eos/effects/skillbonuscapitalpulselaserspecialization.py
@@ -0,0 +1,8 @@
+# skillBonusCapitalPulseLaserSpecialization
+#
+# Used by:
+# Skill: Capital Pulse Laser Specialization
+type = "passive"
+def handler(fit, src, context):
+ lvl = src.level
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Pulse Laser Specialization"), "damageMultiplier", src.getModifiedItemAttr("damageMultiplierBonus") * lvl)
diff --git a/eos/effects/skillbonuscapitalrailgunspecialization.py b/eos/effects/skillbonuscapitalrailgunspecialization.py
new file mode 100644
index 000000000..f341c1e1a
--- /dev/null
+++ b/eos/effects/skillbonuscapitalrailgunspecialization.py
@@ -0,0 +1,8 @@
+# skillBonusCapitalRailgunSpecialization
+#
+# Used by:
+# Skill: Capital Railgun Specialization
+type = "passive"
+def handler(fit, src, context):
+ lvl = src.level
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Railgun Specialization"), "damageMultiplier", src.getModifiedItemAttr("damageMultiplierBonus") * lvl)
diff --git a/eos/effects/skillbonusdoomsdayrapidfiring.py b/eos/effects/skillbonusdoomsdayrapidfiring.py
new file mode 100644
index 000000000..27c182a16
--- /dev/null
+++ b/eos/effects/skillbonusdoomsdayrapidfiring.py
@@ -0,0 +1,8 @@
+# skillBonusDoomsdayRapidFiring
+#
+# Used by:
+# Skill: Doomsday Rapid Firing
+type = "passive"
+def handler(fit, src, context):
+ lvl = src.level
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Doomsday Operation"), "duration", src.getModifiedItemAttr("rofBonus") * lvl)
diff --git a/eos/effects/skillbonusdronedurability.py b/eos/effects/skillbonusdronedurability.py
new file mode 100644
index 000000000..aa0261990
--- /dev/null
+++ b/eos/effects/skillbonusdronedurability.py
@@ -0,0 +1,11 @@
+# skillBonusDroneDurability
+#
+# Used by:
+# Skill: Drone Durability
+type = "passive"
+def handler(fit, src, context):
+ lvl = src.level
+ fit.drones.filteredItemBoost(lambda mod: mod.item.requiresSkill("Drones"), "hp", src.getModifiedItemAttr("hullHpBonus") * lvl)
+ fit.drones.filteredItemBoost(lambda mod: mod.item.requiresSkill("Drones"), "armorHP", src.getModifiedItemAttr("armorHpBonus") * lvl)
+ fit.drones.filteredItemBoost(lambda mod: mod.item.requiresSkill("Drones"), "shieldCapacity", src.getModifiedItemAttr("shieldCapacityBonus") * lvl)
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "shieldCapacity", src.getModifiedItemAttr("shieldCapacityBonus") * lvl)
diff --git a/eos/effects/skillbonusdroneinterfacing.py b/eos/effects/skillbonusdroneinterfacing.py
new file mode 100644
index 000000000..a71416ce6
--- /dev/null
+++ b/eos/effects/skillbonusdroneinterfacing.py
@@ -0,0 +1,12 @@
+# skillBonusDroneInterfacing
+#
+# Used by:
+# Skill: Drone Interfacing
+type = "passive"
+def handler(fit, src, context):
+ lvl = src.level
+ fit.drones.filteredItemBoost(lambda mod: mod.item.requiresSkill("Drones"), "damageMultiplier", src.getModifiedItemAttr("damageMultiplierBonus") * lvl)
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackMissileDamageMultiplier", src.getModifiedItemAttr("damageMultiplierBonus") * lvl)
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackTurretDamageMultiplier", src.getModifiedItemAttr("damageMultiplierBonus") * lvl)
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityMissilesDamageMultiplier", src.getModifiedItemAttr("damageMultiplierBonus") * lvl)
+ fit.drones.filteredItemBoost(lambda drone: drone.item.group.name == "Mining Drone", "miningDroneAmountPercent", src.getModifiedItemAttr("miningAmountBonus") * lvl)
diff --git a/eos/effects/skillbonusdronenavigation.py b/eos/effects/skillbonusdronenavigation.py
new file mode 100644
index 000000000..618ae51fa
--- /dev/null
+++ b/eos/effects/skillbonusdronenavigation.py
@@ -0,0 +1,9 @@
+# skillBonusDroneNavigation
+#
+# Used by:
+# Skill: Drone Navigation
+type = "passive"
+def handler(fit, src, context):
+ lvl = src.level
+ fit.drones.filteredItemBoost(lambda mod: mod.item.requiresSkill("Drones"), "maxVelocity", src.getModifiedItemAttr("droneMaxVelocityBonus") * lvl)
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "maxVelocity", src.getModifiedItemAttr("droneMaxVelocityBonus") * lvl)
diff --git a/eos/effects/skillbonusdronesharpshooting.py b/eos/effects/skillbonusdronesharpshooting.py
new file mode 100644
index 000000000..666ffed05
--- /dev/null
+++ b/eos/effects/skillbonusdronesharpshooting.py
@@ -0,0 +1,11 @@
+# skillBonusDroneSharpshooting
+#
+# Used by:
+# Skill: Drone Sharpshooting
+type = "passive"
+def handler(fit, src, context):
+ lvl = src.level
+ fit.drones.filteredItemBoost(lambda mod: mod.item.requiresSkill("Drones"), "maxRange", src.getModifiedItemAttr("rangeSkillBonus") * lvl)
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityMissilesRange", src.getModifiedItemAttr("rangeSkillBonus") * lvl)
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackTurretRangeOptimal", src.getModifiedItemAttr("rangeSkillBonus") * lvl)
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackMissileRangeOptimal", src.getModifiedItemAttr("rangeSkillBonus") * lvl)
diff --git a/eos/effects/skillbonusfighterhangermanagement.py b/eos/effects/skillbonusfighterhangermanagement.py
new file mode 100644
index 000000000..b871c6173
--- /dev/null
+++ b/eos/effects/skillbonusfighterhangermanagement.py
@@ -0,0 +1,8 @@
+# skillBonusFighterHangerManagement
+#
+# Used by:
+# Skill: Fighter Hangar Management
+type = "passive"
+def handler(fit, src, context):
+ lvl = src.level
+ fit.ship.boostItemAttr("fighterCapacity", src.getModifiedItemAttr("skillBonusFighterHangarSize") * lvl)
diff --git a/eos/effects/skillbonusfighters.py b/eos/effects/skillbonusfighters.py
new file mode 100644
index 000000000..7a362a669
--- /dev/null
+++ b/eos/effects/skillbonusfighters.py
@@ -0,0 +1,10 @@
+# skillBonusFighters
+#
+# Used by:
+# Skill: Fighters
+type = "passive"
+def handler(fit, src, context):
+ lvl = src.level
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackMissileDamageMultiplier", src.getModifiedItemAttr("damageMultiplierBonus") * lvl)
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackTurretDamageMultiplier", src.getModifiedItemAttr("damageMultiplierBonus") * lvl)
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityMissilesDamageMultiplier", src.getModifiedItemAttr("damageMultiplierBonus") * lvl)
diff --git a/eos/effects/skillbonusfightersdamage.py b/eos/effects/skillbonusfightersdamage.py
new file mode 100644
index 000000000..a887ab0c5
--- /dev/null
+++ b/eos/effects/skillbonusfightersdamage.py
@@ -0,0 +1,10 @@
+# skillBonusFightersDamage
+#
+# Used by:
+# Skill: Fighters
+type = "passive"
+def handler(fit, src, context):
+ lvl = src.level
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackTurretDamageMultiplier", src.getModifiedItemAttr("damageMultiplierBonus") * lvl)
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityMissilesDamageMultiplier", src.getModifiedItemAttr("damageMultiplierBonus") * lvl)
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Fighters"), "fighterAbilityAttackMissileDamageMultiplier", src.getModifiedItemAttr("damageMultiplierBonus") * lvl)
diff --git a/eos/effects/skillbonusheavyfighters.py b/eos/effects/skillbonusheavyfighters.py
new file mode 100644
index 000000000..ffbb419fc
--- /dev/null
+++ b/eos/effects/skillbonusheavyfighters.py
@@ -0,0 +1,10 @@
+# skillBonusHeavyFighters
+#
+# Used by:
+# Skill: Heavy Fighters
+type = "passive"
+def handler(fit, src, context):
+ lvl = src.level
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Heavy Fighters"), "fighterAbilityMissilesDamageMultiplier", src.getModifiedItemAttr("damageMultiplierBonus") * lvl)
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Heavy Fighters"), "fighterAbilityAttackMissileDamageMultiplier", src.getModifiedItemAttr("damageMultiplierBonus") * lvl)
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Heavy Fighters"), "fighterAbilityAttackTurretDamageMultiplier", src.getModifiedItemAttr("damageMultiplierBonus") * lvl)
diff --git a/eos/effects/skillbonusheavyfightersdamage.py b/eos/effects/skillbonusheavyfightersdamage.py
new file mode 100644
index 000000000..786b1985e
--- /dev/null
+++ b/eos/effects/skillbonusheavyfightersdamage.py
@@ -0,0 +1,10 @@
+# skillBonusHeavyFightersDamage
+#
+# Used by:
+# Skill: Heavy Fighters
+type = "passive"
+def handler(fit, src, context):
+ lvl = src.level
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Heavy Fighters"), "fighterAbilityAttackMissileDamageMultiplier", src.getModifiedItemAttr("damageMultiplierBonus") * lvl)
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Heavy Fighters"), "fighterAbilityMissilesDamageMultiplier", src.getModifiedItemAttr("damageMultiplierBonus") * lvl)
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Heavy Fighters"), "fighterAbilityAttackTurretDamageMultiplier", src.getModifiedItemAttr("damageMultiplierBonus") * lvl)
diff --git a/eos/effects/skillbonuslightfighters.py b/eos/effects/skillbonuslightfighters.py
new file mode 100644
index 000000000..9a2e0d014
--- /dev/null
+++ b/eos/effects/skillbonuslightfighters.py
@@ -0,0 +1,8 @@
+# skillBonusLightFighters
+#
+# Used by:
+# Skill: Light Fighters
+type = "passive"
+def handler(fit, src, context):
+ lvl = src.level
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Light Fighters"), "maxVelocity", src.getModifiedItemAttr("maxVelocityBonus") * lvl)
diff --git a/eos/effects/skillbonuslightfightersvelocity.py b/eos/effects/skillbonuslightfightersvelocity.py
new file mode 100644
index 000000000..dfcb2dd6f
--- /dev/null
+++ b/eos/effects/skillbonuslightfightersvelocity.py
@@ -0,0 +1,8 @@
+# skillBonusLightFightersVelocity
+#
+# Used by:
+# Skill: Light Fighters
+type = "passive"
+def handler(fit, src, context):
+ lvl = src.level
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Light Fighters"), "maxVelocity", src.getModifiedItemAttr("maxVelocityBonus") * lvl)
diff --git a/eos/effects/skillbonussupportfightersshield.py b/eos/effects/skillbonussupportfightersshield.py
new file mode 100644
index 000000000..bfcb0360c
--- /dev/null
+++ b/eos/effects/skillbonussupportfightersshield.py
@@ -0,0 +1,8 @@
+# skillBonusSupportFightersShield
+#
+# Used by:
+# Skill: Support Fighters
+type = "passive"
+def handler(fit, src, context):
+ lvl = src.level
+ fit.fighters.filteredItemBoost(lambda mod: mod.item.requiresSkill("Support Fighters"), "shieldCapacity", src.getModifiedItemAttr("shieldBonus") * lvl)
diff --git a/eos/effects/skillbonusxlcruisemissilespecialization.py b/eos/effects/skillbonusxlcruisemissilespecialization.py
new file mode 100644
index 000000000..a2adfc740
--- /dev/null
+++ b/eos/effects/skillbonusxlcruisemissilespecialization.py
@@ -0,0 +1,8 @@
+# skillBonusXLCruiseMissileSpecialization
+#
+# Used by:
+# Skill: XL Cruise Missile Specialization
+type = "passive"
+def handler(fit, src, context):
+ lvl = src.level
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("XL Cruise Missile Specialization"), "speed", src.getModifiedItemAttr("rofBonus") * lvl)
diff --git a/eos/effects/skillbonusxltorpedospecialization.py b/eos/effects/skillbonusxltorpedospecialization.py
new file mode 100644
index 000000000..af620d036
--- /dev/null
+++ b/eos/effects/skillbonusxltorpedospecialization.py
@@ -0,0 +1,8 @@
+# skillBonusXLTorpedoSpecialization
+#
+# Used by:
+# Skill: XL Torpedo Specialization
+type = "passive"
+def handler(fit, src, context):
+ lvl = src.level
+ fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("XL Torpedo Specialization"), "speed", src.getModifiedItemAttr("rofBonus") * lvl)
diff --git a/eos/effects/skillreactivearmorhardenercapneedbonus.py b/eos/effects/skillreactivearmorhardenercapneedbonus.py
index 260375d01..a9c02f401 100644
--- a/eos/effects/skillreactivearmorhardenercapneedbonus.py
+++ b/eos/effects/skillreactivearmorhardenercapneedbonus.py
@@ -1,7 +1,7 @@
# skillReactiveArmorHardenerCapNeedBonus
#
# Used by:
-# Skill: Armor Resistance Phasing
+# Skill: Resistance Phasing
type = "passive"
def handler(fit, skill, context):
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Armor Resistance Shift Hardener",
diff --git a/eos/effects/skillreactivearmorhardenerdurationbonus.py b/eos/effects/skillreactivearmorhardenerdurationbonus.py
index cd7528f81..ff0861db3 100644
--- a/eos/effects/skillreactivearmorhardenerdurationbonus.py
+++ b/eos/effects/skillreactivearmorhardenerdurationbonus.py
@@ -1,7 +1,7 @@
# skillReactiveArmorHardenerDurationBonus
#
# Used by:
-# Skill: Armor Resistance Phasing
+# Skill: Resistance Phasing
type = "passive"
def handler(fit, skill, context):
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Armor Resistance Shift Hardener",
diff --git a/eos/effects/skillremoteecmdurationbonus.py b/eos/effects/skillremoteecmdurationbonus.py
index aed112cb6..6f48b8369 100644
--- a/eos/effects/skillremoteecmdurationbonus.py
+++ b/eos/effects/skillremoteecmdurationbonus.py
@@ -1,8 +1,8 @@
# skillRemoteECMDurationBonus
#
# Used by:
-# Skill: Projected Electronic Counter Measures
+# Skill: Burst Projector Operation
type = "passive"
def handler(fit, skill, context):
- fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Remote ECM Burst",
+ fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Burst Projectors",
"duration", skill.getModifiedItemAttr("projECMDurationBonus") * skill.level)
diff --git a/eos/effects/speedboostmassaddition.py b/eos/effects/speedboostmassaddition.py
index c8dd1b62a..950c1abb5 100644
--- a/eos/effects/speedboostmassaddition.py
+++ b/eos/effects/speedboostmassaddition.py
@@ -1,9 +1,7 @@
# speedBoostMassAddition
#
# Used by:
-# Variations of module: 100MN Afterburner I (25 of 25)
-# Variations of module: 10MN Afterburner I (15 of 15)
-# Variations of module: 1MN Afterburner I (16 of 16)
+# Modules from group: Propulsion Module (62 of 127)
type = "active"
runTime = "late"
def handler(fit, module, context):
diff --git a/eos/effects/speedboostmasssigrad.py b/eos/effects/speedboostmasssigrad.py
index 26f9614f3..11051b5a9 100644
--- a/eos/effects/speedboostmasssigrad.py
+++ b/eos/effects/speedboostmasssigrad.py
@@ -1,9 +1,7 @@
# speedBoostMassSigRad
#
# Used by:
-# Variations of module: 500MN Microwarpdrive I (26 of 26)
-# Variations of module: 50MN Microwarpdrive I (16 of 16)
-# Variations of module: 5MN Microwarpdrive I (16 of 16)
+# Modules from group: Propulsion Module (65 of 127)
type = "active"
runTime = "late"
def handler(fit, module, context):
diff --git a/eos/effects/structurerepair.py b/eos/effects/structurerepair.py
index c1809a49f..2dcab2688 100644
--- a/eos/effects/structurerepair.py
+++ b/eos/effects/structurerepair.py
@@ -1,7 +1,7 @@
# structureRepair
#
# Used by:
-# Modules from group: Hull Repair Unit (21 of 21)
+# Modules from group: Hull Repair Unit (25 of 25)
type = "active"
runTime = "late"
def handler(fit, module, context):
diff --git a/eos/effects/superweaponamarr.py b/eos/effects/superweaponamarr.py
index a43d43128..0295fe8cd 100644
--- a/eos/effects/superweaponamarr.py
+++ b/eos/effects/superweaponamarr.py
@@ -1,7 +1,7 @@
# superWeaponAmarr
#
# Used by:
-# Module: Judgement
+# Module: 'Judgment' Electromagnetic Doomsday
type = 'active'
def handler(fit, module, context):
pass
diff --git a/eos/effects/superweaponcaldari.py b/eos/effects/superweaponcaldari.py
index f7fc8f146..a7e8874b3 100644
--- a/eos/effects/superweaponcaldari.py
+++ b/eos/effects/superweaponcaldari.py
@@ -1,7 +1,7 @@
# superWeaponCaldari
#
# Used by:
-# Module: Oblivion
+# Module: 'Oblivion' Kinetic Doomsday
type = 'active'
def handler(fit, module, context):
pass
diff --git a/eos/effects/superweapongallente.py b/eos/effects/superweapongallente.py
index b4e20e364..8f1a06075 100644
--- a/eos/effects/superweapongallente.py
+++ b/eos/effects/superweapongallente.py
@@ -1,7 +1,7 @@
# superWeaponGallente
#
# Used by:
-# Module: Aurora Ominae
+# Module: 'Aurora Ominae' Thermal Doomsday
type = 'active'
def handler(fit, module, context):
pass
diff --git a/eos/effects/superweaponminmatar.py b/eos/effects/superweaponminmatar.py
index 444cc302d..f3e370957 100644
--- a/eos/effects/superweaponminmatar.py
+++ b/eos/effects/superweaponminmatar.py
@@ -1,7 +1,7 @@
# superWeaponMinmatar
#
# Used by:
-# Module: Gjallarhorn
+# Module: 'Gjallarhorn' Explosive Doomsday
type = 'active'
def handler(fit, module, context):
pass
diff --git a/eos/effects/surgicalstrikedamagemultiplierbonuspostpercentdamagemultiplierlocationshipmodulesrequiringgunnery.py b/eos/effects/surgicalstrikedamagemultiplierbonuspostpercentdamagemultiplierlocationshipmodulesrequiringgunnery.py
index eb111421b..c33420947 100644
--- a/eos/effects/surgicalstrikedamagemultiplierbonuspostpercentdamagemultiplierlocationshipmodulesrequiringgunnery.py
+++ b/eos/effects/surgicalstrikedamagemultiplierbonuspostpercentdamagemultiplierlocationshipmodulesrequiringgunnery.py
@@ -1,8 +1,8 @@
# surgicalStrikeDamageMultiplierBonusPostPercentDamageMultiplierLocationShipModulesRequiringGunnery
#
# Used by:
-# Implants named like: Cerebral Accelerator (3 of 3)
# Implants named like: Eifyr and Co. 'Gunslinger' Surgical Strike SS (6 of 6)
+# Implant: Standard Cerebral Accelerator
type = "passive"
def handler(fit, implant, context):
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Gunnery"),
diff --git a/eos/effects/targetarmorrepair.py b/eos/effects/targetarmorrepair.py
index 7adf280c9..8cb72da9d 100644
--- a/eos/effects/targetarmorrepair.py
+++ b/eos/effects/targetarmorrepair.py
@@ -1,7 +1,6 @@
# targetArmorRepair
#
# Used by:
-# Drones named like: Armor Maintenance Bot (6 of 6)
# Module: QA Remote Armor Repair System - 5 Players
type = "projected", "active"
def handler(fit, container, context):
diff --git a/eos/effects/targetattack.py b/eos/effects/targetattack.py
index 3fafbf2fa..156220718 100644
--- a/eos/effects/targetattack.py
+++ b/eos/effects/targetattack.py
@@ -2,8 +2,7 @@
#
# Used by:
# Drones from group: Combat Drone (74 of 74)
-# Drones from group: Fighter Drone (4 of 4)
-# Modules from group: Energy Weapon (186 of 187)
+# Modules from group: Energy Weapon (208 of 209)
type = 'active'
def handler(fit, module, context):
# Set reload time to 1 second
diff --git a/eos/effects/titancaldarimissilekineticdmg2.py b/eos/effects/titancaldarimissilekineticdmg2.py
index 0f5732b82..af9079da1 100644
--- a/eos/effects/titancaldarimissilekineticdmg2.py
+++ b/eos/effects/titancaldarimissilekineticdmg2.py
@@ -4,6 +4,6 @@
# Ship: Leviathan
type = "passive"
def handler(fit, ship, context):
- groups = ("Capital Torpedo", "Capital Cruise")
+ groups = ("XL Torpedo", "XL Cruise Missile")
fit.modules.filteredChargeBoost(lambda mod: mod.charge.group.name in groups,
"kineticDamage", ship.getModifiedItemAttr("shipBonusCT1"), skill="Caldari Titan")
diff --git a/eos/effects/triagemodeeffect3.py b/eos/effects/triagemodeeffect3.py
index eeb4bbf78..763f8ca73 100644
--- a/eos/effects/triagemodeeffect3.py
+++ b/eos/effects/triagemodeeffect3.py
@@ -53,7 +53,7 @@ def handler(fit, module, context):
stackingPenalties=True)
# Mass multiplier
- fit.ship.multiplyItemAttr("mass", module.getModifiedItemAttr("massMultiplier"),
+ fit.ship.multiplyItemAttr("mass", module.getModifiedItemAttr("siegeMassMultiplier"),
stackingPenalties=True)
# Lock range
@@ -70,7 +70,7 @@ def handler(fit, module, context):
# EW cap need increase
groups = [
'Burst Jammer',
- 'Remote ECM Burst',
+ 'Burst Projectors',
'Weapon Disruptor',
'ECM',
'Remote Sensor Damper',
diff --git a/eos/effects/triagemodeeffect7.py b/eos/effects/triagemodeeffect7.py
index 6d19541fe..07f3d45c6 100644
--- a/eos/effects/triagemodeeffect7.py
+++ b/eos/effects/triagemodeeffect7.py
@@ -53,7 +53,7 @@ def handler(fit, module, context):
stackingPenalties=True)
# Mass multiplier
- fit.ship.multiplyItemAttr("mass", module.getModifiedItemAttr("massMultiplier"),
+ fit.ship.multiplyItemAttr("mass", module.getModifiedItemAttr("siegeMassMultiplier"),
stackingPenalties=True)
# Lock range
@@ -80,7 +80,7 @@ def handler(fit, module, context):
# EW cap need increase
groups = [
'ECM Burst',
- 'Remote ECM Burst',
+ 'Burst Projectors',
'Weapon Disruptor',
'ECM',
'Remote Sensor Damper',
diff --git a/eos/effects/usemissiles.py b/eos/effects/usemissiles.py
index 57fe05555..f21a7b778 100644
--- a/eos/effects/usemissiles.py
+++ b/eos/effects/usemissiles.py
@@ -3,8 +3,7 @@
# Used by:
# Modules from group: Missile Launcher Heavy (12 of 12)
# Modules from group: Missile Launcher Rocket (15 of 15)
-# Modules from group: XL Missile Launcher (4 of 4)
-# Modules named like: Launcher (138 of 138)
+# Modules named like: Launcher (151 of 151)
type = 'active'
def handler(fit, module, context):
# Set reload time to 10 seconds
diff --git a/eos/effects/warpscramble.py b/eos/effects/warpscramble.py
index b4af5f5a2..9c819a3bc 100644
--- a/eos/effects/warpscramble.py
+++ b/eos/effects/warpscramble.py
@@ -1,6 +1,7 @@
# warpScramble
#
# Used by:
+# Variations of module: Heavy Warp Disruptor I (7 of 7)
# Variations of module: Warp Disruptor I (19 of 19)
# Module: Civilian Warp Disruptor
type = "projected", "active"
diff --git a/eos/effects/warpscrambleblockmwdwithnpceffect.py b/eos/effects/warpscrambleblockmwdwithnpceffect.py
index 8c7f55f80..55cb867d6 100644
--- a/eos/effects/warpscrambleblockmwdwithnpceffect.py
+++ b/eos/effects/warpscrambleblockmwdwithnpceffect.py
@@ -1,6 +1,7 @@
# warpScrambleBlockMWDWithNPCEffect
#
# Used by:
+# Variations of module: Heavy Warp Scrambler I (7 of 7)
# Variations of module: Warp Scrambler I (19 of 19)
runTime = "early"
type = "projected", "active"
diff --git a/eos/gamedata.py b/eos/gamedata.py
index 3e7c213eb..5f6904a1e 100644
--- a/eos/gamedata.py
+++ b/eos/gamedata.py
@@ -51,6 +51,7 @@ class Effect(EqBase):
Reconstructor, composes the object as we grab it from the database
'''
self.__generated = False
+ self.__effectModule = None
self.handlerName = re.sub(self.nameFilter, "", self.name).lower()
@property
@@ -154,6 +155,7 @@ class Effect(EqBase):
return getattr(self.__effectModule, key, None)
+
def effectDummy(*args, **kwargs):
pass
diff --git a/eos/saveddata/character.py b/eos/saveddata/character.py
index 522ad590a..2d3fc260d 100644
--- a/eos/saveddata/character.py
+++ b/eos/saveddata/character.py
@@ -19,8 +19,9 @@
from sqlalchemy.orm import validates, reconstructor
+from itertools import chain
-from eos.effectHandlerHelpers import HandledItem
+from eos.effectHandlerHelpers import HandledItem, HandledImplantBoosterList
import eos.db
import eos
import logging
@@ -89,7 +90,7 @@ class Character(object):
return all0
def __init__(self, name, defaultLevel=None, initSkills=True):
- self.name = name
+ self.savedName = name
self.__owner = None
self.defaultLevel = defaultLevel
self.__skills = []
@@ -100,7 +101,7 @@ class Character(object):
for item in self.getSkillList():
self.addSkill(Skill(item.ID, self.defaultLevel))
- self.__implants = eos.saveddata.fit.HandledImplantBoosterList()
+ self.__implants = HandledImplantBoosterList()
self.apiKey = None
@reconstructor
@@ -128,11 +129,27 @@ class Character(object):
def owner(self, owner):
self.__owner = owner
+ @property
+ def name(self):
+ return self.savedName if not self.isDirty else "{} *".format(self.savedName)
+
+ @name.setter
+ def name(self, name):
+ self.savedName = name
+
@property
def skills(self):
return self.__skills
def addSkill(self, skill):
+ if skill.itemID in self.__skillIdMap:
+ oldSkill = self.__skillIdMap[skill.itemID]
+ if skill.level > oldSkill.level:
+ # if new skill is higher, remove old skill (new skill will still append)
+ self.__skills.remove(oldSkill)
+ else:
+ return
+
self.__skills.append(skill)
self.__skillIdMap[skill.itemID] = skill
@@ -200,8 +217,13 @@ class Character(object):
skill.calculateModifiedAttributes(fit, runTime)
def clear(self):
- for skill in self.skills:
- skill.clear()
+ c = chain(
+ self.skills,
+ self.implants
+ )
+ for stuff in c:
+ if stuff is not None and stuff != self:
+ stuff.clear()
def __deepcopy__(self, memo):
copy = Character("%s copy" % self.name, initSkills=False)
diff --git a/eos/saveddata/fighter.py b/eos/saveddata/fighter.py
new file mode 100644
index 000000000..0791d3397
--- /dev/null
+++ b/eos/saveddata/fighter.py
@@ -0,0 +1,273 @@
+#===============================================================================
+# 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, ChargeAttrShortcut
+from eos.effectHandlerHelpers import HandledItem, HandledCharge, HandledDroneCargoList
+from sqlalchemy.orm import validates, reconstructor
+import eos.db
+from eos.enum import Enum
+import logging
+from eos.types import FighterAbility, Slot
+
+logger = logging.getLogger(__name__)
+
+
+class Fighter(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
+ DAMAGE_TYPES = ("em", "kinetic", "explosive", "thermal")
+ DAMAGE_TYPES2 = ("EM", "Kin", "Exp", "Therm")
+
+ 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")
+
+ self.itemID = item.ID if item is not None else None
+ self.projected = False
+ self.active = True
+
+ # -1 is a placeholder that represents max squadron size, which we may not know yet as ships may modify this with
+ # their effects. If user changes this, it is then overridden with user value.
+ self.amount = -1
+
+ self.__abilities = self.__getAbilities()
+
+ self.build()
+
+ @reconstructor
+ def init(self):
+ """Initialize a fighter from the database and validate"""
+ self.__item = None
+
+ if self.itemID:
+ self.__item = eos.db.getItem(self.itemID)
+ if self.__item is None:
+ logger.error("Item (id: %d) does not exist", self.itemID)
+ return
+
+ if self.isInvalid:
+ logger.error("Item (id: %d) is not a Fighter", self.itemID)
+ return
+
+ self.build()
+
+ def build(self):
+ """ Build object. Assumes proper and valid item already set """
+ self.__charge = None
+ self.__dps = None
+ self.__volley = None
+ self.__miningyield = None
+ self.__itemModifiedAttributes = ModifiedAttributeDict()
+ self.__chargeModifiedAttributes = ModifiedAttributeDict()
+
+ if len(self.abilities) != len(self.item.effects):
+ self.__abilities = []
+ for ability in self.__getAbilities():
+ self.__abilities.append(ability)
+
+ if self.__item:
+ self.__itemModifiedAttributes.original = self.__item.attributes
+ self.__itemModifiedAttributes.overrides = self.__item.overrides
+ self.__slot = self.__calculateSlot(self.__item)
+
+ chargeID = self.getModifiedItemAttr("fighterAbilityLaunchBombType")
+ if chargeID is not None:
+ charge = eos.db.getItem(int(chargeID))
+ self.__charge = charge
+ self.__chargeModifiedAttributes.original = charge.attributes
+ self.__chargeModifiedAttributes.overrides = charge.overrides
+
+ def __getAbilities(self):
+ """Returns list of FighterAbilities that are loaded with data"""
+ return [FighterAbility(effect) for effect in self.item.effects.values()]
+
+ def __calculateSlot(self, item):
+ types = {"Light": Slot.F_LIGHT,
+ "Support": Slot.F_SUPPORT,
+ "Heavy": Slot.F_HEAVY}
+
+ for t, slot in types.iteritems():
+ if self.getModifiedItemAttr("fighterSquadronIs{}".format(t)):
+ return slot
+
+ @property
+ def slot(self):
+ return self.__slot
+
+ @property
+ def amountActive(self):
+ return int(self.getModifiedItemAttr("fighterSquadronMaxSize")) if self.amount == -1 else self.amount
+
+ @amountActive.setter
+ def amountActive(self, i):
+ self.amount = int(max(min(i, self.getModifiedItemAttr("fighterSquadronMaxSize")), 0))
+
+ @property
+ def abilities(self):
+ return self.__abilities or []
+
+ @property
+ def charge(self):
+ return self.__charge
+
+ @property
+ def itemModifiedAttributes(self):
+ return self.__itemModifiedAttributes
+
+ @property
+ def chargeModifiedAttributes(self):
+ return self.__chargeModifiedAttributes
+
+ @property
+ def isInvalid(self):
+ return self.__item is None or self.__item.category.name != "Fighter"
+
+ @property
+ def item(self):
+ return self.__item
+
+ @property
+ def charge(self):
+ return self.__charge
+
+ @property
+ def hasAmmo(self):
+ return self.charge is not None
+
+ @property
+ def dps(self):
+ return self.damageStats()
+
+ def damageStats(self, targetResists = None):
+ if self.__dps is None:
+ self.__volley = 0
+ self.__dps = 0
+ if self.active:
+ for ability in self.abilities:
+ if ability.dealsDamage and ability.active and self.amountActive > 0:
+
+ cycleTime = self.getModifiedItemAttr("{}Duration".format(ability.attrPrefix))
+ if ability.attrPrefix == "fighterAbilityLaunchBomb":
+ # bomb calcs
+ volley = sum(map(lambda attr: (self.getModifiedChargeAttr("%sDamage" % attr) or 0) * (1 - getattr(targetResists, "%sAmount" % attr, 0)), self.DAMAGE_TYPES))
+ print volley
+ else:
+ volley = sum(map(lambda d2, d:
+ (self.getModifiedItemAttr("{}Damage{}".format(ability.attrPrefix, d2)) or 0) *
+ (1-getattr(targetResists, "{}Amount".format(d), 0)),
+ self.DAMAGE_TYPES2, self.DAMAGE_TYPES))
+
+ volley *= self.amountActive
+ volley *= self.getModifiedItemAttr("{}DamageMultiplier".format(ability.attrPrefix)) or 1
+ self.__volley += volley
+ self.__dps += volley / (cycleTime / 1000.0)
+
+ return self.__dps, self.__volley
+
+ @property
+ def maxRange(self):
+ attrs = ("shieldTransferRange", "powerTransferRange",
+ "energyDestabilizationRange", "empFieldRange",
+ "ecmBurstRange", "maxRange")
+ for attr in attrs:
+ maxRange = self.getModifiedItemAttr(attr)
+ if maxRange is not None: return maxRange
+ if self.charge is not None:
+ delay = self.getModifiedChargeAttr("explosionDelay")
+ speed = self.getModifiedChargeAttr("maxVelocity")
+ if delay is not None and speed is not None:
+ return delay / 1000.0 * speed
+
+ # Had to add this to match the falloff property in modules.py
+ # Fscking ship scanners. If you find any other falloff attributes,
+ # Put them in the attrs tuple.
+ @property
+ def falloff(self):
+ attrs = ("falloff", "falloffEffectiveness")
+ for attr in attrs:
+ falloff = self.getModifiedItemAttr(attr)
+ if falloff is not None: return falloff
+
+ @validates("ID", "itemID", "chargeID", "amount", "amountActive")
+ def validator(self, key, val):
+ map = {"ID": lambda val: isinstance(val, int),
+ "itemID" : lambda val: isinstance(val, int),
+ "chargeID" : lambda val: isinstance(val, int),
+ "amount" : lambda val: isinstance(val, int) and val >= -1,
+ }
+
+ if map[key](val) == False: raise ValueError(str(val) + " is not a valid value for " + key)
+ else: return val
+
+ def clear(self):
+ self.__dps = None
+ self.__volley = None
+ self.__miningyield = None
+ self.itemModifiedAttributes.clear()
+ self.chargeModifiedAttributes.clear()
+
+ def canBeApplied(self, projectedOnto):
+ """Check if fighter can engage specific fitting"""
+ item = self.item
+ # Do not allow to apply offensive modules on ship with offensive module immunite, with few exceptions
+ # (all effects which apply instant modification are exception, generally speaking)
+ if item.offensive and projectedOnto.ship.getModifiedItemAttr("disallowOffensiveModifiers") == 1:
+ offensiveNonModifiers = set(("energyDestabilizationNew", "leech", "energyNosferatuFalloff", "energyNeutralizerFalloff"))
+ if not offensiveNonModifiers.intersection(set(item.effects)):
+ return False
+ # If assistive modules are not allowed, do not let to apply these altogether
+ if item.assistive and projectedOnto.ship.getModifiedItemAttr("disallowAssistance") == 1:
+ return False
+ else:
+ return True
+
+ def calculateModifiedAttributes(self, fit, runTime, forceProjected = False):
+ if self.projected or forceProjected:
+ context = "projected", "fighter"
+ projected = True
+ else:
+ context = ("fighter",)
+ projected = False
+
+ for ability in self.abilities:
+ if ability.active:
+ effect = ability.effect
+ if effect.runTime == runTime and \
+ ((projected and effect.isType("projected")) or not projected):
+ if ability.grouped:
+ effect.handler(fit, self, context)
+ else:
+ i = 0
+ while i != self.amountActive:
+ effect.handler(fit, self, context)
+ i += 1
+
+ def __deepcopy__(self, memo):
+ copy = Fighter(self.item)
+ copy.amount = self.amount
+ return copy
+
+ def fits(self, fit):
+ # If ships doesn't support this type of fighter, don't add it
+ if fit.getNumSlots(self.slot) == 0:
+ return False
+
+ return True
+
diff --git a/eos/saveddata/fighterAbility.py b/eos/saveddata/fighterAbility.py
new file mode 100644
index 000000000..3956a2e4d
--- /dev/null
+++ b/eos/saveddata/fighterAbility.py
@@ -0,0 +1,70 @@
+#===============================================================================
+# 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 sqlalchemy.orm import validates, reconstructor
+import logging
+
+logger = logging.getLogger(__name__)
+
+class FighterAbility(object):
+
+ def __init__(self, effect):
+ """Initialize from the program"""
+ self.__effect = effect
+ self.effectID = effect.ID if effect is not None else None
+ self.active = False
+ self.build()
+
+ @reconstructor
+ def init(self):
+ '''Initialize from the database'''
+ self.__effect = None
+
+ if self.effectID:
+ self.__effect = next((x for x in self.fighter.item.effects.itervalues() if x.ID == self.effectID), None)
+ if self.__effect is None:
+ logger.error("Effect (id: %d) does not exist", self.effectID)
+ return
+
+ self.build()
+
+ def build(self):
+ pass
+
+ @property
+ def effect(self):
+ return self.__effect
+
+ @property
+ def name(self):
+ return self.__effect.getattr('displayName') or self.__effect.handlerName
+
+ @property
+ def attrPrefix(self):
+ return self.__effect.getattr('prefix')
+
+ @property
+ def dealsDamage(self):
+ attr = "{}DamageMultiplier".format(self.attrPrefix)
+ return attr in self.fighter.itemModifiedAttributes or self.fighter.charge is not None
+
+ @property
+ def grouped(self):
+ # is the ability applied per fighter (webs, returns False), or as a group (MWD, returned True)
+ return self.__effect.getattr('grouped')
\ No newline at end of file
diff --git a/eos/saveddata/fit.py b/eos/saveddata/fit.py
index 611478a6d..63e04e747 100644
--- a/eos/saveddata/fit.py
+++ b/eos/saveddata/fit.py
@@ -31,6 +31,8 @@ import eos.db
import time
import copy
from utils.timer import Timer
+from eos.enum import Enum
+
import logging
@@ -41,6 +43,10 @@ try:
except ImportError:
from utils.compat import OrderedDict
+class ImplantLocation(Enum):
+ FIT = 0
+ CHARACTER = 1
+
class Fit(object):
"""Represents a fitting, with modules, ship, implants, etc."""
@@ -50,9 +56,12 @@ class Fit(object):
"""Initialize a fit from the program"""
# use @mode.setter's to set __attr and IDs. This will set mode as well
self.ship = ship
+ if self.ship:
+ self.ship.parent = self
self.__modules = HandledModuleList()
self.__drones = HandledDroneCargoList()
+ self.__fighters = HandledDroneCargoList()
self.__cargo = HandledDroneCargoList()
self.__implants = HandledImplantBoosterList()
self.__boosters = HandledImplantBoosterList()
@@ -82,7 +91,7 @@ class Fit(object):
return
try:
- self.__ship = Ship(item)
+ self.__ship = Ship(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
@@ -185,6 +194,10 @@ class Fit(object):
def drones(self):
return self.__drones
+ @property
+ def fighters(self):
+ return self.__fighters
+
@property
def cargo(self):
return self.__cargo
@@ -318,17 +331,20 @@ class Fit(object):
return -log(0.25) * agility * mass / 1000000
+ @property
+ def implantSource(self):
+ return self.implantLocation
+
+ @implantSource.setter
+ def implantSource(self, source):
+ self.implantLocation = source
+
@property
def appliedImplants(self):
- implantsBySlot = {}
- if self.character:
- for implant in self.character.implants:
- implantsBySlot[implant.slot] = implant
-
- for implant in self.implants:
- implantsBySlot[implant.slot] = implant
-
- return implantsBySlot.values()
+ if self.implantLocation == ImplantLocation.CHARACTER:
+ return self.character.implants
+ else:
+ return self.implants
@validates("ID", "ownerID", "shipID")
def validator(self, key, val):
@@ -365,6 +381,7 @@ class Fit(object):
c = chain(
self.modules,
self.drones,
+ self.fighters,
self.boosters,
self.implants,
self.projectedDrones,
@@ -447,6 +464,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 %r"%self)
elif self.fleet is None:
self.gangBoosts = None
@@ -482,6 +500,7 @@ class Fit(object):
u = [
(self.character, self.ship),
self.drones,
+ self.fighters,
self.boosters,
self.appliedImplants,
self.modules
@@ -600,27 +619,36 @@ class Fit(object):
def getSlotsUsed(self, type, countDummies=False):
amount = 0
- for mod in self.modules:
- if mod.slot is type and (not mod.isEmpty or countDummies):
+
+ for mod in chain(self.modules, self.fighters):
+ if mod.slot is type and (not getattr(mod, "isEmpty", False) or countDummies):
+ if type in (Slot.F_HEAVY, Slot.F_SUPPORT, Slot.F_LIGHT) and not mod.active:
+ continue
amount += 1
return amount
- def getSlotsFree(self, type, countDummies=False):
- slots = {Slot.LOW: "lowSlots",
- Slot.MED: "medSlots",
- Slot.HIGH: "hiSlots",
- Slot.RIG: "rigSlots",
- Slot.SUBSYSTEM: "maxSubSystems"}
+ slots = {Slot.LOW: "lowSlots",
+ Slot.MED: "medSlots",
+ Slot.HIGH: "hiSlots",
+ Slot.RIG: "rigSlots",
+ Slot.SUBSYSTEM: "maxSubSystems",
+ Slot.F_LIGHT: "fighterLightSlots",
+ Slot.F_SUPPORT: "fighterSupportSlots",
+ Slot.F_HEAVY: "fighterHeavySlots"}
+ def getSlotsFree(self, type, countDummies=False):
if type in (Slot.MODE, Slot.SYSTEM):
# These slots don't really exist, return default 0
return 0
slotsUsed = self.getSlotsUsed(type, countDummies)
- totalSlots = self.ship.getModifiedItemAttr(slots[type]) or 0
+ totalSlots = self.ship.getModifiedItemAttr(self.slots[type]) or 0
return int(totalSlots - slotsUsed)
+ def getNumSlots(self, type):
+ return self.ship.getModifiedItemAttr(self.slots[type]) or 0
+
@property
def calibrationUsed(self):
return self.getItemAttrOnlineSum(self.modules, 'upgradeCost')
@@ -649,6 +677,23 @@ class Fit(object):
return amount
+ @property
+ def fighterBayUsed(self):
+ amount = 0
+ for f in self.fighters:
+ amount += f.item.volume * f.amountActive
+
+ return amount
+
+ @property
+ def fighterTubesUsed(self):
+ amount = 0
+ for f in self.fighters:
+ if f.active:
+ amount += 1
+
+ return amount
+
@property
def cargoBayUsed(self):
amount = 0
@@ -747,20 +792,20 @@ class Fit(object):
repairers = []
#Map a repairer type to the attribute it uses
groupAttrMap = {"Armor Repair Unit": "armorDamageAmount",
- "Fueled Armor Repairer": "armorDamageAmount",
+ "Ancillary Armor Repairer": "armorDamageAmount",
"Hull Repair Unit": "structureDamageAmount",
"Shield Booster": "shieldBonus",
- "Fueled Shield Booster": "shieldBonus",
+ "Ancillary Shield Booster": "shieldBonus",
"Remote Armor Repairer": "armorDamageAmount",
"Remote Shield Booster": "shieldBonus"}
#Map repairer type to attribute
groupStoreMap = {"Armor Repair Unit": "armorRepair",
"Hull Repair Unit": "hullRepair",
"Shield Booster": "shieldRepair",
- "Fueled Shield Booster": "shieldRepair",
+ "Ancillary Shield Booster": "shieldRepair",
"Remote Armor Repairer": "armorRepair",
"Remote Shield Booster": "shieldRepair",
- "Fueled Armor Repairer": "armorRepair",}
+ "Ancillary Armor Repairer": "armorRepair",}
capUsed = self.capUsed
for attr in ("shieldRepair", "armorRepair", "hullRepair"):
@@ -976,6 +1021,11 @@ class Fit(object):
droneDPS += dps
droneVolley += volley
+ for fighter in self.fighters:
+ dps, volley = fighter.damageStats(self.targetResists)
+ droneDPS += dps
+ droneVolley += volley
+
self.__weaponDPS = weaponDPS
self.__weaponVolley = weaponVolley
self.__droneDPS = droneDPS
@@ -999,7 +1049,7 @@ class Fit(object):
copy.damagePattern = self.damagePattern
copy.targetResists = self.targetResists
- toCopy = ("modules", "drones", "cargo", "implants", "boosters", "projectedModules", "projectedDrones")
+ toCopy = ("modules", "drones", "fighters", "cargo", "implants", "boosters", "projectedModules", "projectedDrones")
for name in toCopy:
orig = getattr(self, name)
c = getattr(copy, name)
diff --git a/eos/saveddata/implantSet.py b/eos/saveddata/implantSet.py
new file mode 100644
index 000000000..8e495c5ea
--- /dev/null
+++ b/eos/saveddata/implantSet.py
@@ -0,0 +1,58 @@
+#===============================================================================
+# Copyright (C) 2016 Ryan Holmes
+#
+# 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.effectHandlerHelpers import HandledImplantBoosterList
+from copy import deepcopy
+
+class ImplantSet(object):
+ def __init__(self, name=None):
+ self.name = name
+ self.__implants = HandledImplantBoosterList()
+
+ @property
+ def implants(self):
+ return self.__implants
+
+ @classmethod
+ def exportSets(cls, *sets):
+ out = "# Exported from pyfa\n#\n" \
+ "# Values are in following format:\n" \
+ "# [Implant Set name]\n" \
+ "# [Implant name]\n" \
+ "# [Implant name]\n" \
+ "# ...\n\n"
+
+ for set in sets:
+ out += "[{}]\n".format(set.name)
+ for implant in set.implants:
+ out += "{}\n".format(implant.item.name)
+ out += "\n"
+
+ return out.strip()
+
+ def __deepcopy__(self, memo):
+ copy = ImplantSet(self.name)
+ copy.name = "%s copy" % self.name
+
+ orig = getattr(self, 'implants')
+ c = getattr(copy, 'implants')
+ for i in orig:
+ c.append(deepcopy(i, memo))
+
+ return copy
diff --git a/eos/saveddata/module.py b/eos/saveddata/module.py
index 6ea98bfec..3aaf7779e 100644
--- a/eos/saveddata/module.py
+++ b/eos/saveddata/module.py
@@ -46,6 +46,10 @@ 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
+ # fighter 'slots'. Just easier to put them here...
+ F_LIGHT = 10
+ F_SUPPORT = 11
+ F_HEAVY = 12
class Hardpoint(Enum):
NONE = 0
@@ -374,22 +378,21 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
if shipType is not None:
fitsOnType.add(shipType)
- for i in xrange(1, 10):
- shipType = self.getModifiedItemAttr("canFitShipType%d" % i)
- if shipType is not None:
- fitsOnType.add(shipType)
+ for attr in self.itemModifiedAttributes.keys():
+ if attr.startswith("canFitShipType"):
+ shipType = self.getModifiedItemAttr(attr)
+ if shipType is not None:
+ fitsOnType.add(shipType)
-
- # Check ship group restrictions
- for i in xrange(1, 10):
- shipGroup = self.getModifiedItemAttr("canFitShipGroup%d" % i)
- if shipGroup is not None:
- fitsOnGroup.add(shipGroup)
+ for attr in self.itemModifiedAttributes.keys():
+ if attr.startswith("canFitShipGroup"):
+ shipGroup = self.getModifiedItemAttr(attr)
+ if shipGroup is not None:
+ fitsOnGroup.add(shipGroup)
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
-
# 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")
diff --git a/eos/saveddata/ship.py b/eos/saveddata/ship.py
index 0a0e13c45..0d9def9ee 100644
--- a/eos/saveddata/ship.py
+++ b/eos/saveddata/ship.py
@@ -41,7 +41,7 @@ class Ship(ItemAttrShortcut, HandledItem):
# as None unless the Entosis effect sets it.
}
- def __init__(self, item):
+ 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))
@@ -53,6 +53,9 @@ class Ship(ItemAttrShortcut, HandledItem):
self.__itemModifiedAttributes.original.update(self.EXTRA_ATTRIBUTES)
self.__itemModifiedAttributes.overrides = self.item.overrides
+ # there are occasions when we need to get to the parent fit of the ship, such as when we need the character
+ # skills for ship-role gang boosts (Titans)
+ self.parent = parent
self.commandBonus = 0
@property
diff --git a/eos/types.py b/eos/types.py
index c1cafd1f5..05c37767b 100644
--- a/eos/types.py
+++ b/eos/types.py
@@ -27,12 +27,16 @@ from eos.saveddata.targetResists import TargetResists
from eos.saveddata.character import Character, Skill
from eos.saveddata.module import Module, State, Slot, Hardpoint, Rack
from eos.saveddata.drone import Drone
+from eos.saveddata.fighterAbility import FighterAbility
+from eos.saveddata.fighter import Fighter
+
from eos.saveddata.cargo import Cargo
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
+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
diff --git a/eve.db b/eve.db
index 0bb9841e8..d61d4e61e 100644
Binary files a/eve.db and b/eve.db differ
diff --git a/gui/additionsPane.py b/gui/additionsPane.py
index 61490671c..d108686cc 100644
--- a/gui/additionsPane.py
+++ b/gui/additionsPane.py
@@ -21,6 +21,7 @@ import wx
import gui.mainFrame
from gui.boosterView import BoosterView
from gui.droneView import DroneView
+from gui.fighterView import FighterView
from gui.cargoView import CargoView
from gui.implantView import ImplantView
from gui.projectedView import ProjectedView
@@ -50,6 +51,7 @@ class AdditionsPane(TogglePanel):
baseSizer.Add(self.notebook, 1, wx.EXPAND)
droneImg = BitmapLoader.getImage("drone_small", "gui")
+ fighterImg = BitmapLoader.getImage("fighter_small", "gui")
implantImg = BitmapLoader.getImage("implant_small", "gui")
boosterImg = BitmapLoader.getImage("booster_small", "gui")
projectedImg = BitmapLoader.getImage("projected_small", "gui")
@@ -57,6 +59,7 @@ class AdditionsPane(TogglePanel):
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)
@@ -68,7 +71,7 @@ class AdditionsPane(TogglePanel):
self.notebook.AddPage(self.gangPage, "Fleet", tabImage = gangImg, showClose = False)
self.notebook.SetSelection(0)
- PANES = ["Drones", "Cargo", "Implants", "Boosters", "Projected", "Fleet"]
+ PANES = ["Drones", "Fighters", "Cargo", "Implants", "Boosters", "Projected", "Fleet"]
def select(self, name):
self.notebook.SetSelection(self.PANES.index(name))
diff --git a/gui/builtinContextMenus/__init__.py b/gui/builtinContextMenus/__init__.py
index 785e3eebf..55f26256a 100644
--- a/gui/builtinContextMenus/__init__.py
+++ b/gui/builtinContextMenus/__init__.py
@@ -20,4 +20,6 @@ __all__ = [
"priceClear",
"amount",
"metaSwap",
+ "implantSets",
+ "fighterAbilities",
]
diff --git a/gui/builtinContextMenus/amount.py b/gui/builtinContextMenus/amount.py
index 2fe32fc88..ab7c82ca2 100644
--- a/gui/builtinContextMenus/amount.py
+++ b/gui/builtinContextMenus/amount.py
@@ -11,7 +11,7 @@ class ChangeAmount(ContextMenu):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
def display(self, srcContext, selection):
- return srcContext in ("cargoItem","projectedFit")
+ return srcContext in ("cargoItem","projectedFit","fighterItem")
def getText(self, itmContext, selection):
return "Change {0} Quantity".format(itmContext)
@@ -54,6 +54,8 @@ class AmountChanger(wx.Dialog):
sFit.addCargo(fitID, self.thing.item.ID, int(self.input.GetLineText(0)), replace=True)
elif isinstance(self.thing, eos.types.Fit):
sFit.changeAmount(fitID, self.thing, int(self.input.GetLineText(0)))
+ elif isinstance(self.thing, eos.types.Fighter):
+ sFit.changeActiveFighters(fitID, self.thing, int(self.input.GetLineText(0)))
wx.PostEvent(mainFrame, GE.FitChanged(fitID=fitID))
diff --git a/gui/builtinContextMenus/fighterAbilities.py b/gui/builtinContextMenus/fighterAbilities.py
new file mode 100644
index 000000000..da62c3af9
--- /dev/null
+++ b/gui/builtinContextMenus/fighterAbilities.py
@@ -0,0 +1,56 @@
+import wx
+from gui.contextMenu import ContextMenu
+import gui.mainFrame
+import service
+import gui.globalEvents as GE
+
+class FighterAbility(ContextMenu):
+ def __init__(self):
+ self.mainFrame = gui.mainFrame.MainFrame.getInstance()
+
+ def display(self, srcContext, selection):
+ if self.mainFrame.getActiveFit() is None or srcContext != "fighterItem":
+ return False
+
+ self.fighter = selection[0]
+ return True
+
+ def getText(self, itmContext, selection):
+ return "Abilities"
+
+ def addAbility(self, menu, ability):
+ label = ability.name
+ id = wx.NewId()
+ self.abilityIds[id] = ability
+ menuItem = wx.MenuItem(menu, id, label, kind=wx.ITEM_CHECK)
+ menu.Bind(wx.EVT_MENU, self.handleMode, menuItem)
+ return menuItem
+
+ def getSubMenu(self, context, selection, rootMenu, i, pitem):
+ msw = True if "wxMSW" in wx.PlatformInfo else False
+ self.context = context
+ self.abilityIds = {}
+
+ sub = wx.Menu()
+
+ for ability in self.fighter.abilities:
+ if not ability.effect.isImplemented:
+ continue
+ menuItem = self.addAbility(rootMenu if msw else sub, ability)
+ sub.AppendItem(menuItem)
+ menuItem.Check(ability.active)
+
+ return sub
+
+ def handleMode(self, event):
+ ability = self.abilityIds[event.Id]
+ if ability is False or ability not in self.fighter.abilities:
+ event.Skip()
+ return
+
+ sFit = service.Fit.getInstance()
+ fitID = self.mainFrame.getActiveFit()
+ sFit.toggleFighterAbility(fitID, ability)
+ wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
+
+FighterAbility.register()
diff --git a/gui/builtinContextMenus/implantSets.py b/gui/builtinContextMenus/implantSets.py
new file mode 100644
index 000000000..6ae43039b
--- /dev/null
+++ b/gui/builtinContextMenus/implantSets.py
@@ -0,0 +1,78 @@
+from gui.contextMenu import ContextMenu
+import gui.mainFrame
+import service
+import gui.globalEvents as GE
+import wx
+
+class ImplantSets(ContextMenu):
+ def __init__(self):
+ self.mainFrame = gui.mainFrame.MainFrame.getInstance()
+
+ def display(self, srcContext, selection):
+ return srcContext in ("implantView", "implantEditor")
+
+ def getText(self, itmContext, selection):
+ return "Add Implant Set"
+
+ def getSubMenu(self, context, selection, rootMenu, i, pitem):
+ """
+ A note on the selection here: Most context menus act on a fit, so it's easy enough to get the active fit from
+ the MainFrame instance. There's never been a reason to get info from another window, so there's not common
+ way of doing this. However, we use this context menu within the Character Editor to apply implant sets to a
+ character, so we need to access the character editor.
+
+ It is for these reasons that I hijack the selection parameter when calling the menu and pass a pointer to the
+ Character Editor. This way we can use it to get current editing character ID and apply the implants.
+
+ It would probably be better to have a function on the MainFrame to get the currently open Character Editor (as
+ we do with the item stats window). Eventually... Until then, this long ass note will remain to remind me why
+ stupid shit like this is even happening.
+ """
+
+ m = wx.Menu()
+ bindmenu = rootMenu if "wxMSW" in wx.PlatformInfo else m
+
+ sIS = service.ImplantSets.getInstance()
+ implantSets = sIS.getImplantSetList()
+
+ self.context = context
+ if len(selection) == 1:
+ self.selection = selection[0] # dirty hack here
+
+ self.idmap = {}
+
+ for set in implantSets:
+ id = wx.NewId()
+ mitem = wx.MenuItem(rootMenu, id, set.name)
+ bindmenu.Bind(wx.EVT_MENU, self.handleSelection, mitem)
+ self.idmap[id] = set
+ m.AppendItem(mitem)
+
+ return m
+
+ def handleSelection(self, event):
+ set = self.idmap.get(event.Id, None)
+
+ if set is None:
+ event.Skip()
+ return
+
+ if self.context == "implantEditor":
+ # we are calling from character editor, the implant source is different
+ sChar = service.Character.getInstance()
+ charID = self.selection.getActiveCharacter()
+
+ for implant in set.implants:
+ sChar.addImplant(charID, implant.item.ID)
+
+ wx.PostEvent(self.selection, GE.CharChanged())
+ else:
+ sFit = service.Fit.getInstance()
+ fitID = self.mainFrame.getActiveFit()
+ for implant in set.implants:
+ sFit.addImplant(fitID, implant.item.ID, recalc=implant == set.implants[-1])
+
+ wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
+
+
+ImplantSets.register()
diff --git a/gui/builtinContextMenus/itemStats.py b/gui/builtinContextMenus/itemStats.py
index 73ba66a56..7669b1f2f 100644
--- a/gui/builtinContextMenus/itemStats.py
+++ b/gui/builtinContextMenus/itemStats.py
@@ -9,6 +9,7 @@ class ItemStats(ContextMenu):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
def display(self, srcContext, selection):
+
return srcContext in ("marketItemGroup", "marketItemMisc",
"fittingModule", "fittingCharge",
"fittingShip", "baseShip",
@@ -16,7 +17,7 @@ class ItemStats(ContextMenu):
"implantItem", "boosterItem",
"skillItem", "projectedModule",
"projectedDrone", "projectedCharge",
- "itemStats")
+ "itemStats", "fighterItem", "implantItemChar")
def getText(self, itmContext, selection):
return "{0} Stats".format(itmContext if itmContext is not None else "Item")
diff --git a/gui/builtinContextMenus/marketJump.py b/gui/builtinContextMenus/marketJump.py
index 4980bf61f..180935cbf 100644
--- a/gui/builtinContextMenus/marketJump.py
+++ b/gui/builtinContextMenus/marketJump.py
@@ -12,7 +12,8 @@ class MarketJump(ContextMenu):
"fittingCharge", "droneItem",
"implantItem", "boosterItem",
"projectedModule", "projectedDrone",
- "projectedCharge", "cargoItem")
+ "projectedCharge", "cargoItem",
+ "implantItemChar", "fighterItem")
if not srcContext in validContexts or selection is None or len(selection) < 1:
return False
@@ -33,12 +34,10 @@ class MarketJump(ContextMenu):
def activate(self, fullContext, selection, i):
srcContext = fullContext[0]
- if srcContext in ("fittingModule", "droneItem", "implantItem",
- "boosterItem", "projectedModule", "projectedDrone",
- "cargoItem"):
- item = selection[0].item
- elif srcContext in ("fittingCharge", "projectedCharge"):
+ if srcContext in ("fittingCharge", "projectedCharge"):
item = selection[0].charge
+ elif hasattr(selection[0], "item"):
+ item = selection[0].item
else:
item = selection[0]
diff --git a/gui/builtinStatsViews/resourcesViewFull.py b/gui/builtinStatsViews/resourcesViewFull.py
index 24497ecfc..e0ac0da52 100644
--- a/gui/builtinStatsViews/resourcesViewFull.py
+++ b/gui/builtinStatsViews/resourcesViewFull.py
@@ -31,6 +31,8 @@ from gui.utils.numberFormatter import formatAmount
class ResourcesViewFull(StatsView):
name = "resourcesViewFull"
+ contexts = ["drone", "fighter", "cargo"]
+
def __init__(self, parent):
StatsView.__init__(self)
self.parent = parent
@@ -40,21 +42,35 @@ class ResourcesViewFull(StatsView):
def pageChanged(self, event):
page = self.mainFrame.additionsPane.getName(event.GetSelection())
if page == "Cargo":
- self.toggleCargoGauge(True)
+ self.toggleContext("cargo")
+ elif page == "Fighters":
+ self.toggleContext("fighter")
else:
- self.toggleCargoGauge(False)
+ self.toggleContext("drone")
- def toggleCargoGauge(self, showCargo = False):
- if showCargo:
- self.bitmapFullCargoBay.Show()
- self.baseFullCargoBay.Show(True)
- self.bitmapFullDroneBay.Hide()
- self.baseFullDroneBay.Hide(True)
+ def toggleContext(self, context):
+ # Apparently you cannot .Hide(True) on a Window, otherwise I would just .Hide(context !== x).
+ # This is a gimpy way to toggle this shit
+ for x in self.contexts:
+ bitmap = getattr(self, "bitmapFull{}Bay".format(x.capitalize()))
+ base = getattr(self, "baseFull{}Bay".format(x.capitalize()))
+
+ if context == x:
+ bitmap.Show()
+ base.Show(True)
+ else:
+ bitmap.Hide()
+ base.Hide(True)
+
+ fighter_sizer = getattr(self, "boxSizerFighter")
+ drone_sizer = getattr(self, "boxSizerDrones")
+
+ if context != "fighter":
+ fighter_sizer.ShowItems(False)
+ drone_sizer.ShowItems(True)
else:
- self.bitmapFullDroneBay.Show()
- self.baseFullDroneBay.Show(True)
- self.bitmapFullCargoBay.Hide()
- self.baseFullCargoBay.Hide(True)
+ fighter_sizer.ShowItems(True)
+ drone_sizer.ShowItems(False)
self.panel.Layout()
self.headerPanel.Layout()
@@ -72,7 +88,7 @@ class ResourcesViewFull(StatsView):
root = wx.BoxSizer(wx.VERTICAL)
contentSizer.Add(root, 0, wx.EXPAND, 0)
- sizer = wx.GridSizer(1, 4)
+ sizer = wx.BoxSizer(wx.HORIZONTAL)
root.Add(sizer, 0, wx.EXPAND)
root.Add(wx.StaticLine(contentPanel, wx.ID_ANY, style=wx.HORIZONTAL), 0, wx.EXPAND)
@@ -85,10 +101,10 @@ class ResourcesViewFull(StatsView):
base = sizerResources
-
+ sizer.AddSpacer((0, 0), 1, wx.EXPAND, 5)
#Turrets & launcher hardslots display
- tooltipText = {"turret":"Turret hardpoints", "launcher":"Launcher hardpoints", "drones":"Drones active", "calibration":"Calibration"}
- for type in ("turret", "launcher", "drones", "calibration"):
+ tooltipText = {"turret":"Turret hardpoints", "launcher":"Launcher hardpoints", "drones":"Drones active", "fighter": "Fighter squadrons active", "calibration":"Calibration"}
+ for type in ("turret", "launcher", "drones", "fighter", "calibration"):
box = wx.BoxSizer(wx.HORIZONTAL)
bitmap = BitmapLoader.getStaticBitmap("%s_big" % type, parent, "gui")
@@ -99,7 +115,7 @@ class ResourcesViewFull(StatsView):
sizer.Add(box, 0, wx.ALIGN_CENTER)
- suffix = {'turret':'Hardpoints', 'launcher':'Hardpoints', 'drones':'Active', 'calibration':'Points'}
+ suffix = {'turret':'Hardpoints', 'launcher':'Hardpoints', 'drones':'Active', 'fighter':'Tubes', 'calibration':'Points'}
lbl = wx.StaticText(parent, wx.ID_ANY, "0")
setattr(self, "label%sUsed%s%s" % (panel.capitalize(), type.capitalize(), suffix[type].capitalize()), lbl)
box.Add(lbl, 0, wx.ALIGN_CENTER | wx.LEFT, 5)
@@ -109,11 +125,17 @@ class ResourcesViewFull(StatsView):
lbl = wx.StaticText(parent, wx.ID_ANY, "0")
setattr(self, "label%sTotal%s%s" % (panel.capitalize(), type.capitalize(), suffix[type].capitalize()), lbl)
box.Add(lbl, 0, wx.ALIGN_CENTER)
+ setattr(self, "boxSizer{}".format(type.capitalize()), box)
+
+ # Hack - We add a spacer after each thing, but we are always hiding something. The spacer is stil there.
+ # This way, we only have one space after the drones/fighters
+ if type != "drones":
+ sizer.AddSpacer((0, 0), 1, wx.EXPAND, 5)
#PG, Cpu & drone stuff
- tooltipText = {"cpu":"CPU", "pg":"PowerGrid", "droneBay":"Drone bay", "droneBandwidth":"Drone bandwidth", "cargoBay":"Cargo bay"}
- for i, group in enumerate((("cpu", "pg"), ("cargoBay", "droneBay", "droneBandwidth"))):
+ tooltipText = {"cpu":"CPU", "pg":"PowerGrid", "droneBay":"Drone bay", "fighterBay": "Fighter bay", "droneBandwidth":"Drone bandwidth", "cargoBay":"Cargo bay"}
+ for i, group in enumerate((("cpu", "pg"), ("cargoBay", "droneBay", "fighterBay", "droneBandwidth"))):
main = wx.BoxSizer(wx.VERTICAL)
base.Add(main, 1 , wx.ALIGN_CENTER)
@@ -144,7 +166,7 @@ class ResourcesViewFull(StatsView):
setattr(self, "label%sTotal%s" % (panel.capitalize(), capitalizedType), lbl)
absolute.Add(lbl, 0, wx.ALIGN_LEFT)
- units = {"cpu":" tf", "pg":" MW", "droneBandwidth":" mbit/s", "droneBay":u" m\u00B3", "cargoBay":u" m\u00B3"}
+ units = {"cpu":" tf", "pg":" MW", "droneBandwidth":" mbit/s", "droneBay":u" m\u00B3", "fighterBay":u" m\u00B3", "cargoBay":u" m\u00B3"}
lbl = wx.StaticText(parent, wx.ID_ANY, "%s" % units[type])
absolute.Add(lbl, 0, wx.ALIGN_LEFT)
@@ -161,7 +183,7 @@ class ResourcesViewFull(StatsView):
setattr(self, "base%s%s" % (panel.capitalize(), capitalizedType), b)
setattr(self, "bitmap%s%s" % (panel.capitalize(), capitalizedType), bitmap)
- self.toggleCargoGauge(False)
+ self.toggleContext("drone")
def refreshPanel(self, fit):
#If we did anything intresting, we'd update our labels to reflect the new fit's stats here
@@ -172,6 +194,8 @@ class ResourcesViewFull(StatsView):
("label%sTotalLauncherHardpoints", lambda: fit.ship.getModifiedItemAttr('launcherSlotsLeft'), 0, 0, 0),
("label%sUsedDronesActive", lambda: fit.activeDrones, 0, 0, 0),
("label%sTotalDronesActive", lambda: fit.extraAttributes["maxActiveDrones"], 0, 0, 0),
+ ("label%sUsedFighterTubes", lambda: fit.fighterTubesUsed, 3, 0, 9),
+ ("label%sTotalFighterTubes", lambda: fit.ship.getModifiedItemAttr("fighterTubes"), 3, 0, 9),
("label%sUsedCalibrationPoints", lambda: fit.calibrationUsed, 0, 0, 0),
("label%sTotalCalibrationPoints", lambda: fit.ship.getModifiedItemAttr('upgradeCapacity'), 0, 0, 0),
("label%sUsedPg", lambda: fit.pgUsed, 4, 0, 9),
@@ -179,9 +203,11 @@ class ResourcesViewFull(StatsView):
("label%sTotalPg", lambda: fit.ship.getModifiedItemAttr("powerOutput"), 4, 0, 9),
("label%sTotalCpu", lambda: fit.ship.getModifiedItemAttr("cpuOutput"), 4, 0, 9),
("label%sUsedDroneBay", lambda: fit.droneBayUsed, 3, 0, 9),
+ ("label%sUsedFighterBay", lambda: fit.fighterBayUsed, 3, 0, 9),
("label%sUsedDroneBandwidth", lambda: fit.droneBandwidthUsed, 3, 0, 9),
("label%sTotalDroneBay", lambda: fit.ship.getModifiedItemAttr("droneCapacity"), 3, 0, 9),
("label%sTotalDroneBandwidth", lambda: fit.ship.getModifiedItemAttr("droneBandwidth"), 3, 0, 9),
+ ("label%sTotalFighterBay", lambda: fit.ship.getModifiedItemAttr("fighterCapacity"), 3, 0, 9),
("label%sUsedCargoBay", lambda: fit.cargoBayUsed, 3, 0, 9),
("label%sTotalCargoBay", lambda: fit.ship.getModifiedItemAttr("capacity"), 3, 0, 9))
panel = "Full"
@@ -218,6 +244,14 @@ class ResourcesViewFull(StatsView):
totalDronesActive = value
labelTDA = label
+ if labelName % panel == "label%sUsedFighterTubes" % panel:
+ usedFighterTubes = value
+ labelUFT = label
+
+ if labelName % panel == "label%sTotalFighterTubes" % panel:
+ totalFighterTubes = value
+ labelTFT = label
+
if labelName % panel == "label%sUsedCalibrationPoints" % panel:
usedCalibrationPoints = value
labelUCP = label
@@ -248,6 +282,10 @@ class ResourcesViewFull(StatsView):
colorD = colorWarn
else:
colorD = colorNormal
+ if usedFighterTubes > totalFighterTubes:
+ colorF = colorWarn
+ else:
+ colorF = colorNormal
if usedCalibrationPoints > totalCalibrationPoints:
colorC = colorWarn
else:
@@ -259,6 +297,8 @@ class ResourcesViewFull(StatsView):
labelTLH.SetForegroundColour(colorL)
labelUDA.SetForegroundColour(colorD)
labelTDA.SetForegroundColour(colorD)
+ labelUFT.SetForegroundColour(colorF)
+ labelTFT.SetForegroundColour(colorF)
labelUCP.SetForegroundColour(colorC)
labelTCP.SetForegroundColour(colorC)
@@ -266,11 +306,12 @@ class ResourcesViewFull(StatsView):
resMax = (lambda: fit.ship.getModifiedItemAttr("cpuOutput"),
lambda: fit.ship.getModifiedItemAttr("powerOutput"),
lambda: fit.ship.getModifiedItemAttr("droneCapacity"),
+ lambda: fit.ship.getModifiedItemAttr("fighterCapacity"),
lambda: fit.ship.getModifiedItemAttr("droneBandwidth"),
lambda: fit.ship.getModifiedItemAttr("capacity"))
i = 0
- for resourceType in ("cpu", "pg", "droneBay", "droneBandwidth", "cargoBay"):
+ for resourceType in ("cpu", "pg", "droneBay", "fighterBay", "droneBandwidth", "cargoBay"):
if fit is not None:
capitalizedType = resourceType[0].capitalize() + resourceType[1:]
diff --git a/gui/builtinViewColumns/__init__.py b/gui/builtinViewColumns/__init__.py
index 4c5d8495e..d66f423bf 100644
--- a/gui/builtinViewColumns/__init__.py
+++ b/gui/builtinViewColumns/__init__.py
@@ -1,2 +1,2 @@
__all__ = ["ammo", "ammoIcon", "attributeDisplay", "baseIcon", "baseName",
- "capacitorUse", "maxRange", "price", "propertyDisplay", "state", "misc"]
+ "capacitorUse", "maxRange", "price", "propertyDisplay", "state", "misc", "abilities"]
diff --git a/gui/builtinViewColumns/abilities.py b/gui/builtinViewColumns/abilities.py
new file mode 100644
index 000000000..12081500a
--- /dev/null
+++ b/gui/builtinViewColumns/abilities.py
@@ -0,0 +1,41 @@
+# -*- coding: utf-8 -*-
+#===============================================================================
+# Copyright (C) 2010 Diego Duclos
+#
+# This file is part of pyfa.
+#
+# pyfa is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# pyfa is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with pyfa. If not, see .
+#===============================================================================
+
+from gui.viewColumn import ViewColumn
+import gui.mainFrame
+
+import wx
+from eos.types import Drone, Cargo, Fit, Module, Slot, Rack, Implant, Fighter
+import service
+
+class Abilities(ViewColumn):
+ name = "Fighter Abilities"
+ def __init__(self, fittingView, params):
+ ViewColumn.__init__(self, fittingView)
+
+ self.mainFrame = gui.mainFrame.MainFrame.getInstance()
+ self.columnText = "Active Abilities"
+ self.mask = wx.LIST_MASK_TEXT
+
+ def getText(self, stuff):
+ if isinstance(stuff, Fighter):
+ return ", ".join([x.name for x in stuff.abilities if x.active])
+
+Abilities.register()
diff --git a/gui/builtinViewColumns/baseIcon.py b/gui/builtinViewColumns/baseIcon.py
index 30cbf6fb2..868c73a21 100644
--- a/gui/builtinViewColumns/baseIcon.py
+++ b/gui/builtinViewColumns/baseIcon.py
@@ -2,7 +2,7 @@ from gui import builtinViewColumns
from gui.viewColumn import ViewColumn
from gui.bitmapLoader import BitmapLoader
import wx
-from eos.types import Drone, Fit, Module, Slot, Rack
+from eos.types import Drone, Fit, Module, Slot, Rack, Implant
class BaseIcon(ViewColumn):
name = "Base Icon"
@@ -21,6 +21,11 @@ class BaseIcon(ViewColumn):
return self.shipImage
if isinstance(stuff, Rack):
return -1
+ if isinstance(stuff, Implant):
+ if stuff.character: # if it has a character as it's parent
+ return self.fittingView.imageList.GetImageIndex("character_small", "gui")
+ else:
+ return self.shipImage
if isinstance(stuff, Module):
if stuff.isEmpty:
return self.fittingView.imageList.GetImageIndex("slot_%s_small" % Slot.getName(stuff.slot).lower(), "gui")
diff --git a/gui/builtinViewColumns/baseName.py b/gui/builtinViewColumns/baseName.py
index e5f59a9e2..77b4698bd 100644
--- a/gui/builtinViewColumns/baseName.py
+++ b/gui/builtinViewColumns/baseName.py
@@ -22,7 +22,7 @@ from gui.viewColumn import ViewColumn
import gui.mainFrame
import wx
-from eos.types import Drone, Cargo, Fit, Module, Slot, Rack
+from eos.types import Drone, Cargo, Fit, Module, Slot, Rack, Implant, Fighter
import service
class BaseName(ViewColumn):
@@ -39,6 +39,8 @@ class BaseName(ViewColumn):
def getText(self, stuff):
if isinstance(stuff, Drone):
return "%dx %s" % (stuff.amount, stuff.item.name)
+ if isinstance(stuff, Fighter):
+ return "%d/%d %s" % (stuff.amountActive, stuff.getModifiedItemAttr("fighterSquadronMaxSize"), stuff.item.name)
elif isinstance(stuff, Cargo):
return "%dx %s" % (stuff.amount, stuff.item.name)
elif isinstance(stuff, Fit):
@@ -61,6 +63,8 @@ class BaseName(ViewColumn):
return "%s Slot" % Slot.getName(stuff.slot).capitalize()
else:
return stuff.item.name
+ elif isinstance(stuff, Implant):
+ return stuff.item.name
else:
item = getattr(stuff, "item", stuff)
diff --git a/gui/builtinViewColumns/misc.py b/gui/builtinViewColumns/misc.py
index c2f617deb..05c7f9020 100644
--- a/gui/builtinViewColumns/misc.py
+++ b/gui/builtinViewColumns/misc.py
@@ -205,7 +205,7 @@ class Miscellanea(ViewColumn):
tooltip = "{0} disruption".format(formatList(ttEntries)).capitalize()
return text, tooltip
- elif itemGroup in ("ECM", "Burst Jammer", "Remote ECM Burst"):
+ elif itemGroup in ("ECM", "Burst Jammer", "Burst Projectors"):
grav = stuff.getModifiedItemAttr("scanGravimetricStrengthBonus")
ladar = stuff.getModifiedItemAttr("scanLadarStrengthBonus")
radar = stuff.getModifiedItemAttr("scanRadarStrengthBonus")
@@ -458,7 +458,7 @@ class Miscellanea(ViewColumn):
return text, item.name
else:
return "", None
- elif itemGroup in ("Fueled Armor Repairer", "Fueled Shield Booster"):
+ elif itemGroup in ("Ancillary Armor Repairer", "Ancillary Shield Booster"):
hp = stuff.hpBeforeReload
cycles = stuff.numShots
cycleTime = stuff.rawCycleTime
@@ -470,7 +470,7 @@ class Miscellanea(ViewColumn):
useEhp = self.mainFrame.statsPane.nameViewMap["resistancesViewFull"].showEffective
tooltip = "HP restored over duration using charges"
if useEhp:
- if itemGroup == "Fueled Armor Repairer":
+ if itemGroup == "Ancillary Armor Repairer":
hpRatio = ehpTotal["armor"] / hpTotal["armor"]
else:
hpRatio = ehpTotal["shield"] / hpTotal["shield"]
@@ -487,7 +487,7 @@ class Miscellanea(ViewColumn):
if chargeGroup in ("Rocket", "Advanced Rocket", "Light Missile", "Advanced Light Missile", "FoF Light Missile",
"Heavy Assault Missile", "Advanced Heavy Assault Missile", "Heavy Missile", "Advanced Heavy Missile", "FoF Heavy Missile",
"Torpedo", "Advanced Torpedo", "Cruise Missile", "Advanced Cruise Missile", "FoF Cruise Missile",
- "Capital Torpedo", "Capital Cruise"):
+ "XL Torpedo", "XL Cruise Missile"):
cloudSize = stuff.getModifiedChargeAttr("aoeCloudSize")
aoeVelocity = stuff.getModifiedChargeAttr("aoeVelocity")
if not cloudSize or not aoeVelocity:
diff --git a/gui/builtinViewColumns/state.py b/gui/builtinViewColumns/state.py
index c12db54df..cc3dee59b 100644
--- a/gui/builtinViewColumns/state.py
+++ b/gui/builtinViewColumns/state.py
@@ -22,7 +22,7 @@ from gui.bitmapLoader import BitmapLoader
import gui.mainFrame
import wx
-from eos.types import Drone, Module, Rack, Fit
+from eos.types import Drone, Module, Rack, Fit, Implant
from eos.types import State as State_
class State(ViewColumn):
@@ -67,6 +67,9 @@ class State(ViewColumn):
if projectionInfo.active:
return generic_active
return generic_inactive
+ elif isinstance(stuff, Implant) and stuff.character:
+ # if we're showing character implants, show an "online" state, which should not be changed
+ return self.fittingView.imageList.GetImageIndex("state_%s_small" % State_.getName(0).lower(), "gui")
else:
active = getattr(stuff, "active", None)
if active is None:
diff --git a/gui/builtinViews/__init__.py b/gui/builtinViews/__init__.py
index 4d1ed63c6..46a500f7b 100644
--- a/gui/builtinViews/__init__.py
+++ b/gui/builtinViews/__init__.py
@@ -1 +1 @@
-__all__ = ["fittingView", "fleetView"]
+__all__ = ["fittingView", "fleetView", "implantEditor"]
diff --git a/gui/builtinViews/entityEditor.py b/gui/builtinViews/entityEditor.py
new file mode 100644
index 000000000..112c1c63e
--- /dev/null
+++ b/gui/builtinViews/entityEditor.py
@@ -0,0 +1,173 @@
+import wx
+from gui.bitmapLoader import BitmapLoader
+import service
+
+class BaseValidator(wx.PyValidator):
+ def __init__(self):
+ wx.PyValidator.__init__(self)
+
+ def Validate(self, win):
+ raise NotImplementedError()
+
+ def TransferToWindow(self):
+ return True
+
+ def TransferFromWindow(self):
+ return True
+
+class TextEntryValidatedDialog(wx.TextEntryDialog):
+ def __init__(self, parent, validator=None, *args, **kargs):
+ wx.TextEntryDialog.__init__(self, parent, *args, **kargs)
+ self.parent = parent
+
+ self.txtctrl = self.FindWindowById(3000)
+ if validator:
+ self.txtctrl.SetValidator(validator())
+
+class EntityEditor (wx.Panel):
+ """
+ Entity Editor is a panel that takes some sort of list as a source and populates a drop down with options to add/
+ rename/clone/delete an entity. Comes with dialogs that take user input. Classes that derive this class must override
+ functions that get the list from the source, what to do when user does an action, and how to validate the input.
+ """
+
+ def __init__(self, parent, entityName):
+ wx.Panel.__init__(self, parent, id=wx.ID_ANY, style=wx.TAB_TRAVERSAL)
+ self.entityName = entityName
+ self.validator = None
+ self.navSizer = wx.BoxSizer(wx.HORIZONTAL)
+
+ self.choices = []
+ self.choices.sort(key=lambda p: p.name)
+ self.entityChoices = wx.Choice(self, choices=map(lambda p: p.name, self.choices))
+ self.navSizer.Add(self.entityChoices, 1, wx.ALL, 5)
+
+ buttons = (("new", wx.ART_NEW, self.OnNew),
+ ("rename", BitmapLoader.getBitmap("rename", "gui"), self.OnRename),
+ ("copy", wx.ART_COPY, self.OnCopy),
+ ("delete", wx.ART_DELETE, self.OnDelete))
+
+ size = None
+ for name, art, func in buttons:
+ bitmap = wx.ArtProvider.GetBitmap(art, wx.ART_BUTTON) if name != "rename" else art
+ btn = wx.BitmapButton(self, wx.ID_ANY, bitmap)
+ if size is None:
+ size = btn.GetSize()
+
+ btn.SetMinSize(size)
+ btn.SetMaxSize(size)
+
+ btn.SetToolTipString("{} {}".format(name.capitalize(), self.entityName))
+ btn.Bind(wx.EVT_BUTTON, func)
+ setattr(self, "btn%s" % name.capitalize(), btn)
+ self.navSizer.Add(btn, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 2)
+
+ self.SetSizer(self.navSizer)
+ self.Layout()
+
+ self.refreshEntityList()
+
+ def SetEditorValidator(self, validator=None):
+ """ Sets validator class (not an instance of the class) """
+ self.validator = validator
+
+ def getEntitiesFromContext(self):
+ """ Gets list of entities from current context """
+ raise NotImplementedError()
+
+ def DoNew(self, name):
+ """Override method to do new entity logic. Must return the new entity"""
+ raise NotImplementedError()
+
+ def DoCopy(self, entity, name):
+ """Override method to copy entity. Must return the copy"""
+ raise NotImplementedError()
+
+ def DoRename(self, entity, name):
+ """Override method to rename an entity"""
+ raise NotImplementedError()
+
+ def DoDelete(self, entity):
+ """Override method to delete entity"""
+ raise NotImplementedError()
+
+ def OnNew(self, event):
+ dlg = TextEntryValidatedDialog(self, self.validator,
+ "Enter a name for your new {}:".format(self.entityName),
+ "New {}".format(self.entityName))
+ dlg.CenterOnParent()
+
+ if dlg.ShowModal() == wx.ID_OK:
+ new = self.DoNew(dlg.GetValue().strip())
+ self.refreshEntityList(new)
+ wx.PostEvent(self.entityChoices, wx.CommandEvent(wx.wxEVT_COMMAND_CHOICE_SELECTED))
+ else:
+ return False
+
+ def OnCopy(self, event):
+ dlg = TextEntryValidatedDialog(self, self.validator,
+ "Enter a name for your {} copy:".format(self.entityName),
+ "Copy {}".format(self.entityName))
+ active = self.getActiveEntity()
+ dlg.SetValue("{} Copy".format(active.name))
+ dlg.txtctrl.SetInsertionPointEnd()
+ dlg.CenterOnParent()
+
+ if dlg.ShowModal() == wx.ID_OK:
+ copy = self.DoCopy(active, dlg.GetValue().strip())
+ self.refreshEntityList(copy)
+ wx.PostEvent(self.entityChoices, wx.CommandEvent(wx.wxEVT_COMMAND_CHOICE_SELECTED))
+
+ def OnRename(self, event):
+ dlg = TextEntryValidatedDialog(self, self.validator,
+ "Enter a new name for your {}:".format(self.entityName),
+ "Rename {}".format(self.entityName))
+ active = self.getActiveEntity()
+ dlg.SetValue(active.name)
+ dlg.txtctrl.SetInsertionPointEnd()
+ dlg.CenterOnParent()
+
+ if dlg.ShowModal() == wx.ID_OK:
+ self.DoRename(active, dlg.GetValue().strip())
+ self.refreshEntityList(active)
+ wx.PostEvent(self.entityChoices, wx.CommandEvent(wx.wxEVT_COMMAND_CHOICE_SELECTED))
+
+ def OnDelete(self, event):
+ dlg = wx.MessageDialog(self,
+ "Do you really want to delete the {} {}?".format(self.getActiveEntity().name, self.entityName),
+ "Confirm Delete", wx.YES | wx.NO | wx.ICON_QUESTION)
+ dlg.CenterOnParent()
+
+ if dlg.ShowModal() == wx.ID_YES:
+ self.DoDelete(self.getActiveEntity())
+ self.refreshEntityList()
+ wx.PostEvent(self.entityChoices, wx.CommandEvent(wx.wxEVT_COMMAND_CHOICE_SELECTED))
+
+ def refreshEntityList(self, selected=None):
+ self.choices = self.getEntitiesFromContext()
+ self.entityChoices.Clear()
+
+ self.entityChoices.AppendItems(map(lambda p: p.name, self.choices))
+ if selected:
+ idx = self.choices.index(selected)
+ self.entityChoices.SetSelection(idx)
+ else:
+ self.entityChoices.SetSelection(0)
+
+ def getActiveEntity(self):
+ if len(self.choices) == 0:
+ return None
+
+ return self.choices[self.entityChoices.GetSelection()]
+
+ def setActiveEntity(self, entity):
+ self.entityChoices.SetSelection(self.choices.index(entity))
+
+ def checkEntitiesExist(self):
+ if len(self.choices) == 0:
+ self.Parent.Hide()
+ if self.OnNew(None) is False:
+ return False
+ self.Parent.Show()
+
+ return True
\ No newline at end of file
diff --git a/gui/builtinViews/implantEditor.py b/gui/builtinViews/implantEditor.py
new file mode 100644
index 000000000..bcdb96c7b
--- /dev/null
+++ b/gui/builtinViews/implantEditor.py
@@ -0,0 +1,258 @@
+import wx
+import service
+import gui.display as d
+from gui.bitmapLoader import BitmapLoader
+import gui.PFSearchBox as SBox
+from gui.marketBrowser import SearchBox
+from wx.lib.buttons import GenBitmapButton
+
+class BaseImplantEditorView (wx.Panel):
+ def addMarketViewImage(self, iconFile):
+ if iconFile is None:
+ return -1
+ bitmap = BitmapLoader.getBitmap(iconFile, "icons")
+ if bitmap is None:
+ return -1
+ else:
+ return self.availableImplantsImageList.Add(bitmap)
+
+ def __init__(self, parent):
+ wx.Panel.__init__ (self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.TAB_TRAVERSAL)
+ self.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
+
+ pmainSizer = wx.BoxSizer(wx.HORIZONTAL)
+
+ availableSizer = wx.BoxSizer(wx.VERTICAL)
+
+ self.searchBox = SearchBox(self)
+ self.itemView = ItemView(self)
+
+ self.itemView.Hide()
+
+ availableSizer.Add(self.searchBox, 0, wx.EXPAND)
+ availableSizer.Add(self.itemView, 1, wx.EXPAND)
+
+ '''
+ self.availableImplantsSearch = wx.SearchCtrl(self, wx.ID_ANY, style=wx.TE_PROCESS_ENTER)
+ self.availableImplantsSearch.ShowCancelButton(True)
+
+ availableSizer.Add(self.availableImplantsSearch, 0, wx.BOTTOM | wx.EXPAND, 2)
+ '''
+
+ self.availableImplantsTree = wx.TreeCtrl(self, wx.ID_ANY, style=wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT)
+ root = self.availableRoot = self.availableImplantsTree.AddRoot("Available")
+ self.availableImplantsImageList = wx.ImageList(16, 16)
+ self.availableImplantsTree.SetImageList(self.availableImplantsImageList)
+
+ availableSizer.Add(self.availableImplantsTree, 1, wx.EXPAND)
+
+
+ pmainSizer.Add(availableSizer, 1, wx.ALL | wx.EXPAND, 5)
+
+
+ buttonSizer = wx.BoxSizer(wx.VERTICAL)
+ buttonSizer.AddSpacer(( 0, 0), 1)
+
+ self.btnAdd = GenBitmapButton(self, wx.ID_ADD, BitmapLoader.getBitmap("fit_add_small", "gui"), style = wx.BORDER_NONE)
+ buttonSizer.Add(self.btnAdd, 0)
+
+ self.btnRemove = GenBitmapButton(self, wx.ID_REMOVE, BitmapLoader.getBitmap("fit_delete_small", "gui"), style = wx.BORDER_NONE)
+ buttonSizer.Add(self.btnRemove, 0)
+
+ buttonSizer.AddSpacer(( 0, 0), 1)
+ pmainSizer.Add(buttonSizer, 0, wx.EXPAND, 0)
+
+ characterImplantSizer = wx.BoxSizer(wx.VERTICAL)
+ self.pluggedImplantsTree = AvailableImplantsView(self)
+ characterImplantSizer.Add(self.pluggedImplantsTree, 1, wx.ALL|wx.EXPAND, 5)
+ pmainSizer.Add(characterImplantSizer, 1, wx.EXPAND, 5)
+
+ self.SetSizer(pmainSizer)
+
+ # Populate the market tree
+
+ sMkt = service.Market.getInstance()
+ for mktGrp in sMkt.getImplantTree():
+ iconId = self.addMarketViewImage(sMkt.getIconByMarketGroup(mktGrp))
+ childId = self.availableImplantsTree.AppendItem(root, mktGrp.name, iconId, data=wx.TreeItemData(mktGrp.ID))
+ if sMkt.marketGroupHasTypesCheck(mktGrp) is False:
+ self.availableImplantsTree.AppendItem(childId, "dummy")
+
+ self.availableImplantsTree.SortChildren(self.availableRoot)
+
+ #Bind the event to replace dummies by real data
+ self.availableImplantsTree.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.expandLookup)
+ self.availableImplantsTree.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.itemSelected)
+
+ self.itemView.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.itemSelected)
+
+ #Bind add & remove buttons
+ self.btnAdd.Bind(wx.EVT_BUTTON, self.itemSelected)
+ self.btnRemove.Bind(wx.EVT_BUTTON, self.removeItem)
+
+ # We update with an empty list first to set the initial size for Layout(), then update later with actual
+ # implants for character. This helps with sizing issues.
+ self.pluggedImplantsTree.update([])
+ self.bindContext()
+ self.Layout()
+
+ self.update()
+
+ def bindContext(self):
+ # Binds self.contextChanged to whatever changes the context
+ raise NotImplementedError()
+
+ def getImplantsFromContext(self):
+ """ Gets list of implants from current context """
+ raise NotImplementedError()
+
+ def addImplantToContext(self, item):
+ """ Adds implant to the current context"""
+ raise NotImplementedError()
+
+ def removeImplantFromContext(self, implant):
+ """ Removes implant from the current context"""
+ raise NotImplementedError()
+
+ def update(self):
+ """Updates implant list based off the current context"""
+ self.implants = self.getImplantsFromContext()
+ self.implants.sort(key=lambda i: int(i.getModifiedItemAttr("implantness")))
+ self.pluggedImplantsTree.update(self.implants)
+
+ def contextChanged(self, event):
+ self.update()
+ event.Skip()
+
+ def expandLookup(self, event):
+ tree = self.availableImplantsTree
+ sMkt = service.Market.getInstance()
+ parent = event.Item
+ child, _ = tree.GetFirstChild(parent)
+ text = tree.GetItemText(child)
+
+ if text == "dummy" or text == "itemdummy":
+ tree.Delete(child)
+
+ # if the dummy item is a market group, replace with actual market groups
+ if text == "dummy":
+ #Add 'real stoof!' instead
+ currentMktGrp = sMkt.getMarketGroup(tree.GetPyData(parent), eager="children")
+ for childMktGrp in sMkt.getMarketGroupChildren(currentMktGrp):
+ iconId = self.addMarketViewImage(sMkt.getIconByMarketGroup(childMktGrp))
+ childId = tree.AppendItem(parent, childMktGrp.name, iconId, data=wx.TreeItemData(childMktGrp.ID))
+ if sMkt.marketGroupHasTypesCheck(childMktGrp) is False:
+ tree.AppendItem(childId, "dummy")
+ else:
+ tree.AppendItem(childId, "itemdummy")
+
+ # replace dummy with actual items
+ if text == "itemdummy":
+ currentMktGrp = sMkt.getMarketGroup(tree.GetPyData(parent))
+ items = sMkt.getItemsByMarketGroup(currentMktGrp)
+ for item in items:
+ iconId = self.addMarketViewImage(item.icon.iconFile)
+ tree.AppendItem(parent, item.name, iconId, data=wx.TreeItemData(item))
+
+ tree.SortChildren(parent)
+
+ def itemSelected(self, event):
+ if event.EventObject is self.btnAdd:
+ # janky fix that sets EventObject so that we don't have similar code elsewhere.
+ if self.itemView.IsShown():
+ event.EventObject = self.itemView
+ else:
+ event.EventObject = self.availableImplantsTree
+
+ if event.EventObject is self.itemView:
+ curr = event.EventObject.GetFirstSelected()
+
+ while curr != -1:
+ item = self.itemView.items[curr]
+ self.addImplantToContext(item)
+
+ curr = event.EventObject.GetNextSelected(curr)
+ else:
+ root = self.availableImplantsTree.GetSelection()
+
+ if not root.IsOk():
+ return
+
+ nchilds = self.availableImplantsTree.GetChildrenCount(root)
+ if nchilds == 0:
+ item = self.availableImplantsTree.GetPyData(root)
+ self.addImplantToContext(item)
+ else:
+ event.Skip()
+ return
+
+ self.update()
+
+ def removeItem(self, event):
+ pos = self.pluggedImplantsTree.GetFirstSelected()
+ if pos != -1:
+ self.removeImplantFromContext(self.implants[pos])
+ self.update()
+
+class AvailableImplantsView(d.Display):
+ DEFAULT_COLS = ["attr:implantness",
+ "Base Icon",
+ "Base Name"]
+
+ def __init__(self, parent):
+ d.Display.__init__(self, parent, style=wx.LC_SINGLE_SEL)
+ self.Bind(wx.EVT_LEFT_DCLICK, parent.removeItem)
+
+class ItemView(d.Display):
+ DEFAULT_COLS = ["Base Icon",
+ "Base Name",
+ "attr:power,,,True",
+ "attr:cpu,,,True"]
+
+ def __init__(self, parent):
+ d.Display.__init__(self, parent)
+ self.parent = parent
+ self.searchBox = parent.searchBox
+
+ self.items = []
+
+ # Bind search actions
+ self.searchBox.Bind(SBox.EVT_TEXT_ENTER, self.scheduleSearch)
+ self.searchBox.Bind(SBox.EVT_SEARCH_BTN, self.scheduleSearch)
+ self.searchBox.Bind(SBox.EVT_CANCEL_BTN, self.clearSearch)
+ self.searchBox.Bind(SBox.EVT_TEXT, self.scheduleSearch)
+
+ def clearSearch(self, event=None):
+ if self.IsShown():
+ self.parent.availableImplantsTree.Show()
+ self.Hide()
+ self.parent.Layout()
+
+ if event:
+ self.searchBox.Clear()
+
+ self.items = []
+ self.update(self.items)
+
+ def scheduleSearch(self, event=None):
+ sMkt = service.Market.getInstance()
+
+ search = self.searchBox.GetLineText(0)
+ # Make sure we do not count wildcard as search symbol
+ realsearch = search.replace("*", "")
+ # Show nothing if query is too short
+ if len(realsearch) < 3:
+ self.clearSearch()
+ return
+
+ sMkt.searchItems(search, self.populateSearch, ["Implant"])
+
+ def populateSearch(self, items):
+ if not self.IsShown():
+ self.parent.availableImplantsTree.Hide()
+ self.Show()
+ self.parent.Layout()
+
+ self.items = sorted(list(items), key=lambda i: i.name)
+
+ self.update(self.items)
\ No newline at end of file
diff --git a/gui/characterEditor.py b/gui/characterEditor.py
index 7d45dae3d..862660fbb 100644
--- a/gui/characterEditor.py
+++ b/gui/characterEditor.py
@@ -19,15 +19,80 @@
import wx
-import gui.mainFrame
import wx.lib.newevent
import wx.gizmos
from gui.bitmapLoader import BitmapLoader
import service
-import gui.display as d
from gui.contextMenu import ContextMenu
-from wx.lib.buttons import GenBitmapButton
import gui.globalEvents as GE
+from gui.builtinViews.implantEditor import BaseImplantEditorView
+from gui.builtinViews.entityEditor import EntityEditor, BaseValidator
+
+
+class CharacterTextValidor(BaseValidator):
+ def __init__(self):
+ BaseValidator.__init__(self)
+
+ def Clone(self):
+ return CharacterTextValidor()
+
+ def Validate(self, win):
+ profileEditor = win.Parent
+ textCtrl = self.GetWindow()
+ text = textCtrl.GetValue().strip()
+
+ try:
+ if len(text) == 0:
+ raise ValueError("You must supply a name for the Character!")
+ elif text in [x.name for x in profileEditor.entityEditor.choices]:
+ raise ValueError("Character name already in use, please choose another.")
+
+ return True
+ except ValueError, e:
+ wx.MessageBox(u"{}".format(e), "Error")
+ textCtrl.SetFocus()
+ return False
+
+
+class CharacterEntityEditor(EntityEditor):
+ def __init__(self, parent):
+ EntityEditor.__init__(self, parent, "Character")
+ self.SetEditorValidator(CharacterTextValidor)
+
+ def getEntitiesFromContext(self):
+ sChar = service.Character.getInstance()
+ charList = sorted(sChar.getCharacterList(), key=lambda c: c.name)
+
+ # Do some processing to ensure that we have All 0 and All 5 at the top
+ all5 = sChar.all5()
+ all0 = sChar.all0()
+
+ charList.remove(all5)
+ charList.remove(all0)
+
+ charList.insert(0, all5)
+ charList.insert(0, all0)
+
+ return charList
+
+ def DoNew(self, name):
+ sChar = service.Character.getInstance()
+ return sChar.new(name)
+
+ def DoRename(self, entity, name):
+ sChar = service.Character.getInstance()
+ sChar.rename(entity, name)
+
+ def DoCopy(self, entity, name):
+ sChar = service.Character.getInstance()
+ copy = sChar.copy(entity)
+ sChar.rename(copy, name)
+ return copy
+
+ def DoDelete(self, entity):
+ sChar = service.Character.getInstance()
+ sChar.delete(entity)
+
class CharacterEditor(wx.Frame):
def __init__(self, parent):
@@ -38,75 +103,26 @@ class CharacterEditor(wx.Frame):
self.SetIcon(i)
self.mainFrame = parent
-
#self.disableWin = wx.WindowDisabler(self)
- self.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_BTNFACE ) )
+ sFit = service.Fit.getInstance()
+
+ self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE))
mainSizer = wx.BoxSizer(wx.VERTICAL)
- self.navSizer = wx.BoxSizer(wx.HORIZONTAL)
- sChar = service.Character.getInstance()
-
- self.btnSave = wx.Button(self, wx.ID_SAVE)
- self.btnSave.Hide()
- self.btnSave.Bind(wx.EVT_BUTTON, self.processRename)
-
- self.characterRename = wx.TextCtrl(self, wx.ID_ANY, style=wx.TE_PROCESS_ENTER)
- self.characterRename.Hide()
- self.characterRename.Bind(wx.EVT_TEXT_ENTER, self.processRename)
-
- 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.charChoice.Append(name, id)
- if active:
- self.charChoice.SetSelection(i)
-
- self.navSizer.Add(self.btnSave, 0, wx.ALL , 5)
-
-
- buttons = (("new", wx.ART_NEW),
- ("rename", BitmapLoader.getBitmap("rename", "gui")),
- ("copy", wx.ART_COPY),
- ("delete", wx.ART_DELETE))
-
- size = None
- for name, art in buttons:
- bitmap = wx.ArtProvider.GetBitmap(art, wx.ART_BUTTON) if name != "rename" else art
- btn = wx.BitmapButton(self, wx.ID_ANY, bitmap)
- if size is None:
- size = btn.GetSize()
-
- btn.SetMinSize(size)
- btn.SetMaxSize(size)
-
- btn.SetToolTipString("%s character" % name.capitalize())
- btn.Bind(wx.EVT_BUTTON, getattr(self, name))
- setattr(self, "btn%s" % name.capitalize(), btn)
- self.navSizer.Add(btn, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 2)
-
-
- mainSizer.Add(self.navSizer, 0, wx.ALL | wx.EXPAND, 5)
+ self.entityEditor = CharacterEntityEditor(self)
+ mainSizer.Add(self.entityEditor, 0, wx.ALL | wx.EXPAND, 2)
+ # Default drop down to current fit's character
+ self.entityEditor.setActiveEntity(sFit.character)
self.viewsNBContainer = wx.Notebook(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, 0)
self.sview = SkillTreeView(self.viewsNBContainer)
- #self.iview = ImplantsTreeView(self.viewsNBContainer)
- #=======================================================================
- # RC2
- #self.iview.Show(False)
- #=======================================================================
+ self.iview = ImplantEditorView(self.viewsNBContainer)
self.aview = APIView(self.viewsNBContainer)
self.viewsNBContainer.AddPage(self.sview, "Skills")
-
- #=======================================================================
- # Disabled for RC2
- # self.viewsNBContainer.AddPage(self.iview, "Implants")
- #=======================================================================
+ self.viewsNBContainer.AddPage(self.iview, "Implants")
self.viewsNBContainer.AddPage(self.aview, "API")
mainSizer.Add(self.viewsNBContainer, 1, wx.EXPAND | wx.ALL, 5)
@@ -124,7 +140,6 @@ class CharacterEditor(wx.Frame):
bSizerButtons.AddStretchSpacer()
bSizerButtons.Add(self.btnOK, 0, wx.ALL, 5)
-
self.btnSaveChar.Bind(wx.EVT_BUTTON, self.saveChar)
self.btnSaveAs.Bind(wx.EVT_BUTTON, self.saveCharAs)
self.btnRevert.Bind(wx.EVT_BUTTON, self.revertChar)
@@ -139,16 +154,12 @@ class CharacterEditor(wx.Frame):
self.Centre(wx.BOTH)
- charID = self.getActiveCharacter()
- if sChar.getCharName(charID) in ("All 0", "All 5"):
- self.restrict()
-
- self.registerEvents()
+ self.Bind(wx.EVT_CLOSE, self.closeEvent)
+ self.Bind(GE.CHAR_LIST_UPDATED, self.refreshCharacterList)
+ self.entityEditor.Bind(wx.EVT_CHOICE, self.charChanged)
def btnRestrict(self):
- sChar = service.Character.getInstance()
- charID = self.getActiveCharacter()
- char = sChar.getCharacter(charID)
+ char = self.entityEditor.getActiveEntity()
# enable/disable character saving stuff
self.btnSaveChar.Enable(not char.ro and char.isDirty)
@@ -156,46 +167,34 @@ class CharacterEditor(wx.Frame):
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)
-
+ """This is only called when we save a modified character"""
+ active = self.entityEditor.getActiveEntity()
+ self.entityEditor.refreshEntityList(active)
self.btnRestrict()
+ if event:
+ event.Skip()
+
def editingFinished(self, event):
#del self.disableWin
wx.PostEvent(self.mainFrame, GE.CharListUpdated())
self.Destroy()
- def registerEvents(self):
- self.Bind(wx.EVT_CLOSE, self.closeEvent)
- 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()
+ char = self.entityEditor.getActiveEntity()
+ sChr.saveCharacter(char.ID)
wx.PostEvent(self, GE.CharListUpdated())
def saveCharAs(self, event):
- charID = self.getActiveCharacter()
- dlg = SaveCharacterAs(self, charID)
+ char = self.entityEditor.getActiveEntity()
+ dlg = SaveCharacterAs(self, char.ID)
dlg.ShowModal()
- self.sview.populateSkillTree()
def revertChar(self, event):
sChr = service.Character.getInstance()
- charID = self.getActiveCharacter()
- sChr.revertCharacter(charID)
- self.sview.populateSkillTree()
+ char = self.entityEditor.getActiveEntity()
+ sChr.revertCharacter(char.ID)
wx.PostEvent(self, GE.CharListUpdated())
def closeEvent(self, event):
@@ -204,120 +203,25 @@ class CharacterEditor(wx.Frame):
self.Destroy()
def restrict(self):
- self.btnRename.Enable(False)
- self.btnDelete.Enable(False)
- self.aview.stDisabledTip.Show()
- self.aview.inputID.Enable(False)
- self.aview.inputKey.Enable(False)
- self.aview.charChoice.Enable(False)
- self.aview.btnFetchCharList.Enable(False)
- self.aview.btnFetchSkills.Enable(False)
- self.aview.stStatus.SetLabel("")
- self.aview.Layout()
+ self.entityEditor.btnRename.Enable(False)
+ self.entityEditor.btnDelete.Enable(False)
def unrestrict(self):
- self.btnRename.Enable(True)
- self.btnDelete.Enable(True)
- self.aview.stDisabledTip.Hide()
- self.aview.inputID.Enable(True)
- self.aview.inputKey.Enable(True)
- self.aview.btnFetchCharList.Enable(True)
- self.aview.btnFetchSkills.Enable(True)
- self.aview.stStatus.SetLabel("")
- self.aview.Layout()
+ self.entityEditor.btnRename.Enable()
+ self.entityEditor.btnDelete.Enable()
def charChanged(self, event):
- self.sview.populateSkillTree()
- sChar = service.Character.getInstance()
- charID = self.getActiveCharacter()
- if sChar.getCharName(charID) in ("All 0", "All 5"):
+ char = self.entityEditor.getActiveEntity()
+ if char.name in ("All 0", "All 5"):
self.restrict()
else:
self.unrestrict()
- wx.PostEvent(self, GE.CharChanged())
+ self.btnRestrict()
+
if event is not None:
event.Skip()
- def getActiveCharacter(self):
- 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.charChoice.Append(sChar.getCharName(charID), charID)
- self.charChoice.SetSelection(id)
- self.unrestrict()
- self.btnSave.SetLabel("Create")
- self.rename(None)
- self.charChanged(None)
-
- def rename(self, event):
- if event is not None:
- self.btnSave.SetLabel("Rename")
- self.charChoice.Hide()
- self.characterRename.Show()
- self.navSizer.Replace(self.charChoice, self.characterRename)
- self.characterRename.SetFocus()
- for btn in (self.btnNew, self.btnCopy, self.btnRename, self.btnDelete):
- btn.Hide()
-
- self.btnSave.Show()
- self.navSizer.Layout()
-
- sChar = service.Character.getInstance()
- currName = sChar.getCharName(self.getActiveCharacter())
- self.characterRename.SetValue(currName)
- self.characterRename.SetSelection(0, len(currName))
-
- def processRename(self, event):
- sChar = service.Character.getInstance()
- newName = self.characterRename.GetLineText(0)
-
- if newName == "All 0" or newName == "All 5":
- newName = newName + " bases are belong to us"
-
- charID = self.getActiveCharacter()
- sChar.rename(charID, newName)
-
- self.charChoice.Show()
- self.characterRename.Hide()
- 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()
- self.refreshCharacterList()
-
- def copy(self, event):
- sChar = service.Character.getInstance()
- charID = sChar.copy(self.getActiveCharacter())
- id = self.charChoice.Append(sChar.getCharName(charID), charID)
- self.charChoice.SetSelection(id)
- self.unrestrict()
- self.btnSave.SetLabel("Copy")
- self.rename(None)
- wx.PostEvent(self, GE.CharChanged())
-
- def delete(self, event):
- dlg = wx.MessageDialog(self,
- "Do you really want to delete this character?",
- "Confirm Delete", wx.YES | wx.NO | wx.ICON_QUESTION)
-
- if dlg.ShowModal() == wx.ID_YES:
- sChar = service.Character.getInstance()
- sChar.delete(self.getActiveCharacter())
- 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()
-
- wx.PostEvent(self, GE.CharChanged())
-
def Destroy(self):
sFit = service.Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
@@ -329,7 +233,8 @@ class CharacterEditor(wx.Frame):
class SkillTreeView (wx.Panel):
def __init__(self, parent):
- wx.Panel.__init__ (self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.Size(500, 300), style=wx.TAB_TRAVERSAL)
+ wx.Panel.__init__ (self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.TAB_TRAVERSAL)
+ self.charEditor = self.Parent.Parent # first parent is Notebook, second is Character Editor
self.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
pmainSizer = wx.BoxSizer(wx.VERTICAL)
@@ -356,6 +261,10 @@ class SkillTreeView (wx.Panel):
tree.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.expandLookup)
tree.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.scheduleMenu)
+ # bind the Character selection event
+ self.charEditor.entityEditor.Bind(wx.EVT_CHOICE, self.populateSkillTree)
+ self.charEditor.Bind(GE.CHAR_LIST_UPDATED, self.populateSkillTree)
+
srcContext = "skillItem"
itemContext = "Skill"
context = (srcContext, itemContext)
@@ -386,11 +295,10 @@ class SkillTreeView (wx.Panel):
self.Layout()
- def populateSkillTree(self):
+ def populateSkillTree(self, event=None):
sChar = service.Character.getInstance()
- charID = self.Parent.Parent.getActiveCharacter()
- dirtySkills = sChar.getDirtySkills(charID)
- dirtyGroups = set([skill.item.group.ID for skill in dirtySkills])
+ char = self.charEditor.entityEditor.getActiveEntity()
+ dirtyGroups = set([skill.item.group.ID for skill in char.dirtySkills])
groups = sChar.getSkillGroups()
imageId = self.skillBookImageId
@@ -407,6 +315,9 @@ class SkillTreeView (wx.Panel):
tree.SortChildren(root)
+ if event:
+ event.Skip()
+
def expandLookup(self, event):
root = event.Item
tree = self.skillTreeListCtrl
@@ -416,11 +327,11 @@ class SkillTreeView (wx.Panel):
#Get the real intrestin' stuff
sChar = service.Character.getInstance()
- char = self.Parent.Parent.getActiveCharacter()
+ char = self.charEditor.entityEditor.getActiveEntity()
for id, name in sChar.getSkills(tree.GetPyData(root)):
iconId = self.skillBookImageId
childId = tree.AppendItem(root, name, iconId, data=wx.TreeItemData(id))
- level, dirty = sChar.getSkillLevel(char, id)
+ level, dirty = sChar.getSkillLevel(char.ID, id)
tree.SetItemText(childId, "Level %d" % level if isinstance(level, int) else level, 1)
if dirty:
tree.SetItemTextColour(childId, wx.BLUE)
@@ -436,10 +347,9 @@ class SkillTreeView (wx.Panel):
if self.skillTreeListCtrl.GetChildrenCount(item) > 0:
return
- sChar = service.Character.getInstance()
- charID = self.Parent.Parent.getActiveCharacter()
+ char = self.charEditor.entityEditor.getActiveEntity()
sMkt = service.Market.getInstance()
- if sChar.getCharName(charID) not in ("All 0", "All 5"):
+ if char.name not in ("All 0", "All 5"):
self.levelChangeMenu.selection = sMkt.getItem(self.skillTreeListCtrl.GetPyData(item))
self.PopupMenu(self.levelChangeMenu)
else:
@@ -450,21 +360,21 @@ class SkillTreeView (wx.Panel):
level = self.levelIds.get(event.Id)
sChar = service.Character.getInstance()
- charID = self.Parent.Parent.getActiveCharacter()
+ char = self.charEditor.entityEditor.getActiveEntity()
selection = self.skillTreeListCtrl.GetSelection()
skillID = self.skillTreeListCtrl.GetPyData(selection)
if level is not None:
self.skillTreeListCtrl.SetItemText(selection, "Level %d" % level if isinstance(level, int) else level, 1)
- sChar.changeLevel(charID, skillID, level, persist=True)
+ sChar.changeLevel(char.ID, skillID, level, persist=True)
elif event.Id == self.revertID:
- sChar.revertLevel(charID, skillID)
+ sChar.revertLevel(char.ID, skillID)
elif event.Id == self.saveID:
- sChar.saveSkill(charID, skillID)
+ sChar.saveSkill(char.ID, skillID)
self.skillTreeListCtrl.SetItemTextColour(selection, None)
- dirtySkills = sChar.getDirtySkills(charID)
+ dirtySkills = sChar.getDirtySkills(char.ID)
dirtyGroups = set([skill.item.group.ID for skill in dirtySkills])
parentID = self.skillTreeListCtrl.GetItemParent(selection)
@@ -473,156 +383,69 @@ class SkillTreeView (wx.Panel):
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:
- return -1
- bitmap = BitmapLoader.getBitmap(iconFile, "icons")
- if bitmap is None:
- return -1
- else:
- return self.availableImplantsImageList.Add(bitmap)
+class ImplantEditorView(BaseImplantEditorView):
def __init__(self, parent):
- wx.Panel.__init__ (self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.Size(500, 300), style=wx.TAB_TRAVERSAL)
+ BaseImplantEditorView.__init__ (self, parent)
- pmainSizer = wx.BoxSizer(wx.HORIZONTAL)
+ self.determineEnabled()
- availableSizer = wx.BoxSizer(wx.VERTICAL)
- pmainSizer.Add(availableSizer, 1, wx.ALL | wx.EXPAND, 5)
+ if "__WXGTK__" in wx.PlatformInfo:
+ self.pluggedImplantsTree.Bind(wx.EVT_RIGHT_UP, self.scheduleMenu)
+ else:
+ self.pluggedImplantsTree.Bind(wx.EVT_RIGHT_DOWN, self.scheduleMenu)
- self.availableImplantsSearch = wx.SearchCtrl(self, wx.ID_ANY, style=wx.TE_PROCESS_ENTER)
- self.availableImplantsSearch.ShowCancelButton(True)
- availableSizer.Add(self.availableImplantsSearch, 0, wx.BOTTOM | wx.EXPAND, 2)
+ def bindContext(self):
+ self.Parent.Parent.entityEditor.Bind(wx.EVT_CHOICE, self.contextChanged)
- self.availableImplantsTree = wx.TreeCtrl(self, wx.ID_ANY, style=wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT)
- root = self.availableRoot = self.availableImplantsTree.AddRoot("Available")
- self.availableImplantsImageList = wx.ImageList(16, 16)
- self.availableImplantsTree.SetImageList(self.availableImplantsImageList)
+ def contextChanged(self, event):
+ BaseImplantEditorView.contextChanged(self, event)
+ self.determineEnabled()
- availableSizer.Add(self.availableImplantsTree, 1, wx.EXPAND)
-
- buttonSizer = wx.BoxSizer(wx.VERTICAL)
- pmainSizer.Add(buttonSizer, 0, wx.TOP, 5)
-
- self.btnAdd = GenBitmapButton(self, wx.ID_ADD, BitmapLoader.getBitmap("fit_add_small", "gui"), style = wx.BORDER_NONE)
- buttonSizer.Add(self.btnAdd, 0)
- self.btnRemove = GenBitmapButton(self, wx.ID_REMOVE, BitmapLoader.getBitmap("fit_delete_small", "gui"), style = wx.BORDER_NONE)
- buttonSizer.Add(self.btnRemove, 0)
-
- self.pluggedImplantsTree = AvailableImplantsView(self, style=wx.LC_SINGLE_SEL)
-
- pmainSizer.Add(self.pluggedImplantsTree, 1, wx.ALL | wx.EXPAND, 5)
-
- self.SetSizer(pmainSizer)
-
- # Populate the market tree
- sMkt = service.Market.getInstance()
- for mktGrp in sMkt.getImplantTree():
- iconId = self.addMarketViewImage(sMkt.getIconByMarketGroup(mktGrp))
- childId = self.availableImplantsTree.AppendItem(root, mktGrp.name, iconId, data=wx.TreeItemData(mktGrp.ID))
- if sMkt.marketGroupHasTypesCheck(mktGrp) is False:
- self.availableImplantsTree.AppendItem(childId, "dummy")
-
- self.availableImplantsTree.SortChildren(self.availableRoot)
-
- #Bind the event to replace dummies by real data
- self.availableImplantsTree.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.expandLookup)
-
- #Bind add & remove buttons
- self.btnAdd.Bind(wx.EVT_BUTTON, self.addImplant)
- self.btnRemove.Bind(wx.EVT_BUTTON, self.removeImplant)
-
- #Bind the change of a character*
- self.Parent.Parent.Bind(GE.CHAR_CHANGED, self.charChanged)
- self.Enable(False)
- self.Layout()
-
- def update(self, implants):
- self.implants = implants[:]
- self.implants.sort(key=lambda i: int(i.getModifiedItemAttr("implantness")))
- self.pluggedImplantsTree.update(self.implants)
-
- def charChanged(self, event):
+ def getImplantsFromContext(self):
sChar = service.Character.getInstance()
- charID = self.Parent.Parent.getActiveCharacter()
- name = sChar.getCharName(charID)
- if name == "All 0" or name == "All 5":
+ char = self.Parent.Parent.entityEditor.getActiveEntity()
+
+ return sChar.getImplants(char.ID)
+
+ def addImplantToContext(self, item):
+ sChar = service.Character.getInstance()
+ char = self.Parent.Parent.entityEditor.getActiveEntity()
+
+ sChar.addImplant(char.ID, item.ID)
+
+ def removeImplantFromContext(self, implant):
+ sChar = service.Character.getInstance()
+ char = self.Parent.Parent.entityEditor.getActiveEntity()
+
+ sChar.removeImplant(char.ID, implant)
+
+ def scheduleMenu(self, event):
+ event.Skip()
+ wx.CallAfter(self.spawnMenu)
+
+ def spawnMenu(self):
+ context = (("implantEditor",),)
+ # fuck good coding practices, passing a pointer to the character editor here for [reasons] =D
+ # (see implantSets context class for info)
+ menu = ContextMenu.getMenu((self.Parent.Parent,), *context)
+ self.PopupMenu(menu)
+
+ def determineEnabled(self):
+ char = self.Parent.Parent.entityEditor.getActiveEntity()
+
+ if char.name in ("All 0", "All 5"):
self.Enable(False)
else:
- self.Enable(True)
+ self.Enable()
- self.update(sChar.getImplants(charID))
- event.Skip()
-
- def expandLookup(self, event):
- tree = self.availableImplantsTree
- root = event.Item
- child, cookie = tree.GetFirstChild(root)
- text = tree.GetItemText(child)
- if text == "dummy" or text == "itemdummy":
- sMkt = service.Market.getInstance()
- #A DUMMY! Keeeel!!! EBUL DUMMY MUST DIAF!
- tree.Delete(child)
-
- if text == "dummy":
- #Add 'real stoof!' instead
- for id, name, iconFile, more in sMkt.getChildren(tree.GetPyData(root)):
- iconId = self.addMarketViewImage(iconFile)
- childId = tree.AppendItem(root, name, iconId, data=wx.TreeItemData(id))
- if more:
- tree.AppendItem(childId, "dummy")
- else:
- tree.AppendItem(childId, "itemdummy")
-
- if text == "itemdummy":
- sMkt = service.Market.getInstance()
- data, usedMetas = sMkt.getVariations(tree.GetPyData(root))
- for item in data:
- id = item.ID
- name = item.name
- iconFile = item.icon.iconFile
- iconId = self.addMarketViewImage(iconFile)
- tree.AppendItem(root, name, iconId, data=wx.TreeItemData(id))
-
- tree.SortChildren(root)
-
- def addImplant(self, event):
- root = self.availableImplantsTree.GetSelection()
-
- if not root.IsOk():
- return
-
- nchilds = self.availableImplantsTree.GetChildrenCount(root)
- sChar = service.Character.getInstance()
- charID = self.Parent.Parent.getActiveCharacter()
- if nchilds == 0:
- itemID = self.availableImplantsTree.GetPyData(root)
- sChar.addImplant(charID, itemID)
- self.update(sChar.getImplants(charID))
-
- def removeImplant(self, event):
- pos = self.pluggedImplantsTree.GetFirstSelected()
- if pos != -1:
- sChar = service.Character.getInstance()
- charID = self.Parent.Parent.getActiveCharacter()
- sChar.removeImplant(charID, self.implants[pos].slot)
- self.update(sChar.getImplants(charID))
-
-class AvailableImplantsView(d.Display):
- DEFAULT_COLS = ["Base Name",
- "attr:implantness"]
-
- def __init__(self, parent, style):
- d.Display.__init__(self, parent, style=style)
class APIView (wx.Panel):
def __init__(self, parent):
wx.Panel.__init__ (self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.Size(500, 300), style=wx.TAB_TRAVERSAL)
- self.Parent.Parent.Bind(GE.CHAR_CHANGED, self.charChanged)
+ self.charEditor = self.Parent.Parent # first parent is Notebook, second is Character Editor
self.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
self.apiUrlCreatePredefined = u"https://community.eveonline.com/support/api-key/CreatePredefined?accessMask=8"
@@ -706,13 +529,17 @@ class APIView (wx.Panel):
self.hlEveAPI2 = wx.HyperlinkCtrl( self, wx.ID_ANY, self.apiUrlKeyList, self.apiUrlKeyList, wx.DefaultPosition, wx.DefaultSize, wx.HL_DEFAULT_STYLE )
pmainSizer.Add( self.hlEveAPI2, 0, wx.ALL, 2 )
+ self.charEditor.entityEditor.Bind(wx.EVT_CHOICE, self.charChanged)
+
self.SetSizer(pmainSizer)
self.Layout()
self.charChanged(None)
def charChanged(self, event):
sChar = service.Character.getInstance()
- ID, key, char, chars = sChar.getApiDetails(self.Parent.Parent.getActiveCharacter())
+ activeChar = self.charEditor.entityEditor.getActiveEntity()
+
+ ID, key, char, chars = sChar.getApiDetails(activeChar.ID)
self.inputID.SetValue(str(ID))
self.inputKey.SetValue(key)
@@ -730,6 +557,14 @@ class APIView (wx.Panel):
self.charChoice.Enable(False)
self.btnFetchSkills.Enable(False)
+ if activeChar.name in ("All 0", "All 5"):
+ self.Enable(False)
+ self.stDisabledTip.Show()
+ self.Layout()
+ else:
+ self.Enable()
+ self.stDisabledTip.Hide()
+ self.Layout()
if event is not None:
event.Skip()
@@ -742,7 +577,8 @@ class APIView (wx.Panel):
sChar = service.Character.getInstance()
try:
- list = sChar.apiCharList(self.Parent.Parent.getActiveCharacter(), self.inputID.GetLineText(0), self.inputKey.GetLineText(0))
+ activeChar = self.charEditor.entityEditor.getActiveEntity()
+ list = sChar.apiCharList(activeChar.ID, 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:
@@ -766,7 +602,8 @@ class APIView (wx.Panel):
if charName:
try:
sChar = service.Character.getInstance()
- sChar.apiFetch(self.Parent.Parent.getActiveCharacter(), charName)
+ activeChar = self.charEditor.entityEditor.getActiveEntity()
+ sChar.apiFetch(activeChar.ID, charName)
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))
diff --git a/gui/characterSelection.py b/gui/characterSelection.py
index 990dc8bf5..47df7e018 100644
--- a/gui/characterSelection.py
+++ b/gui/characterSelection.py
@@ -83,9 +83,9 @@ class CharacterSelection(wx.Panel):
charList = sChar.getCharacterList()
picked = False
- for id, name, active in charList:
- currId = choice.Append(name, id)
- if id == activeChar:
+ for char in charList:
+ currId = choice.Append(char.name, char.ID)
+ if char.ID == activeChar:
choice.SetSelection(currId)
self.charChanged(None)
picked = True
diff --git a/gui/fighterView.py b/gui/fighterView.py
new file mode 100644
index 000000000..b011f89d0
--- /dev/null
+++ b/gui/fighterView.py
@@ -0,0 +1,310 @@
+#===============================================================================
+# Copyright (C) 2010 Diego Duclos
+#
+# This file is part of pyfa.
+#
+# pyfa is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# pyfa is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with pyfa. If not, see .
+#===============================================================================
+
+import wx
+
+import service
+import gui.globalEvents as GE
+import gui.marketBrowser as mb
+import gui.mainFrame
+import gui.display as d
+from gui.builtinViewColumns.state import State
+from eos.types import Slot
+from gui.contextMenu import ContextMenu
+
+class FighterViewDrop(wx.PyDropTarget):
+ def __init__(self, dropFn):
+ wx.PyDropTarget.__init__(self)
+ self.dropFn = dropFn
+ # this is really transferring an EVE itemID
+ self.dropData = wx.PyTextDataObject()
+ self.SetDataObject(self.dropData)
+
+ def OnData(self, x, y, t):
+ if self.GetData():
+ data = self.dropData.GetText().split(':')
+ self.dropFn(x, y, data)
+ return t
+
+
+class FighterView(wx.Panel):
+ def __init__(self, parent):
+ wx.Panel.__init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, style=wx.TAB_TRAVERSAL )
+ self.mainFrame = gui.mainFrame.MainFrame.getInstance()
+ self.labels = ["Light", "Heavy", "Support"]
+
+ mainSizer = wx.BoxSizer(wx.VERTICAL)
+
+ self.fighterDisplay = FighterDisplay(self)
+ mainSizer.Add(self.fighterDisplay, 1, wx.EXPAND, 0)
+
+ textSizer = wx.BoxSizer(wx.HORIZONTAL)
+ textSizer.AddSpacer(( 0, 0), 1, wx.EXPAND, 5)
+
+ for x in self.labels:
+ lbl = wx.StaticText(self, wx.ID_ANY, x.capitalize())
+ textSizer.Add(lbl, 0, wx.ALIGN_CENTER | wx.LEFT, 5)
+
+ lbl = wx.StaticText(self, wx.ID_ANY, "0")
+ setattr(self, "label%sUsed" % (x.capitalize()), lbl)
+ textSizer.Add(lbl, 0, wx.ALIGN_CENTER | wx.LEFT, 5)
+
+ textSizer.Add(wx.StaticText(self, wx.ID_ANY, "/"), 0, wx.ALIGN_CENTER)
+
+ lbl = wx.StaticText(self, wx.ID_ANY, "0")
+ setattr(self, "label%sTotal" % (x.capitalize()), lbl)
+ textSizer.Add(lbl, 0, wx.ALIGN_CENTER)
+ textSizer.AddSpacer((0, 0), 1, wx.EXPAND, 5)
+
+ mainSizer.Add(textSizer, 0, wx.EXPAND, 5)
+
+ self.SetSizer( mainSizer )
+ self.SetAutoLayout(True)
+
+
+ self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged)
+
+ def fitChanged(self, event):
+ sFit = service.Fit.getInstance()
+ activeFitID = self.mainFrame.getActiveFit()
+ fit = sFit.getFit(activeFitID)
+
+ if fit:
+ for x in self.labels:
+ slot = getattr(Slot, "F_{}".format(x.upper()))
+ used = fit.getSlotsUsed(slot)
+ total = fit.getNumSlots(slot)
+ color = wx.Colour(204, 51, 51) if used > total else wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOWTEXT)
+
+ lbl = getattr(self, "label%sUsed" % x.capitalize())
+ lbl.SetLabel(str(int(used)))
+ lbl.SetForegroundColour(color)
+
+ lbl = getattr(self, "label%sTotal" % x.capitalize())
+ lbl.SetLabel(str(int(total)))
+ lbl.SetForegroundColour(color)
+
+ self.Refresh()
+
+
+class FighterDisplay(d.Display):
+ DEFAULT_COLS = ["State",
+ #"Base Icon",
+ "Base Name",
+ # "prop:droneDps,droneBandwidth",
+ #"Max Range",
+ #"Miscellanea",
+ "attr:maxVelocity",
+ "Fighter Abilities"
+ #"Price",
+ ]
+
+ def __init__(self, parent):
+ d.Display.__init__(self, parent, style=wx.LC_SINGLE_SEL | wx.BORDER_NONE)
+
+ self.lastFitId = None
+
+ self.hoveredRow = None
+ self.hoveredColumn = None
+
+ self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged)
+ self.mainFrame.Bind(mb.ITEM_SELECTED, self.addItem)
+ self.Bind(wx.EVT_LEFT_DCLICK, self.removeItem)
+ self.Bind(wx.EVT_LEFT_DOWN, self.click)
+ self.Bind(wx.EVT_KEY_UP, self.kbEvent)
+ self.Bind(wx.EVT_MOTION, self.OnMouseMove)
+ self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveWindow)
+
+ if "__WXGTK__" in wx.PlatformInfo:
+ self.Bind(wx.EVT_RIGHT_UP, self.scheduleMenu)
+ else:
+ self.Bind(wx.EVT_RIGHT_DOWN, self.scheduleMenu)
+
+
+ self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.startDrag)
+ self.SetDropTarget(FighterViewDrop(self.handleDragDrop))
+
+ def OnLeaveWindow(self, event):
+ self.SetToolTip(None)
+ self.hoveredRow = None
+ self.hoveredColumn = None
+ event.Skip()
+
+ def OnMouseMove(self, event):
+ row, _, col = self.HitTestSubItem(event.Position)
+ if row != self.hoveredRow or col != self.hoveredColumn:
+ if self.ToolTip is not None:
+ self.SetToolTip(None)
+ else:
+ self.hoveredRow = row
+ self.hoveredColumn = col
+ if row != -1 and col != -1 and col < len(self.DEFAULT_COLS):
+ mod = self.fighters[self.GetItemData(row)]
+ if self.DEFAULT_COLS[col] == "Miscellanea":
+ tooltip = self.activeColumns[col].getToolTip(mod)
+ if tooltip is not None:
+ self.SetToolTipString(tooltip)
+ else:
+ self.SetToolTip(None)
+ else:
+ self.SetToolTip(None)
+ else:
+ self.SetToolTip(None)
+ event.Skip()
+
+ def kbEvent(self, event):
+ keycode = event.GetKeyCode()
+ if keycode == wx.WXK_DELETE or keycode == wx.WXK_NUMPAD_DELETE:
+ row = self.GetFirstSelected()
+ firstSel = row
+ if row != -1:
+ fighter = self.fighters[self.GetItemData(row)]
+ self.removeFighter(fighter)
+
+ event.Skip()
+
+ def startDrag(self, event):
+ row = event.GetIndex()
+ if row != -1:
+ data = wx.PyTextDataObject()
+ data.SetText("fighter:"+str(row))
+
+ dropSource = wx.DropSource(self)
+ dropSource.SetData(data)
+ res = dropSource.DoDragDrop()
+
+ def handleDragDrop(self, x, y, data):
+ '''
+ Handles dragging of items from various pyfa displays which support it
+
+ data is list with two indices:
+ data[0] is hard-coded str of originating source
+ data[1] is typeID or index of data we want to manipulate
+ '''
+ if data[0] == "fighter": # we want to merge fighters
+ srcRow = int(data[1])
+ dstRow, _ = self.HitTest((x, y))
+ if srcRow != -1 and dstRow != -1:
+ self._merge(srcRow, dstRow)
+ elif data[0] == "market":
+ wx.PostEvent(self.mainFrame, mb.ItemSelected(itemID=int(data[1])))
+
+ def _merge(self, src, dst):
+ return
+
+ '''
+ DRONE_ORDER = ('Light Scout Drones', 'Medium Scout Drones',
+ 'Heavy Attack Drones', 'Sentry Drones', 'Fighters',
+ 'Fighter Bombers', 'Combat Utility Drones',
+ 'Electronic Warfare Drones', 'Logistic Drones', 'Mining Drones', 'Salvage Drones',
+ 'Light Fighters', 'Heavy Fighters', 'Support Fighters')
+ def droneKey(self, drone):
+ sMkt = service.Market.getInstance()
+
+ groupName = sMkt.getMarketGroupByItem(drone.item).name
+ print groupName
+ return (self.DRONE_ORDER.index(groupName),
+ drone.item.name)
+ '''
+
+ def fitChanged(self, event):
+
+ #Clear list and get out if current fitId is None
+ if event.fitID is None and self.lastFitId is not None:
+ self.DeleteAllItems()
+ self.lastFitId = None
+ 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
+
+ '''
+ if stuff is not None:
+ stuff.sort(key=self.droneKey)
+ '''
+
+ if event.fitID != self.lastFitId:
+ self.lastFitId = event.fitID
+
+ item = self.GetNextItem(-1, wx.LIST_NEXT_ALL, wx.LIST_STATE_DONTCARE)
+
+ if item != -1:
+ self.EnsureVisible(item)
+
+ self.deselectItems()
+
+ self.update(stuff)
+ event.Skip()
+
+
+ def addItem(self, event):
+ sFit = service.Fit.getInstance()
+ fitID = self.mainFrame.getActiveFit()
+ trigger = sFit.addFighter(fitID, event.itemID)
+ if trigger:
+ wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
+ self.mainFrame.additionsPane.select("Fighters")
+
+ event.Skip()
+
+ def removeItem(self, event):
+ row, _ = self.HitTest(event.Position)
+ if row != -1:
+ col = self.getColumn(event.Position)
+ if col != self.getColIndex(State):
+ fighter = self.fighters[self.GetItemData(row)]
+ self.removeFighter(fighter)
+
+ def removeFighter(self, fighter):
+ fitID = self.mainFrame.getActiveFit()
+ sFit = service.Fit.getInstance()
+ sFit.removeFighter(fitID, self.original.index(fighter))
+ wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
+
+ def click(self, event):
+ event.Skip()
+ row, _ = self.HitTest(event.Position)
+ if row != -1:
+ col = self.getColumn(event.Position)
+ if col == self.getColIndex(State):
+ fitID = self.mainFrame.getActiveFit()
+ sFit = service.Fit.getInstance()
+ fighter = self.fighters[row]
+ sFit.toggleFighter(fitID, self.original.index(fighter))
+ wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
+
+ def scheduleMenu(self, event):
+ event.Skip()
+ if self.getColumn(event.Position) != self.getColIndex(State):
+ wx.CallAfter(self.spawnMenu)
+
+ def spawnMenu(self):
+ sel = self.GetFirstSelected()
+ if sel != -1:
+ fighter = self.fighters[sel]
+
+ sMkt = service.Market.getInstance()
+ sourceContext = "fighterItem"
+ itemContext = sMkt.getCategoryByItem(fighter.item).name
+ menu = ContextMenu.getMenu((fighter,), (sourceContext, itemContext))
+ self.PopupMenu(menu)
diff --git a/gui/gangView.py b/gui/gangView.py
index 2e6d7b1da..25a457301 100644
--- a/gui/gangView.py
+++ b/gui/gangView.py
@@ -346,9 +346,8 @@ class GangView ( ScrolledPanel ):
choice.Clear()
currSelFound = False
for char in charList:
- id,name,_ = char
- choice.Append(name, id)
- if chCurrData == id:
+ choice.Append(char.name, char.ID)
+ if chCurrData == char.ID:
currSelFound = True
if chCurrSelection == -1:
diff --git a/gui/implantView.py b/gui/implantView.py
index d87838113..4b4755252 100644
--- a/gui/implantView.py
+++ b/gui/implantView.py
@@ -21,12 +21,62 @@ import wx
import service
import gui.display as d
import gui.marketBrowser as mb
+import gui.mainFrame
from gui.builtinViewColumns.state import State
from gui.contextMenu import ContextMenu
import globalEvents as GE
-class ImplantView(d.Display):
+from eos.types import ImplantLocation
+
+
+class ImplantView(wx.Panel):
+ def __init__(self, parent):
+ wx.Panel.__init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, style=wx.TAB_TRAVERSAL )
+ self.mainFrame = gui.mainFrame.MainFrame.getInstance()
+
+ mainSizer = wx.BoxSizer(wx.VERTICAL)
+
+ self.implantDisplay = ImplantDisplay(self)
+ mainSizer.Add(self.implantDisplay, 1, wx.EXPAND, 0 )
+
+ radioSizer = wx.BoxSizer(wx.HORIZONTAL)
+ radioSizer.AddSpacer(( 0, 0), 1, wx.EXPAND, 5)
+ self.rbFit = wx.RadioButton(self, id=wx.ID_ANY, label="Use Fit-specific Implants", style=wx.RB_GROUP)
+ self.rbChar = wx.RadioButton(self, id=wx.ID_ANY, label="Use Character Implants")
+ radioSizer.Add(self.rbFit, 0, wx.ALL, 5)
+ radioSizer.Add(self.rbChar, 0, wx.ALL, 5)
+ radioSizer.AddSpacer((0, 0), 1, wx.EXPAND, 5)
+
+ mainSizer.Add(radioSizer, 0, wx.EXPAND, 5)
+
+ self.SetSizer( mainSizer )
+ self.SetAutoLayout(True)
+
+ self.Bind(wx.EVT_RADIOBUTTON, self.OnRadioSelect, self.rbFit)
+ self.Bind(wx.EVT_RADIOBUTTON, self.OnRadioSelect, self.rbChar)
+ self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged)
+
+ def fitChanged(self, event):
+ sFit = service.Fit.getInstance()
+ activeFitID = self.mainFrame.getActiveFit()
+ fit = sFit.getFit(activeFitID)
+ if fit:
+ if fit.implantSource == ImplantLocation.FIT:
+ self.rbFit.SetValue(True)
+ else:
+ self.rbChar.SetValue(True)
+
+ def OnRadioSelect(self, event):
+ fitID = self.mainFrame.getActiveFit()
+ sFit = service.Fit.getInstance()
+ sFit.toggleImplantSource(fitID, ImplantLocation.FIT if self.rbFit.GetValue() else ImplantLocation.CHARACTER)
+
+ wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
+
+
+class ImplantDisplay(d.Display):
DEFAULT_COLS = ["State",
"attr:implantness",
+ "Base Icon",
"Base Name"]
def __init__(self, parent):
@@ -65,7 +115,7 @@ class ImplantView(d.Display):
fit = sFit.getFit(event.fitID)
self.original = fit.implants if fit is not None else None
- self.implants = stuff = 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)
if event.fitID != self.lastFitId:
@@ -78,8 +128,7 @@ class ImplantView(d.Display):
self.deselectItems()
- self.populate(stuff)
- self.refresh(stuff)
+ self.update(stuff)
event.Skip()
def addItem(self, event):
@@ -123,14 +172,27 @@ class ImplantView(d.Display):
def spawnMenu(self):
sel = self.GetFirstSelected()
+ menu = None
+
+ sFit = service.Fit.getInstance()
+ fit = sFit.getFit(self.mainFrame.getActiveFit())
+
+ if not fit:
+ return
+
if sel != -1:
- sFit = service.Fit.getInstance()
- fit = sFit.getFit(self.mainFrame.getActiveFit())
- implant = fit.implants[sel]
+ implant = fit.appliedImplants[sel]
sMkt = service.Market.getInstance()
- sourceContext = "implantItem"
+ sourceContext = "implantItem" if fit.implantSource == ImplantLocation.FIT else "implantItemChar"
itemContext = sMkt.getCategoryByItem(implant.item).name
menu = ContextMenu.getMenu((implant,), (sourceContext, itemContext))
+ elif sel == -1 and fit.implantSource == ImplantLocation.FIT:
+ fitID = self.mainFrame.getActiveFit()
+ if fitID is None:
+ return
+ context = (("implantView",),)
+ menu = ContextMenu.getMenu([], *context)
+ if menu is not None:
self.PopupMenu(menu)
diff --git a/gui/itemStats.py b/gui/itemStats.py
index d0ef2db3f..0f2b26eeb 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
+from eos.types import Fit, Ship, Module, Skill, Booster, Implant, Drone, Mode, Fighter
from gui.utils.numberFormatter import formatAmount
import service
import config
@@ -242,6 +242,10 @@ class ItemDescription ( wx.Panel ):
fgcolor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOWTEXT)
self.description = wx.html.HtmlWindow(self)
+
+ if not item.description:
+ return
+
desc = item.description.replace("\r", "
")
# Strip font tags
desc = re.sub("<( *)font( *)color( *)=(.*?)>(?P.*?)<( *)/( *)font( *)>", "\g", desc)
@@ -557,7 +561,7 @@ class ItemEffects (wx.Panel):
class ItemAffectedBy (wx.Panel):
- ORDER = [Fit, Ship, Mode, Module, Drone, Implant, Booster, Skill]
+ ORDER = [Fit, Ship, 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 4c0d39ba7..7557813db 100644
--- a/gui/mainFrame.py
+++ b/gui/mainFrame.py
@@ -50,6 +50,7 @@ from gui.characterEditor import CharacterEditor, SaveCharacterAs
from gui.characterSelection import CharacterSelection
from gui.patternEditor import DmgPatternEditorDlg
from gui.resistsEditor import ResistsEditorDlg
+from gui.setEditor import ImplantSetEditorDlg
from gui.preferenceDialog import PreferenceDialog
from gui.graphFrame import GraphFrame
from gui.copySelectDialog import CopySelectDialog
@@ -358,15 +359,16 @@ class MainFrame(wx.Frame):
dlg.Show()
def showTargetResistsEditor(self, event):
- dlg=ResistsEditorDlg(self)
- dlg.ShowModal()
- dlg.Destroy()
+ ResistsEditorDlg(self)
def showDamagePatternEditor(self, event):
dlg=DmgPatternEditorDlg(self)
dlg.ShowModal()
dlg.Destroy()
+ def showImplantSetEditor(self, event):
+ ImplantSetEditorDlg(self)
+
def showExportDialog(self, event):
""" Export active fit """
sFit = service.Fit.getInstance()
@@ -418,6 +420,8 @@ class MainFrame(wx.Frame):
self.Bind(wx.EVT_MENU, self.showDamagePatternEditor, id=menuBar.damagePatternEditorId)
# Target Resists editor
self.Bind(wx.EVT_MENU, self.showTargetResistsEditor, id=menuBar.targetResistsEditorId)
+ # Implant Set editor
+ self.Bind(wx.EVT_MENU, self.showImplantSetEditor, id=menuBar.implantSetEditorId)
# Import dialog
self.Bind(wx.EVT_MENU, self.fileImportDialog, id=wx.ID_OPEN)
# Export dialog
diff --git a/gui/mainMenuBar.py b/gui/mainMenuBar.py
index 78376fde7..e8c3cb614 100644
--- a/gui/mainMenuBar.py
+++ b/gui/mainMenuBar.py
@@ -33,6 +33,7 @@ class MainMenuBar(wx.MenuBar):
self.characterEditorId = wx.NewId()
self.damagePatternEditorId = wx.NewId()
self.targetResistsEditorId = wx.NewId()
+ self.implantSetEditorId = wx.NewId()
self.graphFrameId = wx.NewId()
self.backupFitsId = wx.NewId()
self.exportSkillsNeededId = wx.NewId()
@@ -101,9 +102,13 @@ class MainMenuBar(wx.MenuBar):
windowMenu.AppendItem(damagePatternEditItem)
targetResistsEditItem = wx.MenuItem(windowMenu, self.targetResistsEditorId, "Target Resists Editor\tCTRL+R")
- targetResistsEditItem.SetBitmap(BitmapLoader.getBitmap("explosive_big", "gui"))
+ targetResistsEditItem.SetBitmap(BitmapLoader.getBitmap("explosive_small", "gui"))
windowMenu.AppendItem(targetResistsEditItem)
+ implantSetEditItem = wx.MenuItem(windowMenu, self.implantSetEditorId, "Implant Set Editor\tCTRL+I")
+ implantSetEditItem.SetBitmap(BitmapLoader.getBitmap("hardwire_small", "gui"))
+ windowMenu.AppendItem(implantSetEditItem)
+
graphFrameItem = wx.MenuItem(windowMenu, self.graphFrameId, "Graphs\tCTRL+G")
graphFrameItem.SetBitmap(BitmapLoader.getBitmap("graphs_small", "gui"))
windowMenu.AppendItem(graphFrameItem)
diff --git a/gui/patternEditor.py b/gui/patternEditor.py
index 40b8e45aa..e04671b8d 100644
--- a/gui/patternEditor.py
+++ b/gui/patternEditor.py
@@ -23,11 +23,64 @@ import service
from wx.lib.intctrl import IntCtrl
from gui.utils.clipboard import toClipboard, fromClipboard
from service.damagePattern import ImportError
-
+from gui.builtinViews.entityEditor import EntityEditor, BaseValidator
###########################################################################
## Class DmgPatternEditorDlg
###########################################################################
+class DmgPatternTextValidor(BaseValidator):
+ def __init__(self):
+ BaseValidator.__init__(self)
+
+ def Clone(self):
+ return DmgPatternTextValidor()
+
+ def Validate(self, win):
+ profileEditor = win.Parent
+ textCtrl = self.GetWindow()
+ text = textCtrl.GetValue().strip()
+
+ try:
+ if len(text) == 0:
+ raise ValueError("You must supply a name for your Damage Profile!")
+ elif text in [x.name for x in profileEditor.entityEditor.choices]:
+ raise ValueError("Damage Profile name already in use, please choose another.")
+
+ return True
+ except ValueError, e:
+ wx.MessageBox(u"{}".format(e), "Error")
+ textCtrl.SetFocus()
+ return False
+
+
+class DmgPatternEntityEditor(EntityEditor):
+ def __init__(self, parent):
+ EntityEditor.__init__(self, parent, "Damage Profile")
+ self.SetEditorValidator(DmgPatternTextValidor)
+
+ def getEntitiesFromContext(self):
+ sDP = service.DamagePattern.getInstance()
+ choices = sorted(sDP.getDamagePatternList(), key=lambda p: p.name)
+ return [c for c in choices if c.name != "Selected Ammo"]
+
+ def DoNew(self, name):
+ sDP = service.DamagePattern.getInstance()
+ return sDP.newPattern(name)
+
+ def DoRename(self, entity, name):
+ sDP = service.DamagePattern.getInstance()
+ sDP.renamePattern(entity, name)
+
+ def DoCopy(self, entity, name):
+ sDP = service.DamagePattern.getInstance()
+ copy = sDP.copyPattern(entity)
+ sDP.renamePattern(copy, name)
+ return copy
+
+ def DoDelete(self, entity):
+ sDP = service.DamagePattern.getInstance()
+ sDP.deletePattern(entity)
+
class DmgPatternEditorDlg(wx.Dialog):
DAMAGE_TYPES = ("em", "thermal", "kinetic", "explosive")
@@ -39,52 +92,8 @@ class DmgPatternEditorDlg(wx.Dialog):
mainSizer = wx.BoxSizer(wx.VERTICAL)
- self.headerSizer = headerSizer = wx.BoxSizer(wx.HORIZONTAL)
-
- sDP = service.DamagePattern.getInstance()
-
- self.choices = sDP.getDamagePatternList()
- # Remove "Selected Ammo" Damage Pattern
- for dp in self.choices:
- if dp.name == "Selected Ammo":
- self.choices.remove(dp)
- # Sort the remaining list and continue on
- self.choices.sort(key=lambda p: p.name)
- self.ccDmgPattern = wx.Choice(self, choices=map(lambda p: p.name, self.choices))
- self.ccDmgPattern.Bind(wx.EVT_CHOICE, self.patternChanged)
- self.ccDmgPattern.SetSelection(0)
-
- self.namePicker = wx.TextCtrl(self, style=wx.TE_PROCESS_ENTER)
- self.namePicker.Bind(wx.EVT_TEXT_ENTER, self.processRename)
- self.namePicker.Hide()
-
- size = None
- headerSizer.Add(self.ccDmgPattern, 1, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT|wx.LEFT, 3)
- buttons = (("new", wx.ART_NEW),
- ("rename", BitmapLoader.getBitmap("rename", "gui")),
- ("copy", wx.ART_COPY),
- ("delete", wx.ART_DELETE))
- for name, art in buttons:
- bitmap = wx.ArtProvider.GetBitmap(art, wx.ART_BUTTON) if name != "rename" else art
- btn = wx.BitmapButton(self, wx.ID_ANY, bitmap)
- if size is None:
- size = btn.GetSize()
-
- btn.SetMinSize(size)
- btn.SetMaxSize(size)
-
- btn.Layout()
- setattr(self, name, btn)
- btn.Enable(True)
- btn.SetToolTipString("%s pattern" % name.capitalize())
- headerSizer.Add(btn, 0, wx.ALIGN_CENTER_VERTICAL)
-
- self.btnSave = wx.Button(self, wx.ID_SAVE)
- self.btnSave.Hide()
- self.btnSave.Bind(wx.EVT_BUTTON, self.processRename)
- self.headerSizer.Add(self.btnSave, 0, wx.ALIGN_CENTER)
-
- mainSizer.Add(headerSizer, 0, wx.EXPAND | wx.ALL, 2)
+ self.entityEditor = DmgPatternEntityEditor(self)
+ mainSizer.Add(self.entityEditor, 0, wx.ALL | wx.EXPAND, 2)
self.sl = wx.StaticLine(self)
mainSizer.Add(self.sl, 0, wx.EXPAND | wx.TOP | wx.BOTTOM, 5)
@@ -108,7 +117,7 @@ class DmgPatternEditorDlg(wx.Dialog):
bmp = wx.StaticBitmap(self, wx.ID_ANY, BitmapLoader.getBitmap("%s_big"%type, "gui"))
if i%2:
style = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT
- border = 10
+ border = 20
else:
style = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT
border = 5
@@ -155,6 +164,7 @@ class DmgPatternEditorDlg(wx.Dialog):
importExport = (("Import", wx.ART_FILE_OPEN, "from"),
("Export", wx.ART_FILE_SAVE_AS, "to"))
+
for name, art, direction in importExport:
bitmap = wx.ArtProvider.GetBitmap(art, wx.ART_BUTTON)
btn = wx.BitmapButton(self, wx.ID_ANY, bitmap)
@@ -170,14 +180,10 @@ class DmgPatternEditorDlg(wx.Dialog):
self.Layout()
bsize = self.GetBestSize()
- self.SetSize((-1,bsize.height))
+ self.SetSize((-1, bsize.height))
+ self.CenterOnParent()
- self.new.Bind(wx.EVT_BUTTON, self.newPattern)
- self.rename.Bind(wx.EVT_BUTTON, self.renamePattern)
- self.copy.Bind(wx.EVT_BUTTON, self.copyPattern)
- self.delete.Bind(wx.EVT_BUTTON, self.deletePattern)
- self.Import.Bind(wx.EVT_BUTTON, self.importPatterns)
- self.Export.Bind(wx.EVT_BUTTON, self.exportPatterns)
+ self.Bind(wx.EVT_CHOICE, self.patternChanged)
self.patternChanged()
@@ -188,7 +194,7 @@ class DmgPatternEditorDlg(wx.Dialog):
if self.block:
return
- p = self.getActivePattern()
+ p = self.entityEditor.getActiveEntity()
total = sum(map(lambda attr: getattr(self, "%sEdit"%attr).GetValue(), self.DAMAGE_TYPES))
for type in self.DAMAGE_TYPES:
editObj = getattr(self, "%sEdit"%type)
@@ -207,24 +213,18 @@ class DmgPatternEditorDlg(wx.Dialog):
for type in self.DAMAGE_TYPES:
editObj = getattr(self, "%sEdit"%type)
editObj.Enable(False)
- self.rename.Enable(False)
- self.delete.Enable(False)
+ self.entityEditor.btnRename.Enable(False)
+ self.entityEditor.btnDelete.Enable(False)
def unrestrict(self):
for type in self.DAMAGE_TYPES:
editObj = getattr(self, "%sEdit"%type)
editObj.Enable()
- self.rename.Enable()
- self.delete.Enable()
-
- def getActivePattern(self):
- if len(self.choices) == 0:
- return None
-
- return self.choices[self.ccDmgPattern.GetSelection()]
+ self.entityEditor.btnRename.Enable()
+ self.entityEditor.btnDelete.Enable()
def patternChanged(self, event=None):
- p = self.getActivePattern()
+ p = self.entityEditor.getActiveEntity()
if p is None:
return
@@ -244,126 +244,9 @@ class DmgPatternEditorDlg(wx.Dialog):
self.block = False
self.ValuesUpdated()
- def newPattern(self, event):
- self.restrict()
-
- self.block = True
- # reset values
- for type in self.DAMAGE_TYPES:
- editObj = getattr(self, "%sEdit"%type)
- editObj.SetValue(0)
-
- self.block = False
-
- self.btnSave.SetLabel("Create")
- self.Refresh()
- self.renamePattern()
-
- def renamePattern(self, event=None):
- if event is not None:
- self.btnSave.SetLabel("Rename")
-
- self.ccDmgPattern.Hide()
- self.namePicker.Show()
- self.headerSizer.Replace(self.ccDmgPattern, self.namePicker)
- self.namePicker.SetFocus()
-
- if event is not None: # Rename mode
- self.btnSave.SetLabel("Rename")
- self.namePicker.SetValue(self.getActivePattern().name)
- else: # Create mode
- self.namePicker.SetValue("")
-
- for btn in (self.new, self.rename, self.delete, self.copy):
- btn.Hide()
-
- self.btnSave.Show()
- self.headerSizer.Layout()
- if event is not None:
- event.Skip()
-
- def processRename(self, event):
- newName = self.namePicker.GetLineText(0)
- self.stNotice.SetLabel("")
-
- if newName == "":
- self.stNotice.SetLabel("Invalid name.")
- return
-
- sDP = service.DamagePattern.getInstance()
- if self.btnSave.Label == "Create":
- p = sDP.newPattern()
- else:
- # we are renaming, so get the current selection
- p = self.getActivePattern()
-
- for pattern in self.choices:
- if pattern.name == newName and p != pattern:
- self.stNotice.SetLabel("Name already used, please choose another")
- return
-
- sDP.renamePattern(p, newName)
-
- self.updateChoices(newName)
- self.headerSizer.Replace(self.namePicker, self.ccDmgPattern)
- self.ccDmgPattern.Show()
- self.namePicker.Hide()
- self.btnSave.Hide()
- for btn in (self.new, self.rename, self.delete, self.copy):
- btn.Show()
-
- sel = self.ccDmgPattern.GetSelection()
- self.ccDmgPattern.Delete(sel)
- self.ccDmgPattern.Insert(newName, sel)
- self.ccDmgPattern.SetSelection(sel)
- self.ValuesUpdated()
- self.unrestrict()
-
- def copyPattern(self,event):
- sDP = service.DamagePattern.getInstance()
- p = sDP.copyPattern(self.getActivePattern())
- self.choices.append(p)
- id = self.ccDmgPattern.Append(p.name)
- self.ccDmgPattern.SetSelection(id)
- self.btnSave.SetLabel("Copy")
- self.renamePattern()
- self.patternChanged()
-
- def deletePattern(self,event):
- sDP = service.DamagePattern.getInstance()
- sel = self.ccDmgPattern.GetSelection()
- sDP.deletePattern(self.getActivePattern())
- self.ccDmgPattern.Delete(sel)
- self.ccDmgPattern.SetSelection(max(0, sel - 1))
- del self.choices[sel]
- self.patternChanged()
-
- def __del__( self ):
+ def __del__(self):
pass
- def updateChoices(self, select=None):
- "Gathers list of patterns and updates choice selections"
- sDP = service.DamagePattern.getInstance()
- self.choices = sDP.getDamagePatternList()
-
- for dp in self.choices:
- if dp.name == "Selected Ammo": # don't include this special butterfly
- self.choices.remove(dp)
-
- # Sort the remaining list and continue on
- self.choices.sort(key=lambda p: p.name)
- self.ccDmgPattern.Clear()
-
- for i, choice in enumerate(map(lambda p: p.name, self.choices)):
- self.ccDmgPattern.Append(choice)
-
- if select is not None and choice == select:
- self.ccDmgPattern.SetSelection(i)
-
- if select is None:
- self.ccDmgPattern.SetSelection(0)
- self.patternChanged()
-
def importPatterns(self, event):
text = fromClipboard()
if text:
diff --git a/gui/resistsEditor.py b/gui/resistsEditor.py
index 3d8ac6ef2..374f9c1fc 100644
--- a/gui/resistsEditor.py
+++ b/gui/resistsEditor.py
@@ -22,6 +22,61 @@ from gui.bitmapLoader import BitmapLoader
import service
from gui.utils.clipboard import toClipboard, fromClipboard
from service.targetResists import ImportError
+from gui.builtinViews.entityEditor import EntityEditor, BaseValidator
+
+
+class TargetResistsTextValidor(BaseValidator):
+ def __init__(self):
+ BaseValidator.__init__(self)
+
+ def Clone(self):
+ return TargetResistsTextValidor()
+
+ def Validate(self, win):
+ profileEditor = win.parent.Parent
+ textCtrl = self.GetWindow()
+ text = textCtrl.GetValue().strip()
+
+ try:
+ if len(text) == 0:
+ raise ValueError("You must supply a name for your Target Resist Profile!")
+ elif text in [x.name for x in profileEditor.entityEditor.choices]:
+ raise ValueError("Target Resist Profile name already in use, please choose another.")
+
+ return True
+ except ValueError, e:
+ wx.MessageBox(u"{}".format(e), "Error")
+ textCtrl.SetFocus()
+ return False
+
+
+class TargetResistsEntityEditor(EntityEditor):
+ def __init__(self, parent):
+ EntityEditor.__init__(self, parent, "Target Resist Profile")
+ self.SetEditorValidator(TargetResistsTextValidor)
+
+ def getEntitiesFromContext(self):
+ sTR = service.TargetResists.getInstance()
+ choices = sorted(sTR.getTargetResistsList(), key=lambda p: p.name)
+ return choices
+
+ def DoNew(self, name):
+ sTR = service.TargetResists.getInstance()
+ return sTR.newPattern(name)
+
+ def DoRename(self, entity, name):
+ sTR = service.TargetResists.getInstance()
+ sTR.renamePattern(entity, name)
+
+ def DoCopy(self, entity, name):
+ sTR = service.TargetResists.getInstance()
+ copy = sTR.copyPattern(entity)
+ sTR.renamePattern(copy, name)
+ return copy
+
+ def DoDelete(self, entity):
+ sTR = service.TargetResists.getInstance()
+ sTR.deletePattern(entity)
class ResistsEditorDlg(wx.Dialog):
@@ -35,51 +90,8 @@ class ResistsEditorDlg(wx.Dialog):
mainSizer = wx.BoxSizer(wx.VERTICAL)
- self.headerSizer = headerSizer = wx.BoxSizer(wx.HORIZONTAL)
-
- sTR = service.TargetResists.getInstance()
-
- self.choices = sTR.getTargetResistsList()
-
- # Sort the remaining list and continue on
- self.choices.sort(key=lambda p: p.name)
- self.ccResists = wx.Choice(self, choices=map(lambda p: p.name, self.choices))
- self.ccResists.Bind(wx.EVT_CHOICE, self.patternChanged)
- self.ccResists.SetSelection(0)
-
- self.namePicker = wx.TextCtrl(self, style=wx.TE_PROCESS_ENTER)
- self.namePicker.Bind(wx.EVT_TEXT_ENTER, self.processRename)
- self.namePicker.Hide()
-
- size = None
- headerSizer.Add(self.ccResists, 1, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT | wx.LEFT, 3)
-
- buttons = (("new", wx.ART_NEW),
- ("rename", BitmapLoader.getBitmap("rename", "gui")),
- ("copy", wx.ART_COPY),
- ("delete", wx.ART_DELETE))
- for name, art in buttons:
- bitmap = wx.ArtProvider.GetBitmap(art, wx.ART_BUTTON) if name != "rename" else art
- btn = wx.BitmapButton(self, wx.ID_ANY, bitmap)
- if size is None:
- size = btn.GetSize()
-
- btn.SetMinSize(size)
- btn.SetMaxSize(size)
-
- btn.Layout()
- setattr(self, name, btn)
- btn.Enable(True)
- btn.SetToolTipString("%s resist profile" % name.capitalize())
- headerSizer.Add(btn, 0, wx.ALIGN_CENTER_VERTICAL)
-
-
- self.btnSave = wx.Button(self, wx.ID_SAVE)
- self.btnSave.Hide()
- self.btnSave.Bind(wx.EVT_BUTTON, self.processRename)
- headerSizer.Add(self.btnSave, 0, wx.ALIGN_CENTER)
-
- mainSizer.Add(headerSizer, 0, wx.EXPAND | wx.ALL, 2)
+ self.entityEditor = TargetResistsEntityEditor(self)
+ mainSizer.Add(self.entityEditor, 0, wx.ALL | wx.EXPAND, 2)
self.sl = wx.StaticLine(self)
mainSizer.Add(self.sl, 0, wx.EXPAND | wx.TOP | wx.BOTTOM, 5)
@@ -157,19 +169,21 @@ class ResistsEditorDlg(wx.Dialog):
btn.SetToolTipString("%s patterns %s clipboard" % (name, direction) )
footerSizer.Add(btn, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_RIGHT)
+ if not self.entityEditor.checkEntitiesExist():
+ self.Destroy()
+ return
+
self.Layout()
bsize = self.GetBestSize()
- self.SetSize((-1,bsize.height))
+ self.SetSize((-1, bsize.height))
+ self.CenterOnParent()
- self.new.Bind(wx.EVT_BUTTON, self.newPattern)
- self.rename.Bind(wx.EVT_BUTTON, self.renamePattern)
- self.copy.Bind(wx.EVT_BUTTON, self.copyPattern)
- self.delete.Bind(wx.EVT_BUTTON, self.deletePattern)
- self.Import.Bind(wx.EVT_BUTTON, self.importPatterns)
- self.Export.Bind(wx.EVT_BUTTON, self.exportPatterns)
+ self.Bind(wx.EVT_CHOICE, self.patternChanged)
self.patternChanged()
+ self.ShowModal()
+
def closeEvent(self, event):
self.Destroy()
@@ -184,7 +198,7 @@ class ResistsEditorDlg(wx.Dialog):
return
try:
- p = self.getActivePattern()
+ p = self.entityEditor.getActiveEntity()
for type in self.DAMAGE_TYPES:
editObj = getattr(self, "%sEdit"%type)
@@ -220,33 +234,15 @@ class ResistsEditorDlg(wx.Dialog):
finally: # Refresh for color changes to take effect immediately
self.Refresh()
- def restrict(self):
- for type in self.DAMAGE_TYPES:
- editObj = getattr(self, "%sEdit"%type)
- editObj.Enable(False)
- self.rename.Enable(False)
- self.delete.Enable(False)
-
- def unrestrict(self):
- for type in self.DAMAGE_TYPES:
- editObj = getattr(self, "%sEdit"%type)
- editObj.Enable()
- self.rename.Enable()
- self.delete.Enable()
-
- def getActivePattern(self):
- if len(self.choices) == 0:
- return None
-
- return self.choices[self.ccResists.GetSelection()]
-
def patternChanged(self, event=None):
"Event fired when user selects pattern. Can also be called from script"
- p = self.getActivePattern()
+
+ if not self.entityEditor.checkEntitiesExist():
+ self.Destroy()
+ return
+
+ p = self.entityEditor.getActiveEntity()
if p is None:
- # This happens when there are no patterns in the DB. As such, force
- # user to create one first or exit dlg.
- self.newPattern(None)
return
self.block = True
@@ -259,142 +255,9 @@ class ResistsEditorDlg(wx.Dialog):
self.block = False
self.ValuesUpdated()
- def newPattern(self, event):
- '''
- Simply does new-pattern specifics: replaces label on button, restricts,
- and resets values to default. Hands off to the rename function for
- further handling.
- '''
- self.btnSave.SetLabel("Create")
- self.restrict()
- # reset values
- for type in self.DAMAGE_TYPES:
- editObj = getattr(self, "%sEdit"%type)
- editObj.ChangeValue("0.0")
- editObj.SetForegroundColour(self.colorReset)
-
- self.Refresh()
- self.renamePattern()
-
- def renamePattern(self, event=None):
- "Changes layout to facilitate naming a pattern"
-
- self.showInput(True)
-
- if event is not None: # Rename mode
- self.btnSave.SetLabel("Rename")
- self.namePicker.SetValue(self.getActivePattern().name)
- else: # Create mode
- self.namePicker.SetValue("")
-
- if event is not None:
- event.Skip()
-
- def processRename(self, event):
- '''
- Processes rename event (which can be new or old patterns). If new
- pattern, creates it; if old, selects it. if checks are valid, rename
- saves pattern to DB.
-
- Also resets to default layout and unrestricts.
- '''
- newName = self.namePicker.GetLineText(0)
- self.stNotice.SetLabel("")
-
- if newName == "":
- self.stNotice.SetLabel("Invalid name")
- return
-
- sTR = service.TargetResists.getInstance()
- if self.btnSave.Label == "Create":
- p = sTR.newPattern()
- else:
- # we are renaming, so get the current selection
- p = self.getActivePattern()
-
- # test for patterns of the same name
- for pattern in self.choices:
- if pattern.name == newName and p != pattern:
- self.stNotice.SetLabel("Name already used, please choose another")
- return
-
- # rename regardless of new or rename
- sTR.renamePattern(p, newName)
-
- self.updateChoices(newName)
- self.showInput(False)
- sel = self.ccResists.GetSelection()
- self.ValuesUpdated()
- self.unrestrict()
-
- def copyPattern(self,event):
- sTR = service.TargetResists.getInstance()
- p = sTR.copyPattern(self.getActivePattern())
- self.choices.append(p)
- id = self.ccResists.Append(p.name)
- self.ccResists.SetSelection(id)
- self.btnSave.SetLabel("Copy")
- self.renamePattern()
- self.patternChanged()
-
- def deletePattern(self,event):
- sTR = service.TargetResists.getInstance()
- sel = self.ccResists.GetSelection()
- sTR.deletePattern(self.getActivePattern())
- self.ccResists.Delete(sel)
- self.ccResists.SetSelection(max(0, sel - 1))
- del self.choices[sel]
- self.patternChanged()
-
- def showInput(self, bool):
- if bool and not self.namePicker.IsShown():
- self.ccResists.Hide()
- self.namePicker.Show()
- self.headerSizer.Replace(self.ccResists, self.namePicker)
- self.namePicker.SetFocus()
- for btn in (self.new, self.rename, self.delete, self.copy):
- btn.Hide()
- self.btnSave.Show()
- self.restrict()
- self.headerSizer.Layout()
- elif not bool and self.namePicker.IsShown():
- self.headerSizer.Replace(self.namePicker, self.ccResists)
- self.ccResists.Show()
- self.namePicker.Hide()
- self.btnSave.Hide()
- for btn in (self.new, self.rename, self.delete, self.copy):
- btn.Show()
- self.unrestrict()
- self.headerSizer.Layout()
-
-
def __del__( self ):
pass
- def updateChoices(self, select=None):
- "Gathers list of patterns and updates choice selections"
- sTR = service.TargetResists.getInstance()
- self.choices = sTR.getTargetResistsList()
-
- if len(self.choices) == 0:
- #self.newPattern(None)
- return
-
- # Sort the remaining list and continue on
- self.choices.sort(key=lambda p: p.name)
- self.ccResists.Clear()
-
- for i, choice in enumerate(map(lambda p: p.name, self.choices)):
- self.ccResists.Append(choice)
-
- if select is not None and choice == select:
- self.ccResists.SetSelection(i)
-
- if select is None:
- self.ccResists.SetSelection(0)
-
- self.patternChanged()
-
def importPatterns(self, event):
"Event fired when import from clipboard button is clicked"
diff --git a/gui/setEditor.py b/gui/setEditor.py
new file mode 100644
index 000000000..4e8baa9ed
--- /dev/null
+++ b/gui/setEditor.py
@@ -0,0 +1,214 @@
+#===============================================================================
+# Copyright (C) 2016 Ryan Holmes
+#
+# This file is part of pyfa.
+#
+# pyfa is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# pyfa is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with pyfa. If not, see .
+#===============================================================================
+
+import wx
+from gui.bitmapLoader import BitmapLoader
+from gui.builtinViews.implantEditor import BaseImplantEditorView
+import service
+from gui.utils.clipboard import toClipboard, fromClipboard
+from service.implantSet import ImportError
+import logging
+from gui.builtinViews.entityEditor import EntityEditor, BaseValidator
+
+logger = logging.getLogger(__name__)
+
+class ImplantTextValidor(BaseValidator):
+ def __init__(self):
+ BaseValidator.__init__(self)
+
+ def Clone(self):
+ return ImplantTextValidor()
+
+ def Validate(self, win):
+ profileEditor = win.parent.Parent
+ textCtrl = self.GetWindow()
+ text = textCtrl.GetValue().strip()
+
+ try:
+ if len(text) == 0:
+ raise ValueError("You must supply a name for the Implant Set!")
+ elif text in [x.name for x in profileEditor.entityEditor.choices]:
+ raise ValueError("Imlplant Set name already in use, please choose another.")
+
+ return True
+ except ValueError, e:
+ wx.MessageBox(u"{}".format(e), "Error")
+ textCtrl.SetFocus()
+ return False
+
+
+class ImplantSetEntityEditor(EntityEditor):
+ def __init__(self, parent):
+ EntityEditor.__init__(self, parent, "Implant Set")
+ self.SetEditorValidator(ImplantTextValidor)
+
+ def getEntitiesFromContext(self):
+ sIS = service.ImplantSets.getInstance()
+ return sorted(sIS.getImplantSetList(), key=lambda c: c.name)
+
+ def DoNew(self, name):
+ sIS = service.ImplantSets.getInstance()
+ return sIS.newSet(name)
+
+ def DoRename(self, entity, name):
+ sIS = service.ImplantSets.getInstance()
+ sIS.renameSet(entity, name)
+
+ def DoCopy(self, entity, name):
+ sIS = service.ImplantSets.getInstance()
+ copy = sIS.copySet(entity)
+ sIS.renameSet(copy, name)
+ return copy
+
+ def DoDelete(self, entity):
+ sIS = service.ImplantSets.getInstance()
+ sIS.deleteSet(entity)
+
+
+class ImplantSetEditor(BaseImplantEditorView):
+ def __init__(self, parent):
+ BaseImplantEditorView.__init__(self, parent)
+ if 'wxMSW' in wx.PlatformInfo:
+ self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE))
+
+ def bindContext(self):
+ self.Parent.entityEditor.Bind(wx.EVT_CHOICE, self.contextChanged)
+
+ def getImplantsFromContext(self):
+ sIS = service.ImplantSets.getInstance()
+ set = self.Parent.entityEditor.getActiveEntity()
+ if set:
+ return sIS.getImplants(set.ID)
+ return []
+
+ def addImplantToContext(self, item):
+ sIS = service.ImplantSets.getInstance()
+ set = self.Parent.entityEditor.getActiveEntity()
+
+ sIS.addImplant(set.ID, item.ID)
+
+ def removeImplantFromContext(self, implant):
+ sIS = service.ImplantSets.getInstance()
+ set = self.Parent.entityEditor.getActiveEntity()
+
+ sIS.removeImplant(set.ID, implant)
+
+class ImplantSetEditorDlg(wx.Dialog):
+
+ def __init__(self, parent):
+ wx.Dialog.__init__(self, parent, id = wx.ID_ANY, title = u"Implant Set Editor", size = wx.Size(640, 600))
+
+ self.block = False
+ self.SetSizeHintsSz(wx.DefaultSize, wx.DefaultSize)
+
+ mainSizer = wx.BoxSizer(wx.VERTICAL)
+
+ self.entityEditor = ImplantSetEntityEditor(self)
+ mainSizer.Add(self.entityEditor, 0, wx.ALL | wx.EXPAND, 2)
+
+ self.sl = wx.StaticLine(self)
+ mainSizer.Add(self.sl, 0, wx.EXPAND | wx.TOP | wx.BOTTOM, 5)
+
+ self.iview = ImplantSetEditor(self)
+ mainSizer.Add(self.iview, 1, wx.ALL | wx.EXPAND, 5)
+
+ self.slfooter = wx.StaticLine(self)
+ mainSizer.Add(self.slfooter, 0, wx.EXPAND | wx.TOP, 5)
+
+ footerSizer = wx.BoxSizer(wx.HORIZONTAL)
+
+ self.stNotice = wx.StaticText(self, wx.ID_ANY, u"")
+ self.stNotice.Wrap(-1)
+ footerSizer.Add(self.stNotice, 1, wx.BOTTOM | wx.TOP | wx.LEFT, 5)
+
+ if "wxGTK" in wx.PlatformInfo:
+ self.closeBtn = wx.Button( self, wx.ID_ANY, u"Close", wx.DefaultPosition, wx.DefaultSize, 0 )
+ mainSizer.Add( self.closeBtn, 0, wx.ALL|wx.ALIGN_RIGHT, 5 )
+ self.closeBtn.Bind(wx.EVT_BUTTON, self.closeEvent)
+
+ importExport = (("Import", wx.ART_FILE_OPEN, "from"),
+ ("Export", wx.ART_FILE_SAVE_AS, "to"))
+
+ for name, art, direction in importExport:
+ bitmap = wx.ArtProvider.GetBitmap(art, wx.ART_BUTTON)
+ btn = wx.BitmapButton(self, wx.ID_ANY, bitmap)
+
+ btn.SetMinSize( btn.GetSize() )
+ btn.SetMaxSize( btn.GetSize() )
+
+ btn.Layout()
+ setattr(self, name, btn)
+ btn.Enable(True)
+ btn.SetToolTipString("%s implant sets %s clipboard" % (name, direction) )
+ footerSizer.Add(btn, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_RIGHT)
+
+ mainSizer.Add(footerSizer, 0, wx.ALL | wx.EXPAND, 5)
+
+ self.SetSizer(mainSizer)
+ self.Layout()
+
+ if not self.entityEditor.checkEntitiesExist():
+ self.Destroy()
+ return
+
+ self.Bind(wx.EVT_CHOICE, self.entityChanged)
+
+ self.Import.Bind(wx.EVT_BUTTON, self.importPatterns)
+ self.Export.Bind(wx.EVT_BUTTON, self.exportPatterns)
+
+ self.CenterOnParent()
+ self.ShowModal()
+
+ def entityChanged(self, event):
+ if not self.entityEditor.checkEntitiesExist():
+ self.Destroy()
+ return
+
+ def closeEvent(self, event):
+ self.Destroy()
+
+ def __del__( self ):
+ pass
+
+ def importPatterns(self, event):
+ "Event fired when import from clipboard button is clicked"
+
+ text = fromClipboard()
+ if text:
+ sIS = service.ImplantSets.getInstance()
+ try:
+ sIS.importSets(text)
+ self.stNotice.SetLabel("Patterns successfully imported from clipboard")
+ self.showInput(False)
+ except ImportError, e:
+ self.stNotice.SetLabel(str(e))
+ except Exception, e:
+ logging.exception("Unhandled Exception")
+ self.stNotice.SetLabel("Could not import from clipboard: unknown errors")
+ finally:
+ self.updateChoices()
+ else:
+ self.stNotice.SetLabel("Could not import from clipboard")
+
+ def exportPatterns(self, event):
+ "Event fired when export to clipboard button is clicked"
+
+ sIS = service.ImplantSets.getInstance()
+ toClipboard(sIS.exportSets())
+ self.stNotice.SetLabel("Sets exported to clipboard")
diff --git a/imgs/gui/fighterBay_big.png b/imgs/gui/fighterBay_big.png
new file mode 100644
index 000000000..ad6171cee
Binary files /dev/null and b/imgs/gui/fighterBay_big.png differ
diff --git a/imgs/gui/fighterTubes_big.png b/imgs/gui/fighterTubes_big.png
new file mode 100644
index 000000000..077115e18
Binary files /dev/null and b/imgs/gui/fighterTubes_big.png differ
diff --git a/imgs/gui/fighter_big.png b/imgs/gui/fighter_big.png
new file mode 100644
index 000000000..afc5c3734
Binary files /dev/null and b/imgs/gui/fighter_big.png differ
diff --git a/imgs/gui/fighter_small.png b/imgs/gui/fighter_small.png
new file mode 100644
index 000000000..1e6696414
Binary files /dev/null and b/imgs/gui/fighter_small.png differ
diff --git a/imgs/gui/hardwire_small.png b/imgs/gui/hardwire_small.png
new file mode 100644
index 000000000..58b63b045
Binary files /dev/null and b/imgs/gui/hardwire_small.png differ
diff --git a/imgs/icons/124_10.png b/imgs/icons/124_10.png
new file mode 100644
index 000000000..c53dada1e
Binary files /dev/null and b/imgs/icons/124_10.png differ
diff --git a/imgs/icons/124_11.png b/imgs/icons/124_11.png
new file mode 100644
index 000000000..12e664125
Binary files /dev/null and b/imgs/icons/124_11.png differ
diff --git a/imgs/icons/124_14.png b/imgs/icons/124_14.png
new file mode 100644
index 000000000..e9dd2555c
Binary files /dev/null and b/imgs/icons/124_14.png differ
diff --git a/imgs/icons/124_15.png b/imgs/icons/124_15.png
new file mode 100644
index 000000000..9faca0b3f
Binary files /dev/null and b/imgs/icons/124_15.png differ
diff --git a/imgs/icons/124_5.png b/imgs/icons/124_5.png
new file mode 100644
index 000000000..c7c8d52f5
Binary files /dev/null and b/imgs/icons/124_5.png differ
diff --git a/imgs/icons/124_6.png b/imgs/icons/124_6.png
new file mode 100644
index 000000000..6b61be8dc
Binary files /dev/null and b/imgs/icons/124_6.png differ
diff --git a/imgs/icons/124_7.png b/imgs/icons/124_7.png
new file mode 100644
index 000000000..152968851
Binary files /dev/null and b/imgs/icons/124_7.png differ
diff --git a/imgs/icons/124_9.png b/imgs/icons/124_9.png
new file mode 100644
index 000000000..1891b9fbf
Binary files /dev/null and b/imgs/icons/124_9.png differ
diff --git a/imgs/icons/5_17.png b/imgs/icons/5_17.png
index 60182777f..c7772da4e 100644
Binary files a/imgs/icons/5_17.png and b/imgs/icons/5_17.png differ
diff --git a/imgs/icons/5_18.png b/imgs/icons/5_18.png
index b9e9d3b5a..7ba26a473 100644
Binary files a/imgs/icons/5_18.png and b/imgs/icons/5_18.png differ
diff --git a/imgs/icons/5_19.png b/imgs/icons/5_19.png
index e47daa18b..d71f2877f 100644
Binary files a/imgs/icons/5_19.png and b/imgs/icons/5_19.png differ
diff --git a/imgs/icons/5_20.png b/imgs/icons/5_20.png
index 1f3fd652f..f3c2accff 100644
Binary files a/imgs/icons/5_20.png and b/imgs/icons/5_20.png differ
diff --git a/imgs/icons/5_21.png b/imgs/icons/5_21.png
index 926361acd..07f00b4ec 100644
Binary files a/imgs/icons/5_21.png and b/imgs/icons/5_21.png differ
diff --git a/imgs/renders/37604.png b/imgs/renders/37604.png
new file mode 100644
index 000000000..8c2eb4343
Binary files /dev/null and b/imgs/renders/37604.png differ
diff --git a/imgs/renders/37605.png b/imgs/renders/37605.png
new file mode 100644
index 000000000..07c1eb99f
Binary files /dev/null and b/imgs/renders/37605.png differ
diff --git a/imgs/renders/37606.png b/imgs/renders/37606.png
new file mode 100644
index 000000000..317a37c20
Binary files /dev/null and b/imgs/renders/37606.png differ
diff --git a/imgs/renders/37607.png b/imgs/renders/37607.png
new file mode 100644
index 000000000..1cd489c7e
Binary files /dev/null and b/imgs/renders/37607.png differ
diff --git a/scripts/itemDiff.py b/scripts/itemDiff.py
index a0aaa9672..c25312bf8 100755
--- a/scripts/itemDiff.py
+++ b/scripts/itemDiff.py
@@ -103,7 +103,7 @@ def main(old, new, groups=True, effects=True, attributes=True, renames=True):
if implementedtag:
print("\n[{0}] \"{1}\"\n[{2}] \"{3}\"".format(geteffst(couple[0]), couple[0], geteffst(couple[1]), couple[1]))
else:
- print(" \"{0}\": \"{1}\",".format(couple[0], couple[1]))
+ print(" \"{0}\": \"{1}\",".format(couple[0].encode('utf-8'), couple[1].encode('utf-8')))
groupcats = {}
def getgroupcat(grp):
@@ -256,10 +256,7 @@ def main(old, new, groups=True, effects=True, attributes=True, renames=True):
attrid = row[1]
attrval = row[2]
attrdict = dictionary[itemid][2]
- if attrid in attrdict:
- print("Warning: base attribute is described in non-base attribute table")
- else:
- attrdict[attrid] = attrval
+ attrdict[attrid] = attrval
# Get set of IDs from both dictionaries
items_old = set(old_itmdata.keys())
@@ -414,6 +411,26 @@ def main(old, new, groups=True, effects=True, attributes=True, renames=True):
pass
# Print jobs
print("Comparing databases:\n{0} -> {1}\n".format(old_meta.get("client_build"), new_meta.get("client_build")))
+
+ if renames:
+ title = 'effects'
+ printrenames(ren_effects, title, implementedtag=True)
+
+ title = 'attributes'
+ printrenames(ren_attributes, title)
+
+ title = 'categories'
+ printrenames(ren_categories, title)
+
+ title = 'groups'
+ printrenames(ren_groups, title)
+
+ title = 'market groups'
+ printrenames(ren_marketgroups, title)
+
+ title = 'items'
+ printrenames(ren_items, title)
+
if effects or attributes or groups:
# Print legend only when there're any interesting changes
if len(global_itmdata[S["removed"]]) > 0 or len(global_itmdata[S["changed"]]) > 0 or len(global_itmdata[S["added"]]) > 0:
@@ -446,7 +463,7 @@ def main(old, new, groups=True, effects=True, attributes=True, renames=True):
for item in itemorder:
groupdata = items[item][0]
groupstr = " ({0} => {1})".format(getgroupname(groupdata[1]), getgroupname(groupdata[2])) if groupdata[0] == S["changed"] else ""
- print("\n[{0}] {1}{2}".format(TG[itmstate], getitemname(item), groupstr))
+ print("\n[{0}] {1}{2}".format(TG[itmstate], getitemname(item).encode('utf-8'), groupstr))
effdata = items[item][1]
for effstate in stateorder:
@@ -478,25 +495,6 @@ def main(old, new, groups=True, effects=True, attributes=True, renames=True):
valline = "{0} => {1}".format(attrs[attr][0] or 0, attrs[attr][1] or 0)
print(" [{0}] {1}: {2}".format(TG[attrstate], getattrname(attr), valline))
- if renames:
- title = 'effects'
- printrenames(ren_effects, title, implementedtag=True)
-
- title = 'attributes'
- printrenames(ren_attributes, title)
-
- title = 'categories'
- printrenames(ren_categories, title)
-
- title = 'groups'
- printrenames(ren_groups, title)
-
- title = 'market groups'
- printrenames(ren_marketgroups, title)
-
- title = 'items'
- printrenames(ren_items, title)
-
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Compare two databases generated from eve dump to find eos-related differences")
parser.add_argument("-o", "--old", type=str, help="path to old cache data dump, defaults to current pyfa eve.db", default=default_old)
diff --git a/scripts/jsonToSql.py b/scripts/jsonToSql.py
index 078b006e0..d87db0190 100755
--- a/scripts/jsonToSql.py
+++ b/scripts/jsonToSql.py
@@ -176,7 +176,10 @@ def main(db, json_path):
for row in data["evetypes"]:
# 1306 - group Ship Modifiers, for items like tactical t3 ship modes
# (3638, 3634, 3636, 3640) - Civilian weapons
- if (row["published"] or row['groupID'] == 1306 or row['typeID'] in (3638, 3634, 3636, 3640)):
+ # (41549, 41548, 41551, 41550) - Micro Bombs (Fighters)
+ if (row["published"] or row['groupID'] == 1306
+ or row['typeID'] in (3638, 3634, 3636, 3640)
+ or row['typeID'] in (41549, 41548, 41551,41550)):
eveTypes.add(row["typeID"])
# ignore checker
diff --git a/scripts/prep_data.py b/scripts/prep_data.py
index 823b4d037..2767bd8ba 100644
--- a/scripts/prep_data.py
+++ b/scripts/prep_data.py
@@ -78,7 +78,7 @@ if not args.nojson:
)
list = "dgmexpressions,dgmattribs,dgmeffects,dgmtypeattribs,dgmtypeeffects,"\
- "dgmunits,icons,invcategories,invgroups,invmetagroups,invmetatypes,"\
+ "dgmunits,invcategories,invgroups,invmetagroups,invmetatypes,"\
"invtypes,mapbulk_marketGroups,phbmetadata,phbtraits,fsdTypeOverrides,"\
"evegroups,evetypes,evecategories"
diff --git a/service/__init__.py b/service/__init__.py
index e7e0286d4..b19c6db17 100644
--- a/service/__init__.py
+++ b/service/__init__.py
@@ -10,6 +10,7 @@ from service.update import Update
from service.price import Price
from service.network import Network
from service.eveapi import EVEAPIConnection, ParseXML
+from service.implantSet import ImplantSets
import wx
if not 'wxMac' in wx.PlatformInfo or ('wxMac' in wx.PlatformInfo and wx.VERSION >= (3,0)):
diff --git a/service/character.py b/service/character.py
index 83e50bbaa..c7c65b0af 100644
--- a/service/character.py
+++ b/service/character.py
@@ -32,7 +32,9 @@ import eos.db
import eos.types
import service
import config
+import logging
+logger = logging.getLogger(__name__)
class CharacterImportThread(threading.Thread):
def __init__(self, paths, callback):
@@ -48,16 +50,15 @@ class CharacterImportThread(threading.Thread):
# we try to parse api XML data first
with open(path, mode='r') as charFile:
sheet = service.ParseXML(charFile)
- charID = sCharacter.new()
- sCharacter.rename(charID, sheet.name+" (imported)")
- sCharacter.apiUpdateCharSheet(charID, sheet.skills)
+ char = sCharacter.new(sheet.name+" (imported)")
+ sCharacter.apiUpdateCharSheet(char.ID, sheet.skills)
except:
# if it's not api XML data, try this
# this is a horrible logic flow, but whatever
try:
charFile = open(path, mode='r').read()
doc = minidom.parseString(charFile)
- if doc.documentElement.tagName != "SerializableCCPCharacter":
+ if doc.documentElement.tagName not in ("SerializableCCPCharacter", "SerializableUriCharacter"):
raise RuntimeError("Incorrect EVEMon XML sheet")
name = doc.getElementsByTagName("name")[0].firstChild.nodeValue
skill_els = doc.getElementsByTagName("skill")
@@ -67,10 +68,10 @@ class CharacterImportThread(threading.Thread):
"typeID": int(skill.getAttribute("typeID")),
"level": int(skill.getAttribute("level")),
})
- charID = sCharacter.new()
- sCharacter.rename(charID, name+" (EVEMon)")
- sCharacter.apiUpdateCharSheet(charID, skills)
- except:
+ char = sCharacter.new(name+" (EVEMon)")
+ sCharacter.apiUpdateCharSheet(char.ID, skills)
+ except Exception, e:
+ print e.message
continue
wx.CallAfter(self.callback)
@@ -114,6 +115,11 @@ class Character(object):
return cls.instance
+ def __init__(self):
+ # Simply initializes default characters in case they aren't in the database yet
+ self.all0()
+ self.all5()
+
def exportText(self):
data = "Pyfa exported plan for \""+self.skillReqsDict['charname']+"\"\n"
data += "=" * 79 + "\n"
@@ -183,10 +189,7 @@ class Character(object):
return self.all5().ID
def getCharacterList(self):
- baseChars = [eos.types.Character.getAll0(), eos.types.Character.getAll5()]
- sFit = service.Fit.getInstance()
-
- return map(lambda c: (c.ID, c.name if not c.isDirty else "{} *".format(c.name), c == sFit.character), eos.db.getCharacterList())
+ return eos.db.getCharacterList()
def getCharacter(self, charID):
char = eos.db.getCharacter(charID)
@@ -246,25 +249,21 @@ class Character(object):
def getCharName(self, charID):
return eos.db.getCharacter(charID).name
- def new(self):
- char = eos.types.Character("New Character")
+ def new(self, name="New Character"):
+ char = eos.types.Character(name)
eos.db.save(char)
- return char.ID
+ return char
- def rename(self, charID, newName):
- char = eos.db.getCharacter(charID)
+ def rename(self, char, newName):
char.name = newName
eos.db.commit()
- def copy(self, charID):
- char = eos.db.getCharacter(charID)
+ def copy(self, char):
newChar = copy.deepcopy(char)
eos.db.save(newChar)
- return newChar.ID
+ return newChar
- def delete(self, charID):
- char = eos.db.getCharacter(charID)
- eos.db.commit()
+ def delete(self, char):
eos.db.remove(char)
def getApiDetails(self, charID):
@@ -343,13 +342,18 @@ class Character(object):
def addImplant(self, charID, itemID):
char = eos.db.getCharacter(charID)
- implant = eos.types.Implant(eos.db.getItem(itemID))
- char.implants.freeSlot(implant.slot)
- char.implants.append(implant)
+ if char.ro:
+ logger.error("Trying to add implant to read-only character")
+ return
- def removeImplant(self, charID, slot):
+ implant = eos.types.Implant(eos.db.getItem(itemID))
+ char.implants.append(implant)
+ eos.db.commit()
+
+ def removeImplant(self, charID, implant):
char = eos.db.getCharacter(charID)
- char.implants.freeSlot(slot)
+ char.implants.remove(implant)
+ eos.db.commit()
def getImplants(self, charID):
char = eos.db.getCharacter(charID)
diff --git a/service/conversions/releaseApril2016.py b/service/conversions/releaseApril2016.py
new file mode 100644
index 000000000..a20914179
--- /dev/null
+++ b/service/conversions/releaseApril2016.py
@@ -0,0 +1,45 @@
+"""
+Conversion pack for Citadel release
+"""
+
+CONVERSIONS = {
+ # Renamed items
+ "Capital Inefficient Armor Repair Unit": "CONCORD Capital Armor Repairer",
+ "Capital Neutron Saturation Injector I": "CONCORD Capital Shield Booster",
+ "Limited Mega Ion Siege Blaster I": "CONCORD Ion Siege Blaster",
+ "Dual 1000mm 'Scout' Accelerator Cannon": "CONCORD Dual 1000mm Railgun",
+ "Dual Modal Giga Pulse Laser I": "CONCORD Dual Giga Pulse Laser",
+ "Dual Giga Modal Laser I": "CONCORD Dual Giga Beam Laser",
+ "'Limos' XL Cruise Launcher I": "CONCORD XL Cruise Missile Launcher",
+ "Shock 'Limos' XL Torpedo Bay I": "CONCORD XL Torpedo Launcher",
+ "Quad 3500mm Gallium Cannon": "CONCORD Quad 3500mm Siege Artillery",
+ "6x2500mm Heavy Gallium Repeating Cannon": "CONCORD Hexa 2500mm Repeating Cannon",
+ "Capital Murky Remote Capacitor Transmitter": "CONCORD Capital Remote Capacitor Transmitter",
+ "Ion Siege Blaster Cannon I": "Ion Siege Blaster I",
+ "6x2500mm Repeating Cannon I": "Hexa 2500mm Repeating Cannon I",
+ "Templar": "Templar I",
+ "Dragonfly": "Dragonfly I",
+ "Firbolg": "Firbolg I",
+ "Einherji": "Einherji I",
+ "Gjallarhorn": "'Gjallarhorn' Explosive Doomsday",
+ "Drone Control Unit I": "Fighter Support Unit I",
+ "Judgement": "'Judgment' Electromagnetic Doomsday",
+ "Oblivion": "'Oblivion' Kinetic Doomsday",
+ "Aurora Ominae": "'Aurora Ominae' Thermal Doomsday",
+ "Advanced Drone Interfacing": "Fighter Hangar Management",
+ "Remote ECM Burst I": "ECM Jammer Burst Projector",
+ "Projected Electronic Counter Measures": "Burst Projector Operation",
+ "Cyclops": "Cyclops I",
+ "Fighter Bombers": "Heavy Fighters",
+ "Malleus": "Malleus I",
+ "Tyrfing": "Tyrfing I",
+ "Mantis": "Mantis I",
+ "XL Cruise Launcher I": "XL Cruise Missile Launcher I",
+ "Armor Resistance Phasing": "Resistance Phasing",
+ "Unit D-34343's Modified Drone Control Unit": "Unit D-34343's Modified Fighter Support Unit",
+ "Unit F-435454's Modified Drone Control Unit": "Unit F-435454's Modified Fighter Support Unit",
+ "Unit P-343554's Modified Drone Control Unit": "Unit P-343554's Modified Fighter Support Unit",
+ "Unit W-634's Modified Drone Control Unit": "Unit W-634's Modified Fighter Support Unit",
+ "Heavy Shadow Serpentis Stasis Grappler": "Shadow Serpentis Heavy Stasis Grappler",
+ "Heavy Domination Stasis Grappler": "Domination Heavy Stasis Grappler",
+}
\ No newline at end of file
diff --git a/service/damagePattern.py b/service/damagePattern.py
index 374940e0c..b67b10956 100644
--- a/service/damagePattern.py
+++ b/service/damagePattern.py
@@ -46,9 +46,10 @@ class DamagePattern():
def getDamagePattern(self, name):
return eos.db.getDamagePattern(name)
- def newPattern(self):
+ def newPattern(self, name):
p = eos.types.DamagePattern(0, 0, 0, 0)
- p.name = ""
+ p.name = name
+ eos.db.save(p)
return p
def renamePattern(self, p, newName):
diff --git a/service/fit.py b/service/fit.py
index 590651abe..84c42d723 100644
--- a/service/fit.py
+++ b/service/fit.py
@@ -277,7 +277,7 @@ class Fit(object):
fit.timestamp))
return fits
- def addImplant(self, fitID, itemID):
+ def addImplant(self, fitID, itemID, recalc=True):
if fitID is None:
return False
@@ -289,7 +289,8 @@ class Fit(object):
return False
fit.implants.append(implant)
- self.recalc(fit)
+ if recalc:
+ self.recalc(fit)
return True
def removeImplant(self, fitID, position):
@@ -400,6 +401,13 @@ class Fit(object):
eos.db.commit()
self.recalc(fit)
+ def changeActiveFighters(self, fitID, fighter, amount):
+ fit = eos.db.getFit(fitID)
+ fighter.amountActive = amount
+
+ eos.db.commit()
+ self.recalc(fit)
+
def removeProjected(self, fitID, thing):
fit = eos.db.getFit(fitID)
if isinstance(thing, eos.types.Drone):
@@ -615,6 +623,42 @@ class Fit(object):
self.recalc(fit)
return True
+ def addFighter(self, fitID, itemID):
+ if fitID is None:
+ return False
+
+ fit = eos.db.getFit(fitID)
+ item = eos.db.getItem(itemID, eager=("attributes", "group.category"))
+ if item.category.name == "Fighter":
+ fighter = None
+ '''
+ for d in fit.fighters.find(item):
+ if d is not None and d.amountActive == 0 and d.amount < max(5, fit.extraAttributes["maxActiveDrones"]):
+ drone = d
+ break
+ '''
+ if fighter is None:
+ fighter = eos.types.Fighter(item)
+ if fighter.fits(fit) is True:
+ fit.fighters.append(fighter)
+ else:
+ return False
+
+ eos.db.commit()
+ self.recalc(fit)
+ return True
+ else:
+ return False
+
+ def removeFighter(self, fitID, i):
+ fit = eos.db.getFit(fitID)
+ f = fit.fighters[i]
+ fit.fighters.remove(f)
+
+ eos.db.commit()
+ self.recalc(fit)
+ return True
+
def addDrone(self, fitID, itemID):
if fitID is None:
return False
@@ -712,6 +756,15 @@ class Fit(object):
self.recalc(fit)
return True
+ def toggleFighter(self, fitID, i):
+ fit = eos.db.getFit(fitID)
+ f = fit.fighters[i]
+ f.active = not f.active
+
+ eos.db.commit()
+ self.recalc(fit)
+ return True
+
def toggleImplant(self, fitID, i):
fit = eos.db.getFit(fitID)
implant = fit.implants[i]
@@ -721,6 +774,14 @@ class Fit(object):
self.recalc(fit)
return True
+ def toggleImplantSource(self, fitID, source):
+ fit = eos.db.getFit(fitID)
+ fit.implantSource = source
+
+ eos.db.commit()
+ self.recalc(fit)
+ return True
+
def toggleBooster(self, fitID, i):
fit = eos.db.getFit(fitID)
booster = fit.boosters[i]
@@ -730,6 +791,12 @@ class Fit(object):
self.recalc(fit)
return True
+ def toggleFighterAbility(self, fitID, ability):
+ fit = eos.db.getFit(fitID)
+ ability.active = not ability.active
+ eos.db.commit()
+ self.recalc(fit)
+
def changeChar(self, fitID, charID):
if fitID is None or charID is None:
if charID is not None:
diff --git a/service/implantSet.py b/service/implantSet.py
new file mode 100644
index 000000000..0d0df5808
--- /dev/null
+++ b/service/implantSet.py
@@ -0,0 +1,125 @@
+#===============================================================================
+# Copyright (C) 2016 Ryan Holmes
+#
+# This file is part of pyfa.
+#
+# pyfa is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# pyfa is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with pyfa. If not, see .
+#===============================================================================
+
+import eos.db
+import eos.types
+import copy
+import service.market
+
+class ImportError(Exception):
+ pass
+
+class ImplantSets():
+ instance = None
+ @classmethod
+ def getInstance(cls):
+ if cls.instance is None:
+ cls.instance = ImplantSets()
+
+ return cls.instance
+
+ def getImplantSetList(self):
+ return eos.db.getImplantSetList(None)
+
+ def getImplantSet(self, name):
+ return eos.db.getImplantSet(name)
+
+ def getImplants(self, setID):
+ set = eos.db.getImplantSet(setID)
+ return set.implants
+
+ def addImplant(self, setID, itemID):
+ set = eos.db.getImplantSet(setID)
+ implant = eos.types.Implant(eos.db.getItem(itemID))
+ set.implants.append(implant)
+ eos.db.commit()
+
+ def removeImplant(self, setID, implant):
+ set = eos.db.getImplantSet(setID)
+ set.implants.remove(implant)
+ eos.db.commit()
+
+ def newSet(self, name):
+ s = eos.types.ImplantSet()
+ s.name = name
+ eos.db.save(s)
+ return s
+
+ def renameSet(self, s, newName):
+ s.name = newName
+ eos.db.save(s)
+
+ def deleteSet(self, s):
+ eos.db.remove(s)
+
+ def copySet(self, s):
+ newS = copy.deepcopy(s)
+ eos.db.save(newS)
+ return newS
+
+ def saveChanges(self, s):
+ eos.db.save(s)
+
+ def importSets(self, text):
+ sMkt = service.Market.getInstance()
+ lines = text.splitlines()
+ newSets = []
+ errors = 0
+ current = None
+ lookup = {}
+
+ for i, line in enumerate(lines):
+ line = line.strip()
+ try:
+ if line == '' or line[0] == "#": # comments / empty string
+ continue
+ if line[:1] == "[" and line[-1:] == "]":
+ current = eos.types.ImplantSet(line[1:-1])
+ newSets.append(current)
+ else:
+ item = sMkt.getItem(line)
+ current.implants.append(eos.types.Implant(item))
+ except:
+ errors += 1
+ continue
+
+ for set in self.getImplantSetList():
+ lookup[set.name] = set
+
+ for set in newSets:
+ if set.name in lookup:
+ match = lookup[set.name]
+ for implant in set.implants:
+ match.implants.append(eos.types.Implant(implant.item))
+ else:
+ eos.db.save(set)
+
+ eos.db.commit()
+
+ lenImports = len(newSets)
+ if lenImports == 0:
+ raise ImportError("No patterns found for import")
+ if errors > 0:
+ raise ImportError("%d sets imported from clipboard; %d errors"%(lenImports, errors))
+
+ def exportSets(self):
+ patterns = self.getImplantSetList()
+ patterns.sort(key=lambda p: p.name)
+ return eos.types.ImplantSet.exportSets(*patterns)
+
diff --git a/service/market.py b/service/market.py
index 39c700ce5..0d8538732 100644
--- a/service/market.py
+++ b/service/market.py
@@ -29,12 +29,15 @@ import eos.types
from service.settings import SettingsProvider, NetworkSettings
import service
import service.conversions as conversions
+import logging
try:
from collections import OrderedDict
except ImportError:
from utils.compat import OrderedDict
+logger = logging.getLogger(__name__)
+
# Event which tells threads dependent on Market that it's initialized
mktRdy = threading.Event()
@@ -120,11 +123,14 @@ class SearchWorkerThread(threading.Thread):
self.searchRequest = None
cv.release()
sMkt = Market.getInstance()
- if filterOn:
+ if filterOn is True:
# Rely on category data provided by eos as we don't hardcode them much in service
filter = eos.types.Category.name.in_(sMkt.SEARCH_CATEGORIES)
+ elif filterOn: # filter by selected categories
+ filter = eos.types.Category.name.in_(filterOn)
else:
filter=None
+
results = eos.db.searchItems(request, where=filter,
join=(eos.types.Item.group, eos.types.Group.category),
eager=("icon", "group.category", "metaGroup", "metaGroup.parent"))
@@ -318,7 +324,7 @@ class Market():
("faction", frozenset((4, 3))),
("complex", frozenset((6,))),
("officer", frozenset((5,)))])
- self.SEARCH_CATEGORIES = ("Drone", "Module", "Subsystem", "Charge", "Implant", "Deployable")
+ self.SEARCH_CATEGORIES = ("Drone", "Module", "Subsystem", "Charge", "Implant", "Deployable", "Fighter")
self.ROOT_MARKET_GROUPS = (9, # Modules
1111, # Rigs
157, # Drones
@@ -346,20 +352,25 @@ class Market():
def getItem(self, identity, *args, **kwargs):
"""Get item by its ID or name"""
- if isinstance(identity, eos.types.Item):
- item = identity
- elif isinstance(identity, int):
- item = eos.db.getItem(identity, *args, **kwargs)
- elif isinstance(identity, basestring):
- # We normally lookup with string when we are using import/export
- # features. Check against overrides
- identity = conversions.all.get(identity, identity)
- item = eos.db.getItem(identity, *args, **kwargs)
- elif isinstance(identity, float):
- id = int(identity)
- item = eos.db.getItem(id, *args, **kwargs)
- else:
- raise TypeError("Need Item object, integer, float or string as argument")
+ try:
+ if isinstance(identity, eos.types.Item):
+ item = identity
+ elif isinstance(identity, int):
+ item = eos.db.getItem(identity, *args, **kwargs)
+ elif isinstance(identity, basestring):
+ # We normally lookup with string when we are using import/export
+ # features. Check against overrides
+ identity = conversions.all.get(identity, identity)
+ item = eos.db.getItem(identity, *args, **kwargs)
+ elif isinstance(identity, float):
+ id = int(identity)
+ item = eos.db.getItem(id, *args, **kwargs)
+ else:
+ raise TypeError("Need Item object, integer, float or string as argument")
+ except:
+ logger.error("Could not get item: %s", identity)
+ raise
+
return item
def getGroup(self, identity, *args, **kwargs):
diff --git a/service/port.py b/service/port.py
index 718ee3fe4..71076bb46 100644
--- a/service/port.py
+++ b/service/port.py
@@ -58,6 +58,8 @@ class Port(object):
nested_dict = lambda: collections.defaultdict(nested_dict)
fit = nested_dict()
sCrest = service.Crest.getInstance()
+ sFit = service.Fit.getInstance()
+
eve = sCrest.eve
# max length is 50 characters
@@ -71,6 +73,7 @@ class Port(object):
fit['items'] = []
slotNum = {}
+ charges = {}
for module in ofit.modules:
if module.isEmpty:
continue
@@ -95,6 +98,12 @@ class Port(object):
item['type']['name'] = ''
fit['items'].append(item)
+ if module.charge and sFit.serviceFittingOptions["exportCharges"]:
+ if not module.chargeID in charges:
+ charges[module.chargeID] = 0
+ # `or 1` because some charges (ie scripts) are without qty
+ charges[module.chargeID] += module.numCharges or 1
+
for cargo in ofit.cargo:
item = nested_dict()
item['flag'] = INV_FLAG_CARGOBAY
@@ -104,6 +113,15 @@ class Port(object):
item['type']['name'] = ''
fit['items'].append(item)
+ for chargeID, amount in charges.items():
+ item = nested_dict()
+ item['flag'] = INV_FLAG_CARGOBAY
+ item['quantity'] = amount
+ item['type']['href'] = "%stypes/%d/"%(eve._authed_endpoint, chargeID)
+ item['type']['id'] = chargeID
+ item['type']['name'] = ''
+ fit['items'].append(item)
+
for drone in ofit.drones:
item = nested_dict()
item['flag'] = INV_FLAG_DRONEBAY
@@ -793,7 +811,7 @@ class Port(object):
if slot == Slot.SUBSYSTEM:
# Order of subsystem matters based on this attr. See GH issue #130
- slotId = module.getModifiedItemAttr("subSystemSlot") - 124
+ slotId = module.getModifiedItemAttr("subSystemSlot") - 125
else:
if not slot in slotNum:
slotNum[slot] = 0
diff --git a/service/targetResists.py b/service/targetResists.py
index a8f61b9f9..2640551f4 100644
--- a/service/targetResists.py
+++ b/service/targetResists.py
@@ -39,9 +39,10 @@ class TargetResists():
def getTargetResists(self, name):
return eos.db.getTargetResists(name)
- def newPattern(self):
+ def newPattern(self, name):
p = eos.types.TargetResists(0.0, 0.0, 0.0, 0.0)
- p.name = ""
+ p.name = name
+ eos.db.save(p)
return p
def renamePattern(self, p, newName):