Compare commits

..

2 Commits

Author SHA1 Message Date
DarkPhoenix
9cc50076bd Fix mass of t3ds 2015-04-14 18:53:55 +03:00
DarkPhoenix
f37f28d0fa t3d changes preview from https://forums.eveonline.com/default.aspx?g=posts&m=5665060#post5665060 2015-04-14 13:09:06 +03:00
1897 changed files with 3544 additions and 4492 deletions

1
.gitignore vendored
View File

@@ -20,4 +20,3 @@ saveddata/
#Pyfa file
pyfaFits.html
build/

View File

@@ -6,13 +6,6 @@ It provides many advanced features such as graphs and full calculations of any p
Please see the [FAQ](https://github.com/DarkFenX/Pyfa/wiki/FAQ) for answers to common questions / concerns
#### A note for Linux users
pyfa currently only supports wxPython 2.8. However, there are some distros that have started to support 3.0 and subsequently dropped support for 2.8 altogether (such as Debian Jessie). If this is the case and wxPython 3.0 is the only version installed, the official pyfa releases will not run. You must either find a package for 2.8 or compile it yourself.
For Debian Jessie, wxPython 2.8 is available in Sid (the unstable repo). you can use apt-pinning to install select packages from unstable and still keep your stable system. See http://jaqque.sbih.org/kplug/apt-pinning.html for me details.
3.0 support is being worked on and can be found on the wx3 branch. It may be stable enough for you, but there are a few bugs related to it. Please see the wx3 label on the GitHub issues area for me information on known issues (biggest one currently is GTK warning spam): https://github.com/DarkFenX/Pyfa/labels/wx3
#### Links
* [Development repository: http://github.com/DarkFenX/Pyfa](http://github.com/DarkFenX/Pyfa)
* [XMPP conference:

View File

@@ -1,11 +1,6 @@
import os
import sys
# TODO: move all logging back to pyfa.py main loop
# We moved it here just to avoid rebuilding windows skeleton for now (any change to pyfa.py needs it)
import logging
import logging.handlers
# Load variable overrides specific to distribution type
try:
import configforced
@@ -17,43 +12,23 @@ debug = False
# Defines if our saveddata will be in pyfa root or not
saveInRoot = False
if debug:
logLevel = logging.DEBUG
else:
logLevel = logging.WARN
# Version data
version = "1.15.0"
tag = "Stable"
expansionName = "Vanguard"
expansionVersion = "1.0"
version = "1.10.1"
tag = "preview"
expansionName = "t3d_changes"
expansionVersion = "1.1"
evemonMinVersion = "4081"
# Database version (int ONLY)
# Increment every time we need to flag for user database upgrade/modification
dbversion = 6
pyfaPath = None
savePath = None
staticPath = None
saveDB = None
gameDB = None
class StreamToLogger(object):
"""
Fake file-like stream object that redirects writes to a logger instance.
From: http://www.electricmonk.nl/log/2011/08/14/redirect-stdout-and-stderr-to-a-logger-in-python/
"""
def __init__(self, logger, log_level=logging.INFO):
self.logger = logger
self.log_level = log_level
self.linebuf = ''
def write(self, buf):
for line in buf.rstrip().splitlines():
self.logger.log(self.log_level, line.rstrip())
def __createDirs(path):
if not os.path.exists(path):
os.makedirs(path)
def defPaths():
global pyfaPath
global savePath
@@ -79,25 +54,19 @@ def defPaths():
savePath = unicode(os.path.expanduser(os.path.join("~", ".pyfa")),
sys.getfilesystemencoding())
__createDirs(savePath)
# Redirect stderr to file if we're requested to do so
stderrToFile = getattr(configforced, "stderrToFile", None)
if stderrToFile is True:
if not os.path.exists(savePath):
os.mkdir(savePath)
sys.stderr = open(os.path.join(savePath, "error_log.txt"), "w")
format = '%(asctime)s %(name)-24s %(levelname)-8s %(message)s'
logging.basicConfig(format=format, level=logLevel)
handler = logging.handlers.RotatingFileHandler(os.path.join(savePath, "log.txt"), maxBytes=1000000, backupCount=3)
formatter = logging.Formatter(format)
handler.setFormatter(formatter)
logging.getLogger('').addHandler(handler)
logging.info("Starting pyfa")
if hasattr(sys, 'frozen'):
stdout_logger = logging.getLogger('STDOUT')
sl = StreamToLogger(stdout_logger, logging.INFO)
sys.stdout = sl
stderr_logger = logging.getLogger('STDERR')
sl = StreamToLogger(stderr_logger, logging.ERROR)
sys.stderr = sl
# Same for stdout
stdoutToFile = getattr(configforced, "stdoutToFile", None)
if stdoutToFile is True:
if not os.path.exists(savePath):
os.mkdir(savePath)
sys.stdout = open(os.path.join(savePath, "output_log.txt"), "w")
# Static EVE Data from the staticdata repository, should be in the staticdata
# directory in our pyfa directory

View File

@@ -82,25 +82,18 @@ class CapSimulator(object):
if self.scale:
duration, capNeed = self.scale_activation(duration, capNeed)
# set clipSize to infinite if reloads are disabled unless it's
# a cap booster module.
if not self.reload and capNeed > 0:
clipSize = 0
if self.stagger:
if clipSize == 0:
duration = int(duration/amount)
else:
stagger_amount = (duration*clipSize+10000)/(amount*clipSize)
for i in range(1, amount):
heapq.heappush(self.state,
[i*stagger_amount, duration,
capNeed, 0, clipSize])
duration = int(duration/amount)
else:
capNeed *= amount
period = lcm(period, duration)
# set clipSize to infinite if reloads are disabled unless it's
# a cap booster module.
if not self.reload and capNeed > 0:
clipSize = 0
# period optimization doesn't work when reloads are active.
if clipSize:
disable_period = True

View File

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

View File

@@ -1,46 +1,32 @@
import config
import shutil
import time
import re
import os
def getAppVersion():
# calculate app version based on upgrade files we have
appVersion = 0
for fname in os.listdir(os.path.join(os.path.dirname(__file__), "migrations")):
m = re.match("^upgrade(?P<index>\d+)\.py$", fname)
if not m:
continue
index = int(m.group("index"))
appVersion = max(appVersion, index)
return appVersion
def getVersion(db):
cursor = db.execute('PRAGMA user_version')
return cursor.fetchone()[0]
def update(saveddata_engine):
dbVersion = getVersion(saveddata_engine)
appVersion = getAppVersion()
currversion = getVersion(saveddata_engine)
if dbVersion == appVersion:
if currversion == config.dbversion:
return
if dbVersion < appVersion:
if currversion < config.dbversion:
# Automatically backup database
toFile = "%s/saveddata_migration_%d-%d_%s.db"%(
config.savePath,
dbVersion,
appVersion,
currversion,
config.dbversion,
time.strftime("%Y%m%d_%H%M%S"))
shutil.copyfile(config.saveDB, toFile)
for version in xrange(dbVersion, appVersion):
module = __import__("eos.db.migrations.upgrade{}".format(version + 1), fromlist=True)
for version in xrange(currversion, config.dbversion):
module = __import__('eos.db.migrations.upgrade%d'%(version+1), fromlist=True)
upgrade = getattr(module, "upgrade", False)
if upgrade:
upgrade(saveddata_engine)
# when all is said and done, set version to current
saveddata_engine.execute("PRAGMA user_version = {}".format(appVersion))
saveddata_engine.execute('PRAGMA user_version = %d'%config.dbversion)

View File

@@ -1,16 +0,0 @@
"""
Migration 10
- Adds active attribute to projected fits
"""
import sqlalchemy
def upgrade(saveddata_engine):
# Update projectedFits schema to include active attribute
try:
saveddata_engine.execute("SELECT active FROM projectedFits LIMIT 1")
except sqlalchemy.exc.DatabaseError:
saveddata_engine.execute("ALTER TABLE projectedFits ADD COLUMN active BOOLEAN")
saveddata_engine.execute("UPDATE projectedFits SET active = 1")
saveddata_engine.execute("UPDATE projectedFits SET amount = 1")

View File

@@ -1,24 +0,0 @@
"""
Migration 7
- Converts Scorpion Ishukone Watch to Scorpion
Mosaic introduced proper skinning system, and Ishukone Scorp
was the only ship which was presented as stand-alone ship in
Pyfa.
"""
CONVERSIONS = {
640: ( # Scorpion
4005, # Scorpion Ishukone Watch
)
}
def upgrade(saveddata_engine):
# Convert ships
for replacement_item, list in CONVERSIONS.iteritems():
for retired_item in list:
saveddata_engine.execute('UPDATE "fits" SET "shipID" = ? WHERE "shipID" = ?', (replacement_item, retired_item))

View File

@@ -1,85 +0,0 @@
"""
Migration 8
- Converts modules based on Carnyx Module Tiericide
Some modules have been unpublished (and unpublished module attributes are removed
from database), which causes pyfa to crash. We therefore replace these
modules with their new replacements
"""
CONVERSIONS = {
8529: ( # Large F-S9 Regolith Compact Shield Extender
8409, # Large Subordinate Screen Stabilizer I
),
8419: ( # Large Azeotropic Restrained Shield Extender
8489, # Large Supplemental Barrier Emitter I
),
8517: ( # Medium F-S9 Regolith Compact Shield Extender
8397, # Medium Subordinate Screen Stabilizer I
),
8433: ( # Medium Azeotropic Restrained Shield Extender
8477, # Medium Supplemental Barrier Emitter I
),
20627: ( # Small 'Trapper' Shield Extender
8437, # Micro Azeotropic Ward Salubrity I
8505, # Micro F-S9 Regolith Shield Induction
3849, # Micro Shield Extender I
3851, # Micro Shield Extender II
8387, # Micro Subordinate Screen Stabilizer I
8465, # Micro Supplemental Barrier Emitter I
),
8521: ( # Small F-S9 Regolith Compact Shield Extender
8401, # Small Subordinate Screen Stabilizer I
),
8427: ( # Small Azeotropic Restrained Shield Extender
8481, # Small Supplemental Barrier Emitter I
),
11343: ( # 100mm Crystalline Carbonide Restrained Plates
11345, # 100mm Reinforced Nanofiber Plates I
),
11341: ( # 100mm Rolled Tungsten Compact Plates
11339, # 100mm Reinforced Titanium Plates I
),
11327: ( # 1600mm Crystalline Carbonide Restrained Plates
11329, # 1600mm Reinforced Nanofiber Plates I
),
11325: ( # 1600mm Rolled Tungsten Compact Plates
11323, # 1600mm Reinforced Titanium Plates I
),
11351: ( # 200mm Crystalline Carbonide Restrained Plates
11353, # 200mm Reinforced Nanofiber Plates I
),
11349: ( # 200mm Rolled Tungsten Compact Plates
11347, # 200mm Reinforced Titanium Plates I
),
11311: ( # 400mm Crystalline Carbonide Restrained Plates
11313, # 400mm Reinforced Nanofiber Plates I
),
11309: ( # 400mm Rolled Tungsten Compact Plates
11307, # 400mm Reinforced Titanium Plates I
),
23791: ( # 'Citadella' 100mm Steel Plates
11335, # 50mm Reinforced Crystalline Carbonide Plates I
11337, # 50mm Reinforced Nanofiber Plates I
11333, # 50mm Reinforced Rolled Tungsten Plates I
11291, # 50mm Reinforced Steel Plates I
20343, # 50mm Reinforced Steel Plates II
11331, # 50mm Reinforced Titanium Plates I
),
11319: ( # 800mm Crystalline Carbonide Restrained Plates
11321, # 800mm Reinforced Nanofiber Plates I
),
11317: ( # 800mm Rolled Tungsten Compact Plates
11315, # 800mm Reinforced Titanium Plates I
),
}
def upgrade(saveddata_engine):
# Convert modules
for replacement_item, list in CONVERSIONS.iteritems():
for retired_item in list:
saveddata_engine.execute('UPDATE "modules" SET "itemID" = ? WHERE "itemID" = ?', (replacement_item, retired_item))
saveddata_engine.execute('UPDATE "cargo" SET "itemID" = ? WHERE "itemID" = ?', (replacement_item, retired_item))

View File

@@ -1,23 +0,0 @@
"""
Migration 9
Effectively drops UNIQUE constraint from boosters table. SQLite does not support
this, so we have to copy the table to the updated schema and then rename it
"""
tmpTable = """
CREATE TABLE boostersTemp (
'ID' INTEGER NOT NULL,
'itemID' INTEGER,
'fitID' INTEGER NOT NULL,
'active' BOOLEAN,
PRIMARY KEY(ID),
FOREIGN KEY('fitID') REFERENCES fits ('ID')
)
"""
def upgrade(saveddata_engine):
saveddata_engine.execute(tmpTable)
saveddata_engine.execute("INSERT INTO boostersTemp (ID, itemID, fitID, active) SELECT ID, itemID, fitID, active FROM boosters")
saveddata_engine.execute("DROP TABLE boosters")
saveddata_engine.execute("ALTER TABLE boostersTemp RENAME TO boosters")

View File

@@ -29,7 +29,7 @@ boosters_table = Table("boosters", saveddata_meta,
Column("itemID", Integer),
Column("fitID", Integer, ForeignKey("fits.ID"), nullable = False),
Column("active", Boolean),
)
UniqueConstraint("itemID", "fitID"))
activeSideEffects_table = Table("boostersActiveSideEffects", saveddata_meta,
Column("boosterID", ForeignKey("boosters.ID"), primary_key = True),

View File

@@ -17,11 +17,9 @@
# along with eos. If not, see <http://www.gnu.org/licenses/>.
#===============================================================================
from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy import Table, Column, Integer, ForeignKey, String, Boolean
from sqlalchemy.orm import relation, mapper
from sqlalchemy.sql import and_
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.orm.collections import attribute_mapped_collection
from eos.db import saveddata_meta
from eos.db.saveddata.module import modules_table
@@ -29,7 +27,9 @@ from eos.db.saveddata.drone import drones_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.effectHandlerHelpers import *
from eos.effectHandlerHelpers import HandledModuleList, HandledDroneList, \
HandledImplantBoosterList, HandledProjectedModList, HandledProjectedDroneList, \
HandledProjectedFitList, HandledCargoList
fits_table = Table("fits", saveddata_meta,
Column("ID", Integer, primary_key = True),
@@ -47,119 +47,31 @@ fits_table = Table("fits", saveddata_meta,
projectedFits_table = Table("projectedFits", saveddata_meta,
Column("sourceID", ForeignKey("fits.ID"), primary_key = True),
Column("victimID", ForeignKey("fits.ID"), primary_key = True),
Column("amount", Integer, nullable = False, default = 1),
Column("active", Boolean, nullable = False, default = 1),
)
class ProjectedFit(object):
def __init__(self, sourceID, source_fit, amount=1, active=True):
self.sourceID = sourceID
self.source_fit = source_fit
self.active = active
self.__amount = amount
@reconstructor
def init(self):
if self.source_fit.isInvalid:
# Very rare for this to happen, but be prepared for it
eos.db.saveddata_session.delete(self.source_fit)
eos.db.saveddata_session.flush()
eos.db.saveddata_session.refresh(self.victim_fit)
# We have a series of setters and getters here just in case someone
# downgrades and screws up the table with NULL values
@property
def amount(self):
return self.__amount or 1
@amount.setter
def amount(self, amount):
self.__amount = amount
def __repr__(self):
return "ProjectedFit(sourceID={}, victimID={}, amount={}, active={}) at {}".format(
self.sourceID, self.victimID, self.amount, self.active, hex(id(self))
)
Fit._Fit__projectedFits = association_proxy(
"victimOf", # look at the victimOf association...
"source_fit", # .. and return the source fits
creator=lambda sourceID, source_fit: ProjectedFit(sourceID, source_fit)
)
Column("amount", Integer))
mapper(Fit, fits_table,
properties = {
"_Fit__modules": relation(
Module,
collection_class=HandledModuleList,
primaryjoin=and_(modules_table.c.fitID == fits_table.c.ID, modules_table.c.projected == False),
order_by=modules_table.c.position,
cascade='all, delete, delete-orphan'),
"_Fit__projectedModules": relation(
Module,
collection_class=HandledProjectedModList,
cascade='all, delete, delete-orphan',
single_parent=True,
primaryjoin=and_(modules_table.c.fitID == fits_table.c.ID, modules_table.c.projected == True)),
"owner": relation(
User,
backref="fits"),
"itemID": fits_table.c.shipID,
"shipID": fits_table.c.shipID,
"_Fit__boosters": relation(
Booster,
collection_class=HandledImplantBoosterList,
cascade='all, delete, delete-orphan',
single_parent=True),
"_Fit__drones": relation(
Drone,
collection_class=HandledDroneCargoList,
cascade='all, delete, delete-orphan',
single_parent=True,
primaryjoin=and_(drones_table.c.fitID == fits_table.c.ID, drones_table.c.projected == False)),
"_Fit__cargo": relation(
Cargo,
collection_class=HandledDroneCargoList,
cascade='all, delete, delete-orphan',
single_parent=True,
primaryjoin=and_(cargo_table.c.fitID == fits_table.c.ID)),
"_Fit__projectedDrones": relation(
Drone,
collection_class=HandledProjectedDroneList,
cascade='all, delete, delete-orphan',
single_parent=True,
primaryjoin=and_(drones_table.c.fitID == fits_table.c.ID, drones_table.c.projected == True)),
"_Fit__implants": relation(
Implant,
collection_class=HandledImplantBoosterList,
cascade='all, delete, delete-orphan',
backref='fit',
single_parent=True,
primaryjoin=fitImplants_table.c.fitID == fits_table.c.ID,
secondaryjoin=fitImplants_table.c.implantID == Implant.ID,
secondary=fitImplants_table),
"_Fit__character": relation(
Character,
backref="fits"),
"_Fit__damagePattern": relation(DamagePattern),
"_Fit__targetResists": relation(TargetResists),
"projectedOnto": relationship(
ProjectedFit,
primaryjoin=projectedFits_table.c.sourceID == fits_table.c.ID,
backref='source_fit',
collection_class=attribute_mapped_collection('victimID'),
cascade='all, delete, delete-orphan'),
"victimOf": relationship(
ProjectedFit,
primaryjoin=fits_table.c.ID == projectedFits_table.c.victimID,
backref='victim_fit',
collection_class=attribute_mapped_collection('sourceID'),
cascade='all, delete, delete-orphan'),
}
)
mapper(ProjectedFit, projectedFits_table,
properties = {
"_ProjectedFit__amount": projectedFits_table.c.amount,
}
)
properties = {"_Fit__modules" : relation(Module, collection_class = HandledModuleList,
primaryjoin = and_(modules_table.c.fitID == fits_table.c.ID, modules_table.c.projected == False),
order_by = modules_table.c.position, cascade='all, delete, delete-orphan'),
"_Fit__projectedModules" : relation(Module, collection_class = HandledProjectedModList, cascade='all, delete, delete-orphan', single_parent=True,
primaryjoin = and_(modules_table.c.fitID == fits_table.c.ID, modules_table.c.projected == True)),
"owner" : relation(User, backref = "fits"),
"_Fit__boosters" : relation(Booster, collection_class = HandledImplantBoosterList, cascade='all, delete, delete-orphan', single_parent=True),
"_Fit__drones" : relation(Drone, collection_class = HandledDroneList, cascade='all, delete, delete-orphan', single_parent=True,
primaryjoin = and_(drones_table.c.fitID == fits_table.c.ID, drones_table.c.projected == False)),
"_Fit__cargo" : relation(Cargo, collection_class = HandledCargoList, cascade='all, delete, delete-orphan', single_parent=True,
primaryjoin = and_(cargo_table.c.fitID == fits_table.c.ID)),
"_Fit__projectedDrones" : relation(Drone, collection_class = HandledProjectedDroneList, cascade='all, delete, delete-orphan', single_parent=True,
primaryjoin = and_(drones_table.c.fitID == fits_table.c.ID, drones_table.c.projected == True)),
"_Fit__implants" : relation(Implant, collection_class = HandledImplantBoosterList, cascade='all, delete, delete-orphan', single_parent=True,
primaryjoin = fitImplants_table.c.fitID == fits_table.c.ID,
secondaryjoin = fitImplants_table.c.implantID == Implant.ID,
secondary = fitImplants_table),
"_Fit__character" : relation(Character, backref = "fits"),
"_Fit__damagePattern" : relation(DamagePattern),
"_Fit__targetResists" : relation(TargetResists),
"_Fit__projectedFits" : relation(Fit,
primaryjoin = projectedFits_table.c.victimID == fits_table.c.ID,
secondaryjoin = fits_table.c.ID == projectedFits_table.c.sourceID,
secondary = projectedFits_table,
collection_class = HandledProjectedFitList)
})

View File

@@ -185,12 +185,6 @@ def getFit(lookfor, eager=None):
fit = saveddata_session.query(Fit).options(*eager).filter(Fit.ID == fitID).first()
else:
raise TypeError("Need integer as argument")
if fit and fit.isInvalid:
with sd_lock:
removeInvalid([fit])
return None
return fit
@cachedQuery(Fleet, 1, "fleetID")
@@ -250,10 +244,9 @@ def getFitsWithShip(shipID, ownerID=None, where=None, eager=None):
filter = processWhere(filter, where)
eager = processEager(eager)
with sd_lock:
fits = removeInvalid(saveddata_session.query(Fit).options(*eager).filter(filter).all())
fits = saveddata_session.query(Fit).options(*eager).filter(filter).all()
else:
raise TypeError("ShipID must be integer")
return fits
def getBoosterFits(ownerID=None, where=None, eager=None):
@@ -271,8 +264,7 @@ def getBoosterFits(ownerID=None, where=None, eager=None):
filter = processWhere(filter, where)
eager = processEager(eager)
with sd_lock:
fits = removeInvalid(saveddata_session.query(Fit).options(*eager).filter(filter).all())
fits = saveddata_session.query(Fit).options(*eager).filter(filter).all()
return fits
def countAllFits():
@@ -303,8 +295,7 @@ def countFitsWithShip(shipID, ownerID=None, where=None, eager=None):
def getFitList(eager=None):
eager = processEager(eager)
with sd_lock:
fits = removeInvalid(saveddata_session.query(Fit).options(*eager).all())
fits = saveddata_session.query(Fit).options(*eager).all()
return fits
def getFleetList(eager=None):
@@ -394,8 +385,7 @@ def searchFits(nameLike, where=None, eager=None):
filter = processWhere(Fit.name.like(nameLike, escape="\\"), where)
eager = processEager(eager)
with sd_lock:
fits = removeInvalid(saveddata_session.query(Fit).options(*eager).filter(filter).all())
fits = saveddata_session.query(Fit).options(*eager).filter(filter).all()
return fits
def getSquadsIDsWithFitID(fitID):
@@ -416,16 +406,6 @@ def getProjectedFits(fitID):
else:
raise TypeError("Need integer as argument")
def removeInvalid(fits):
invalids = [f for f in fits if f.isInvalid]
if invalids:
map(fits.remove, invalids)
map(saveddata_session.delete, invalids)
saveddata_session.commit()
return fits
def add(stuff):
with sd_lock:
saveddata_session.add(stuff)

View File

@@ -17,12 +17,8 @@
# along with eos. If not, see <http://www.gnu.org/licenses/>.
#===============================================================================
#from sqlalchemy.orm.attributes import flag_modified
import eos.db
import eos.types
import logging
logger = logging.getLogger(__name__)
class HandledList(list):
def filteredItemPreAssign(self, filter, *args, **kwargs):
@@ -105,14 +101,6 @@ class HandledList(list):
except AttributeError:
pass
def remove(self, thing):
# We must flag it as modified, otherwise it not be removed from the database
# @todo: flag_modified isn't in os x skel. need to rebuild to include
#flag_modified(thing, "itemID")
if thing.isInvalid: # see GH issue #324
thing.itemID = 0
list.remove(self, thing)
class HandledModuleList(HandledList):
def append(self, mod):
emptyPosition = float("Inf")
@@ -127,14 +115,10 @@ class HandledModuleList(HandledList):
del self[emptyPosition]
mod.position = emptyPosition
HandledList.insert(self, emptyPosition, mod)
if mod.isInvalid:
self.remove(mod)
return
mod.position = len(self)
HandledList.append(self, mod)
if mod.isInvalid:
self.remove(mod)
def insert(self, index, mod):
mod.position = index
@@ -159,82 +143,139 @@ class HandledModuleList(HandledList):
dummy.position = index
self[index] = dummy
def toModule(self, index, mod):
mod.position = index
self[index] = mod
def freeSlot(self, slot):
for i in range(len(self) -1, -1, -1):
mod = self[i]
if mod.getModifiedItemAttr("subSystemSlot") == slot:
del self[i]
class HandledDroneCargoList(HandledList):
class HandledDroneList(HandledList):
def find(self, item):
for o in self:
if o.item == item:
yield o
for d in self:
if d.item == item:
yield d
def findFirst(self, item):
for o in self.find(item):
return o
for d in self.find(item):
return d
def append(self, thing):
HandledList.append(self, thing)
def append(self, drone):
list.append(self, drone)
if thing.isInvalid:
self.remove(thing)
def remove(self, drone):
HandledList.remove(self, drone)
def appendItem(self, item, amount = 1):
if amount < 1: ValueError("Amount of drones to add should be >= 1")
d = self.findFirst(item)
if d is None:
d = eos.types.Drone(item)
self.append(d)
d.amount += amount
return d
def removeItem(self, item, amount):
if amount < 1: ValueError("Amount of drones to remove should be >= 1")
d = self.findFirst(item)
if d is None: return
d.amount -= amount
if d.amount <= 0:
self.remove(d)
return None
return d
class HandledCargoList(HandledList):
# shameless copy of HandledDroneList
# I have no idea what this does, but I needed it
# @todo: investigate this
def find(self, item):
for d in self:
if d.item == item:
yield d
def findFirst(self, item):
for d in self.find(item):
return d
def append(self, cargo):
list.append(self, cargo)
def remove(self, cargo):
HandledList.remove(self, cargo)
def appendItem(self, item, qty = 1):
if qty < 1: ValueError("Amount of cargo to add should be >= 1")
d = self.findFirst(item)
if d is None:
d = eos.types.Cargo(item)
self.append(d)
d.qty += qty
return d
def removeItem(self, item, qty):
if qty < 1: ValueError("Amount of cargo to remove should be >= 1")
d = self.findFirst(item)
if d is None: return
d.qty -= qty
if d.qty <= 0:
self.remove(d)
return None
return d
class HandledImplantBoosterList(HandledList):
def append(self, thing):
if thing.isInvalid:
HandledList.append(self, thing)
self.remove(thing)
return
def __init__(self):
self.__slotCache = {}
# if needed, remove booster that was occupying slot
oldObj = next((m for m in self if m.slot == thing.slot), None)
if oldObj:
logging.info("Slot %d occupied with %s, replacing with %s", thing.slot, oldObj.item.name, thing.item.name)
oldObj.itemID = 0 # hack to remove from DB. See GH issue #324
self.remove(oldObj)
def append(self, implant):
if self.__slotCache.has_key(implant.slot):
raise ValueError("Implant/Booster slot already in use, remove the old one first or set replace = True")
self.__slotCache[implant.slot] = implant
HandledList.append(self, implant)
HandledList.append(self, thing)
def remove(self, implant):
HandledList.remove(self, implant)
del self.__slotCache[implant.slot]
# While we deleted this implant, in edge case seems like not all references
# to it are removed and object still lives in session; forcibly remove it,
# or otherwise when adding the same booster twice booster's table (typeID, fitID)
# constraint will report database integrity error
# TODO: make a proper fix, probably by adjusting fit-boosters sqlalchemy relationships
eos.db.remove(implant)
def freeSlot(self, slot):
if hasattr(slot, "slot"):
slot = slot.slot
try:
implant = self.__slotCache[slot]
except KeyError:
return False
try:
self.remove(implant)
except ValueError:
return False
return True
class HandledProjectedModList(HandledList):
def append(self, proj):
if proj.isInvalid:
# we must include it before we remove it. doing it this way ensures
# rows and relationships in database are removed as well
HandledList.append(self, proj)
self.remove(proj)
return
proj.projected = True
isSystemEffect = proj.item.group.name == "Effect Beacon"
if isSystemEffect:
# remove other system effects - only 1 per fit plz
oldEffect = next((m for m in self if m.item.group.name == "Effect Beacon"), None)
if oldEffect:
logging.info("System effect occupied with %s, replacing with %s", oldEffect.item.name, proj.item.name)
self.remove(oldEffect)
HandledList.append(self, proj)
# Remove non-projectable modules
if not proj.item.isType("projected") and not isSystemEffect:
self.remove(proj)
class HandledProjectedDroneList(HandledDroneCargoList):
class HandledProjectedDroneList(HandledDroneList):
def append(self, proj):
proj.projected = True
HandledList.append(self, proj)
list.append(self, proj)
# Remove invalid or non-projectable drones
if proj.isInvalid or not proj.item.isType("projected"):
self.remove(proj)
class HandledProjectedFitList(HandledList):
def append(self, proj):
proj.projected = True
list.append(self, proj)
class HandledItem(object):
def preAssignItemAttr(self, *args, **kwargs):

View File

@@ -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 (37 of 37)
type = "passive"
def handler(fit, module, context):
fit.ship.increaseItemAttr("signatureRadius", module.getModifiedItemAttr("signatureRadiusAdd"))

View File

@@ -1,7 +1,7 @@
# ammoInfluenceCapNeed
#
# Used by:
# Items from category: Charge (458 of 831)
# Items from category: Charge (458 of 829)
type = "passive"
def handler(fit, module, context):
# Dirty hack to work around cap charges setting cap booster

View File

@@ -1,7 +1,7 @@
# ammoInfluenceRange
#
# Used by:
# Items from category: Charge (559 of 831)
# Items from category: Charge (559 of 829)
type = "passive"
def handler(fit, module, context):
module.multiplyItemAttr("maxRange", module.getModifiedChargeAttr("weaponRangeMultiplier"))

View File

@@ -6,4 +6,4 @@ type = "passive"
def handler(fit, implant, context):
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Repair Systems"),
"armorDamageAmount", implant.getModifiedItemAttr("repairBonus"),
stackingPenalties=True)
stackingPenalties = True)

View File

@@ -1,7 +1,7 @@
# armorHPBonusAdd
#
# Used by:
# Modules from group: Armor Reinforcer (41 of 41)
# Modules from group: Armor Reinforcer (57 of 57)
type = "passive"
def handler(fit, module, context):
fit.ship.increaseItemAttr("armorHP", module.getModifiedItemAttr("armorHPBonusAdd"))

View File

@@ -1,7 +1,7 @@
# armorReinforcerMassAdd
#
# Used by:
# Modules from group: Armor Reinforcer (41 of 41)
# Modules from group: Armor Reinforcer (57 of 57)
type = "passive"
def handler(fit, module, context):
fit.ship.increaseItemAttr("mass", module.getModifiedItemAttr("massAddition"))

View File

@@ -1,9 +0,0 @@
# battlecruiserDroneSpeed
#
# Used by:
# Ship: Myrmidon
# Ship: Prophecy
type = "passive"
def handler(fit, ship, context):
fit.drones.filteredItemBoost(lambda drone: drone.item.requiresSkill("Drones"),
"maxVelocity", ship.getModifiedItemAttr("roleBonusCBC"))

View File

@@ -1,10 +0,0 @@
# battlecruiserMETRange
#
# Used by:
# Ships named like: Harbinger (2 of 2)
type = "passive"
def handler(fit, ship, context):
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Medium Energy Turret"),
"maxRange", ship.getModifiedItemAttr("roleBonusCBC"))
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Medium Energy Turret"),
"falloff", ship.getModifiedItemAttr("roleBonusCBC"))

