Browse Source

update pyfa/eos to 2.30.0

pull/4/head
Mike 3 years ago
parent
commit
a791251bf2
  1. 4
      cogs/killstream.py
  2. 18
      eos/config.py
  3. 10
      eos/db/gamedata/attribute.py
  4. 9
      eos/db/gamedata/category.py
  5. 9
      eos/db/gamedata/group.py
  6. 51
      eos/db/gamedata/item.py
  7. 36
      eos/db/gamedata/marketGroup.py
  8. 22
      eos/db/gamedata/metaGroup.py
  9. 4
      eos/db/gamedata/queries.py
  10. 20
      eos/db/gamedata/traits.py
  11. 4
      eos/db/gamedata/unit.py
  12. 279
      eos/effects.py
  13. 8
      eos/gamedata.py
  14. 2
      eos/saveddata/character.py
  15. 243
      eos/saveddata/damagePattern.py
  16. 108
      eos/saveddata/fit.py
  17. 22
      eos/saveddata/module.py
  18. 24
      eos/saveddata/mutator.py
  19. 364
      eos/saveddata/targetProfile.py
  20. 6
      eos/utils/stats.py
  21. BIN
      eve.db

4
cogs/killstream.py

@ -242,9 +242,9 @@ class Killstream(commands.Cog):
except KeyError:
return await ctx.send(f"{entity_type.capitalize()} not found")
if entity_type is 'character':
if entity_type == 'character':
entity_sheet = await self.bot.esi.character_sheet(character_id=entity_id)
elif entity_type is 'corporation':
elif entity_type == 'corporation':
entity_sheet = await self.bot.esi.corporation_sheet(corporation_id=entity_id)
else:
entity_sheet = await self.bot.esi.alliance_sheet(alliance_id=entity_id)

18
eos/config.py

@ -13,6 +13,24 @@ saveddataCache = True
gamedata_version = ""
gamedata_date = ""
gamedata_connectionstring = 'sqlite:///' + realpath(join(dirname(abspath(__file__)), "..", "eve.db"))
lang = ""
# Maps supported langauges to their suffix in the database
translation_mapping = {
"en": "",
"fr": "_fr",
# "it": "_it",
"ja": "_ja",
"ko": "_ko",
"ru": "_ru",
"zh": "_zh",
}
def set_lang(i18n_lang):
global lang
lang = translation_mapping.get(i18n_lang, translation_mapping.get("en"))
pyfalog.debug("Gamedata connection string: {0}", gamedata_connectionstring)
if istravis is True or hasattr(sys, '_called_from_test'):

10
eos/db/gamedata/attribute.py