View File

@@ -1,11 +0,0 @@
# battlecruiserMHTRange
#
# Used by:
# Ships named like: Brutix (2 of 2)
# Ship: Ferox
type = "passive"
def handler(fit, ship, context):
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Medium Hybrid Turret"),
"maxRange", ship.getModifiedItemAttr("roleBonusCBC"))
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Medium Hybrid Turret"),
"falloff", ship.getModifiedItemAttr("roleBonusCBC"))

View File

@@ -1,9 +0,0 @@
# battlecruiserMissileRange
#
# Used by:
# Ships named like: Drake (2 of 2)
# Ship: Cyclone
type = "passive"
def handler(fit, skill, context):
fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("Missile Launcher Operation"),
"maxVelocity", skill.getModifiedItemAttr("roleBonusCBC"))

View File

@@ -1,10 +0,0 @@
# battlecruiserMPTRange
#
# Used by:
# Ships named like: Hurricane (2 of 2)
type = "passive"
def handler(fit, ship, context):
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Medium Projectile Turret"),
"maxRange", ship.getModifiedItemAttr("roleBonusCBC"))
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Medium Projectile Turret"),
"falloff", ship.getModifiedItemAttr("roleBonusCBC"))

View File

@@ -5,5 +5,6 @@
type = "passive"
runTime = "early"
def handler(fit, ship, context):
level = fit.character.getSkill("Transport Ships").level
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Cloaking Device",
"cpu", ship.getModifiedItemAttr("eliteIndustrialCovertCloakBonus"), skill="Transport Ships")
"cpu", ship.getModifiedItemAttr("eliteIndustrialCovertCloakBonus") * level)

View File

@@ -1,7 +1,7 @@
# boosterArmorHpPenalty
#
# Used by:
# Implants from group: Booster (12 of 39)
# Implants from group: Booster (12 of 37)
type = "boosterSideEffect"
def handler(fit, booster, context):
fit.ship.boostItemAttr("armorHP", booster.getModifiedItemAttr("boosterArmorHPPenalty"))

View File

@@ -1,7 +1,7 @@
# boosterArmorRepairAmountPenalty
#
# Used by:
# Implants from group: Booster (9 of 39)
# Implants from group: Booster (9 of 37)
type = "boosterSideEffect"
def handler(fit, booster, context):
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Armor Repair Unit",

View File

@@ -1,7 +1,7 @@
# boosterMaxVelocityPenalty
#
# Used by:
# Implants from group: Booster (12 of 39)
# Implants from group: Booster (12 of 37)
type = "boosterSideEffect"
def handler(fit, booster, context):
fit.ship.boostItemAttr("maxVelocity", booster.getModifiedItemAttr("boosterMaxVelocityPenalty"))

View File

@@ -1,7 +1,7 @@
# boosterShieldCapacityPenalty
#
# Used by:
# Implants from group: Booster (12 of 39)
# Implants from group: Booster (12 of 37)
type = "boosterSideEffect"
def handler(fit, booster, context):
fit.ship.boostItemAttr("shieldCapacity", booster.getModifiedItemAttr("boosterShieldCapacityPenalty"))