@ -23,7 +23,7 @@ from sqlalchemy.orm import relation, mapper, synonym, deferred
from eos.db import gamedata_meta
from eos.gamedata import Attribute, AttributeInfo, Unit
import eos.config
typeattributes_table = Table("dgmtypeattribs", gamedata_meta,
Column("value", Float),
Column("typeID", Integer, ForeignKey("invtypes.typeID"), primary_key=True, index=True),
@ -36,11 +36,11 @@ attributes_table = Table("dgmattribs", gamedata_meta,
Column("maxAttributeID", Integer, ForeignKey("dgmattribs.attributeID")),
Column("description", Unicode),
Column("published", Boolean),
Column("displayName", String),
*[Column("displayName{}".format(lang), String) for lang in eos.config.translation_mapping.values()],
Column("highIsGood", Boolean),
Column("iconID", Integer),
Column("attributeCategory", Integer),
Column("tooltipDescription", Integer),
# Column("tooltipDescription", Integer), # deprecated...?
Column("unitID", Integer, ForeignKey("dgmunits.unitID")))
mapper(Attribute, typeattributes_table,
@ -51,14 +51,14 @@ mapper(AttributeInfo, attributes_table,
"unit" : relation(Unit),
"ID" : synonym("attributeID"),
"name" : synonym("attributeName"),
"description": deferred(attributes_table.c.description)
"description": deferred(attributes_table.c.description),
})
Attribute.ID = association_proxy("info", "attributeID")
Attribute.name = association_proxy("info", "attributeName")
Attribute.description = association_proxy("info", "description")
Attribute.published = association_proxy("info", "published")
Attribute.displayName = association_proxy("info", "displayName")
Attribute.displayName = association_proxy("info", "displayName{}".format(eos.config.lang))
Attribute.highIsGood = association_proxy("info", "highIsGood")
Attribute.iconID = association_proxy("info", "iconID")
Attribute.icon = association_proxy("info", "icon")

9
eos/db/gamedata/category.py

@ -22,17 +22,18 @@ from sqlalchemy.orm import deferred, mapper, synonym
from eos.db import gamedata_meta
from eos.gamedata import Category
import eos.config
categories_table = Table("invcategories", gamedata_meta,
Column("categoryID", Integer, primary_key=True),
Column("categoryName", String),
Column("description", String),
*[Column("name{}".format(lang), String) for lang in eos.config.translation_mapping.values()],
# Column("description", String), # deprecated
Column("published", Boolean),
Column("iconID", Integer))
mapper(Category, categories_table,
properties={
"ID" : synonym("categoryID"),
"name" : synonym("categoryName"),
"description": deferred(categories_table.c.description)
"displayName": synonym("name{}".format(eos.config.lang)),
# "description": deferred(categories_table.c.description) # deprecated
})

9
eos/db/gamedata/group.py

@ -22,11 +22,12 @@ from sqlalchemy.orm import relation, mapper, synonym, deferred, backref
from eos.db import gamedata_meta
from eos.gamedata import Category, Group
import eos.config
groups_table = Table("invgroups", gamedata_meta,
Column("groupID", Integer, primary_key=True),
Column("groupName", String),
Column("description", String),
*[Column("name{}".format(lang), String) for lang in eos.config.translation_mapping.values()],
# Column("description", String), # deprecated
Column("published", Boolean),
Column("categoryID", Integer, ForeignKey("invcategories.categoryID")),
Column("iconID", Integer))
@ -35,6 +36,6 @@ mapper(Group, groups_table,
properties={
"category" : relation(Category, backref=backref("groups", cascade="all,delete")),
"ID" : synonym("groupID"),
"name" : synonym("groupName"),
"description": deferred(groups_table.c.description)
"displayName" : synonym("name{}".format(eos.config.lang)),
# "description": deferred(groups_table.c.description) # deprecated
})

51
eos/db/gamedata/item.py

@ -27,10 +27,12 @@ from eos.db.gamedata.dynamicAttributes import dynamicApplicable_table
from eos.db.gamedata.effect import typeeffects_table
from eos.gamedata import Attribute, DynamicItem, Effect, Group, Item, Traits, MetaGroup
import eos.config
items_table = Table("invtypes", gamedata_meta,
Column("typeID", Integer, primary_key=True),
Column("typeName", String, index=True),
Column("description", String),
*[Column("typeName{}".format(lang), String, index=True) for lang in eos.config.translation_mapping.values()],
*[Column("typeDescription{}".format(lang), String) for lang in eos.config.translation_mapping.values()],
Column("raceID", Integer),
Column("factionID", Integer),
Column("published", Boolean),
@ -43,27 +45,38 @@ items_table = Table("invtypes", gamedata_meta,
Column("variationParentTypeID", Integer, ForeignKey("invtypes.typeID"), index=True),
Column("replacements", String),
Column("reqskills", String),
Column("requiredfor", String))
Column("requiredfor", String),
)
from .traits import traits_table # noqa
mapper(Item, items_table,
properties={
"group" : relation(Group, backref=backref("items", cascade="all,delete")),
props = {
"group": relation(Group, backref=backref("items", cascade="all,delete")),
"_Item__attributes": relation(Attribute, cascade='all, delete, delete-orphan', collection_class=attribute_mapped_collection('name')),
"effects": relation(Effect, secondary=typeeffects_table, collection_class=attribute_mapped_collection('name')),
"metaGroup" : relation(MetaGroup, backref=backref("items", cascade="all,delete")),
"varParent" : relation(Item, backref=backref("varChildren", cascade="all,delete"), remote_side=items_table.c.typeID),
"ID" : synonym("typeID"),
"name" : synonym("typeName"),
"description" : deferred(items_table.c.description),
"traits" : relation(Traits,
primaryjoin=traits_table.c.typeID == items_table.c.typeID,
uselist=False),
"mutaplasmids": relation(DynamicItem,
primaryjoin=dynamicApplicable_table.c.applicableTypeID == items_table.c.typeID,
secondaryjoin=dynamicApplicable_table.c.typeID == DynamicItem.typeID,
secondary=dynamicApplicable_table,
backref="applicableItems")})
"metaGroup": relation(MetaGroup, backref=backref("items", cascade="all,delete")),
"varParent": relation(Item, backref=backref("varChildren", cascade="all,delete"), remote_side=items_table.c.typeID),
"ID": synonym("typeID"),
"name": synonym("typeName{}".format(eos.config.lang)),
"description" : synonym("_description{}".format(eos.config.lang)),
"traits": relation(
Traits,
primaryjoin=traits_table.c.typeID == items_table.c.typeID,
uselist=False
),
"mutaplasmids": relation(
DynamicItem,
primaryjoin=dynamicApplicable_table.c.applicableTypeID == items_table.c.typeID,
secondaryjoin=dynamicApplicable_table.c.typeID == DynamicItem.typeID,
secondary=dynamicApplicable_table,
backref="applicableItems"
)
}
# Create deferred columns shadowing all the description fields. The literal `description` property will dynamically
# be assigned as synonym to one of these
props.update({'_description' + v: deferred(items_table.c['typeDescription' + v]) for (k, v) in eos.config.translation_mapping.items()})
mapper(Item, items_table, properties=props)
Item.category = association_proxy("group", "category")

36
eos/db/gamedata/marketGroup.py

@ -22,22 +22,34 @@ from sqlalchemy.orm import relation, mapper, synonym, deferred
from eos.db import gamedata_meta
from eos.gamedata import Item, MarketGroup
import eos.config
marketgroups_table = Table("invmarketgroups", gamedata_meta,
Column("marketGroupID", Integer, primary_key=True),
Column("marketGroupName", String),
Column("description", String),
*[Column("marketGroupName{}".format(lang), String) for lang in eos.config.translation_mapping.values()],
*[Column("marketGroupDescription{}".format(lang), String) for lang in eos.config.translation_mapping.values()],
Column("hasTypes", Boolean),
Column("parentGroupID", Integer,
ForeignKey("invmarketgroups.marketGroupID", initially="DEFERRED", deferrable=True)),
ForeignKey("invmarketgroups.marketGroupID", initially="DEFERRED", deferrable=True)),
Column("iconID", Integer))
mapper(MarketGroup, marketgroups_table,
properties={
"items" : relation(Item, backref="marketGroup"),
"parent" : relation(MarketGroup, backref="children",
remote_side=[marketgroups_table.c.marketGroupID]),
"ID" : synonym("marketGroupID"),
"name" : synonym("marketGroupName"),
"description": deferred(marketgroups_table.c.description)
})
props = {
"items": relation(Item, backref="marketGroup"),
"parent": relation(MarketGroup, backref="children", remote_side=[marketgroups_table.c.marketGroupID]),
"ID": synonym("marketGroupID"),
"name": synonym("marketGroupName{}".format(eos.config.lang)),
"description": synonym("_description{}".format(eos.config.lang)),
}
# Create deferred columns shadowing all the description fields. The literal `description` property will dynamically
# be assigned as synonym to one of these
# this is mostly here to allow the db_update to be language-agnostic
# todo: determine if we ever use market group descriptions... can we just get with of these?
props.update({'_description' + v: deferred(marketgroups_table.c['marketGroupDescription' + v]) for (k, v) in eos.config.translation_mapping.items()})
mapper(
MarketGroup,
marketgroups_table,
properties=props
)

22
eos/db/gamedata/metaGroup.py

@ -22,12 +22,20 @@ from sqlalchemy.orm import mapper, synonym
from eos.db import gamedata_meta
from eos.gamedata import MetaGroup
import eos.config
metagroups_table = Table("invmetagroups", gamedata_meta,
Column("metaGroupID", Integer, primary_key=True),
Column("metaGroupName", String))
metagroups_table = Table(
"invmetagroups",
gamedata_meta,
Column("metaGroupID", Integer, primary_key=True),
*[Column("metaGroupName{}".format(lang), String) for lang in eos.config.translation_mapping.values()],
)
mapper(MetaGroup, metagroups_table,
properties={
"ID" : synonym("metaGroupID"),
"name": synonym("metaGroupName")})
mapper(
MetaGroup,
metagroups_table,
properties={
"ID" : synonym("metaGroupID"),
"name": synonym("metaGroupName{}".format(eos.config.lang))
}
)

4
eos/db/gamedata/queries.py