View File

@@ -1,7 +1,7 @@
# boosterTurretOptimalRangePenalty
#
# Used by:
# Implants from group: Booster (9 of 39)
# Implants from group: Booster (9 of 37)
type = "boosterSideEffect"
def handler(fit, booster, context):
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Gunnery"),

View File

@@ -2,7 +2,9 @@
#
# Used by:
# Ship: Scorpion
# Ship: Scorpion Ishukone Watch
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Caldari Battleship").level
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "ECM Burst",
"ecmBurstRange", ship.getModifiedItemAttr("shipBonusCB3"), skill="Caldari Battleship")
"ecmBurstRange", ship.getModifiedItemAttr("shipBonusCB3") * level)

View File

@@ -6,5 +6,6 @@
# Ship: Rook
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Caldari Cruiser").level
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "ECM",
"capacitorNeed", ship.getModifiedItemAttr("shipBonusCC"), skill="Caldari Cruiser")
"capacitorNeed", ship.getModifiedItemAttr("shipBonusCC") * level)

View File

@@ -4,5 +4,6 @@
# Variations of ship: Griffin (2 of 2)
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Caldari Frigate").level
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "ECM",
"capacitorNeed", ship.getModifiedItemAttr("shipBonusCF2"), skill="Caldari Frigate")
"capacitorNeed", ship.getModifiedItemAttr("shipBonusCF2") * level)

View File

@@ -2,7 +2,9 @@
#
# Used by:
# Ship: Scorpion
# Ship: Scorpion Ishukone Watch
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Caldari Battleship").level
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "ECM",
"falloff", ship.getModifiedItemAttr("shipBonusCB3"), skill="Caldari Battleship")
"falloff", ship.getModifiedItemAttr("shipBonusCB3") * level)

View File

@@ -4,5 +4,6 @@
# Ship: Blackbird
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Caldari Cruiser").level
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "ECM",
"falloff", ship.getModifiedItemAttr("shipBonusCC2"), skill="Caldari Cruiser")
"falloff", ship.getModifiedItemAttr("shipBonusCC2") * level)

View File

@@ -2,7 +2,9 @@
#
# Used by:
# Ship: Scorpion
# Ship: Scorpion Ishukone Watch
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Caldari Battleship").level
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "ECM",
"maxRange", ship.getModifiedItemAttr("shipBonusCB3"), skill="Caldari Battleship")
"maxRange", ship.getModifiedItemAttr("shipBonusCB3") * level)

View File

@@ -4,5 +4,6 @@
# Ship: Blackbird
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Caldari Cruiser").level
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "ECM",
"maxRange", ship.getModifiedItemAttr("shipBonusCC2"), skill="Caldari Cruiser")
"maxRange", ship.getModifiedItemAttr("shipBonusCC2") * level)

View File

@@ -2,9 +2,11 @@
#
# Used by:
# Ship: Scorpion
# Ship: Scorpion Ishukone Watch
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Caldari Battleship").level
for sensorType in ("Gravimetric", "Ladar", "Magnetometric", "Radar"):
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "ECM",
"scan{0}StrengthBonus".format(sensorType),
ship.getModifiedItemAttr("shipBonusCB"), skill="Caldari Battleship")
ship.getModifiedItemAttr("shipBonusCB") * level)

View File

@@ -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 (107 of 107)
# Modules from group: Reactor Control Unit (22 of 22)
# Modules from group: Shield Flux Coil (11 of 11)
# Modules from group: Shield Power Relay (11 of 11)

View File

@@ -5,7 +5,9 @@
# Ship: Archon
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Amarr Carrier").level
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Remote Armor Repair Systems"),
"maxRange", ship.getModifiedItemAttr("carrierAmarrBonus3"), skill="Amarr Carrier")
"maxRange", ship.getModifiedItemAttr("carrierAmarrBonus3") * level)
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Capacitor Emission Systems"),
"powerTransferRange", ship.getModifiedItemAttr("carrierAmarrBonus3"), skill="Amarr Carrier")
"powerTransferRange", ship.getModifiedItemAttr("carrierAmarrBonus3") * level)

View File

@@ -5,6 +5,7 @@
# Ship: Archon
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Amarr Carrier").level
for resType in ("Em", "Explosive", "Kinetic", "Thermal"):
fit.ship.boostItemAttr("armor{0}DamageResonance".format(resType),
ship.getModifiedItemAttr("carrierAmarrBonus2"), skill="Amarr Carrier")
ship.getModifiedItemAttr("carrierAmarrBonus2") * level)

View File

@@ -5,4 +5,6 @@
# Ship: Archon
type = "passive"
def handler(fit, ship, context):
fit.extraAttributes.increase("maxActiveDrones", ship.getModifiedItemAttr("carrierAmarrBonus1"), skill="Amarr Carrier")
level = fit.character.getSkill("Amarr Carrier").level
amount = ship.getModifiedItemAttr("carrierAmarrBonus1")
fit.extraAttributes.increase("maxActiveDrones", amount * level)

View File

@@ -4,5 +4,6 @@
# Ship: Revenant
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Amarr Carrier").level
fit.drones.filteredItemBoost(lambda drone: drone.item.requiresSkill("Fighter Bombers"),
"maxVelocity", ship.getModifiedItemAttr("carrierAmarrBonus2"), skill="Amarr Carrier")
"maxVelocity", ship.getModifiedItemAttr("carrierAmarrBonus2") * level)