@ -91,7 +91,7 @@ def getItem(lookfor, eager=None):
item = get_gamedata_session().query(Item).options(*processEager(eager)).filter(Item.ID == id).first()
else:
# Item names are unique, so we can use first() instead of one()
item = get_gamedata_session().query(Item).options(*processEager(eager)).filter(Item.name == lookfor).first()
item = get_gamedata_session().query(Item).options(*processEager(eager)).filter(Item.typeName == lookfor).first()
if item is not None:
itemNameMap[lookfor] = item.ID
else:
@ -265,7 +265,7 @@ def getMetaGroup(lookfor, eager=None):
else:
# MetaGroup names are unique, so we can use first() instead of one()
metaGroup = get_gamedata_session().query(MetaGroup).options(*processEager(eager)).filter(
MetaGroup.name == lookfor).first()
MetaGroup.metaGroupName == lookfor).first()
if metaGroup is not None:
metaGroupNameMap[lookfor] = metaGroup.ID
else:

20
eos/db/gamedata/traits.py

@ -1,11 +1,21 @@
from sqlalchemy import Column, Table, Integer, String, ForeignKey
from sqlalchemy.orm import mapper
from sqlalchemy.orm import mapper, synonym
from eos.db import gamedata_meta
from eos.gamedata import Traits
import eos.config
traits_table = Table("invtraits", gamedata_meta,
Column("typeID", Integer, ForeignKey("invtypes.typeID"), primary_key=True),
Column("traitText", String))
traits_table = Table(
"invtraits",
gamedata_meta,
Column("typeID", Integer, ForeignKey("invtypes.typeID"), primary_key=True),
*[Column("traitText{}".format(lang), String) for lang in eos.config.translation_mapping.values()],
)
mapper(Traits, traits_table)
mapper(
Traits,
traits_table,
properties={
"display": synonym("traitText{}".format(eos.config.lang)),
}
)

4
eos/db/gamedata/unit.py

@ -22,11 +22,13 @@ from sqlalchemy.orm import mapper, synonym
from eos.db import gamedata_meta
from eos.gamedata import Unit
import eos.config
groups_table = Table("dgmunits", gamedata_meta,
Column("unitID", Integer, primary_key=True),
Column("unitName", String),
Column("displayName", String))
*[Column("displayName{}".format(lang), String) for lang in eos.config.translation_mapping.values()],
)
mapper(Unit, groups_table,
properties={

279
eos/effects.py

@ -42,7 +42,7 @@ class Effect4(BaseEffect):
shieldBoosting
Used by:
Modules from group: Shield Booster (89 of 89)
Modules from group: Shield Booster (90 of 90)
"""
runTime = 'late'
@ -148,7 +148,7 @@ class Effect27(BaseEffect):
armorRepair
Used by:
Modules from group: Armor Repair Unit (100 of 100)
Modules from group: Armor Repair Unit (101 of 101)
"""
runTime = 'late'
@ -203,7 +203,7 @@ class Effect39(BaseEffect):
warpDisrupt
Used by:
Modules named like: Warp Disruptor (28 of 28)
Modules named like: Warp Disruptor (29 of 29)
"""
type = 'projected', 'active'
@ -374,7 +374,7 @@ class Effect58(BaseEffect):
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 (68 of 133)
Modules from group: Propulsion Module (69 of 135)
Modules from group: Reactor Control Unit (22 of 22)
"""
@ -1126,6 +1126,7 @@ class Effect394(BaseEffect):
Implants named like: grade Snake (16 of 18)
Modules named like: Auxiliary Thrusters (8 of 8)
Implant: Quafe Zero
Implant: Serenity YC122.9 Season Booster - Max Velocity
Skill: Navigation
"""
@ -1150,6 +1151,7 @@ class Effect395(BaseEffect):
Implants named like: grade Nomad (10 of 12)
Modules named like: Low Friction Nozzle Joints (8 of 8)
Implant: Genolution Core Augmentation CA-4
Implant: Serenity YC122.9 Season Booster - Agility
Skill: Evasive Maneuvering
Skill: Spaceship Command
"""
@ -1782,7 +1784,7 @@ class Effect596(BaseEffect):
ammoInfluenceRange
Used by:
Items from category: Charge (608 of 973)
Items from category: Charge (608 of 974)
"""
type = 'passive'
@ -1801,6 +1803,7 @@ class Effect598(BaseEffect):
Charges from group: Interdiction Probe (2 of 2)
Charges from group: Structure Festival Charges (2 of 2)
Special Edition Assetss from group: Festival Charges Expired (4 of 4)
Charge: Stasis Webification Probe
"""
type = 'passive'
@ -2369,7 +2372,7 @@ class Effect804(BaseEffect):
ammoInfluenceCapNeed
Used by:
Items from category: Charge (514 of 973)
Items from category: Charge (514 of 974)
"""
type = 'passive'
@ -2440,6 +2443,7 @@ class Effect856(BaseEffect):
Implants named like: Eifyr and Co. 'Rogue' Warp Drive Speed WS (6 of 6)
Implants named like: grade Ascendancy (10 of 12)
Modules named like: Hyperspatial Velocity Optimizer (8 of 8)
Implant: Serenity YC122.9 Season Booster - Warp Speed
"""
type = 'passive'
@ -3737,6 +3741,7 @@ class Effect1185(BaseEffect):
Used by:
Implants named like: X Instinct Booster (4 of 4)
Implants named like: grade Halo (15 of 18)
Implant: Serenity YC122.9 Season Booster - Signature Radius
"""
type = 'passive'
@ -4491,6 +4496,7 @@ class Effect1452(BaseEffect):
Used by:
Implants named like: grade Centurion (10 of 12)
Modules named like: Particle Dispersion Projector (8 of 8)
Implant: Serenity YC122.9 Season Booster - EW Range
Skill: Long Distance Jamming
"""
@ -5208,7 +5214,7 @@ class Effect1720(BaseEffect):
Used by:
Modules from group: Capacitor Power Relay (20 of 20)
Modules from group: Shield Boost Amplifier (25 of 25)
Modules from group: Shield Boost Amplifier (23 of 23)
"""
type = 'passive'
@ -6651,23 +6657,6 @@ class Effect2189(BaseEffect):
skill='Amarr Cruiser', **kwargs)
class Effect2200(BaseEffect):
"""
eliteBonusInterdictorsMissileKineticDamage1
Used by:
Ship: Flycatcher
"""
type = 'passive'
@staticmethod
def handler(fit, ship, context, projectionRange, **kwargs):
fit.modules.filteredChargeBoost(
lambda mod: mod.charge.requiresSkill('Light Missiles') or mod.charge.requiresSkill('Rockets'),
'kineticDamage', ship.getModifiedItemAttr('eliteBonusInterdictors1'), skill='Interdictors', **kwargs)
class Effect2201(BaseEffect):
"""
eliteBonusInterdictorsProjectileFalloff1
@ -6830,7 +6819,7 @@ class Effect2255(BaseEffect):
tractorBeamCan
Used by:
Deployables from group: Mobile Tractor Unit (3 of 3)
Deployables from group: Mobile Tractor Unit (4 of 4)
Modules from group: Tractor Beam (4 of 4)
"""
@ -9223,8 +9212,8 @@ class Effect3002(BaseEffect):
Used by:
Modules from group: Ancillary Remote Shield Booster (4 of 4)
Modules from group: Capacitor Booster (41 of 41)
Modules from group: Energy Neutralizer (54 of 54)
Modules from group: Energy Nosferatu (54 of 54)
Modules from group: Energy Neutralizer (55 of 55)
Modules from group: Energy Nosferatu (55 of 55)
Modules from group: Hull Repair Unit (25 of 25)
Modules from group: Remote Armor Repairer (39 of 39)
Modules from group: Remote Capacitor Transmitter (35 of 35)
@ -9468,7 +9457,7 @@ class Effect3061(BaseEffect):
heatDamageBonus
Used by:
Modules from group: Shield Boost Amplifier (25 of 25)
Modules from group: Shield Boost Amplifier (23 of 23)
"""
type = 'passive'
@ -9542,7 +9531,7 @@ class Effect3174(BaseEffect):
Used by:
Modules from group: Stasis Grappler (7 of 7)
Modules from group: Stasis Web (19 of 19)
Modules from group: Warp Scrambler (54 of 55)
Modules from group: Warp Scrambler (56 of 57)
"""
type = 'overheat'
@ -9558,7 +9547,7 @@ class Effect3175(BaseEffect):
overloadSelfSpeedBonus
Used by:
Modules from group: Propulsion Module (133 of 133)
Modules from group: Propulsion Module (135 of 135)
"""
type = 'overheat'
@ -9610,8 +9599,8 @@ class Effect3200(BaseEffect):
overloadSelfArmorDamageAmountDurationBonus
Used by:
Modules from group: Ancillary Armor Repairer (7 of 7)
Modules from group: Armor Repair Unit (100 of 100)
Modules from group: Ancillary Armor Repairer (8 of 8)
Modules from group: Armor Repair Unit (101 of 101)
"""
type = 'overheat'
@ -9628,8 +9617,8 @@ class Effect3201(BaseEffect):
overloadSelfShieldBonusDurationBonus
Used by:
Modules from group: Ancillary Shield Booster (8 of 8)
Modules from group: Shield Booster (89 of 89)
Modules from group: Ancillary Shield Booster (9 of 9)
Modules from group: Shield Booster (90 of 90)
"""
type = 'overheat'
@ -11206,6 +11195,7 @@ class Effect3650(BaseEffect):
Used by:
Implants named like: grade Centurion (10 of 12)
Implant: Serenity YC122.9 Season Booster - EW Range
"""
type = 'passive'
@ -11222,6 +11212,7 @@ class Effect3651(BaseEffect):
Used by:
Implants named like: grade Centurion (10 of 12)
Implant: Serenity YC122.9 Season Booster - EW Range
"""
type = 'passive'
@ -11238,6 +11229,7 @@ class Effect3652(BaseEffect):
Used by:
Implants named like: grade Centurion (10 of 12)
Implant: Serenity YC122.9 Season Booster - EW Range
"""
type = 'passive'
@ -11254,6 +11246,7 @@ class Effect3653(BaseEffect):
Used by:
Implants named like: grade Centurion (10 of 12)
Implant: Serenity YC122.9 Season Booster - EW Range
"""
type = 'passive'
@ -11354,6 +11347,7 @@ class Effect3668(BaseEffect):
Used by:
Implants named like: grade Harvest (10 of 12)
Implant: Serenity YC122.9 Season Booster - Mining Range
"""
type = 'passive'
@ -11370,6 +11364,7 @@ class Effect3669(BaseEffect):
Used by:
Implants named like: grade Harvest (10 of 12)
Implant: Serenity YC122.9 Season Booster - Mining Range
"""
type = 'passive'
@ -11386,6 +11381,7 @@ class Effect3670(BaseEffect):
Used by:
Implants named like: grade Harvest (10 of 12)
Implant: Serenity YC122.9 Season Booster - Mining Range
"""
type = 'passive'
@ -11402,6 +11398,7 @@ class Effect3671(BaseEffect):
Used by:
Implants named like: grade Harvest (10 of 12)
Implant: Serenity YC122.9 Season Booster - Mining Range
"""
type = 'passive'
@ -11418,6 +11415,7 @@ class Effect3672(BaseEffect):
Used by:
Implants named like: grade Harvest (12 of 12)
Implant: Serenity YC122.9 Season Booster - Mining Range
"""
runTime = 'early'
@ -13594,6 +13592,7 @@ class Effect4162(BaseEffect):
Implants named like: Poteque 'Prospector' Astrometric Rangefinding AR (3 of 3)
Implants named like: grade Virtue (10 of 12)
Modules named like: Gravity Capacitor Upgrade (8 of 8)
Implant: Serenity YC122.9 Season Booster - Probe Scanning Strength
Skill: Astrometric Rangefinding
Skill: Astrometrics
"""
@ -14321,7 +14320,7 @@ class Effect4358(BaseEffect):
ecmRangeBonusModuleEffect
Used by:
Modules from group: ECM Stabilizer (6 of 6)
Modules from group: ECM Stabilizer (3 of 3)
"""
type = 'passive'
@ -16093,7 +16092,7 @@ class Effect4809(BaseEffect):
ecmGravimetricStrengthBonusPercent
Used by:
Modules from group: ECM Stabilizer (6 of 6)
Modules from group: ECM Stabilizer (3 of 3)
"""
type = 'passive'
@ -16110,7 +16109,7 @@ class Effect4810(BaseEffect):
ecmLadarStrengthBonusPercent
Used by:
Modules from group: ECM Stabilizer (6 of 6)
Modules from group: ECM Stabilizer (3 of 3)
"""
type = 'passive'
@ -16127,7 +16126,7 @@ class Effect4811(BaseEffect):
ecmMagnetometricStrengthBonusPercent
Used by:
Modules from group: ECM Stabilizer (6 of 6)
Modules from group: ECM Stabilizer (3 of 3)
"""
type = 'passive'
@ -16145,7 +16144,7 @@ class Effect4812(BaseEffect):
ecmRadarStrengthBonusPercent
Used by:
Modules from group: ECM Stabilizer (6 of 6)
Modules from group: ECM Stabilizer (3 of 3)
"""
type = 'passive'
@ -16691,7 +16690,7 @@ class Effect4936(BaseEffect):
fueledShieldBoosting
Used by:
Modules from group: Ancillary Shield Booster (8 of 8)
Modules from group: Ancillary Shield Booster (9 of 9)
"""
runTime = 'late'
@ -18977,7 +18976,7 @@ class Effect5275(BaseEffect):
fueledArmorRepair
Used by:
Modules from group: Ancillary Armor Repairer (7 of 7)
Modules from group: Ancillary Armor Repairer (8 of 8)
"""
runTime = 'late'
@ -21730,39 +21729,6 @@ class Effect5673(BaseEffect):
skill='Interceptors', **kwargs)
class Effect5676(BaseEffect):
"""
shipBonusSmallMissileExplosionRadiusCD2
Used by:
Ship: Flycatcher
"""
type = 'passive'
@staticmethod
def handler(fit, ship, context, projectionRange, **kwargs):
fit.modules.filteredChargeBoost(
lambda mod: mod.charge.requiresSkill('Rockets') or mod.charge.requiresSkill('Light Missiles'),
'aoeCloudSize', ship.getModifiedItemAttr('shipBonusCD2'), skill='Caldari Destroyer', **kwargs)
class Effect5688(BaseEffect):
"""
shipBonusMissileVelocityAD2
Used by:
Ship: Heretic
"""
type = 'passive'
@staticmethod
def handler(fit, ship, context, projectionRange, **kwargs):
fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill('Missile Launcher Operation'),
'maxVelocity', ship.getModifiedItemAttr('shipBonusAD2'), skill='Amarr Destroyer', **kwargs)
class Effect5695(BaseEffect):
"""
eliteBonusInterdictorsArmorResist1
@ -21813,22 +21779,6 @@ class Effect5721(BaseEffect):
'maxRange', ship.getModifiedItemAttr('shipBonusRole7'), **kwargs)
class Effect5722(BaseEffect):
"""
shipHybridOptimalGD1
Used by:
Ship: Eris
"""
type = 'passive'
@staticmethod
def handler(fit, ship, context, projectionRange, **kwargs):
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill('Small Hybrid Turret'),
'maxRange', ship.getModifiedItemAttr('shipBonusGD1'), skill='Gallente Destroyer', **kwargs)
class Effect5723(BaseEffect):
"""
eliteBonusInterdictorsMWDSigRadius2
@ -22930,6 +22880,7 @@ class Effect5889(BaseEffect):
Used by:
Ships from group: Deep Space Transport (4 of 4)
Ships from group: Interceptor (4 of 10)
"""
type = 'passive'
@ -22946,6 +22897,7 @@ class Effect5890(BaseEffect):
Used by:
Ships from group: Deep Space Transport (4 of 4)
Ships from group: Interceptor (4 of 10)
"""
type = 'passive'
@ -23417,7 +23369,7 @@ class Effect5934(BaseEffect):
warpScrambleBlockMWDWithNPCEffect
Used by:
Modules named like: Warp Scrambler (27 of 27)
Modules named like: Warp Scrambler (28 of 28)
"""
runTime = 'early'
@ -23470,22 +23422,6 @@ class Effect5939(BaseEffect):
'speed', ship.getModifiedItemAttr('shipBonus2AF'), skill='Amarr Frigate', **kwargs)
class Effect5940(BaseEffect):
"""
eliteBonusInterdictorsSHTRoF1
Used by:
Ship: Eris
"""
type = 'passive'
@staticmethod
def handler(fit, ship, context, projectionRange, **kwargs):
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill('Small Hybrid Turret'),
'speed', ship.getModifiedItemAttr('eliteBonusInterdictors1'), skill='Interdictors', **kwargs)
class Effect5944(BaseEffect):
"""
shipMissileLauncherRoFAD1Fixed
@ -25147,7 +25083,7 @@ class Effect6187(BaseEffect):
energyNeutralizerFalloff
Used by:
Modules from group: Energy Neutralizer (54 of 54)
Modules from group: Energy Neutralizer (55 of 55)
"""
type = 'active', 'projected'
@ -25238,7 +25174,7 @@ class Effect6197(BaseEffect):
energyNosferatuFalloff
Used by:
Modules from group: Energy Nosferatu (54 of 54)
Modules from group: Energy Nosferatu (55 of 55)
"""
runTime = 'late'
@ -29081,7 +29017,7 @@ class Effect6582(BaseEffect):
moduleBonusSiegeModule
Used by:
Variations of module: Siege Module I (2 of 2)
Modules named like: Siege Module (3 of 3)
"""
runTime = 'early'
@ -31524,7 +31460,7 @@ class Effect6730(BaseEffect):
moduleBonusMicrowarpdrive
Used by:
Modules from group: Propulsion Module (68 of 133)
Modules from group: Propulsion Module (69 of 135)
"""
runTime = 'late'
@ -31548,7 +31484,7 @@ class Effect6731(BaseEffect):
moduleBonusAfterburner
Used by:
Modules from group: Propulsion Module (65 of 133)
Modules from group: Propulsion Module (66 of 135)
"""
runTime = 'late'
@ -37181,3 +37117,122 @@ class Effect8085(BaseEffect):
lambda mod: mod.item.requiresSkill('Fighters'),
'fighterAbilityMissilesExplosionRadius', container.getModifiedItemAttr('aoeCloudSizeMultiplier'),
stackingPenalties=True, penaltyGroup='postMul', **kwargs)
class Effect8091(BaseEffect):
"""
shipBonusForceAuxiliaryG2CapBoosterStrength
Used by:
Ship: Ninazu
"""
type = 'passive'
@staticmethod
def handler(fit, ship, context, projectionRange, **kwargs):
fit.modules.filteredChargeBoost(
lambda mod: mod.charge.group.name == 'Capacitor Booster Charge',
'capacitorBonus', ship.getModifiedItemAttr('shipBonusForceAuxiliaryG2'),
skill='Gallente Carrier', **kwargs)
class Effect8092(BaseEffect):
"""
shipBonusForceAuxiliaryM2CapBoosterStrength
Used by:
Ship: Lif
"""
type = 'passive'
@staticmethod
def handler(fit, ship, context, projectionRange, **kwargs):
fit.modules.filteredChargeBoost(
lambda mod: mod.charge.group.name == 'Capacitor Booster Charge',
'capacitorBonus', ship.getModifiedItemAttr('shipBonusForceAuxiliaryM2'),
skill='Minmatar Carrier', **kwargs)
class Effect8094(BaseEffect):
"""
shipBonusHybridROFGD1
Used by:
Ship: Eris
"""
type = 'passive'
@staticmethod
def handler(fit, ship, context, projectionRange, **kwargs):
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill('Small Hybrid Turret'),
'speed', ship.getModifiedItemAttr('shipBonusGD1'),
skill='Gallente Destroyer', **kwargs)
class Effect8095(BaseEffect):
"""
eliteBonusInterdictors1massAddition
Used by:
Ship: Eris
"""
type = 'passive'
@staticmethod
def handler(fit, ship, context, projectionRange, **kwargs):
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == 'Armor Plate',
'massAddition', ship.getModifiedItemAttr('eliteBonusInterdictors1'),
skill='Interdictors', **kwargs)
class Effect8096(BaseEffect):
"""
shipBonusKinMissileDamageCD2
Used by:
Ship: Flycatcher
"""
type = 'passive'
@staticmethod
def handler(fit, ship, context, projectionRange, **kwargs):
fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill('Missile Launcher Operation'),
'kineticDamage', ship.getModifiedItemAttr('shipBonusCD2'),
skill='Caldari Destroyer', **kwargs)
class Effect8097(BaseEffect):
"""
eliteBonusInterdictors1ShieldCapacity
Used by:
Ship: Flycatcher
"""
type = 'passive'
@staticmethod
def handler(fit, ship, context, projectionRange, **kwargs):
fit.ship.boostItemAttr('shieldCapacity', ship.getModifiedItemAttr('eliteBonusInterdictors1'),
skill='Interdictors', **kwargs)
class Effect8098(BaseEffect):
"""
shipBonusArmorHPAD2
Used by:
Ship: Heretic
"""
type = 'passive'
@staticmethod
def handler(fit, ship, context, projectionRange, **kwargs):
fit.ship.boostItemAttr('armorHP', ship.getModifiedItemAttr('shipBonusAD2'),
skill='Amarr Destroyer', **kwargs)