View File

@@ -4,5 +4,6 @@
# Ship: Revenant
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Amarr Carrier").level
fit.drones.filteredItemBoost(lambda drone: drone.item.requiresSkill("Fighters"),
"maxVelocity", ship.getModifiedItemAttr("carrierAmarrBonus2"), skill="Amarr Carrier")
"maxVelocity", ship.getModifiedItemAttr("carrierAmarrBonus2") * level)

View File

@@ -5,5 +5,6 @@
# Ship: Revenant
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Amarr Carrier").level
fit.modules.filteredItemIncrease(lambda mod: mod.item.group.name == "Gang Coordinator",
"maxGroupActive", ship.getModifiedItemAttr("carrierAmarrBonus4"), skill="Amarr Carrier")
"maxGroupActive", ship.getModifiedItemAttr("carrierAmarrBonus4") * level)

View File

@@ -5,4 +5,6 @@
# Ship: Wyvern
type = "passive"
def handler(fit, ship, context):
fit.extraAttributes.increase("maxActiveDrones", ship.getModifiedItemAttr("carrierCaldariBonus1"), skill="Caldari Carrier")
level = fit.character.getSkill("Caldari Carrier").level
amount = ship.getModifiedItemAttr("carrierCaldariBonus1")
fit.extraAttributes.increase("maxActiveDrones", amount * level)

View File

@@ -4,5 +4,6 @@
# Ship: Revenant
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Caldari Carrier").level
fit.drones.filteredItemBoost(lambda drone: drone.item.requiresSkill("Fighters") or drone.item.requiresSkill("Fighter Bombers"),
"signatureRadius", ship.getModifiedItemAttr("carrierCaldariBonus1"), skill="Caldari Carrier")
"signatureRadius", ship.getModifiedItemAttr("carrierCaldariBonus1") * level)

View File

@@ -4,5 +4,6 @@
# Ship: Wyvern
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Caldari Carrier").level
fit.modules.filteredItemIncrease(lambda mod: mod.item.group.name == "Gang Coordinator",
"maxGroupActive", ship.getModifiedItemAttr("carrierCaldariBonus4"), skill="Caldari Carrier")
"maxGroupActive", ship.getModifiedItemAttr("carrierCaldariBonus4") * level)

View File

@@ -6,7 +6,8 @@
# Ship: Wyvern
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Caldari Carrier").level
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Shield Emission Systems"),
"shieldTransferRange", ship.getModifiedItemAttr("carrierCaldariBonus3"), skill="Caldari Carrier")
"shieldTransferRange", ship.getModifiedItemAttr("carrierCaldariBonus3") * level)
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Capacitor Emission Systems"),
"powerTransferRange", ship.getModifiedItemAttr("carrierCaldariBonus3"), skill="Caldari Carrier")
"powerTransferRange", ship.getModifiedItemAttr("carrierCaldariBonus3") * level)

View File

@@ -5,6 +5,7 @@
# Ship: Wyvern
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Caldari Carrier").level
for resType in ("Em", "Explosive", "Kinetic", "Thermal"):
fit.ship.boostItemAttr("shield{0}DamageResonance".format(resType),
ship.getModifiedItemAttr("carrierCaldariBonus2"), skill="Caldari Carrier")
ship.getModifiedItemAttr("carrierCaldariBonus2") * level)

View File

@@ -5,7 +5,8 @@
# Ship: Thanatos
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Gallente Carrier").level
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Shield Emission Systems"),
"shieldTransferRange", ship.getModifiedItemAttr("carrierGallenteBonus3"), skill="Gallente Carrier")
"shieldTransferRange", ship.getModifiedItemAttr("carrierGallenteBonus3") * level)
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Remote Armor Repair Systems"),
"maxRange", ship.getModifiedItemAttr("carrierGallenteBonus3"), skill="Gallente Carrier")
"maxRange", ship.getModifiedItemAttr("carrierGallenteBonus3") * level)

View File

@@ -4,5 +4,6 @@
# Ship: Nyx
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Gallente Carrier").level
fit.drones.filteredItemBoost(lambda drone: drone.item.requiresSkill("Fighter Bombers"),
"damageMultiplier", ship.getModifiedItemAttr("carrierGallenteBonus2"), skill="Gallente Carrier")
"damageMultiplier", ship.getModifiedItemAttr("carrierGallenteBonus2") * level)

View File

@@ -5,4 +5,6 @@
# Ship: Thanatos
type = "passive"
def handler(fit, ship, context):
fit.extraAttributes.increase("maxActiveDrones", ship.getModifiedItemAttr("carrierGallenteBonus1"), skill="Gallente Carrier")
level = fit.character.getSkill("Gallente Carrier").level
amount = ship.getModifiedItemAttr("carrierGallenteBonus1")
fit.extraAttributes.increase("maxActiveDrones", amount * level)

View File

@@ -5,5 +5,6 @@
# Ship: Thanatos
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Gallente Carrier").level
fit.drones.filteredItemBoost(lambda drone: drone.item.requiresSkill("Fighters"),
"damageMultiplier", ship.getModifiedItemAttr("carrierGallenteBonus2"), skill="Gallente Carrier")
"damageMultiplier", ship.getModifiedItemAttr("carrierGallenteBonus2") * level)

View File

@@ -4,5 +4,6 @@
# Ship: Nyx
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Gallente Carrier").level
fit.modules.filteredItemIncrease(lambda mod: mod.item.group.name == "Gang Coordinator",
"maxGroupActive", ship.getModifiedItemAttr("carrierGallenteBonus4"), skill="Gallente Carrier")
"maxGroupActive", ship.getModifiedItemAttr("carrierGallenteBonus4") * level)

View File

@@ -5,7 +5,8 @@
# Ship: Nidhoggur
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Minmatar Carrier").level
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Remote Shield Booster",
"shieldBonus", ship.getModifiedItemAttr("carrierMinmatarBonus2"), skill="Minmatar Carrier")
"shieldBonus", ship.getModifiedItemAttr("carrierMinmatarBonus2") * level)
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Remote Armor Repairer",
"armorDamageAmount", ship.getModifiedItemAttr("carrierMinmatarBonus2"), skill="Minmatar Carrier")
"armorDamageAmount", ship.getModifiedItemAttr("carrierMinmatarBonus2") * level)

View File

@@ -5,7 +5,8 @@
# Ship: Nidhoggur
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Minmatar Carrier").level
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Shield Emission Systems"),
"shieldTransferRange", ship.getModifiedItemAttr("carrierMinmatarBonus3"), skill="Minmatar Carrier")
"shieldTransferRange", ship.getModifiedItemAttr("carrierMinmatarBonus3") * level)
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Remote Armor Repair Systems"),
"maxRange", ship.getModifiedItemAttr("carrierMinmatarBonus3"), skill="Minmatar Carrier")
"maxRange", ship.getModifiedItemAttr("carrierMinmatarBonus3") * level)

View File

@@ -5,4 +5,6 @@
# Ship: Nidhoggur
type = "passive"
def handler(fit, ship, context):
fit.extraAttributes.increase("maxActiveDrones", ship.getModifiedItemAttr("carrierMinmatarBonus1"), skill="Minmatar Carrier")
level = fit.character.getSkill("Minmatar Carrier").level
amount = ship.getModifiedItemAttr("carrierMinmatarBonus1")
fit.extraAttributes.increase("maxActiveDrones", amount * level)

View File

@@ -4,5 +4,6 @@
# Ship: Hel
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Minmatar Carrier").level
fit.modules.filteredItemIncrease(lambda mod: mod.item.group.name == "Gang Coordinator",
"maxGroupActive", ship.getModifiedItemAttr("carrierMinmatarBonus4"), skill="Minmatar Carrier")
"maxGroupActive", ship.getModifiedItemAttr("carrierMinmatarBonus4") * level)

View File

@@ -8,5 +8,5 @@ type = "active", "gang"
def handler(fit, module, context):
if "gang" not in context: return
for bonus in ("maxRangeBonus", "falloffBonus", "trackingSpeedBonus"):
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Weapon Disruption"),
fit.modules.filteredItemBoost(lambda mod: lambda mod: mod.item.requiresSkill("Weapon Disruption"),
bonus, module.getModifiedItemAttr("commandBonusTD"))