8
eos/gamedata.py

@ -344,7 +344,7 @@ class Item(EqBase):
try:
if (
self.category.categoryName == 'Structure' or
self.category.name == 'Structure' or
# Here until CCP puts their shit together
self.name in ("Thunderchild", "Stormbringer", "Skybreaker")
):
@ -423,7 +423,7 @@ class Item(EqBase):
def requiresSkill(self, skill, level=None):
for s, l in self.requiredSkills.items():
if isinstance(skill, str):
if s.name == skill and (level is None or l == level):
if s.typeName == skill and (level is None or l == level):
return True
elif isinstance(skill, int) and (level is None or l == level):
@ -506,8 +506,8 @@ class Item(EqBase):
return False
def __repr__(self):
return "Item(ID={}, name={}) at {}".format(
self.ID, self.name, hex(id(self))
return "Item(ID={}, name={}, display={}) at {}".format(
self.ID, self.typeName, self.name, hex(id(self))
)

2
eos/saveddata/character.py

@ -96,7 +96,7 @@ class Character:
if cls.__itemNameMap is None:
map = {}
for skill in cls.getSkillList():
map[skill.name] = skill
map[skill.typeName] = skill
cls.__itemNameMap = map

243
eos/saveddata/damagePattern.py

@ -25,122 +25,140 @@ from sqlalchemy.orm import reconstructor
import eos.db
def _t(x):
return x
def _c(x):
return '[' + x + ']'
# Order is significant here - UI uses order as-is for built-in patterns
BUILTINS = OrderedDict([
(-1, ('Uniform', 25, 25, 25, 25)),
(-2, ('[Generic]EM', 1, 0, 0, 0)),
(-3, ('[Generic]Thermal', 0, 1, 0, 0)),
(-4, ('[Generic]Kinetic', 0, 0, 1, 0)),
(-5, ('[Generic]Explosive', 0, 0, 0, 1)),
(-6, ('[Frequency Crystals]|[T2] Aurora', 5, 3, 0, 0)),
(-7, ('[Frequency Crystals]|[T2] Scorch', 9, 2, 0, 0)),
(-8, ('[Frequency Crystals]Radio', 5, 0, 0, 0)),
(-9, ('[Frequency Crystals]Microwave', 4, 2, 0, 0)),
(-10, ('[Frequency Crystals]Infrared', 5, 2, 0, 0)),
(-11, ('[Frequency Crystals]Standard', 5, 3, 0, 0)),
(-12, ('[Frequency Crystals]Ultraviolet', 6, 3, 0, 0)),
(-13, ('[Frequency Crystals]Xray', 6, 4, 0, 0)),
(-14, ('[Frequency Crystals]Gamma', 7, 4, 0, 0)),
(-15, ('[Frequency Crystals]Multifrequency', 7, 5, 0, 0)),
(-16, ('[Frequency Crystals]|[T2] Gleam', 7, 7, 0, 0)),
(-17, ('[Frequency Crystals]|[T2] Conflagration', 7.7, 7.7, 0, 0)),
(-1, (_t('Uniform'), 25, 25, 25, 25)),
(-2, (_c(_t('Generic')) + _t('EM'), 1, 0, 0, 0)),
(-3, (_c(_t('Generic')) + _t('Thermal'), 0, 1, 0, 0)),
(-4, (_c(_t('Generic')) + _t('Kinetic'), 0, 0, 1, 0)),
(-5, (_c(_t('Generic')) + _t('Explosive'), 0, 0, 0, 1)),
(-6, (_c(_t('Frequency Crystals')) + '|' + _t('[T2] Aurora'), 5, 3, 0, 0)),
(-7, (_c(_t('Frequency Crystals')) + '|' + _t('[T2] Scorch'), 9, 2, 0, 0)),
(-8, (_c(_t('Frequency Crystals')) + _t('Radio'), 5, 0, 0, 0)),
(-9, (_c(_t('Frequency Crystals')) + _t('Microwave'), 4, 2, 0, 0)),
(-10, (_c(_t('Frequency Crystals')) + _t('Infrared'), 5, 2, 0, 0)),
(-11, (_c(_t('Frequency Crystals')) + _t('Standard'), 5, 3, 0, 0)),
(-12, (_c(_t('Frequency Crystals')) + _t('Ultraviolet'), 6, 3, 0, 0)),
(-13, (_c(_t('Frequency Crystals')) + _t('Xray'), 6, 4, 0, 0)),
(-14, (_c(_t('Frequency Crystals')) + _t('Gamma'), 7, 4, 0, 0)),
(-15, (_c(_t('Frequency Crystals')) + _t('Multifrequency'), 7, 5, 0, 0)),
(-16, (_c(_t('Frequency Crystals')) + '|' + _t('[T2] Gleam'), 7, 7, 0, 0)),
(-17, (_c(_t('Frequency Crystals')) + '|' + _t('[T2] Conflagration'), 7.7, 7.7, 0, 0)),
# Different sizes of plasma do different damage ratios, the values here
# are average of ratios across sizes
(-18, ('[Exotic Plasma]|[T2] Mystic', 0, 66319, 0, 33681)),
(-19, ('[Exotic Plasma]Meson', 0, 60519, 0, 39481)),
(-20, ('[Exotic Plasma]Baryon', 0, 59737, 0, 40263)),
(-21, ('[Exotic Plasma]Tetryon', 0, 69208, 0, 30792)),
(-22, ('[Exotic Plasma]|[T2] Occult', 0, 55863, 0, 44137)),
(-23, ('[Hybrid Charges]|[T2] Spike', 0, 4, 4, 0)),
(-24, ('[Hybrid Charges]|[T2] Null', 0, 6, 5, 0)),
(-25, ('[Hybrid Charges]Iron', 0, 2, 3, 0)),
(-26, ('[Hybrid Charges]Tungsten', 0, 2, 4, 0)),
(-27, ('[Hybrid Charges]Iridium', 0, 3, 4, 0)),
(-28, ('[Hybrid Charges]Lead', 0, 3, 5, 0)),
(-29, ('[Hybrid Charges]Thorium', 0, 4, 5, 0)),
(-30, ('[Hybrid Charges]Uranium', 0, 4, 6, 0)),
(-31, ('[Hybrid Charges]Plutonium', 0, 5, 6, 0)),
(-32, ('[Hybrid Charges]Antimatter', 0, 5, 7, 0)),
(-33, ('[Hybrid Charges]|[T2] Javelin', 0, 8, 6, 0)),
(-34, ('[Hybrid Charges]|[T2] Void', 0, 7.7, 7.7, 0)),
(-35, ('[Projectile Ammo]|[T2] Tremor', 0, 0, 3, 5)),
(-36, ('[Projectile Ammo]|[T2] Barrage', 0, 0, 5, 6)),
(-37, ('[Projectile Ammo]Carbonized Lead', 0, 0, 4, 1)),
(-38, ('[Projectile Ammo]Nuclear', 0, 0, 1, 4)),
(-39, ('[Projectile Ammo]Proton', 3, 0, 2, 0)),
(-40, ('[Projectile Ammo]Depleted Uranium', 0, 3, 2, 3)),
(-41, ('[Projectile Ammo]Titanium Sabot', 0, 0, 6, 2)),
(-42, ('[Projectile Ammo]EMP', 9, 0, 1, 2)),
(-43, ('[Projectile Ammo]Phased Plasma', 0, 10, 2, 0)),
(-44, ('[Projectile Ammo]Fusion', 0, 0, 2, 10)),
(-45, ('[Projectile Ammo]|[T2] Quake', 0, 0, 5, 9)),
(-46, ('[Projectile Ammo]|[T2] Hail', 0, 0, 3.3, 12.1)),
(-47, ('[Missiles]Mjolnir', 1, 0, 0, 0)),
(-48, ('[Missiles]Inferno', 0, 1, 0, 0)),
(-49, ('[Missiles]Scourge', 0, 0, 1, 0)),
(-50, ('[Missiles]Nova', 0, 0, 0, 1)),
(-51, ('[Bombs]Electron Bomb', 6400, 0, 0, 0)),
(-52, ('[Bombs]Scorch Bomb', 0, 6400, 0, 0)),
(-53, ('[Bombs]Concussion Bomb', 0, 0, 6400, 0)),
(-54, ('[Bombs]Shrapnel Bomb', 0, 0, 0, 6400)),
# Source: ticket #2067
(-55, ('[NPC][Abyssal]All', 130, 396, 258, 216)),
(-56, ('[NPC][Abyssal]Drifter', 250, 250, 250, 250)),
(-57, ('[NPC][Abyssal]Drones', 250, 250, 250, 250)),
(-58, ('[NPC][Abyssal]Overmind', 0, 408, 592, 0)),
(-59, ('[NPC][Abyssal]Seeker', 406, 406, 94, 94)),
(-60, ('[NPC][Abyssal]Sleeper', 313, 313, 187, 187)),
(-61, ('[NPC][Abyssal]Triglavian', 0, 610, 0, 390)),
(-62, ('[NPC][Asteroid]Angel Cartel', 1838, 562, 2215, 3838)),
(-63, ('[NPC][Asteroid]Blood Raiders', 5067, 4214, 0, 0)),
(-64, ('[NPC][Asteroid]Guristas', 0, 1828, 7413, 0)),
(-65, ('[NPC][Asteroid]Rogue Drone', 394, 666, 1090, 1687)),
(-66, ('[NPC][Asteroid]Sanshas Nation', 5586, 4112, 0, 0)),
(-67, ('[NPC][Asteroid]Serpentis', 0, 5373, 4813, 0)),
(-68, ('[NPC][Burner]Cruor (Blood Raiders)', 90, 90, 0, 0)),
(-69, ('[NPC][Burner]Dramiel (Angel)', 55, 0, 20, 96)),
(-70, ('[NPC][Burner]Daredevil (Serpentis)', 0, 110, 154, 0)),
(-71, ('[NPC][Burner]Succubus (Sanshas Nation)', 135, 30, 0, 0)),
(-72, ('[NPC][Burner]Worm (Guristas)', 0, 0, 228, 0)),
(-73, ('[NPC][Burner]Enyo', 0, 147, 147, 0)),
(-74, ('[NPC][Burner]Hawk', 0, 0, 247, 0)),
(-75, ('[NPC][Burner]Jaguar', 36, 0, 50, 182)),
(-76, ('[NPC][Burner]Vengeance', 232, 0, 0, 0)),
(-77, ('[NPC][Burner]Ashimmu (Blood Raiders)', 260, 100, 0, 0)),
(-78, ('[NPC][Burner]Talos', 0, 413, 413, 0)),
(-79, ('[NPC][Burner]Sentinel', 0, 75, 0, 90)),
(-80, ('[NPC][Deadspace]Angel Cartel', 369, 533, 1395, 3302)),
(-81, ('[NPC][Deadspace]Blood Raiders', 6040, 5052, 10, 15)),
(-82, ('[NPC][Deadspace]Guristas', 0, 1531, 9680, 0)),
(-83, ('[NPC][Deadspace]Rogue Drone', 276, 1071, 1069, 871)),
(-84, ('[NPC][Deadspace]Sanshas Nation', 3009, 2237, 0, 0)),
(-85, ('[NPC][Deadspace]Serpentis', 0, 3110, 1929, 0)),
(-18, (_c(_t('Exotic Plasma')) + '|' + _t('[T2] Mystic'), 0, 66319, 0, 33681)),
(-19, (_c(_t('Exotic Plasma')) + _t('Meson'), 0, 60519, 0, 39481)),
(-20, (_c(_t('Exotic Plasma')) + _t('Baryon'), 0, 59737, 0, 40263)),
(-21, (_c(_t('Exotic Plasma')) + _t('Tetryon'), 0, 69208, 0, 30792)),
(-22, (_c(_t('Exotic Plasma')) + '|' + _t('[T2] Occult'), 0, 55863, 0, 44137)),
(-23, (_c(_t('Hybrid Charges')) + '|' + _t('[T2] Spike'), 0, 4, 4, 0)),
(-24, (_c(_t('Hybrid Charges')) + '|' + _t('[T2] Null'), 0, 6, 5, 0)),
(-25, (_c(_t('Hybrid Charges')) + _t('Iron'), 0, 2, 3, 0)),
(-26, (_c(_t('Hybrid Charges')) + _t('Tungsten'), 0, 2, 4, 0)),
(-27, (_c(_t('Hybrid Charges')) + _t('Iridium'), 0, 3, 4, 0)),
(-28, (_c(_t('Hybrid Charges')) + _t('Lead'), 0, 3, 5, 0)),
(-29, (_c(_t('Hybrid Charges')) + _t('Thorium'), 0, 4, 5, 0)),
(-30, (_c(_t('Hybrid Charges')) + _t('Uranium'), 0, 4, 6, 0)),
(-31, (_c(_t('Hybrid Charges')) + _t('Plutonium'), 0, 5, 6, 0)),
(-32, (_c(_t('Hybrid Charges')) + _t('Antimatter'), 0, 5, 7, 0)),
(-33, (_c(_t('Hybrid Charges')) + '|' + _t('[T2] Javelin'), 0, 8, 6, 0)),
(-34, (_c(_t('Hybrid Charges')) + '|' + _t('[T2] Void'), 0, 7.7, 7.7, 0)),
(-35, (_c(_t('Projectile Ammo')) + '|' + _t('[T2] Tremor'), 0, 0, 3, 5)),
(-36, (_c(_t('Projectile Ammo')) + '|' + _t('[T2] Barrage'), 0, 0, 5, 6)),
(-37, (_c(_t('Projectile Ammo')) + _t('Carbonized Lead'), 0, 0, 4, 1)),
(-38, (_c(_t('Projectile Ammo')) + _t('Nuclear'), 0, 0, 1, 4)),
(-39, (_c(_t('Projectile Ammo')) + _t('Proton'), 3, 0, 2, 0)),
(-40, (_c(_t('Projectile Ammo')) + _t('Depleted Uranium'), 0, 3, 2, 3)),
(-41, (_c(_t('Projectile Ammo')) + _t('Titanium Sabot'), 0, 0, 6, 2)),
(-42, (_c(_t('Projectile Ammo')) + _t('EMP'), 9, 0, 1, 2)),
(-43, (_c(_t('Projectile Ammo')) + _t('Phased Plasma'), 0, 10, 2, 0)),
(-44, (_c(_t('Projectile Ammo')) + _t('Fusion'), 0, 0, 2, 10)),
(-45, (_c(_t('Projectile Ammo')) + '|' + _t('[T2] Quake'), 0, 0, 5, 9)),
(-46, (_c(_t('Projectile Ammo')) + '|' + _t('[T2] Hail'), 0, 0, 3.3, 12.1)),
(-47, (_c(_t('Missiles')) + _t('Mjolnir'), 1, 0, 0, 0)),
(-48, (_c(_t('Missiles')) + _t('Inferno'), 0, 1, 0, 0)),
(-49, (_c(_t('Missiles')) + _t('Scourge'), 0, 0, 1, 0)),
(-50, (_c(_t('Missiles')) + _t('Nova'), 0, 0, 0, 1)),
(-51, (_c(_t('Bombs')) + _t('Electron Bomb'), 6400, 0, 0, 0)),
(-52, (_c(_t('Bombs')) + _t('Scorch Bomb'), 0, 6400, 0, 0)),
(-53, (_c(_t('Bombs')) + _t('Concussion Bomb'), 0, 0, 6400, 0)),
(-54, (_c(_t('Bombs')) + _t('Shrapnel Bomb'), 0, 0, 0, 6400)),
# Source: ticket #2067 and #2265
(-55, (_c(_t('NPC')) + _c(_t('Abyssal')) + _t('All'), 126, 427, 218, 230)),
(-109, (_c(_t('NPC')) + _c(_t('Abyssal')) + _t('Angel'), 450, 72, 80, 398)),
(-107, (_c(_t('NPC')) + _c(_t('Abyssal')) + _t('Concord'), 53, 559, 94, 295)),
(-56, (_c(_t('NPC')) + _c(_t('Abyssal')) + _t('Drifter'), 250, 250, 250, 250)),
(-57, (_c(_t('NPC')) + _c(_t('Abyssal')) + _t('Drones'), 250, 250, 250, 250)),
(-58, (_c(_t('NPC')) + _c(_t('Abyssal')) + _t('Overmind'), 0, 410, 590, 0)),
(-108, (_c(_t('NPC')) + _c(_t('Abyssal')) + _t('Sansha'), 569, 431, 0, 0)),
(-59, (_c(_t('NPC')) + _c(_t('Abyssal')) + _t('Seeker'), 402, 402, 98, 98)),
(-60, (_c(_t('NPC')) + _c(_t('Abyssal')) + _t('Sleeper'), 313, 313, 187, 187)),
(-61, (_c(_t('NPC')) + _c(_t('Abyssal')) + _t('Triglavian'), 0, 615, 0, 385)),
(-62, (_c(_t('NPC')) + _c(_t('Asteroid')) + _t('Angel Cartel'), 1838, 562, 2215, 3838)),
(-63, (_c(_t('NPC')) + _c(_t('Asteroid')) + _t('Blood Raiders'), 5067, 4214, 0, 0)),
(-64, (_c(_t('NPC')) + _c(_t('Asteroid')) + _t('Guristas'), 0, 1828, 7413, 0)),
(