View File

@@ -1,9 +1,9 @@
# commandshipMultiRelayEffect
#
# Used by:
# Ships from group: Capital Industrial Ship (2 of 2)
# Ships from group: Command Ship (8 of 8)
# Ship: Orca
# Ship: Rorqual
# Ships from group: Industrial Command Ship (2 of 2)
type = "passive"
def handler(fit, ship, context):
fit.modules.filteredItemIncrease(lambda mod: mod.item.group.name == "Gang Coordinator",

View File

@@ -5,5 +5,6 @@
type = "passive"
runTime = "early"
def handler(fit, ship, context):
level = fit.character.getSkill("Covert Ops").level
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Cloaking Device",
"cpu", ship.getModifiedItemAttr("eliteBonusCoverOps1"), skill="Covert Ops")
"cpu", ship.getModifiedItemAttr("eliteBonusCoverOps1") * level)

View File

@@ -2,6 +2,7 @@
#
# Used by:
# Modules from group: Rig Drones (64 of 64)
# Modules named like: Optimizer (16 of 16)
type = "passive"
def handler(fit, module, context):
fit.ship.boostItemAttr("cpuOutput", module.getModifiedItemAttr("drawback"))

View File

@@ -2,7 +2,6 @@
#
# Used by:
# Modules from group: Rig Shield (72 of 72)
# Modules named like: Optimizer (16 of 16)
type = "passive"
def handler(fit, module, context):
fit.ship.boostItemAttr("signatureRadius", module.getModifiedItemAttr("drawback"), stackingPenalties = True)

View File

@@ -1,8 +1,9 @@
# dreadnoughtMD1ProjDmgBonus
#
# Used by:
# Ship: Naglfar
# Ships named like: Naglfar (2 of 2)
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Minmatar Dreadnought").level
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Projectile Turret"),
"damageMultiplier", ship.getModifiedItemAttr("dreadnoughtShipBonusM1"), skill="Minmatar Dreadnought")
"damageMultiplier", ship.getModifiedItemAttr("dreadnoughtShipBonusM1") * level)

View File

@@ -1,8 +1,9 @@
# dreadnoughtMD3ProjRoFBonus
#
# Used by:
# Ship: Naglfar
# Ships named like: Naglfar (2 of 2)
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Minmatar Dreadnought").level
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Projectile Turret"),
"speed", ship.getModifiedItemAttr("dreadnoughtShipBonusM3"), skill="Minmatar Dreadnought")
"speed", ship.getModifiedItemAttr("dreadnoughtShipBonusM3") * level)

View File

@@ -1,8 +1,9 @@
# dreadnoughtShipBonusHybridDmgG1
#
# Used by:
# Ship: Moros
# Ships named like: Moros (2 of 2)
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Gallente Dreadnought").level
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Hybrid Turret"),
"damageMultiplier", ship.getModifiedItemAttr("dreadnoughtShipBonusG1"), skill="Gallente Dreadnought")
"damageMultiplier", ship.getModifiedItemAttr("dreadnoughtShipBonusG1") * level)

View File

@@ -1,8 +1,9 @@
# dreadnoughtShipBonusHybridRoFG2
#
# Used by:
# Ship: Moros
# Ships named like: Moros (2 of 2)
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Gallente Dreadnought").level
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Hybrid Turret"),
"speed", ship.getModifiedItemAttr("dreadnoughtShipBonusG2"), skill="Gallente Dreadnought")
"speed", ship.getModifiedItemAttr("dreadnoughtShipBonusG2") * level)

View File

@@ -1,8 +1,9 @@
# dreadnoughtShipBonusLaserCapNeedA1
#
# Used by:
# Ship: Revelation
# Ships named like: Revelation (2 of 2)
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Amarr Dreadnought").level
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Energy Turret"),
"capacitorNeed", ship.getModifiedItemAttr("dreadnoughtShipBonusA1"), skill="Amarr Dreadnought")
"capacitorNeed", ship.getModifiedItemAttr("dreadnoughtShipBonusA1") * level)

View File

@@ -1,8 +1,9 @@
# dreadnoughtShipBonusLaserRofA2
#
# Used by:
# Ship: Revelation
# Ships named like: Revelation (2 of 2)
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Amarr Dreadnought").level
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Energy Turret"),
"speed", ship.getModifiedItemAttr("dreadnoughtShipBonusA2"), skill="Amarr Dreadnought")
"speed", ship.getModifiedItemAttr("dreadnoughtShipBonusA2") * level)

View File

@@ -1,9 +1,10 @@
# dreadnoughtShipBonusShieldResistancesC2
#
# Used by:
# Ship: Phoenix
# Ships named like: Phoenix (2 of 2)
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Caldari Dreadnought").level
for damageType in ("em", "thermal", "explosive", "kinetic"):
fit.ship.boostItemAttr("shield{}DamageResonance".format(damageType.capitalize()),
ship.getModifiedItemAttr("dreadnoughtShipBonusC2"), skill="Caldari Dreadnought")
ship.getModifiedItemAttr("dreadnoughtShipBonusC2") * level)

View File

@@ -1,8 +1,9 @@
# eliteBargeBonusIceHarvestingCycleTimeBarge3
#
# Used by:
# Ships from group: Exhumer (3 of 3)
# Ships from group: Exhumer (4 of 4)
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Exhumers").level
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Ice Harvesting"),
"duration", ship.getModifiedItemAttr("eliteBonusBarge2"), skill="Exhumers")
"duration", ship.getModifiedItemAttr("eliteBonusBarge2") * level)

View File

@@ -1,8 +1,9 @@
# eliteBargeBonusMiningDurationBarge2
#
# Used by:
# Ships from group: Exhumer (3 of 3)
# Ships from group: Exhumer (4 of 4)
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Exhumers").level
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Mining"),
"duration", ship.getModifiedItemAttr("eliteBonusBarge2"), skill="Exhumers")
"duration", ship.getModifiedItemAttr("eliteBonusBarge2") * level)

View File

@@ -1,9 +1,10 @@
# eliteBargeShieldResistance1
#
# Used by:
# Ships from group: Exhumer (3 of 3)
# Ships from group: Exhumer (4 of 4)
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Exhumers").level
for damageType in ("em", "thermal", "explosive", "kinetic"):
fit.ship.boostItemAttr("shield{}DamageResonance".format(damageType.capitalize()),
ship.getModifiedItemAttr("eliteBonusBarge1"), skill="Exhumers")
ship.getModifiedItemAttr("eliteBonusBarge1") * level)

View File

@@ -4,5 +4,6 @@
# Ship: Cambion
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Assault Frigates").level
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Missile Launcher Light",
"speed", ship.getModifiedItemAttr("eliteBonusGunship1"), skill="Assault Frigates")
"speed", ship.getModifiedItemAttr("eliteBonusGunship1") * level)

View File

@@ -4,5 +4,6 @@
# Ship: Hawk
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Assault Frigates").level
fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("Missile Launcher Operation"),
"maxVelocity", ship.getModifiedItemAttr("eliteBonusGunship1"), skill="Assault Frigates")
"maxVelocity", ship.getModifiedItemAttr("eliteBonusGunship1") * level)

View File

@@ -4,5 +4,6 @@
# Ship: Cambion
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Assault Frigates").level
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Missile Launcher Rocket",
"speed", ship.getModifiedItemAttr("eliteBonusGunship1"), skill="Assault Frigates")
"speed", ship.getModifiedItemAttr("eliteBonusGunship1") * level)

View File

@@ -4,4 +4,5 @@
# Ship: Sin
type = "passive"
def handler(fit, ship, context):
fit.ship.boostItemAttr("agility", ship.getModifiedItemAttr("eliteBonusBlackOps1"), skill="Black Ops")
level = fit.character.getSkill("Black Ops").level
fit.ship.boostItemAttr("agility", ship.getModifiedItemAttr("eliteBonusBlackOps1") * level)

View File

@@ -5,4 +5,5 @@
type = "passive"
def handler(fit, ship, context):
if fit.extraAttributes["cloaked"]:
fit.ship.multiplyItemAttr("maxVelocity", ship.getModifiedItemAttr("eliteBonusBlackOps2"), skill="Black Ops")
level = fit.character.getSkill("Black Ops").level
fit.ship.multiplyItemAttr("maxVelocity", ship.getModifiedItemAttr("eliteBonusBlackOps2") * level)

View File

@@ -4,7 +4,8 @@
# Ship: Widow
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Black Ops").level
sensorTypes = ("Gravimetric", "Ladar", "Magnetometric", "Radar")
for type in sensorTypes:
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "ECM Burst", "scan{0}StrengthBonus".format(type),
ship.getModifiedItemAttr("eliteBonusBlackOps1"), skill="Black Ops")
ship.getModifiedItemAttr("eliteBonusBlackOps1") * level)

View File

@@ -4,7 +4,8 @@
# Ship: Widow
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Black Ops").level
sensorTypes = ("Gravimetric", "Ladar", "Magnetometric", "Radar")
for type in sensorTypes:
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "ECM", "scan{0}StrengthBonus".format(type),
ship.getModifiedItemAttr("eliteBonusBlackOps1"), skill="Black Ops")
ship.getModifiedItemAttr("eliteBonusBlackOps1") * level)

View File

@@ -4,5 +4,6 @@
# Ship: Redeemer
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Black Ops").level
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Large Energy Turret"),
"trackingSpeed", ship.getModifiedItemAttr("eliteBonusBlackOps1"), skill="Black Ops")
"trackingSpeed", ship.getModifiedItemAttr("eliteBonusBlackOps1") * level)

View File

@@ -4,4 +4,5 @@
# Ship: Panther
type = "passive"
def handler(fit, ship, context):
fit.ship.boostItemAttr("maxVelocity", ship.getModifiedItemAttr("eliteBonusBlackOps1"), skill="Black Ops")
level = fit.character.getSkill("Black Ops").level
fit.ship.boostItemAttr("maxVelocity", ship.getModifiedItemAttr("eliteBonusBlackOps1") * level)

View File

@@ -4,5 +4,6 @@
# Ships from group: Command Ship (4 of 8)
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Command Ships").level
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Armored Warfare Specialist"),
"commandBonus", ship.getModifiedItemAttr("eliteBonusCommandShips3"), skill="Command Ships")
"commandBonus", ship.getModifiedItemAttr("eliteBonusCommandShips3") * level)

View File

@@ -4,4 +4,5 @@
# Ship: Damnation
type = "passive"
def handler(fit, ship, context):
fit.ship.boostItemAttr("armorHP", ship.getModifiedItemAttr("eliteBonusCommandShips1"), skill="Command Ships")
level = fit.character.getSkill("Command Ships").level
fit.ship.boostItemAttr("armorHP", ship.getModifiedItemAttr("eliteBonusCommandShips1") * level)

View File

@@ -5,5 +5,6 @@
# Ship: Nighthawk
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Command Ships").level
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Missile Launcher Heavy Assault",
"speed", ship.getModifiedItemAttr("eliteBonusCommandShips1"), skill="Command Ships")
"speed", ship.getModifiedItemAttr("eliteBonusCommandShips1") * level)

View File

@@ -4,7 +4,8 @@
# Ship: Damnation
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Command Ships").level
damageTypes = ("em", "explosive", "kinetic", "thermal")
for damageType in damageTypes:
fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("Heavy Assault Missiles"),
"{0}Damage".format(damageType), ship.getModifiedItemAttr("eliteBonusCommandShips2"), skill="Command Ships")
"{0}Damage".format(damageType), ship.getModifiedItemAttr("eliteBonusCommandShips2") * level)

View File

@@ -4,5 +4,6 @@
# Ship: Eos
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Command Ships").level
fit.drones.filteredItemBoost(lambda drone: drone.item.requiresSkill("Heavy Drone Operation"),
"trackingSpeed", ship.getModifiedItemAttr("eliteBonusCommandShips2"), skill="Command Ships")
"trackingSpeed", ship.getModifiedItemAttr("eliteBonusCommandShips2") * level)

View File

@@ -4,5 +4,6 @@
# Ship: Eos
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Command Ships").level
fit.drones.filteredItemBoost(lambda drone: drone.item.requiresSkill("Heavy Drone Operation"),
"maxVelocity", ship.getModifiedItemAttr("eliteBonusCommandShips2"), skill="Command Ships")
"maxVelocity", ship.getModifiedItemAttr("eliteBonusCommandShips2") * level)

View File

@@ -4,7 +4,8 @@
# Ship: Damnation
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Command Ships").level
damageTypes = ("em", "explosive", "kinetic", "thermal")
for damageType in damageTypes:
fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("Heavy Missiles"),
"{0}Damage".format(damageType), ship.getModifiedItemAttr("eliteBonusCommandShips2"), skill="Command Ships")
"{0}Damage".format(damageType), ship.getModifiedItemAttr("eliteBonusCommandShips2") * level)

View File

@@ -5,5 +5,6 @@
# Ship: Nighthawk
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Command Ships").level
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Missile Launcher Heavy",
"speed", ship.getModifiedItemAttr("eliteBonusCommandShips1"), skill="Command Ships")
"speed", ship.getModifiedItemAttr("eliteBonusCommandShips1") * level)

View File

@@ -4,5 +4,6 @@
# Ship: Astarte
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Command Ships").level
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Medium Hybrid Turret"),
"falloff", ship.getModifiedItemAttr("eliteBonusCommandShips2"), skill="Command Ships")
"falloff", ship.getModifiedItemAttr("eliteBonusCommandShips2") * level)

View File

@@ -4,5 +4,6 @@
# Ship: Vulture
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Command Ships").level
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Medium Hybrid Turret"),
"maxRange", ship.getModifiedItemAttr("eliteBonusCommandShips1"), skill="Command Ships")
"maxRange", ship.getModifiedItemAttr("eliteBonusCommandShips1") * level)

View File

@@ -4,5 +4,6 @@
# Ships from group: Command Ship (4 of 8)
type = "passive"
def handler(fit, module, context):
level = fit.character.getSkill("Command Ships").level
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Information Warfare Specialist"),
"commandBonus", module.getModifiedItemAttr("eliteBonusCommandShips3"), skill="Command Ships")
"commandBonus", module.getModifiedItemAttr("eliteBonusCommandShips3") * level)

View File

@@ -4,5 +4,6 @@
# Ships from group: Command Ship (4 of 8)
type = "passive"
def handler(fit, module, context):
level = fit.character.getSkill("Command Ships").level
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Information Warfare Specialist"),
"commandBonusHidden", module.getModifiedItemAttr("eliteBonusCommandShips3"), skill="Command Ships")
"commandBonusHidden", module.getModifiedItemAttr("eliteBonusCommandShips3") * level)

View File

@@ -4,5 +4,6 @@
# Ship: Absolution
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Command Ships").level
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Medium Energy Turret"),
"damageMultiplier", ship.getModifiedItemAttr("eliteBonusCommandShips1"), skill="Command Ships")
"damageMultiplier", ship.getModifiedItemAttr("eliteBonusCommandShips1") * level)

View File

@@ -4,5 +4,6 @@
# Ship: Absolution
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Command Ships").level
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Medium Energy Turret"),
"speed", ship.getModifiedItemAttr("eliteBonusCommandShips2"), skill="Command Ships")
"speed", ship.getModifiedItemAttr("eliteBonusCommandShips2") * level)

View File

@@ -4,5 +4,6 @@
# Ship: Vulture
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Command Ships").level
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Medium Hybrid Turret"),
"damageMultiplier", ship.getModifiedItemAttr("eliteBonusCommandShips2"), skill="Command Ships")
"damageMultiplier", ship.getModifiedItemAttr("eliteBonusCommandShips2") * level)

View File

@@ -4,5 +4,6 @@
# Ship: Astarte
type = "passive"
def handler(fit, ship, context):
level = fit.character.getSkill("Command Ships").level
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Medium Hybrid Turret"),
"speed", ship.getModifiedItemAttr("eliteBonusCommandShips1"), skill="Command Ships")
"speed", ship.getModifiedItemAttr("eliteBonusCommandShips1") * level)

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