Merge branch 'master' into ammo_graph
This commit is contained in:
403
db_update.py
403
db_update.py
@@ -32,7 +32,7 @@ DB_PATH = os.path.join(ROOT_DIR, 'eve.db')
|
||||
JSON_DIR = os.path.join(ROOT_DIR, 'staticdata')
|
||||
if ROOT_DIR not in sys.path:
|
||||
sys.path.insert(0, ROOT_DIR)
|
||||
GAMEDATA_SCHEMA_VERSION = 1
|
||||
GAMEDATA_SCHEMA_VERSION = 3
|
||||
|
||||
|
||||
def db_needs_update():
|
||||
@@ -88,52 +88,164 @@ def update_db():
|
||||
# Create the database tables
|
||||
eos.db.gamedata_meta.create_all()
|
||||
|
||||
# Config dict
|
||||
tables = {
|
||||
'clonegrades': ('fsd_lite', eos.gamedata.AlphaCloneSkill),
|
||||
'dogmaattributes': ('bulkdata', eos.gamedata.AttributeInfo),
|
||||
'dogmaeffects': ('bulkdata', eos.gamedata.Effect),
|
||||
'dogmatypeattributes': ('bulkdata', eos.gamedata.Attribute),
|
||||
'dogmatypeeffects': ('bulkdata', eos.gamedata.ItemEffect),
|
||||
'dogmaunits': ('bulkdata', eos.gamedata.Unit),
|
||||
'evecategories': ('fsd_lite', eos.gamedata.Category),
|
||||
'evegroups': ('fsd_lite', eos.gamedata.Group),
|
||||
'metagroups': ('fsd_binary', eos.gamedata.MetaGroup),
|
||||
'evetypes': ('fsd_lite', eos.gamedata.Item),
|
||||
'traits': ('phobos', eos.gamedata.Traits),
|
||||
'metadata': ('phobos', eos.gamedata.MetaData),
|
||||
'marketgroups': ('fsd_binary', eos.gamedata.MarketGroup)}
|
||||
def _readData(minerName, jsonName, keyIdName=None):
|
||||
with open(os.path.join(JSON_DIR, minerName, '{}.json'.format(jsonName)), encoding='utf-8') as f:
|
||||
rawData = json.load(f)
|
||||
if not keyIdName:
|
||||
return rawData
|
||||
# IDs in keys, rows in values
|
||||
data = []
|
||||
for k, v in rawData.items():
|
||||
row = {}
|
||||
row.update(v)
|
||||
if keyIdName not in row:
|
||||
row[keyIdName] = int(k)
|
||||
data.append(row)
|
||||
return data
|
||||
|
||||
fieldMapping = {
|
||||
'marketgroups': {
|
||||
'id': 'marketGroupID',
|
||||
'name': 'marketGroupName'},
|
||||
'metagroups': {
|
||||
'id': 'metaGroupID'}}
|
||||
def _addRows(data, cls, fieldMap=None):
|
||||
if fieldMap is None:
|
||||
fieldMap = {}
|
||||
for row in data:
|
||||
instance = cls()
|
||||
for k, v in row.items():
|
||||
if isinstance(v, str):
|
||||
v = v.strip()
|
||||
setattr(instance, fieldMap.get(k, k), v)
|
||||
eos.db.gamedata_session.add(instance)
|
||||
|
||||
rowsInValues = (
|
||||
'evetypes',
|
||||
'evegroups',
|
||||
'evecategories',
|
||||
'marketgroups',
|
||||
'metagroups')
|
||||
def processEveTypes():
|
||||
print('processing evetypes')
|
||||
data = _readData('fsd_lite', 'evetypes', keyIdName='typeID')
|
||||
for row in data:
|
||||
if (
|
||||
# Apparently people really want Civilian modules available
|
||||
(row['typeName'].startswith('Civilian') and "Shuttle" not in row['typeName']) or
|
||||
row['typeName'] in ('Capsule', 'Dark Blood Tracking Disruptor')
|
||||
):
|
||||
row['published'] = True
|
||||
|
||||
def convertIcons(data):
|
||||
new = []
|
||||
for k, v in list(data.items()):
|
||||
v['iconID'] = k
|
||||
new.append(v)
|
||||
return new
|
||||
|
||||
def convertClones(data):
|
||||
newData = []
|
||||
for row in data:
|
||||
if (
|
||||
row['published'] or
|
||||
# group Ship Modifiers, for items like tactical t3 ship modes
|
||||
row['groupID'] == 1306 or
|
||||
# Micro Bombs (Fighters)
|
||||
row['typeID'] in (41549, 41548, 41551, 41550) or
|
||||
# Abyssal weather (environment)
|
||||
row['groupID'] in (
|
||||
1882,
|
||||
1975,
|
||||
1971,
|
||||
# the "container" for the abyssal environments
|
||||
1983)
|
||||
):
|
||||
newData.append(row)
|
||||
|
||||
_addRows(newData, eos.gamedata.Item)
|
||||
return newData
|
||||
|
||||
def processEveGroups():
|
||||
print('processing evegroups')
|
||||
data = _readData('fsd_lite', 'evegroups', keyIdName='groupID')
|
||||
_addRows(data, eos.gamedata.Group)
|
||||
return data
|
||||
|
||||
def processEveCategories():
|
||||
print('processing evecategories')
|
||||
data = _readData('fsd_lite', 'evecategories', keyIdName='categoryID')
|
||||
_addRows(data, eos.gamedata.Category)
|
||||
|
||||
def processDogmaAttributes():
|
||||
print('processing dogmaattributes')
|
||||
data = _readData('fsd_binary', 'dogmaattributes', keyIdName='attributeID')
|
||||
_addRows(data, eos.gamedata.AttributeInfo)
|
||||
|
||||
def processDogmaTypeAttributes(eveTypesData):
|
||||
print('processing dogmatypeattributes')
|
||||
data = _readData('fsd_binary', 'typedogma', keyIdName='typeID')
|
||||
eveTypeIds = set(r['typeID'] for r in eveTypesData)
|
||||
newData = []
|
||||
for row in eveTypesData:
|
||||
for attrId, attrName in {4: 'mass', 38: 'capacity', 161: 'volume', 162: 'radius'}.items():
|
||||
if attrName in row:
|
||||
newData.append({'typeID': row['typeID'], 'attributeID': attrId, 'value': row[attrName]})
|
||||
for typeData in data:
|
||||
if typeData['typeID'] not in eveTypeIds:
|
||||
continue
|
||||
for row in typeData.get('dogmaAttributes', ()):
|
||||
row['typeID'] = typeData['typeID']
|
||||
newData.append(row)
|
||||
_addRows(newData, eos.gamedata.Attribute)
|
||||
return newData
|
||||
|
||||
def processDynamicItemAttributes():
|
||||
print('processing dynamicitemattributes')
|
||||
data = _readData('fsd_binary', 'dynamicitemattributes')
|
||||
for mutaID, mutaData in data.items():
|
||||
muta = eos.gamedata.DynamicItem()
|
||||
muta.typeID = mutaID
|
||||
muta.resultingTypeID = mutaData['inputOutputMapping'][0]['resultingType']
|
||||
eos.db.gamedata_session.add(muta)
|
||||
|
||||
for x in mutaData['inputOutputMapping'][0]['applicableTypes']:
|
||||
item = eos.gamedata.DynamicItemItem()
|
||||
item.typeID = mutaID
|
||||
item.applicableTypeID = x
|
||||
eos.db.gamedata_session.add(item)
|
||||
|
||||
for attrID, attrData in mutaData['attributeIDs'].items():
|
||||
attr = eos.gamedata.DynamicItemAttribute()
|
||||
attr.typeID = mutaID
|
||||
attr.attributeID = attrID
|
||||
attr.min = attrData['min']
|
||||
attr.max = attrData['max']
|
||||
eos.db.gamedata_session.add(attr)
|
||||
|
||||
def processDogmaEffects():
|
||||
print('processing dogmaeffects')
|
||||
data = _readData('fsd_binary', 'dogmaeffects', keyIdName='effectID')
|
||||
_addRows(data, eos.gamedata.Effect, fieldMap={'resistanceAttributeID': 'resistanceID'})
|
||||
|
||||
def processDogmaTypeEffects(eveTypesData):
|
||||
print('processing dogmatypeeffects')
|
||||
data = _readData('fsd_binary', 'typedogma', keyIdName='typeID')
|
||||
eveTypeIds = set(r['typeID'] for r in eveTypesData)
|
||||
newData = []
|
||||
for typeData in data:
|
||||
if typeData['typeID'] not in eveTypeIds:
|
||||
continue
|
||||
for row in typeData.get('dogmaEffects', ()):
|
||||
row['typeID'] = typeData['typeID']
|
||||
newData.append(row)
|
||||
_addRows(newData, eos.gamedata.ItemEffect)
|
||||
return newData
|
||||
|
||||
def processDogmaUnits():
|
||||
print('processing dogmaunits')
|
||||
data = _readData('fsd_binary', 'dogmaunits', keyIdName='unitID')
|
||||
_addRows(data, eos.gamedata.Unit, fieldMap={'name': 'unitName'})
|
||||
|
||||
def processMarketGroups():
|
||||
print('processing marketgroups')
|
||||
data = _readData('fsd_binary', 'marketgroups', keyIdName='marketGroupID')
|
||||
_addRows(data, eos.gamedata.MarketGroup, fieldMap={'name': 'marketGroupName'})
|
||||
|
||||
def processMetaGroups():
|
||||
print('processing metagroups')
|
||||
data = _readData('fsd_binary', 'metagroups', keyIdName='metaGroupID')
|
||||
_addRows(data, eos.gamedata.MetaGroup)
|
||||
|
||||
def processCloneGrades():
|
||||
print('processing clonegrades')
|
||||
data = _readData('fsd_lite', 'clonegrades')
|
||||
|
||||
newData = []
|
||||
# December, 2017 - CCP decided to use only one set of skill levels for alpha clones. However, this is still
|
||||
# represented in the data as a skillset per race. To ensure that all skills are the same, we store them in a way
|
||||
# that we can check to make sure all races have the same skills, as well as skill levels
|
||||
|
||||
check = {}
|
||||
|
||||
for ID in data:
|
||||
for skill in data[ID]['skills']:
|
||||
newData.append({
|
||||
@@ -144,18 +256,25 @@ def update_db():
|
||||
if ID not in check:
|
||||
check[ID] = {}
|
||||
check[ID][int(skill['typeID'])] = int(skill['level'])
|
||||
|
||||
if not functools.reduce(lambda a, b: a if a == b else False, [v for _, v in check.items()]):
|
||||
raise Exception('Alpha Clones not all equal')
|
||||
|
||||
newData = [x for x in newData if x['alphaCloneID'] == 1]
|
||||
|
||||
if len(newData) == 0:
|
||||
raise Exception('Alpha Clone processing failed')
|
||||
|
||||
return newData
|
||||
tmp = []
|
||||
for row in newData:
|
||||
if row['alphaCloneID'] not in tmp:
|
||||
cloneParent = eos.gamedata.AlphaClone()
|
||||
setattr(cloneParent, 'alphaCloneID', row['alphaCloneID'])
|
||||
setattr(cloneParent, 'alphaCloneName', row['alphaCloneName'])
|
||||
eos.db.gamedata_session.add(cloneParent)
|
||||
tmp.append(row['alphaCloneID'])
|
||||
_addRows(newData, eos.gamedata.AlphaCloneSkill)
|
||||
|
||||
def convertTraits(data):
|
||||
def processTraits():
|
||||
print('processing traits')
|
||||
data = _readData('phobos', 'traits')
|
||||
|
||||
def convertSection(sectionData):
|
||||
sectionLines = []
|
||||
@@ -182,9 +301,42 @@ def update_db():
|
||||
traitLine = '<br />\n<br />\n'.join(typeLines)
|
||||
newRow = {'typeID': typeId, 'traitText': traitLine}
|
||||
newData.append(newRow)
|
||||
return newData
|
||||
|
||||
def fillReplacements(tables):
|
||||
_addRows(newData, eos.gamedata.Traits)
|
||||
|
||||
def processMetadata():
|
||||
print('processing metadata')
|
||||
data = _readData('phobos', 'metadata')
|
||||
_addRows(data, eos.gamedata.MetaData)
|
||||
|
||||
def processReqSkills(eveTypesData):
|
||||
print('processing requiredskillsfortypes')
|
||||
|
||||
def composeReqSkills(raw):
|
||||
reqSkills = {}
|
||||
for skillTypeID, skillLevels in raw.items():
|
||||
reqSkills[int(skillTypeID)] = skillLevels[0]
|
||||
return reqSkills
|
||||
|
||||
eveTypeIds = set(r['typeID'] for r in eveTypesData)
|
||||
data = _readData('fsd_binary', 'requiredskillsfortypes')
|
||||
reqsByItem = {}
|
||||
itemsByReq = {}
|
||||
for typeID, skillreqData in data.items():
|
||||
typeID = int(typeID)
|
||||
if typeID not in eveTypeIds:
|
||||
continue
|
||||
for skillTypeID, skillLevel in composeReqSkills(skillreqData).items():
|
||||
reqsByItem.setdefault(typeID, {})[skillTypeID] = skillLevel
|
||||
itemsByReq.setdefault(skillTypeID, {})[typeID] = skillLevel
|
||||
for item in eos.db.gamedata_session.query(eos.gamedata.Item).all():
|
||||
if item.typeID in reqsByItem:
|
||||
item.reqskills = json.dumps(reqsByItem[item.typeID])
|
||||
if item.typeID in itemsByReq:
|
||||
item.requiredfor = json.dumps(itemsByReq[item.typeID])
|
||||
|
||||
def processReplacements(eveTypesData, eveGroupsData, dogmaTypeAttributesData, dogmaTypeEffectsData):
|
||||
print('finding item replacements')
|
||||
|
||||
def compareAttrs(attrs1, attrs2):
|
||||
# Consider items as different if they have no attrs
|
||||
@@ -196,7 +348,6 @@ def update_db():
|
||||
return True
|
||||
return False
|
||||
|
||||
print('finding replacements')
|
||||
skillReqAttribs = {
|
||||
182: 277,
|
||||
183: 278,
|
||||
@@ -208,18 +359,18 @@ def update_db():
|
||||
# Get data on type groups
|
||||
# Format: {type ID: group ID}
|
||||
typesGroups = {}
|
||||
for row in tables['evetypes']:
|
||||
for row in eveTypesData:
|
||||
typesGroups[row['typeID']] = row['groupID']
|
||||
# Get data on item effects
|
||||
# Format: {type ID: set(effect, IDs)}
|
||||
typesEffects = {}
|
||||
for row in tables['dogmatypeeffects']:
|
||||
for row in dogmaTypeEffectsData:
|
||||
typesEffects.setdefault(row['typeID'], set()).add(row['effectID'])
|
||||
# Get data on type attributes
|
||||
# Format: {type ID: {attribute ID: attribute value}}
|
||||
typesNormalAttribs = {}
|
||||
typesSkillAttribs = {}
|
||||
for row in tables['dogmatypeattributes']:
|
||||
for row in dogmaTypeAttributesData:
|
||||
attributeID = row['attributeID']
|
||||
if attributeID in skillReqAttribsFlat:
|
||||
typeSkillAttribs = typesSkillAttribs.setdefault(row['typeID'], {})
|
||||
@@ -258,13 +409,13 @@ def update_db():
|
||||
typeSkillReqs[skillType] = skillLevel
|
||||
# Format: {group ID: category ID}
|
||||
groupCategories = {}
|
||||
for row in tables['evegroups']:
|
||||
for row in eveGroupsData:
|
||||
groupCategories[row['groupID']] = row['categoryID']
|
||||
# As EVE affects various types mostly depending on their group or skill requirements,
|
||||
# we're going to group various types up this way
|
||||
# Format: {(group ID, frozenset(skillreq, type, IDs), frozenset(type, effect, IDs): [type ID, {attribute ID: attribute value}]}
|
||||
groupedData = {}
|
||||
for row in tables['evetypes']:
|
||||
for row in eveTypesData:
|
||||
typeID = row['typeID']
|
||||
# Ignore items outside of categories we need
|
||||
if groupCategories[typesGroups[typeID]] not in (
|
||||
@@ -301,134 +452,30 @@ def update_db():
|
||||
if compareAttrs(type1[1], type2[1]):
|
||||
replacements.setdefault(type1[0], set()).add(type2[0])
|
||||
replacements.setdefault(type2[0], set()).add(type1[0])
|
||||
# Put this data into types table so that normal process hooks it up
|
||||
for row in tables['evetypes']:
|
||||
row['replacements'] = ','.join('{}'.format(tid) for tid in sorted(replacements.get(row['typeID'], ())))
|
||||
# Update DB session with data we generated
|
||||
for item in eos.db.gamedata_session.query(eos.gamedata.Item).all():
|
||||
itemReplacements = replacements.get(item.typeID)
|
||||
if itemReplacements is not None:
|
||||
item.replacements = ','.join('{}'.format(tid) for tid in sorted(itemReplacements))
|
||||
|
||||
data = {}
|
||||
eveTypesData = processEveTypes()
|
||||
eveGroupsData = processEveGroups()
|
||||
processEveCategories()
|
||||
processDogmaAttributes()
|
||||
dogmaTypeAttributesData = processDogmaTypeAttributes(eveTypesData)
|
||||
processDynamicItemAttributes()
|
||||
processDogmaEffects()
|
||||
dogmaTypeEffectsData = processDogmaTypeEffects(eveTypesData)
|
||||
processDogmaUnits()
|
||||
processMarketGroups()
|
||||
processMetaGroups()
|
||||
processCloneGrades()
|
||||
processTraits()
|
||||
processMetadata()
|
||||
|
||||
# Dump all data to memory so we can easely cross check ignored rows
|
||||
for jsonName, (minerName, cls) in tables.items():
|
||||
with open(os.path.join(JSON_DIR, minerName, '{}.json'.format(jsonName)), encoding='utf-8') as f:
|
||||
tableData = json.load(f)
|
||||
if jsonName in rowsInValues:
|
||||
newTableData = []
|
||||
for k, v in tableData.items():
|
||||
row = {}
|
||||
row.update(v)
|
||||
if 'id' not in row:
|
||||
row['id'] = int(k)
|
||||
newTableData.append(row)
|
||||
tableData = newTableData
|
||||
if jsonName == 'icons':
|
||||
tableData = convertIcons(tableData)
|
||||
if jsonName == 'traits':
|
||||
tableData = convertTraits(tableData)
|
||||
if jsonName == 'clonegrades':
|
||||
tableData = convertClones(tableData)
|
||||
data[jsonName] = tableData
|
||||
|
||||
fillReplacements(data)
|
||||
|
||||
# Set with typeIDs which we will have in our database
|
||||
# Sometimes CCP unpublishes some items we want to have published, we
|
||||
# can do it here - just add them to initial set
|
||||
eveTypes = set()
|
||||
for row in data['evetypes']:
|
||||
if (
|
||||
row['published'] or
|
||||
row['typeName'] == 'Capsule' or
|
||||
# group Ship Modifiers, for items like tactical t3 ship modes
|
||||
row['groupID'] == 1306 or
|
||||
# Civilian weapons
|
||||
(row['typeName'].startswith('Civilian') and "Shuttle" not in row['typeName']) or
|
||||
# Micro Bombs (Fighters)
|
||||
row['typeID'] in (41549, 41548, 41551, 41550) or
|
||||
# Abyssal weather (environment)
|
||||
row['groupID'] in (
|
||||
1882,
|
||||
1975,
|
||||
1971,
|
||||
# the "container" for the abyssal environments
|
||||
1983) or
|
||||
# Dark Blood Tracking Disruptor (drops, but rarely)
|
||||
row['typeID'] == 32416
|
||||
):
|
||||
eveTypes.add(row['typeID'])
|
||||
|
||||
# ignore checker
|
||||
def isIgnored(file, row):
|
||||
if file in ('evetypes', 'dogmatypeeffects', 'dogmatypeattributes') and row['typeID'] not in eveTypes:
|
||||
return True
|
||||
return False
|
||||
|
||||
# Loop through each json file and write it away, checking ignored rows
|
||||
for jsonName, table in data.items():
|
||||
fieldMap = fieldMapping.get(jsonName, {})
|
||||
tmp = []
|
||||
|
||||
print('processing {}'.format(jsonName))
|
||||
|
||||
for row in table:
|
||||
# We don't care about some kind of rows, filter it out if so
|
||||
if not isIgnored(jsonName, row):
|
||||
if (
|
||||
jsonName == 'evetypes' and (
|
||||
# Apparently people really want Civilian modules available
|
||||
(row['typeName'].startswith('Civilian') and "Shuttle" not in row['typeName']) or
|
||||
row['typeName'] in ('Capsule', 'Dark Blood Tracking Disruptor'))
|
||||
):
|
||||
row['published'] = True
|
||||
|
||||
instance = tables[jsonName][1]()
|
||||
# fix for issue 80
|
||||
if jsonName is 'icons' and 'res:/ui/texture/icons/' in str(row['iconFile']).lower():
|
||||
row['iconFile'] = row['iconFile'].lower().replace('res:/ui/texture/icons/', '').replace('.png', '')
|
||||
# with res:/ui... references, it points to the actual icon file (including it's size variation of #_size_#)
|
||||
# strip this info out and get the identifying info
|
||||
split = row['iconFile'].split('_')
|
||||
if len(split) == 3:
|
||||
row['iconFile'] = '{}_{}'.format(split[0], split[2])
|
||||
if jsonName is 'icons' and 'modules/' in str(row['iconFile']).lower():
|
||||
row['iconFile'] = row['iconFile'].lower().replace('modules/', '').replace('.png', '')
|
||||
|
||||
if jsonName is 'clonegrades':
|
||||
if row['alphaCloneID'] not in tmp:
|
||||
cloneParent = eos.gamedata.AlphaClone()
|
||||
setattr(cloneParent, 'alphaCloneID', row['alphaCloneID'])
|
||||
setattr(cloneParent, 'alphaCloneName', row['alphaCloneName'])
|
||||
eos.db.gamedata_session.add(cloneParent)
|
||||
tmp.append(row['alphaCloneID'])
|
||||
|
||||
for k, v in row.items():
|
||||
if isinstance(v, str):
|
||||
v = v.strip()
|
||||
setattr(instance, fieldMap.get(k, k), v)
|
||||
|
||||
eos.db.gamedata_session.add(instance)
|
||||
|
||||
# quick and dirty hack to get this data in
|
||||
with open(os.path.join(JSON_DIR, 'fsd_binary', 'dynamicitemattributes.json'), encoding='utf-8') as f:
|
||||
bulkdata = json.load(f)
|
||||
for mutaID, data in bulkdata.items():
|
||||
muta = eos.gamedata.DynamicItem()
|
||||
muta.typeID = mutaID
|
||||
muta.resultingTypeID = data['inputOutputMapping'][0]['resultingType']
|
||||
eos.db.gamedata_session.add(muta)
|
||||
|
||||
for x in data['inputOutputMapping'][0]['applicableTypes']:
|
||||
item = eos.gamedata.DynamicItemItem()
|
||||
item.typeID = mutaID
|
||||
item.applicableTypeID = x
|
||||
eos.db.gamedata_session.add(item)
|
||||
|
||||
for attrID, attrData in data['attributeIDs'].items():
|
||||
attr = eos.gamedata.DynamicItemAttribute()
|
||||
attr.typeID = mutaID
|
||||
attr.attributeID = attrID
|
||||
attr.min = attrData['min']
|
||||
attr.max = attrData['max']
|
||||
eos.db.gamedata_session.add(attr)
|
||||
eos.db.gamedata_session.flush()
|
||||
processReqSkills(eveTypesData)
|
||||
processReplacements(eveTypesData, eveGroupsData, dogmaTypeAttributesData, dogmaTypeEffectsData)
|
||||
|
||||
# Add schema version to prevent further updates
|
||||
metadata_schema_version = eos.gamedata.MetaData()
|
||||
@@ -436,7 +483,7 @@ def update_db():
|
||||
metadata_schema_version.field_value = GAMEDATA_SCHEMA_VERSION
|
||||
eos.db.gamedata_session.add(metadata_schema_version)
|
||||
|
||||
eos.db.gamedata_session.commit()
|
||||
eos.db.gamedata_session.flush()
|
||||
|
||||
# CCP still has 5 subsystems assigned to T3Cs, even though only 4 are available / usable. They probably have some
|
||||
# old legacy requirement or assumption that makes it difficult for them to change this value in the data. But for
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
# This apes hook-matplotlib.backends.py, but REMOVES backends, all but
|
||||
# the ones in the list below.
|
||||
# Courtesy of https://github.com/bpteague/cytoflow/blob/70f9291/packaging/hook-matplotlib.backends.py
|
||||
|
||||
KEEP = ["WXAgg", "WX", "agg"]
|
||||
|
||||
from PyInstaller.compat import is_darwin
|
||||
from PyInstaller.utils.hooks import (
|
||||
eval_statement, exec_statement, logger)
|
||||
|
||||
|
||||
def get_matplotlib_backend_module_names():
|
||||
"""
|
||||
List the names of all matplotlib backend modules importable under the
|
||||
current Python installation.
|
||||
Returns
|
||||
----------
|
||||
list
|
||||
List of the fully-qualified names of all such modules.
|
||||
"""
|
||||
# Statement safely importing a single backend module.
|
||||
import_statement = """
|
||||
import os, sys
|
||||
# Preserve stdout.
|
||||
sys_stdout = sys.stdout
|
||||
try:
|
||||
# Redirect output printed by this importation to "/dev/null", preventing
|
||||
# such output from being erroneously interpreted as an error.
|
||||
with open(os.devnull, 'w') as dev_null:
|
||||
sys.stdout = dev_null
|
||||
__import__('%s')
|
||||
# If this is an ImportError, print this exception's message without a traceback.
|
||||
# ImportError messages are human-readable and require no additional context.
|
||||
except ImportError as exc:
|
||||
sys.stdout = sys_stdout
|
||||
print(exc)
|
||||
# Else, print this exception preceded by a traceback. traceback.print_exc()
|
||||
# prints to stderr rather than stdout and must not be called here!
|
||||
except Exception:
|
||||
sys.stdout = sys_stdout
|
||||
import traceback
|
||||
print(traceback.format_exc())
|
||||
"""
|
||||
|
||||
# List of the human-readable names of all available backends.
|
||||
backend_names = eval_statement(
|
||||
'import matplotlib; print(matplotlib.rcsetup.all_backends)')
|
||||
|
||||
# List of the fully-qualified names of all importable backend modules.
|
||||
module_names = []
|
||||
|
||||
# If the current system is not OS X and the "CocoaAgg" backend is available,
|
||||
# remove this backend from consideration. Attempting to import this backend
|
||||
# on non-OS X systems halts the current subprocess without printing output
|
||||
# or raising exceptions, preventing its reliable detection.
|
||||
if not is_darwin and 'CocoaAgg' in backend_names:
|
||||
backend_names.remove('CocoaAgg')
|
||||
|
||||
# For safety, attempt to import each backend in a unique subprocess.
|
||||
for backend_name in backend_names:
|
||||
if backend_name in KEEP:
|
||||
continue
|
||||
|
||||
module_name = 'matplotlib.backends.backend_%s' % backend_name.lower()
|
||||
stdout = exec_statement(import_statement % module_name)
|
||||
|
||||
# If no output was printed, this backend is importable.
|
||||
if not stdout:
|
||||
module_names.append(module_name)
|
||||
logger.info(' Matplotlib backend "%s": removed' % backend_name)
|
||||
|
||||
return module_names
|
||||
|
||||
# Freeze all importable backends, as PyInstaller is unable to determine exactly
|
||||
# which backends are required by the current program.
|
||||
e=get_matplotlib_backend_module_names()
|
||||
print(e)
|
||||
excludedimports = e
|
||||
@@ -44,7 +44,9 @@ items_table = Table("invtypes", gamedata_meta,
|
||||
Column("metaLevel", Integer),
|
||||
Column("metaGroupID", Integer, ForeignKey("invmetagroups.metaGroupID"), index=True),
|
||||
Column("variationParentTypeID", Integer, ForeignKey("invtypes.typeID"), index=True),
|
||||
Column("replacements", String))
|
||||
Column("replacements", String),
|
||||
Column("reqskills", String),
|
||||
Column("requiredfor", String))
|
||||
|
||||
from .traits import traits_table # noqa
|
||||
|
||||
|
||||
@@ -424,25 +424,3 @@ def getDynamicItem(itemID, eager=None):
|
||||
except exc.NoResultFound:
|
||||
result = None
|
||||
return result
|
||||
|
||||
|
||||
def getRequiredFor(itemID, attrMapping):
|
||||
Attribute1 = aliased(Attribute)
|
||||
Attribute2 = aliased(Attribute)
|
||||
|
||||
skillToLevelClauses = []
|
||||
|
||||
for attrSkill, attrLevel in attrMapping.items():
|
||||
skillToLevelClauses.append(and_(Attribute1.attributeID == attrSkill, Attribute2.attributeID == attrLevel))
|
||||
|
||||
queryOr = or_(*skillToLevelClauses)
|
||||
|
||||
q = select((Attribute2.typeID, Attribute2.value),
|
||||
and_(Attribute1.value == itemID, queryOr),
|
||||
from_obj=[
|
||||
join(Attribute1, Attribute2, Attribute1.typeID == Attribute2.typeID)
|
||||
])
|
||||
|
||||
result = gamedata_session.execute(q).fetchall()
|
||||
|
||||
return result
|
||||
|
||||
@@ -8,43 +8,25 @@ many upgrade files as there are database versions (version 5 would include
|
||||
upgrade files 1-5)
|
||||
"""
|
||||
|
||||
import pkgutil
|
||||
import re
|
||||
|
||||
from eos.utils.pyinst_support import iterNamespace
|
||||
|
||||
updates = {}
|
||||
appVersion = 0
|
||||
|
||||
prefix = __name__ + "."
|
||||
|
||||
# load modules to work based with and without pyinstaller
|
||||
# from: https://github.com/webcomics/dosage/blob/master/dosagelib/loader.py
|
||||
# see: https://github.com/pyinstaller/pyinstaller/issues/1905
|
||||
|
||||
# load modules using iter_modules()
|
||||
# (should find all filters in normal build, but not pyinstaller)
|
||||
module_names = [m[1] for m in pkgutil.iter_modules(__path__, prefix)]
|
||||
|
||||
# special handling for PyInstaller
|
||||
importers = map(pkgutil.get_importer, __path__)
|
||||
toc = set()
|
||||
for i in importers:
|
||||
if hasattr(i, 'toc'):
|
||||
toc |= i.toc
|
||||
|
||||
for elm in toc:
|
||||
if elm.startswith(prefix):
|
||||
module_names.append(elm)
|
||||
|
||||
for modname in module_names:
|
||||
for modName in iterNamespace(__name__, __path__):
|
||||
# loop through python files, extracting update number and function, and
|
||||
# adding it to a list
|
||||
modname_tail = modname.rsplit('.', 1)[-1]
|
||||
module = __import__(modname, fromlist=True)
|
||||
modname_tail = modName.rsplit('.', 1)[-1]
|
||||
m = re.match("^upgrade(?P<index>\d+)$", modname_tail)
|
||||
if not m:
|
||||
continue
|
||||
index = int(m.group("index"))
|
||||
appVersion = max(appVersion, index)
|
||||
module = __import__(modName, fromlist=True)
|
||||
upgrade = getattr(module, "upgrade", False)
|
||||
if upgrade:
|
||||
updates[index] = upgrade
|
||||
|
||||
@@ -280,6 +280,17 @@ class Effect51(BaseEffect):
|
||||
fit.ship.multiplyItemAttr('rechargeRate', module.getModifiedItemAttr('capacitorRechargeRateMultiplier'), **kwargs)
|
||||
|
||||
|
||||
class Effect54(BaseEffect):
|
||||
"""
|
||||
targetPassively
|
||||
|
||||
Used by:
|
||||
Modules from group: Passive Targeting System (6 of 6)
|
||||
"""
|
||||
|
||||
type = 'active'
|
||||
|
||||
|
||||
class Effect55(BaseEffect):
|
||||
"""
|
||||
targetHostiles
|
||||
@@ -1751,9 +1762,10 @@ class Effect598(BaseEffect):
|
||||
ammoSpeedMultiplier
|
||||
|
||||
Used by:
|
||||
Charges from group: Festival Charges (28 of 28)
|
||||
Charges from group: Festival Charges (27 of 28)
|
||||
Charges from group: Interdiction Probe (2 of 2)
|
||||
Items from market group: Special Edition Assets > Special Edition Festival Assets (32 of 35)
|
||||
Charges from group: Structure Festival Charges (2 of 2)
|
||||
Special Edition Assetss from group: Festival Charges Expired (4 of 4)
|
||||
"""
|
||||
|
||||
type = 'passive'
|
||||
@@ -6808,7 +6820,10 @@ class Effect2298(BaseEffect):
|
||||
scanStrengthBonusPercentPassive
|
||||
|
||||
Used by:
|
||||
Implants named like: High grade (20 of 66)
|
||||
Implants named like: High grade Grail (5 of 6)
|
||||
Implants named like: High grade Jackal (5 of 6)
|
||||
Implants named like: High grade Spur (5 of 6)
|
||||
Implants named like: High grade Talon (5 of 6)
|
||||
"""
|
||||
|
||||
type = 'passive'
|
||||
@@ -9163,7 +9178,7 @@ class Effect3001(BaseEffect):
|
||||
|
||||
Used by:
|
||||
Modules from group: Missile Launcher Torpedo (22 of 22)
|
||||
Items from market group: Ship Equipment > Turrets & Bays (429 of 889)
|
||||
Items from market group: Ship Equipment > Turrets & Launchers (429 of 889)
|
||||
Module: Interdiction Sphere Launcher I
|
||||
"""
|
||||
|
||||
@@ -12759,8 +12774,8 @@ class Effect4038(BaseEffect):
|
||||
|
||||
@staticmethod
|
||||
def handler(fit, module, context, projectionRange, **kwargs):
|
||||
fit.modules.filteredItemMultiply(lambda mod: 'overloadECMStrenghtBonus' in mod.itemModifiedAttributes,
|
||||
'overloadECMStrenghtBonus', module.getModifiedItemAttr('overloadBonusMultiplier'), **kwargs)
|
||||
fit.modules.filteredItemMultiply(lambda mod: 'overloadECMStrengthBonus' in mod.itemModifiedAttributes,
|
||||
'overloadECMStrengthBonus', module.getModifiedItemAttr('overloadBonusMultiplier'), **kwargs)
|
||||
|
||||
|
||||
class Effect4039(BaseEffect):
|
||||
@@ -27507,12 +27522,32 @@ class Effect6439(BaseEffect):
|
||||
stackingPenalties=True, **kwargs)
|
||||
|
||||
|
||||
class Effect6440(BaseEffect):
|
||||
"""
|
||||
fighterAbilityAfterburner
|
||||
|
||||
Used by:
|
||||
Fighters named like: Shadow (2 of 2)
|
||||
Fighters named like: Siren (4 of 4)
|
||||
"""
|
||||
|
||||
displayName = 'Afterburner'
|
||||
grouped = True
|
||||
runTime = 'late'
|
||||
type = 'active'
|
||||
|
||||
@staticmethod
|
||||
def handler(fit, module, context, projectionRange, **kwargs):
|
||||
module.boostItemAttr('maxVelocity', module.getModifiedItemAttr('fighterAbilityAfterburnerSpeedBonus'),
|
||||
stackingPenalties=True, **kwargs)
|
||||
|
||||
|
||||
class Effect6441(BaseEffect):
|
||||
"""
|
||||
fighterAbilityMicroWarpDrive
|
||||
|
||||
Used by:
|
||||
Items from category: Fighter (48 of 82)
|
||||
Items from category: Fighter (44 of 82)
|
||||
"""
|
||||
|
||||
displayName = 'Microwarpdrive'
|
||||
@@ -27913,7 +27948,7 @@ class Effect6488(BaseEffect):
|
||||
Charges from group: Sensor Booster Script (3 of 3)
|
||||
"""
|
||||
|
||||
type = 'active'
|
||||
type = 'passive'
|
||||
|
||||
@staticmethod
|
||||
def handler(fit, module, context, projectionRange, **kwargs):
|
||||
@@ -36185,3 +36220,35 @@ class Effect7248(BaseEffect):
|
||||
def handler(fit, ship, context, projectionRange, **kwargs):
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill('Small Projectile Turret'),
|
||||
'speed', ship.getModifiedItemAttr('shipBonusMF'), skill='Minmatar Frigate', **kwargs)
|
||||
|
||||
|
||||
class Effect8011(BaseEffect):
|
||||
"""
|
||||
shieldHpBonusPostPercentHpLocationShip
|
||||
|
||||
Used by:
|
||||
Implants named like: grade Nirvana (10 of 12)
|
||||
"""
|
||||
|
||||
type = 'passive'
|
||||
|
||||
@staticmethod
|
||||
def handler(fit, container, context, projectionRange, **kwargs):
|
||||
fit.ship.boostItemAttr('shieldCapacity', container.getModifiedItemAttr('shieldHpBonus'), **kwargs)
|
||||
|
||||
|
||||
class Effect8013(BaseEffect):
|
||||
"""
|
||||
setBonusNirvana
|
||||
|
||||
Used by:
|
||||
Implants named like: grade Nirvana (12 of 12)
|
||||
"""
|
||||
|
||||
runTime = 'early'
|
||||
type = 'passive'
|
||||
|
||||
@staticmethod
|
||||
def handler(fit, implant, context, projectionRange, **kwargs):
|
||||
fit.appliedImplants.filteredItemMultiply(lambda target: target.item.requiresSkill('Cybernetics'),
|
||||
'shieldHpBonus', implant.getModifiedItemAttr('ImplantSetNirvana') or 1, **kwargs)
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
# ===============================================================================
|
||||
|
||||
|
||||
import json
|
||||
from collections import OrderedDict
|
||||
|
||||
from logbook import Logger
|
||||
@@ -324,50 +325,26 @@ class Item(EqBase):
|
||||
eos.db.saveddata_session.delete(override)
|
||||
eos.db.commit()
|
||||
|
||||
srqIDMap = {182: 277, 183: 278, 184: 279, 1285: 1286, 1289: 1287, 1290: 1288}
|
||||
|
||||
@property
|
||||
def requiredSkills(self):
|
||||
if self.__requiredSkills is None:
|
||||
requiredSkills = OrderedDict()
|
||||
self.__requiredSkills = requiredSkills
|
||||
# Map containing attribute IDs we may need for required skills
|
||||
# { requiredSkillX : requiredSkillXLevel }
|
||||
combinedAttrIDs = set(self.srqIDMap.keys()).union(set(self.srqIDMap.values()))
|
||||
# Map containing result of the request
|
||||
# { attributeID : attributeValue }
|
||||
skillAttrs = {}
|
||||
# Get relevant attribute values from db (required skill IDs and levels) for our item
|
||||
for attrInfo in eos.db.directAttributeRequest((self.ID,), tuple(combinedAttrIDs)):
|
||||
attrID = attrInfo[1]
|
||||
attrVal = attrInfo[2]
|
||||
skillAttrs[attrID] = attrVal
|
||||
# Go through all attributeID pairs
|
||||
for srqIDAtrr, srqLvlAttr in self.srqIDMap.items():
|
||||
# Check if we have both in returned result
|
||||
if srqIDAtrr in skillAttrs and srqLvlAttr in skillAttrs:
|
||||
skillID = int(skillAttrs[srqIDAtrr])
|
||||
skillLvl = skillAttrs[srqLvlAttr]
|
||||
# Fetch item from database and fill map
|
||||
item = eos.db.getItem(skillID)
|
||||
requiredSkills[item] = skillLvl
|
||||
self.__requiredSkills = {}
|
||||
if self.reqskills:
|
||||
for skillTypeID, skillLevel in json.loads(self.reqskills).items():
|
||||
skillItem = eos.db.getItem(int(skillTypeID))
|
||||
if skillItem:
|
||||
self.__requiredSkills[skillItem] = skillLevel
|
||||
return self.__requiredSkills
|
||||
|
||||
@property
|
||||
def requiredFor(self):
|
||||
if self.__requiredFor is None:
|
||||
self.__requiredFor = dict()
|
||||
|
||||
# Map containing attribute IDs we may need for required skills
|
||||
|
||||
# Get relevant attribute values from db (required skill IDs and levels) for our item
|
||||
q = eos.db.getRequiredFor(self.ID, self.srqIDMap)
|
||||
|
||||
for itemID, lvl in q:
|
||||
# Fetch item from database and fill map
|
||||
item = eos.db.getItem(itemID)
|
||||
self.__requiredFor[item] = lvl
|
||||
|
||||
self.__requiredFor = {}
|
||||
if self.requiredfor:
|
||||
for typeID, skillLevel in json.loads(self.requiredfor).items():
|
||||
requiredForItem = eos.db.getItem(int(typeID))
|
||||
if requiredForItem:
|
||||
self.__requiredFor[requiredForItem] = skillLevel
|
||||
return self.__requiredFor
|
||||
|
||||
factionMap = {
|
||||
@@ -410,6 +387,7 @@ class Item(EqBase):
|
||||
9 : "guristas", # Caldari + Gallente
|
||||
10 : "angelserp", # Minmatar + Gallente, final race depends on the order of skills
|
||||
12 : "sisters", # Amarr + Gallente
|
||||
15 : "concord",
|
||||
16 : "jove",
|
||||
32 : "sansha", # Incrusion Sansha
|
||||
128: "ore",
|
||||
|
||||
@@ -25,106 +25,118 @@ from sqlalchemy.orm import reconstructor
|
||||
import eos.db
|
||||
|
||||
|
||||
# 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, ('[Bombs]Electron Bomb', 6400, 0, 0, 0)),
|
||||
(-7, ('[Bombs]Scorch Bomb', 0, 6400, 0, 0)),
|
||||
(-8, ('[Bombs]Concussion Bomb', 0, 0, 6400, 0)),
|
||||
(-9, ('[Bombs]Shrapnel Bomb', 0, 0, 0, 6400)),
|
||||
(-10, ('[Frequency Crystals]|[T2] Conflagration', 7.7, 7.7, 0, 0)),
|
||||
(-11, ('[Frequency Crystals]|[T2] Scorch', 9, 2, 0, 0)),
|
||||
(-12, ('[Frequency Crystals]|[T2] Gleam', 7, 7, 0, 0)),
|
||||
(-13, ('[Frequency Crystals]|[T2] Aurora', 5, 3, 0, 0)),
|
||||
(-14, ('[Frequency Crystals]Multifrequency', 7, 5, 0, 0)),
|
||||
(-15, ('[Frequency Crystals]Gamma', 7, 4, 0, 0)),
|
||||
(-16, ('[Frequency Crystals]Xray', 6, 4, 0, 0)),
|
||||
(-17, ('[Frequency Crystals]Ultraviolet', 6, 3, 0, 0)),
|
||||
(-18, ('[Frequency Crystals]Standard', 5, 3, 0, 0)),
|
||||
(-19, ('[Frequency Crystals]Infrared', 5, 2, 0, 0)),
|
||||
(-20, ('[Frequency Crystals]Microwave', 4, 2, 0, 0)),
|
||||
(-21, ('[Frequency Crystals]Radio', 5, 0, 0, 0)),
|
||||
(-22, ('[Hybrid Charges]|[T2] Void', 0, 7.7, 7.7, 0)),
|
||||
(-23, ('[Hybrid Charges]|[T2] Null', 0, 6, 5, 0)),
|
||||
(-24, ('[Hybrid Charges]|[T2] Javelin', 0, 8, 6, 0)),
|
||||
(-25, ('[Hybrid Charges]|[T2] Spike', 0, 4, 4, 0)),
|
||||
(-26, ('[Hybrid Charges]Antimatter', 0, 5, 7, 0)),
|
||||
(-27, ('[Hybrid Charges]Plutonium', 0, 5, 6, 0)),
|
||||
(-28, ('[Hybrid Charges]Uranium', 0, 4, 6, 0)),
|
||||
(-29, ('[Hybrid Charges]Thorium', 0, 4, 5, 0)),
|
||||
(-30, ('[Hybrid Charges]Lead', 0, 3, 5, 0)),
|
||||
(-31, ('[Hybrid Charges]Iridium', 0, 3, 4, 0)),
|
||||
(-32, ('[Hybrid Charges]Tungsten', 0, 2, 4, 0)),
|
||||
(-33, ('[Hybrid Charges]Iron', 0, 2, 3, 0)),
|
||||
(-34, ('[Missiles]Mjolnir', 1, 0, 0, 0)),
|
||||
(-35, ('[Missiles]Inferno', 0, 1, 0, 0)),
|
||||
(-36, ('[Missiles]Scourge', 0, 0, 1, 0)),
|
||||
(-37, ('[Missiles]Nova', 0, 0, 0, 1)),
|
||||
(-38, ('[Missiles]|[Structure] Standup Missile', 1, 1, 1, 1)),
|
||||
(-39, ('[Projectile Ammo]|[T2] Hail', 0, 0, 3.3, 12.1)),
|
||||
(-40, ('[Projectile Ammo]|[T2] Barrage', 0, 0, 5, 6)),
|
||||
(-41, ('[Projectile Ammo]|[T2] Quake', 0, 0, 5, 9)),
|
||||
(-42, ('[Projectile Ammo]|[T2] Tremor', 0, 0, 3, 5)),
|
||||
(-43, ('[Projectile Ammo]EMP', 9, 0, 1, 2)),
|
||||
(-44, ('[Projectile Ammo]Phased Plasma', 0, 10, 2, 0)),
|
||||
(-45, ('[Projectile Ammo]Fusion', 0, 0, 2, 10)),
|
||||
(-46, ('[Projectile Ammo]Depleted Uranium', 0, 3, 2, 3)),
|
||||
(-47, ('[Projectile Ammo]Titanium Sabot', 0, 0, 6, 2)),
|
||||
(-48, ('[Projectile Ammo]Proton', 3, 0, 2, 0)),
|
||||
(-49, ('[Projectile Ammo]Carbonized Lead', 0, 0, 4, 1)),
|
||||
(-50, ('[Projectile Ammo]Nuclear', 0, 0, 1, 4)),
|
||||
(-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)),
|
||||
# Different sizes of plasma do different damage ratios, the values here
|
||||
# are average of ratios across sizes
|
||||
(-51, ('[Exotic Plasma]|[T2] Occult', 0, 55863, 0, 44137)),
|
||||
(-52, ('[Exotic Plasma]|[T2] Mystic', 0, 66319, 0, 33681)),
|
||||
(-53, ('[Exotic Plasma]Tetryon', 0, 69208, 0, 30792)),
|
||||
(-54, ('[Exotic Plasma]Baryon', 0, 59737, 0, 40263)),
|
||||
(-55, ('[Exotic Plasma]Meson', 0, 60519, 0, 39481)),
|
||||
(-56, ('[NPC][Asteroid]Angel Cartel', 1838, 562, 2215, 3838)),
|
||||
(-57, ('[NPC][Asteroid]Blood Raiders', 5067, 4214, 0, 0)),
|
||||
(-58, ('[NPC][Asteroid]Guristas', 0, 1828, 7413, 0)),
|
||||
(-59, ('[NPC][Asteroid]Rogue Drone', 394, 666, 1090, 1687)),
|
||||
(-60, ('[NPC][Asteroid]Sanshas Nation', 5586, 4112, 0, 0)),
|
||||
(-61, ('[NPC][Asteroid]Serpentis', 0, 5373, 4813, 0)),
|
||||
(-62, ('[NPC][Deadspace]Angel Cartel', 369, 533, 1395, 3302)),
|
||||
(-63, ('[NPC][Deadspace]Blood Raiders', 6040, 5052, 10, 15)),
|
||||
(-64, ('[NPC][Deadspace]Guristas', 0, 1531, 9680, 0)),
|
||||
(-65, ('[NPC][Deadspace]Rogue Drone', 276, 1071, 1069, 871)),
|
||||
(-66, ('[NPC][Deadspace]Sanshas Nation', 3009, 2237, 0, 0)),
|
||||
(-67, ('[NPC][Deadspace]Serpentis', 0, 3110, 1929, 0)),
|
||||
(-68, ('[NPC][Mission]Amarr Empire', 4464, 3546, 97, 0)),
|
||||
(-69, ('[NPC][Mission]Caldari State', 0, 2139, 4867, 0)),
|
||||
(-70, ('[NPC][Mission]CONCORD', 336, 134, 212, 412)),
|
||||
(-71, ('[NPC][Mission]Gallente Federation', 9, 3712, 2758, 0)),
|
||||
(-72, ('[NPC][Mission]Khanid', 612, 483, 43, 6)),
|
||||
(-73, ('[NPC][Mission]Minmatar Republic', 1024, 388, 1655, 4285)),
|
||||
(-74, ('[NPC][Mission]Mordus Legion', 25, 262, 625, 0)),
|
||||
(-75, ('[NPC][Mission]Thukker', 0, 52, 10, 79)),
|
||||
(-76, ('[NPC][Burner]Cruor (Blood Raiders)', 90, 90, 0, 0)),
|
||||
(-77, ('[NPC][Burner]Dramiel (Angel)', 55, 0, 20, 96)),
|
||||
(-78, ('[NPC][Burner]Daredevil (Serpentis)', 0, 110, 154, 0)),
|
||||
(-79, ('[NPC][Burner]Succubus (Sanshas Nation)', 135, 30, 0, 0)),
|
||||
(-80, ('[NPC][Burner]Worm (Guristas)', 0, 0, 228, 0)),
|
||||
(-81, ('[NPC][Burner]Enyo', 0, 147, 147, 0)),
|
||||
(-82, ('[NPC][Burner]Hawk', 0, 0, 247, 0)),
|
||||
(-83, ('[NPC][Burner]Jaguar', 36, 0, 50, 182)),
|
||||
(-84, ('[NPC][Burner]Vengeance', 232, 0, 0, 0)),
|
||||
(-85, ('[NPC][Burner]Ashimmu (Blood Raiders)', 260, 100, 0, 0)),
|
||||
(-86, ('[NPC][Burner]Talos', 0, 413, 413, 0)),
|
||||
(-87, ('[NPC][Burner]Sentinel', 0, 75, 0, 90)),
|
||||
(-88, ('[NPC][Other]Sleepers', 1472, 1472, 1384, 1384)),
|
||||
(-89, ('[NPC][Other]Sansha Incursion', 1682, 1347, 3678, 3678)),
|
||||
(-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
|
||||
(-90, ('[NPC][Invasion][Invading Precursor Entities]0% spool up', 31, 29, 24, 16)),
|
||||
(-91, ('[NPC][Invasion][Invading Precursor Entities]50% spool up', 29, 37, 15, 19)),
|
||||
(-92, ('[NPC][Invasion][Invading Precursor Entities]100% spool up', 28, 41, 11, 20)),
|
||||
(-93, ('[NPC][Invasion]Retaliating Amarr Entities', 58, 42, 0, 0)),
|
||||
(-94, ('[NPC][Invasion]Retaliating Caldari Entities', 30, 43, 2, 25)),
|
||||
(-95, ('[NPC][Invasion]Retaliating Gallente Entities', 0, 42, 58, 0)),
|
||||
(-96, ('[NPC][Invasion]Retaliating Minmatar Entities', 17, 8, 44, 31))])
|
||||
(-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)),
|
||||
# Source: ticket #2067
|
||||
(-86, ('[NPC][Invasion][Invading Precursor Entities]Dread', 0, 417, 0, 583)),
|
||||
(-87, ('[NPC][Invasion][Invading Precursor Entities]Normal Subcaps', 0, 610, 0, 390)),
|
||||
(-88, ('[NPC][Invasion][Invading Precursor Entities]Subcaps w/missiles 0% spool up', 363, 160, 363, 115)),
|
||||
(-89, ('[NPC][Invasion][Invading Precursor Entities]Subcaps w/missiles 50% spool up', 286, 249, 286, 179)),
|
||||
(-90, ('[NPC][Invasion][Invading Precursor Entities]Subcaps w/missiles 100% spool up', 236, 307, 236, 221)),
|
||||
(-91, ('[NPC][Invasion][Retaliating Amarr Entities]Dread/Subcaps', 583, 417, 0, 0)),
|
||||
(-92, ('[NPC][Invasion][Retaliating Caldari Entities]Dread', 1000, 0, 0, 0)),
|
||||
(-93, ('[NPC][Invasion][Retaliating Caldari Entities]Subcaps', 511, 21, 29, 439)),
|
||||
(-94, ('[NPC][Invasion][Retaliating Gallente Entities]Dread/Subcaps', 0, 417, 583, 0)),
|
||||
(-95, ('[NPC][Invasion][Retaliating Minmatar Entities]Dread', 0, 0, 583, 417)),
|
||||
(-96, ('[NPC][Invasion][Retaliating Minmatar Entities]Subcaps', 302, 132, 330, 236)),
|
||||
(-97, ('[NPC][Mission]Amarr Empire', 4464, 3546, 97, 0)),
|
||||
(-98, ('[NPC][Mission]Caldari State', 0, 2139, 4867, 0)),
|
||||
(-99, ('[NPC][Mission]CONCORD', 336, 134, 212, 412)),
|
||||
(-100, ('[NPC][Mission]Gallente Federation', 9, 3712, 2758, 0)),
|
||||
(-101, ('[NPC][Mission]Khanid', 612, 483, 43, 6)),
|
||||
(-102, ('[NPC][Mission]Minmatar Republic', 1024, 388, 1655, 4285)),
|
||||
(-103, ('[NPC][Mission]Mordus Legion', 25, 262, 625, 0)),
|
||||
(-104, ('[NPC][Mission]Thukker', 0, 52, 10, 79)),
|
||||
(-105, ('[NPC]Sansha Incursion', 1682, 1347, 3678, 3678)),
|
||||
(-106, ('[NPC]Sleepers', 1472, 1472, 1384, 1384))])
|
||||
|
||||
|
||||
class DamagePattern:
|
||||
|
||||
@@ -99,7 +99,7 @@ class Fighter(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
self.__itemModifiedAttributes = ModifiedAttributeDict()
|
||||
self.__chargeModifiedAttributes = ModifiedAttributeDict()
|
||||
|
||||
if len(self.abilities) != len(self.item.effects):
|
||||
if {a.effectID for a in self.abilities} != {e.ID for e in self.item.effects.values()}:
|
||||
self.__abilities = []
|
||||
for ability in self.__getAbilities():
|
||||
self.__abilities.append(ability)
|
||||
|
||||
@@ -165,6 +165,9 @@ class Fit:
|
||||
self.__capUsed = None
|
||||
self.__capRecharge = None
|
||||
self.__savedCapSimData.clear()
|
||||
# Ancillary tank modules affect this
|
||||
self.__sustainableTank = None
|
||||
self.__effectiveSustainableTank = None
|
||||
|
||||
@property
|
||||
def targetProfile(self):
|
||||
|
||||
@@ -84,11 +84,102 @@ BUILTINS = OrderedDict([
|
||||
(-50, ('[NPC][Burner]Talos', 0.68, 0.59, 0.59, 0.43)),
|
||||
(-51, ('[NPC][Burner]Sentinel', 0.58, 0.45, 0.52, 0.66)),
|
||||
# Source: ticket #2067
|
||||
(-52, ('[NPC][Invasion]Invading Precursor Entities', 0.46, 0.39, 0.48, 0.42)),
|
||||
(-53, ('[NPC][Invasion]Retaliating Amarr Entities', 0.36, 0.31, 0.44, 0.60)),
|
||||
(-54, ('[NPC][Invasion]Retaliating Caldari Entities', 0.28, 0.61, 0.48, 0.39)),
|
||||
(-55, ('[NPC][Invasion]Retaliating Gallente Entities', 0.36, 0.39, 0.56, 0.50)),
|
||||
(-56, ('[NPC][Invasion]Retaliating Minmatar Entities', 0.62, 0.42, 0.35, 0.40))])
|
||||
(-52, ('[NPC][Invasion]Invading Precursor Entities', 0.422, 0.367, 0.453, 0.411)),
|
||||
(-53, ('[NPC][Invasion]Retaliating Amarr Entities', 0.360, 0.310, 0.441, 0.602)),
|
||||
(-54, ('[NPC][Invasion]Retaliating Caldari Entities', 0.287, 0.610, 0.487, 0.401)),
|
||||
(-55, ('[NPC][Invasion]Retaliating Gallente Entities', 0.383, 0.414, 0.578, 0.513)),
|
||||
(-56, ('[NPC][Invasion]Retaliating Minmatar Entities', 0.620, 0.422, 0.355, 0.399)),
|
||||
(-57, ('[NPC][Abyssal][Dark Matter All Tiers]Drones', 0.439, 0.522, 0.529, 0.435)),
|
||||
(-58, ('[NPC][Abyssal][Dark Matter All Tiers]Overmind', 0.626, 0.576, 0.612, 0.624)),
|
||||
(-59, ('[NPC][Abyssal][Dark Matter All Tiers]Seeker', 0.082, 0.082, 0.082, 0.082)),
|
||||
(-60, ('[NPC][Abyssal][Dark Matter All Tiers]Triglavian', 0.477, 0.401, 0.449, 0.37)),
|
||||
(-61, ('[NPC][Abyssal][Dark Matter All Tiers]Drifter', 0.403, 0.403, 0.403, 0.403)),
|
||||
(-62, ('[NPC][Abyssal][Dark Matter All Tiers]Sleeper', 0.435, 0.435, 0.435, 0.435)),
|
||||
(-63, ('[NPC][Abyssal][Dark Matter All Tiers]All', 0.507, 0.477, 0.502, 0.493)),
|
||||
(-64, ('[NPC][Abyssal][Electrical T1/T2]Drones', 0.323, 0.522, 0.529, 0.435)),
|
||||
(-65, ('[NPC][Abyssal][Electrical T1/T2]Overmind', 0.521, 0.576, 0.612, 0.624)),
|
||||
(-66, ('[NPC][Abyssal][Electrical T1/T2]Seeker', 0, 0.082, 0.082, 0.082)),
|
||||
(-67, ('[NPC][Abyssal][Electrical T1/T2]Triglavian', 0.333, 0.401, 0.449, 0.37)),
|
||||
(-68, ('[NPC][Abyssal][Electrical T1/T2]Drifter', 0.267, 0.403, 0.403, 0.403)),
|
||||
(-69, ('[NPC][Abyssal][Electrical T1/T2]Sleeper', 0.329, 0.435, 0.435, 0.435)),
|
||||
(-70, ('[NPC][Abyssal][Electrical T1/T2]All', 0.385, 0.477, 0.502, 0.493)),
|
||||
(-71, ('[NPC][Abyssal][Electrical T3 (Some T5 Rooms)]Drones', 0.255, 0.522, 0.529, 0.435)),
|
||||
(-72, ('[NPC][Abyssal][Electrical T3 (Some T5 Rooms)]Overmind', 0.457, 0.576, 0.612, 0.624)),
|
||||
(-73, ('[NPC][Abyssal][Electrical T3 (Some T5 Rooms)]Seeker', 0, 0.082, 0.082, 0.082)),
|
||||
(-74, ('[NPC][Abyssal][Electrical T3 (Some T5 Rooms)]Triglavian', 0.241, 0.401, 0.449, 0.37)),
|
||||
(-75, ('[NPC][Abyssal][Electrical T3 (Some T5 Rooms)]Drifter', 0.184, 0.403, 0.403, 0.403)),
|
||||
(-76, ('[NPC][Abyssal][Electrical T3 (Some T5 Rooms)]Sleeper', 0.268, 0.435, 0.435, 0.435)),
|
||||
(-77, ('[NPC][Abyssal][Electrical T3 (Some T5 Rooms)]All', 0.313, 0.477, 0.502, 0.493)),
|
||||
(-78, ('[NPC][Abyssal][Electrical T4/T5]Drones', 0.193, 0.522, 0.529, 0.435)),
|
||||
(-79, ('[NPC][Abyssal][Electrical T4/T5]Overmind', 0.398, 0.576, 0.612, 0.624)),
|
||||
(-80, ('[NPC][Abyssal][Electrical T4/T5]Seeker', 0, 0.082, 0.082, 0.082)),
|
||||
(-81, ('[NPC][Abyssal][Electrical T4/T5]Triglavian', 0.183, 0.401, 0.449, 0.37)),
|
||||
(-82, ('[NPC][Abyssal][Electrical T4/T5]Drifter', 0.107, 0.403, 0.403, 0.403)),
|
||||
(-83, ('[NPC][Abyssal][Electrical T4/T5]Sleeper', 0.215, 0.435, 0.435, 0.435)),
|
||||
(-84, ('[NPC][Abyssal][Electrical T4/T5]All', 0.25, 0.477, 0.502, 0.493)),
|
||||
(-85, ('[NPC][Abyssal][Firestorm T1/T2]Drones', 0.461, 0.425, 0.541, 0.443)),
|
||||
(-86, ('[NPC][Abyssal][Firestorm T1/T2]Overmind', 0.65, 0.469, 0.625, 0.633)),
|
||||
(-87, ('[NPC][Abyssal][Firestorm T1/T2]Seeker', 0.084, 0, 0.084, 0.084)),
|
||||
(-88, ('[NPC][Abyssal][Firestorm T1/T2]Triglavian', 0.534, 0.266, 0.484, 0.366)),
|
||||
(-89, ('[NPC][Abyssal][Firestorm T1/T2]Drifter', 0.422, 0.282, 0.422, 0.422)),
|
||||
(-90, ('[NPC][Abyssal][Firestorm T1/T2]Sleeper', 0.512, 0.402, 0.512, 0.512)),
|
||||
(-91, ('[NPC][Abyssal][Firestorm T1/T2]All', 0.541, 0.365, 0.524, 0.504)),
|
||||
(-92, ('[NPC][Abyssal][Firestorm T3 (Some T5 Rooms)]Drones', 0.461, 0.36, 0.541, 0.443)),
|
||||
(-93, ('[NPC][Abyssal][Firestorm T3 (Some T5 Rooms)]Overmind', 0.65, 0.391, 0.625, 0.633)),
|
||||
(-94, ('[NPC][Abyssal][Firestorm T3 (Some T5 Rooms)]Seeker', 0.084, 0, 0.084, 0.084)),
|
||||
(-95, ('[NPC][Abyssal][Firestorm T3 (Some T5 Rooms)]Triglavian', 0.534, 0.161, 0.484, 0.366)),
|
||||
(-96, ('[NPC][Abyssal][Firestorm T3 (Some T5 Rooms)]Drifter', 0.422, 0.196, 0.422, 0.422)),
|
||||
(-97, ('[NPC][Abyssal][Firestorm T3 (Some T5 Rooms)]Sleeper', 0.512, 0.337, 0.512, 0.512)),
|
||||
(-98, ('[NPC][Abyssal][Firestorm T3 (Some T5 Rooms)]All', 0.541, 0.284, 0.524, 0.504)),
|
||||
(-99, ('[NPC][Abyssal][Firestorm T4/T5]Drones', 0.461, 0.305, 0.541, 0.443)),
|
||||
(-100, ('[NPC][Abyssal][Firestorm T4/T5]Overmind', 0.65, 0.323, 0.625, 0.633)),
|
||||
(-101, ('[NPC][Abyssal][Firestorm T4/T5]Seeker', 0.084, 0, 0.084, 0.084)),
|
||||
(-102, ('[NPC][Abyssal][Firestorm T4/T5]Triglavian', 0.534, 0.082, 0.484, 0.366)),
|
||||
(-103, ('[NPC][Abyssal][Firestorm T4/T5]Drifter', 0.422, 0.114, 0.422, 0.422)),
|
||||
(-104, ('[NPC][Abyssal][Firestorm T4/T5]Sleeper', 0.512, 0.276, 0.512, 0.512)),
|
||||
(-105, ('[NPC][Abyssal][Firestorm T4/T5]All', 0.541, 0.214, 0.524, 0.504)),
|
||||
(-106, ('[NPC][Abyssal][Exotic T1/T2]Drones', 0.439, 0.522, 0.417, 0.435)),
|
||||
(-107, ('[NPC][Abyssal][Exotic T1/T2]Overmind', 0.626, 0.576, 0.496, 0.624)),
|
||||
(-108, ('[NPC][Abyssal][Exotic T1/T2]Seeker', 0.082, 0.082, 0, 0.082)),
|
||||
(-109, ('[NPC][Abyssal][Exotic T1/T2]Triglavian', 0.477, 0.401, 0.284, 0.37)),
|
||||
(-110, ('[NPC][Abyssal][Exotic T1/T2]Drifter', 0.403, 0.403, 0.267, 0.403)),
|
||||
(-111, ('[NPC][Abyssal][Exotic T1/T2]Sleeper', 0.435, 0.435, 0.329, 0.435)),
|
||||
(-112, ('[NPC][Abyssal][Exotic T1/T2]All', 0.507, 0.477, 0.373, 0.493)),
|
||||
(-113, ('[NPC][Abyssal][Exotic T3 (Some T5 Rooms)]Drones', 0.439, 0.522, 0.351, 0.435)),
|
||||
(-114, ('[NPC][Abyssal][Exotic T3 (Some T5 Rooms)]Overmind', 0.626, 0.576, 0.419, 0.624)),
|
||||
(-115, ('[NPC][Abyssal][Exotic T3 (Some T5 Rooms)]Seeker', 0.082, 0.082, 0, 0.082)),
|
||||
(-116, ('[NPC][Abyssal][Exotic T3 (Some T5 Rooms)]Triglavian', 0.477, 0.401, 0.176, 0.37)),
|
||||
(-117, ('[NPC][Abyssal][Exotic T3 (Some T5 Rooms)]Drifter', 0.403, 0.403, 0.184, 0.403)),
|
||||
(-118, ('[NPC][Abyssal][Exotic T3 (Some T5 Rooms)]Sleeper', 0.435, 0.435, 0.268, 0.435)),
|
||||
(-119, ('[NPC][Abyssal][Exotic T3 (Some T5 Rooms)]All', 0.507, 0.477, 0.293, 0.493)),
|
||||
(-120, ('[NPC][Abyssal][Exotic T4/T5]Drones', 0.439, 0.522, 0.293, 0.435)),
|
||||
(-121, ('[NPC][Abyssal][Exotic T4/T5]Overmind', 0.626, 0.576, 0.344, 0.624)),
|
||||
(-122, ('[NPC][Abyssal][Exotic T4/T5]Seeker', 0.082, 0.082, 0, 0.082)),
|
||||
(-123, ('[NPC][Abyssal][Exotic T4/T5]Triglavian', 0.477, 0.401, 0.107, 0.37)),
|
||||
(-124, ('[NPC][Abyssal][Exotic T4/T5]Drifter', 0.403, 0.403, 0.107, 0.403)),
|
||||
(-125, ('[NPC][Abyssal][Exotic T4/T5]Sleeper', 0.435, 0.435, 0.215, 0.435)),
|
||||
(-126, ('[NPC][Abyssal][Exotic T4/T5]All', 0.507, 0.477, 0.223, 0.493)),
|
||||
(-127, ('[NPC][Abyssal][Gamma T1/T2]Drones', 0.449, 0.54, 0.549, 0.336)),
|
||||
(-128, ('[NPC][Abyssal][Gamma T1/T2]Overmind', 0.6, 0.557, 0.601, 0.504)),
|
||||
(-129, ('[NPC][Abyssal][Gamma T1/T2]Seeker', 0.085, 0.085, 0.085, 0)),
|
||||
(-130, ('[NPC][Abyssal][Gamma T1/T2]Triglavian', 0.463, 0.392, 0.447, 0.193)),
|
||||
(-131, ('[NPC][Abyssal][Gamma T1/T2]Drifter', 0.428, 0.428, 0.428, 0.287)),
|
||||
(-132, ('[NPC][Abyssal][Gamma T1/T2]Sleeper', 0.435, 0.435, 0.435, 0.329)),
|
||||
(-133, ('[NPC][Abyssal][Gamma T1/T2]All', 0.493, 0.472, 0.5, 0.362)),
|
||||
(-134, ('[NPC][Abyssal][Gamma T3 (Some T5 Rooms)]Drones', 0.449, 0.54, 0.549, 0.264)),
|
||||
(-135, ('[NPC][Abyssal][Gamma T3 (Some T5 Rooms)]Overmind', 0.6, 0.557, 0.601, 0.428)),
|
||||
(-136, ('[NPC][Abyssal][Gamma T3 (Some T5 Rooms)]Seeker', 0.085, 0.085, 0.085, 0)),
|
||||
(-137, ('[NPC][Abyssal][Gamma T3 (Some T5 Rooms)]Triglavian', 0.463, 0.392, 0.447, 0.071)),
|
||||
(-138, ('[NPC][Abyssal][Gamma T3 (Some T5 Rooms)]Drifter', 0.428, 0.428, 0.428, 0.2)),
|
||||
(-139, ('[NPC][Abyssal][Gamma T3 (Some T5 Rooms)]Sleeper', 0.435, 0.435, 0.435, 0.268)),
|
||||
(-140, ('[NPC][Abyssal][Gamma T3 (Some T5 Rooms)]All', 0.493, 0.472, 0.5, 0.28)),
|
||||
(-141, ('[NPC][Abyssal][Gamma T4/T5]Drones', 0.449, 0.54, 0.549, 0.197)),
|
||||
(-142, ('[NPC][Abyssal][Gamma T4/T5]Overmind', 0.6, 0.557, 0.601, 0.356)),
|
||||
(-143, ('[NPC][Abyssal][Gamma T4/T5]Seeker', 0.085, 0.085, 0.085, 0)),
|
||||
(-144, ('[NPC][Abyssal][Gamma T4/T5]Triglavian', 0.463, 0.392, 0.447, 0.029)),
|
||||
(-145, ('[NPC][Abyssal][Gamma T4/T5]Drifter', 0.428, 0.428, 0.428, 0.117)),
|
||||
(-146, ('[NPC][Abyssal][Gamma T4/T5]Sleeper', 0.435, 0.435, 0.435, 0.215)),
|
||||
(-147, ('[NPC][Abyssal][Gamma T4/T5]All', 0.493, 0.472, 0.5, 0.21))])
|
||||
|
||||
|
||||
class TargetProfile:
|
||||
|
||||
39
eos/utils/pyinst_support.py
Normal file
39
eos/utils/pyinst_support.py
Normal file
@@ -0,0 +1,39 @@
|
||||
"""
|
||||
Slightly modified version of function taken from here:
|
||||
https://github.com/pyinstaller/pyinstaller/issues/1905#issuecomment-525221546
|
||||
"""
|
||||
|
||||
|
||||
import pkgutil
|
||||
|
||||
|
||||
def iterNamespace(name, path):
|
||||
"""Pyinstaller-compatible namespace iteration.
|
||||
|
||||
Yields the name of all modules found at a given Fully-qualified path.
|
||||
|
||||
To have it running with pyinstaller, it requires to ensure a hook inject the
|
||||
"hidden" modules from your plugins folder inside the executable:
|
||||
|
||||
- if your plugins are under the ``myappname/pluginfolder`` module
|
||||
- create a file ``specs/hook-<myappname.pluginfolder>.py``
|
||||
- content of this file should be:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from PyInstaller.utils.hooks import collect_submodules
|
||||
hiddenimports = collect_submodules('<myappname.pluginfolder>')
|
||||
"""
|
||||
prefix = name + "."
|
||||
for p in pkgutil.iter_modules(path, prefix):
|
||||
yield p[1]
|
||||
|
||||
# special handling when the package is bundled with PyInstaller 3.5
|
||||
# See https://github.com/pyinstaller/pyinstaller/issues/1905#issuecomment-445787510
|
||||
toc = set()
|
||||
for importer in pkgutil.iter_importers(name.partition(".")[0]):
|
||||
if hasattr(importer, 'toc'):
|
||||
toc |= importer.toc
|
||||
for name in toc:
|
||||
if name.startswith(prefix):
|
||||
yield name
|
||||
@@ -299,7 +299,10 @@ class ImplantDisplay(d.Display):
|
||||
sourceContext1 = "implantItem" if fit.implantSource == ImplantLocation.FIT else "implantItemChar"
|
||||
sourceContext2 = "implantItemMisc" if fit.implantSource == ImplantLocation.FIT else "implantItemMiscChar"
|
||||
itemContext = None if mainImplant is None else Market.getInstance().getCategoryByItem(mainImplant.item).name
|
||||
menu = ContextMenu.getMenu(self, mainImplant, selection, (sourceContext1, itemContext), (sourceContext2, itemContext))
|
||||
menu = ContextMenu.getMenu(self, mainImplant, selection,
|
||||
(sourceContext1, itemContext),
|
||||
(sourceContext2, itemContext)
|
||||
)
|
||||
if menu:
|
||||
self.PopupMenu(menu)
|
||||
|
||||
|
||||
@@ -37,7 +37,8 @@ from gui.builtinContextMenus import cargoAdd
|
||||
from gui.builtinContextMenus import cargoAddAmmo
|
||||
from gui.builtinContextMenus import itemProject
|
||||
from gui.builtinContextMenus import ammoToDmgPattern
|
||||
from gui.builtinContextMenus import implantSetAdd
|
||||
from gui.builtinContextMenus import implantSetApply
|
||||
from gui.builtinContextMenus import implantSetSave
|
||||
# Price
|
||||
from gui.builtinContextMenus import priceOptions
|
||||
# Resistance panel
|
||||
|
||||
@@ -3,7 +3,6 @@ from gui.contextMenu import ContextMenuUnconditional
|
||||
from gui.utils.clipboard import toClipboard
|
||||
from service.fit import Fit
|
||||
from service.port.eft import exportDrones, exportFighters, exportCargo, exportImplants, exportBoosters
|
||||
from service.settings import ContextMenuSettings
|
||||
|
||||
|
||||
viewSpecMap = {
|
||||
@@ -17,12 +16,12 @@ viewSpecMap = {
|
||||
|
||||
class AdditionsExportAll(ContextMenuUnconditional):
|
||||
|
||||
visibilitySetting = 'additionsCopyPaste'
|
||||
|
||||
def __init__(self):
|
||||
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
|
||||
|
||||
def display(self, callingWindow, srcContext):
|
||||
if not ContextMenuSettings.getInstance().get('additionsCopyPaste'):
|
||||
return False
|
||||
if srcContext not in viewSpecMap:
|
||||
return False
|
||||
fit = Fit.getInstance().getFit(self.mainFrame.getActiveFit())
|
||||
|
||||
@@ -3,7 +3,6 @@ from gui.contextMenu import ContextMenuSelection
|
||||
from gui.utils.clipboard import toClipboard
|
||||
from service.fit import Fit
|
||||
from service.port.eft import exportDrones, exportFighters, exportCargo, exportImplants, exportBoosters
|
||||
from service.settings import ContextMenuSettings
|
||||
|
||||
|
||||
viewSpecMap = {
|
||||
@@ -17,12 +16,12 @@ viewSpecMap = {
|
||||
|
||||
class AdditionsExportAll(ContextMenuSelection):
|
||||
|
||||
visibilitySetting = 'additionsCopyPaste'
|
||||
|
||||
def __init__(self):
|
||||
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
|
||||
|
||||
def display(self, callingWindow, srcContext, selection):
|
||||
if not ContextMenuSettings.getInstance().get('additionsCopyPaste'):
|
||||
return False
|
||||
if srcContext not in viewSpecMap:
|
||||
return False
|
||||
if not selection:
|
||||
|
||||
@@ -4,7 +4,6 @@ from gui.contextMenu import ContextMenuUnconditional
|
||||
from gui.utils.clipboard import fromClipboard
|
||||
from service.fit import Fit
|
||||
from service.port.eft import parseAdditions
|
||||
from service.settings import ContextMenuSettings
|
||||
|
||||
|
||||
viewSpecMap = {
|
||||
@@ -18,12 +17,12 @@ viewSpecMap = {
|
||||
|
||||
class AdditionsImport(ContextMenuUnconditional):
|
||||
|
||||
visibilitySetting = 'additionsCopyPaste'
|
||||
|
||||
def __init__(self):
|
||||
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
|
||||
|
||||
def display(self, callingWindow, srcContext):
|
||||
if not ContextMenuSettings.getInstance().get('additionsCopyPaste'):
|
||||
return False
|
||||
if srcContext not in viewSpecMap:
|
||||
return False
|
||||
fit = Fit.getInstance().getFit(self.mainFrame.getActiveFit())
|
||||
|
||||
@@ -5,19 +5,16 @@ import gui.globalEvents as GE
|
||||
import gui.mainFrame
|
||||
from gui.contextMenu import ContextMenuSingle
|
||||
from service.fit import Fit
|
||||
from service.settings import ContextMenuSettings
|
||||
|
||||
|
||||
class AmmoToDmgPattern(ContextMenuSingle):
|
||||
|
||||
visibilitySetting = 'ammoPattern'
|
||||
|
||||
def __init__(self):
|
||||
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
|
||||
self.settings = ContextMenuSettings.getInstance()
|
||||
|
||||
def display(self, callingWindow, srcContext, mainItem):
|
||||
if not self.settings.get('ammoPattern'):
|
||||
return False
|
||||
|
||||
if srcContext not in ("marketItemGroup", "marketItemMisc") or self.mainFrame.getActiveFit() is None:
|
||||
return False
|
||||
|
||||
|
||||
@@ -19,8 +19,8 @@ class AddToCargo(ContextMenuSingle):
|
||||
sFit = Fit.getInstance()
|
||||
fitID = self.mainFrame.getActiveFit()
|
||||
fit = sFit.getFit(fitID)
|
||||
# Make sure context menu registers in the correct view
|
||||
if not fit or fit.isStructure:
|
||||
|
||||
if not fit or (fit.isStructure and mainItem.category.ID != 8):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
@@ -30,13 +30,15 @@ class ChangeDamagePattern(ContextMenuUnconditional):
|
||||
fitID = self.mainFrame.getActiveFit()
|
||||
self.fit = sFit.getFit(fitID)
|
||||
|
||||
builtinPatterns = sDP.getBuiltinDamagePatternList()
|
||||
userPatterns = sorted(sDP.getUserDamagePatternList(), key=lambda p: smartSort(p.fullName))
|
||||
# Order here is important: patterns with duplicate names from the latter will overwrite
|
||||
# patterns from the former
|
||||
self.patterns = list(chain(sDP.getBuiltinDamagePatternList(), sDP.getUserDamagePatternList()))
|
||||
self.patterns.sort(key=lambda p: (p.fullName not in ["Uniform", "Selected Ammo"], smartSort(p.fullName)))
|
||||
self.patterns = sorted(
|
||||
chain(builtinPatterns, userPatterns),
|
||||
key=lambda p: p.fullName not in ["Uniform", "Selected Ammo"])
|
||||
|
||||
self.patternEventMap = {}
|
||||
|
||||
self.items = (OrderedDict(), OrderedDict())
|
||||
for pattern in self.patterns:
|
||||
container = self.items
|
||||
|
||||
@@ -5,7 +5,7 @@ from gui.contextMenu import ContextMenuUnconditional
|
||||
from service.implantSet import ImplantSets as s_ImplantSets
|
||||
|
||||
|
||||
class AddImplantSet(ContextMenuUnconditional):
|
||||
class ImplantSetApply(ContextMenuUnconditional):
|
||||
|
||||
def display(self, callingWindow, srcContext):
|
||||
|
||||
@@ -14,10 +14,11 @@ class AddImplantSet(ContextMenuUnconditional):
|
||||
|
||||
if len(implantSets) == 0:
|
||||
return False
|
||||
|
||||
return srcContext in ("implantItemMisc", "implantEditor")
|
||||
|
||||
def getText(self, callingWindow, itmContext):
|
||||
return "Add Implant Set"
|
||||
def getText(self, callingWindow, context):
|
||||
return "Apply Implant Set"
|
||||
|
||||
def getSubMenu(self, callingWindow, context, rootMenu, i, pitem):
|
||||
m = wx.Menu()
|
||||
@@ -49,4 +50,4 @@ class AddImplantSet(ContextMenuUnconditional):
|
||||
self.callingWindow.addImplantSet(impSet)
|
||||
|
||||
|
||||
AddImplantSet.register()
|
||||
ImplantSetApply.register()
|
||||
77
gui/builtinContextMenus/implantSetSave.py
Normal file
77
gui/builtinContextMenus/implantSetSave.py
Normal file
@@ -0,0 +1,77 @@
|
||||
import wx
|
||||
|
||||
import gui.mainFrame
|
||||
from gui.contextMenu import ContextMenuUnconditional
|
||||
from service.fit import Fit
|
||||
|
||||
|
||||
class ImplantSetSave(ContextMenuUnconditional):
|
||||
|
||||
def __init__(self):
|
||||
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
|
||||
|
||||
def display(self, callingWindow, srcContext):
|
||||
if srcContext not in ('implantItemMisc', 'implantItemMiscChar'):
|
||||
return False
|
||||
|
||||
fit = Fit.getInstance().getFit(self.mainFrame.getActiveFit())
|
||||
self.implants = fit.appliedImplants[:]
|
||||
if not self.implants:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def getText(self, callingWindow, context):
|
||||
return 'Save as New Implant Set'
|
||||
|
||||
def activate(self, callingWindow, fullContext, i):
|
||||
with NameDialog(self.mainFrame, '') as dlg:
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
name = dlg.input.GetLineText(0).strip()
|
||||
if name == '':
|
||||
return
|
||||
from gui.setEditor import ImplantSetEditor
|
||||
ImplantSetEditor.openOne(parent=self.mainFrame, dataToAdd=(name, self.implants))
|
||||
|
||||
|
||||
ImplantSetSave.register()
|
||||
|
||||
|
||||
class NameDialog(wx.Dialog):
|
||||
|
||||
def __init__(self, parent, value):
|
||||
super().__init__(parent, title='New Implant Set', style=wx.DEFAULT_DIALOG_STYLE)
|
||||
self.SetMinSize((346, 156))
|
||||
|
||||
bSizer1 = wx.BoxSizer(wx.VERTICAL)
|
||||
|
||||
bSizer2 = wx.BoxSizer(wx.VERTICAL)
|
||||
text = wx.StaticText(self, wx.ID_ANY, 'Enter a name for your new Implant Set:')
|
||||
bSizer2.Add(text, 0)
|
||||
|
||||
bSizer1.Add(bSizer2, 0, wx.ALL, 10)
|
||||
|
||||
self.input = wx.TextCtrl(self, wx.ID_ANY, style=wx.TE_PROCESS_ENTER)
|
||||
if value is None:
|
||||
value = ''
|
||||
else:
|
||||
value = str(value)
|
||||
self.input.SetValue(value)
|
||||
self.input.SelectAll()
|
||||
|
||||
bSizer1.Add(self.input, 0, wx.LEFT | wx.RIGHT | wx.EXPAND, 15)
|
||||
|
||||
bSizer3 = wx.BoxSizer(wx.VERTICAL)
|
||||
bSizer3.Add(wx.StaticLine(self, wx.ID_ANY), 0, wx.BOTTOM | wx.EXPAND, 15)
|
||||
|
||||
bSizer3.Add(self.CreateStdDialogButtonSizer(wx.OK | wx.CANCEL), 0, wx.EXPAND)
|
||||
bSizer1.Add(bSizer3, 0, wx.ALL | wx.EXPAND, 10)
|
||||
|
||||
self.input.SetFocus()
|
||||
self.input.Bind(wx.EVT_TEXT_ENTER, self.processEnter)
|
||||
self.SetSizer(bSizer1)
|
||||
self.CenterOnParent()
|
||||
self.Fit()
|
||||
|
||||
def processEnter(self, evt):
|
||||
self.EndModal(wx.ID_OK)
|
||||
@@ -1,19 +1,16 @@
|
||||
import gui.fitCommands as cmd
|
||||
import gui.mainFrame
|
||||
from gui.contextMenu import ContextMenuSingle
|
||||
from service.settings import ContextMenuSettings
|
||||
|
||||
|
||||
class FillWithItem(ContextMenuSingle):
|
||||
|
||||
visibilitySetting = 'moduleFill'
|
||||
|
||||
def __init__(self):
|
||||
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
|
||||
self.settings = ContextMenuSettings.getInstance()
|
||||
|
||||
def display(self, callingWindow, srcContext, mainItem):
|
||||
if not self.settings.get('moduleFill'):
|
||||
return False
|
||||
|
||||
if srcContext not in ('marketItemGroup', 'marketItemMisc'):
|
||||
return False
|
||||
|
||||
|
||||
@@ -2,19 +2,16 @@ import gui.fitCommands as cmd
|
||||
import gui.mainFrame
|
||||
from gui.contextMenu import ContextMenuSingle
|
||||
from service.fit import Fit
|
||||
from service.settings import ContextMenuSettings
|
||||
|
||||
|
||||
class ProjectItem(ContextMenuSingle):
|
||||
|
||||
visibilitySetting = 'project'
|
||||
|
||||
def __init__(self):
|
||||
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
|
||||
self.settings = ContextMenuSettings.getInstance()
|
||||
|
||||
def display(self, callingWindow, srcContext, mainItem):
|
||||
if not self.settings.get('project'):
|
||||
return False
|
||||
|
||||
if srcContext not in ("marketItemGroup", "marketItemMisc") or self.mainFrame.getActiveFit() is None:
|
||||
return False
|
||||
|
||||
|
||||
@@ -7,19 +7,16 @@ from gui.contextMenu import ContextMenuCombined
|
||||
from gui.fitCommands.helpers import getSimilarModPositions, getSimilarFighters
|
||||
from service.fit import Fit
|
||||
from service.market import Market
|
||||
from service.settings import ContextMenuSettings
|
||||
|
||||
|
||||
class ChangeItemToVariation(ContextMenuCombined):
|
||||
|
||||
visibilitySetting = 'metaSwap'
|
||||
|
||||
def __init__(self):
|
||||
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
|
||||
self.settings = ContextMenuSettings.getInstance()
|
||||
|
||||
def display(self, callingWindow, srcContext, mainItem, selection):
|
||||
if not self.settings.get('metaSwap'):
|
||||
return False
|
||||
|
||||
if self.mainFrame.getActiveFit() is None or srcContext not in (
|
||||
'fittingModule',
|
||||
'droneItem',
|
||||
@@ -59,8 +56,11 @@ class ChangeItemToVariation(ContextMenuCombined):
|
||||
return x.metaLevel or 0
|
||||
|
||||
def get_metagroup(x):
|
||||
# We want deadspace before officer mods
|
||||
remap = {5: 6, 6: 5}
|
||||
remap = {
|
||||
# We want deadspace before officer mods
|
||||
5: 6, 6: 5,
|
||||
# For structures we want t1-t2-faction
|
||||
54: 52, 52: 54}
|
||||
metaGroup = sMkt.getMetaGroupByItem(x)
|
||||
return remap.get(metaGroup.ID, metaGroup.ID) if metaGroup is not None else 0
|
||||
|
||||
|
||||
@@ -2,20 +2,16 @@ import gui.fitCommands as cmd
|
||||
import gui.mainFrame
|
||||
from gui.contextMenu import ContextMenuSingle
|
||||
from service.fit import Fit
|
||||
from service.settings import ContextMenuSettings
|
||||
|
||||
|
||||
class FillWithModule(ContextMenuSingle):
|
||||
|
||||
visibilitySetting = 'moduleFill'
|
||||
|
||||
def __init__(self):
|
||||
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
|
||||
self.settings = ContextMenuSettings.getInstance()
|
||||
|
||||
def display(self, callingWindow, srcContext, mainItem):
|
||||
|
||||
if not self.settings.get('moduleFill'):
|
||||
return False
|
||||
|
||||
if mainItem is None or getattr(mainItem, 'isEmpty', False):
|
||||
return False
|
||||
|
||||
|
||||
@@ -9,20 +9,17 @@ import gui.mainFrame
|
||||
from eos.utils.spoolSupport import SpoolType, SpoolOptions
|
||||
from gui.contextMenu import ContextMenuSingle
|
||||
from service.fit import Fit
|
||||
from service.settings import ContextMenuSettings
|
||||
|
||||
|
||||
class ChangeModuleSpool(ContextMenuSingle):
|
||||
|
||||
visibilitySetting = 'spoolup'
|
||||
|
||||
def __init__(self):
|
||||
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
|
||||
self.settings = ContextMenuSettings.getInstance()
|
||||
self.resetId = None
|
||||
|
||||
def display(self, callingWindow, srcContext, mainItem):
|
||||
if not self.settings.get('spoolup'):
|
||||
return False
|
||||
|
||||
if srcContext not in ('fittingModule', 'projectedModule') or self.mainFrame.getActiveFit() is None:
|
||||
return False
|
||||
|
||||
|
||||
@@ -8,19 +8,16 @@ from gui.bitmap_loader import BitmapLoader
|
||||
from gui.contextMenu import ContextMenuSingle
|
||||
from service.character import Character
|
||||
from service.fit import Fit
|
||||
from service.settings import ContextMenuSettings
|
||||
|
||||
|
||||
class ChangeAffectingSkills(ContextMenuSingle):
|
||||
|
||||
visibilitySetting = 'changeAffectingSkills'
|
||||
|
||||
def __init__(self):
|
||||
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
|
||||
self.settings = ContextMenuSettings.getInstance()
|
||||
|
||||
def display(self, callingWindow, srcContext, mainItem):
|
||||
if not self.settings.get('changeAffectingSkills'):
|
||||
return False
|
||||
|
||||
if srcContext not in (
|
||||
"fittingModule", "fittingCharge",
|
||||
"fittingShip", "droneItem",
|
||||
|
||||
@@ -10,12 +10,13 @@ _ValueChanged, EVT_VALUE_CHANGED = wx.lib.newevent.NewEvent()
|
||||
|
||||
|
||||
class AttributeSliderChangeEvent:
|
||||
def __init__(self, obj, old_value, new_value, old_percentage, new_percentage):
|
||||
def __init__(self, obj, old_value, new_value, old_percentage, new_percentage, affect_modified_flag=True):
|
||||
self.__obj = obj
|
||||
self.__old = old_value
|
||||
self.__new = new_value
|
||||
self.__old_percent = old_percentage
|
||||
self.__new_percent = new_percentage
|
||||
self.__affect_modified_flag = affect_modified_flag
|
||||
|
||||
def GetObj(self):
|
||||
return self.__obj
|
||||
@@ -32,6 +33,10 @@ class AttributeSliderChangeEvent:
|
||||
def GetPercentage(self):
|
||||
return self.__new_percent
|
||||
|
||||
@property
|
||||
def AffectsModifiedFlag(self):
|
||||
return self.__affect_modified_flag
|
||||
|
||||
Object = property(GetObj)
|
||||
OldValue = property(GetOldValue)
|
||||
Value = property(GetValue)
|
||||
@@ -40,9 +45,9 @@ class AttributeSliderChangeEvent:
|
||||
|
||||
|
||||
class ValueChanged(_ValueChanged, AttributeSliderChangeEvent):
|
||||
def __init__(self, obj, old_value, new_value, old_percentage, new_percentage):
|
||||
def __init__(self, obj, old_value, new_value, old_percentage, new_percentage, affect_modified_flag=True):
|
||||
_ValueChanged.__init__(self)
|
||||
AttributeSliderChangeEvent.__init__(self, obj, old_value, new_value, old_percentage, new_percentage)
|
||||
AttributeSliderChangeEvent.__init__(self, obj, old_value, new_value, old_percentage, new_percentage, affect_modified_flag=affect_modified_flag)
|
||||
|
||||
|
||||
class AttributeSlider(wx.Panel):
|
||||
@@ -118,7 +123,7 @@ class AttributeSlider(wx.Panel):
|
||||
self.SetValue(self.GetValue())
|
||||
evt.Skip()
|
||||
|
||||
def SetValue(self, value, post_event=True):
|
||||
def SetValue(self, value, post_event=True, affect_modified_flag=True):
|
||||
self.ctrl.SetValue(value)
|
||||
invert_factor = -1 if self.inverse else 1
|
||||
if value >= self.base_value:
|
||||
@@ -127,7 +132,7 @@ class AttributeSlider(wx.Panel):
|
||||
slider_percentage = (value - self.base_value) / (self.base_value - self.UserMinValue) * 100 * invert_factor
|
||||
self.slider.SetValue(slider_percentage)
|
||||
if post_event:
|
||||
wx.PostEvent(self, ValueChanged(self, None, value, None, slider_percentage))
|
||||
wx.PostEvent(self, ValueChanged(self, None, value, None, slider_percentage, affect_modified_flag=affect_modified_flag))
|
||||
|
||||
def OnMouseWheel(self, evt):
|
||||
if evt.GetWheelRotation() > 0 and evt.GetWheelAxis() == wx.MOUSE_WHEEL_VERTICAL:
|
||||
|
||||
@@ -76,6 +76,7 @@ class ItemMutatorList(wx.ScrolledWindow):
|
||||
self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW))
|
||||
self.mod = mod
|
||||
self.timer = None
|
||||
self.isModified = False
|
||||
|
||||
goodColor = wx.Colour(96, 191, 0)
|
||||
badColor = wx.Colour(255, 64, 0)
|
||||
@@ -171,6 +172,8 @@ class ItemMutatorList(wx.ScrolledWindow):
|
||||
self.SetSizer(sizer)
|
||||
|
||||
def changeMutatedValue(self, evt):
|
||||
if evt.AffectsModifiedFlag:
|
||||
self.isModified = True
|
||||
m = self.event_mapping[evt.Object]
|
||||
value = evt.Value
|
||||
value = m.attribute.unit.ComplicateValue(value)
|
||||
@@ -188,29 +191,32 @@ class ItemMutatorList(wx.ScrolledWindow):
|
||||
self.timer = wx.CallLater(1000, self.callLater)
|
||||
|
||||
def resetMutatedValues(self, evt):
|
||||
self.isModified = True
|
||||
sFit = Fit.getInstance()
|
||||
for slider, m in self.event_mapping.items():
|
||||
value = sFit.changeMutatedValuePrelim(m, m.baseValue)
|
||||
value = m.attribute.unit.SimplifyValue(value)
|
||||
slider.SetValue(value)
|
||||
slider.SetValue(value, affect_modified_flag=False)
|
||||
evt.Skip()
|
||||
|
||||
def randomMutatedValues(self, evt):
|
||||
self.isModified = True
|
||||
sFit = Fit.getInstance()
|
||||
for slider, m in self.event_mapping.items():
|
||||
value = random.uniform(m.minValue, m.maxValue)
|
||||
value = sFit.changeMutatedValuePrelim(m, value)
|
||||
value = m.attribute.unit.SimplifyValue(value)
|
||||
slider.SetValue(value)
|
||||
slider.SetValue(value, affect_modified_flag=False)
|
||||
evt.Skip()
|
||||
|
||||
def revertChanges(self, evt):
|
||||
self.isModified = False
|
||||
sFit = Fit.getInstance()
|
||||
for slider, m in self.event_mapping.items():
|
||||
if m.attrID in self.initialMutations:
|
||||
value = sFit.changeMutatedValuePrelim(m, self.initialMutations[m.attrID])
|
||||
value = m.attribute.unit.SimplifyValue(value)
|
||||
slider.SetValue(value)
|
||||
slider.SetValue(value, affect_modified_flag=False)
|
||||
evt.Skip()
|
||||
|
||||
def OnWindowClose(self):
|
||||
@@ -218,15 +224,18 @@ class ItemMutatorList(wx.ScrolledWindow):
|
||||
sFit = Fit.getInstance()
|
||||
fit = sFit.getFit(self.carryingFitID)
|
||||
if self.mod in fit.modules:
|
||||
currentMutation = {}
|
||||
for slider, m in self.event_mapping.items():
|
||||
# Sliders may have more up-to-date info than mutator in case we changed
|
||||
# value in slider and without confirming it, decided to close window
|
||||
value = slider.GetValue()
|
||||
value = m.attribute.unit.ComplicateValue(value)
|
||||
if value != m.value:
|
||||
value = sFit.changeMutatedValuePrelim(m, value)
|
||||
currentMutation[m.attrID] = value
|
||||
if self.isModified:
|
||||
currentMutation = {}
|
||||
for slider, m in self.event_mapping.items():
|
||||
# Sliders may have more up-to-date info than mutator in case we changed
|
||||
# value in slider and without confirming it, decided to close window
|
||||
value = slider.GetValue()
|
||||
value = m.attribute.unit.ComplicateValue(value)
|
||||
if value != m.value:
|
||||
value = sFit.changeMutatedValuePrelim(m, value)
|
||||
currentMutation[m.attrID] = value
|
||||
else:
|
||||
currentMutation = self.initialMutations
|
||||
mainFrame = gui.mainFrame.MainFrame.getInstance()
|
||||
mainFrame.getCommandForFit(self.carryingFitID).Submit(cmd.GuiChangeLocalModuleMutationCommand(
|
||||
fitID=self.carryingFitID,
|
||||
|
||||
@@ -21,9 +21,12 @@ class PFContextMenuPref(PreferenceView):
|
||||
self.stTitle.SetFont(wx.Font(12, 70, 90, 90, False, wx.EmptyString))
|
||||
mainSizer.Add(self.stTitle, 0, wx.EXPAND | wx.ALL, 5)
|
||||
|
||||
self.stSubTitle = wx.StaticText(panel, wx.ID_ANY,
|
||||
"Disabling context menus can improve responsiveness.",
|
||||
wx.DefaultPosition, wx.DefaultSize, 0)
|
||||
self.stSubTitle = wx.StaticText(
|
||||
panel, wx.ID_ANY,
|
||||
'Disabling context menus can improve responsiveness.\n'
|
||||
'You can hold {} key + right-click to show all menu items regardless of these settings.'.format(
|
||||
'Command' if 'wxMac' in wx.PlatformInfo else 'Control'),
|
||||
wx.DefaultPosition, wx.DefaultSize, 0)
|
||||
self.stSubTitle.Wrap(-1)
|
||||
mainSizer.Add(self.stSubTitle, 0, wx.ALL, 5)
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
import wx
|
||||
from gui.statsView import StatsView
|
||||
from gui.bitmap_loader import BitmapLoader
|
||||
from gui.utils.numberFormatter import formatAmount
|
||||
from gui.utils.numberFormatter import formatAmount, roundToPrec
|
||||
|
||||
|
||||
class CapacitorViewFull(StatsView):
|
||||
@@ -139,14 +139,14 @@ class CapacitorViewFull(StatsView):
|
||||
lines.append(' +{} GJ/s'.format(formatAmount(cap_recharge, 3, 0, 3)))
|
||||
lines.append(' -{} GJ/s'.format(formatAmount(cap_use, 3, 0, 3)))
|
||||
delta = round(cap_recharge - cap_use, 3)
|
||||
if delta > 0 and neut_res < 1:
|
||||
if delta > 0 and 0 < round(neut_res, 4) < 1:
|
||||
lines.append('')
|
||||
lines.append('Effective excessive gain:')
|
||||
lines.append(' +{} GJ/s'.format(formatAmount(delta / neut_res, 3, 0, 3)))
|
||||
label.SetToolTip(wx.ToolTip('\n'.join(lines)))
|
||||
if labelName == 'label%sCapacitorResist':
|
||||
texts = ['Neutralizer resistance']
|
||||
if cap_amount > 0 and neut_res < 1:
|
||||
if cap_amount > 0 and 0 < round(neut_res, 4) < 1:
|
||||
texts.append('Effective capacity: {} GJ'.format(formatAmount(cap_amount / neut_res, 3, 0, 9)))
|
||||
label.SetToolTip(wx.ToolTip('\n'.join(texts)))
|
||||
|
||||
|
||||
@@ -339,23 +339,25 @@ class Miscellanea(ViewColumn):
|
||||
formatAmount(radar, 3, 0, 3),
|
||||
)
|
||||
return text, tooltip
|
||||
elif itemGroup in ("Remote Sensor Booster", "Sensor Booster", "Signal Amplifier"):
|
||||
elif itemGroup in ("Remote Sensor Booster", "Sensor Booster", "Signal Amplifier", "Structure Signal Amplifier"):
|
||||
textLines = []
|
||||
tooltipLines = []
|
||||
scanResBonus = stuff.getModifiedItemAttr("scanResolutionBonus")
|
||||
if scanResBonus:
|
||||
textLines.append("{}%".format(formatAmount(scanResBonus, 3, 0, 3)))
|
||||
tooltipLines.append("{}% scan resolution".format(formatAmount(scanResBonus, 3, 0, 3)))
|
||||
lockRangeBonus = stuff.getModifiedItemAttr("maxTargetRangeBonus")
|
||||
if lockRangeBonus:
|
||||
textLines.append("{}%".format(formatAmount(lockRangeBonus, 3, 0, 3)))
|
||||
tooltipLines.append("{}% lock range".format(formatAmount(lockRangeBonus, 3, 0, 3)))
|
||||
gravBonus = stuff.getModifiedItemAttr("scanGravimetricStrengthPercent")
|
||||
if scanResBonus is None or lockRangeBonus is None or gravBonus is None:
|
||||
if gravBonus:
|
||||
textLines.append("{}%".format(formatAmount(gravBonus, 3, 0, 3)))
|
||||
tooltipLines.append("{}% sensor strength".format(formatAmount(gravBonus, 3, 0, 3)))
|
||||
if not textLines:
|
||||
return "", None
|
||||
|
||||
text = "{0}% | {1}% | {2}%".format(
|
||||
formatAmount(scanResBonus, 3, 0, 3),
|
||||
formatAmount(lockRangeBonus, 3, 0, 3),
|
||||
formatAmount(gravBonus, 3, 0, 3),
|
||||
)
|
||||
tooltip = "Applied bonuses:\n{0}% scan resolution | {1}% lock range | {2}% sensor strength".format(
|
||||
formatAmount(scanResBonus, 3, 0, 3),
|
||||
formatAmount(lockRangeBonus, 3, 0, 3),
|
||||
formatAmount(gravBonus, 3, 0, 3),
|
||||
)
|
||||
text = " | ".join(textLines)
|
||||
tooltip = "Applied bonuses:\n{}".format(" | ".join(tooltipLines))
|
||||
return text, tooltip
|
||||
elif itemGroup in ("Projected ECCM", "ECCM", "Sensor Backup Array"):
|
||||
grav = stuff.getModifiedItemAttr("scanGravimetricStrengthPercent")
|
||||
@@ -588,7 +590,7 @@ class Miscellanea(ViewColumn):
|
||||
):
|
||||
if "Armor" in itemGroup or "Shield" in itemGroup:
|
||||
boosted_attribute = "HP"
|
||||
reload_time = item.getAttribute("reloadTime", 0) / 1000
|
||||
reload_time = stuff.getModifiedItemAttr("reloadTime", 0) / 1000
|
||||
elif "Capacitor" in itemGroup:
|
||||
boosted_attribute = "Cap"
|
||||
reload_time = 10
|
||||
|
||||
@@ -178,10 +178,17 @@ class EntityEditor(wx.Panel):
|
||||
return True
|
||||
|
||||
def checkEntitiesExist(self):
|
||||
if len(self.choices) == 0:
|
||||
self.Parent.Hide()
|
||||
if self.OnNew(None) is False:
|
||||
return False
|
||||
self.Parent.Show()
|
||||
if len(self.choices) > 0:
|
||||
return True
|
||||
else:
|
||||
return self.enterNewEntity()
|
||||
|
||||
def enterNewEntity(self):
|
||||
self.Parent.Hide()
|
||||
if self.OnNew(None) is False:
|
||||
return False
|
||||
self.Parent.Show()
|
||||
|
||||
return True
|
||||
|
||||
|
||||
|
||||
@@ -23,6 +23,8 @@ from abc import ABCMeta, abstractmethod
|
||||
import wx
|
||||
from logbook import Logger
|
||||
|
||||
from service.settings import ContextMenuSettings
|
||||
|
||||
|
||||
pyfalog = Logger(__name__)
|
||||
|
||||
@@ -32,6 +34,7 @@ class ContextMenu(metaclass=ABCMeta):
|
||||
menus = []
|
||||
_ids = [] # [wx.NewId() for x in xrange(200)] # init with decent amount
|
||||
_idxid = -1
|
||||
visibilitySetting = None
|
||||
|
||||
@classmethod
|
||||
def register(cls):
|
||||
@@ -72,6 +75,10 @@ class ContextMenu(metaclass=ABCMeta):
|
||||
ContextMenu._idxid = -1
|
||||
debug_start = len(ContextMenu._ids)
|
||||
|
||||
# Control being pressed forces all hidden menu items to be shown
|
||||
visibilitySettingOverride = wx.GetMouseState().GetModifiers() == wx.MOD_CONTROL
|
||||
cmSettings = ContextMenuSettings.getInstance()
|
||||
|
||||
rootMenu = wx.Menu()
|
||||
rootMenu.info = {}
|
||||
rootMenu.selection = (selection,) if not hasattr(selection, "__iter__") else selection
|
||||
@@ -87,7 +94,11 @@ class ContextMenu(metaclass=ABCMeta):
|
||||
for menuHandler in cls.menus:
|
||||
# loop through registered menus
|
||||
m = menuHandler()
|
||||
if m._baseDisplay(callingWindow, srcContext, mainItem, selection):
|
||||
if m.visibilitySetting:
|
||||
visible = visibilitySettingOverride or cmSettings.get(m.visibilitySetting)
|
||||
else:
|
||||
visible = True
|
||||
if visible and m._baseDisplay(callingWindow, srcContext, mainItem, selection):
|
||||
display_amount += 1
|
||||
texts = m._baseGetText(callingWindow, itemContext, mainItem, selection)
|
||||
|
||||
|
||||
@@ -321,7 +321,10 @@ def activeStateLimit(itemIdentity):
|
||||
item = Market.getInstance().getItem(itemIdentity)
|
||||
if {
|
||||
'moduleBonusAssaultDamageControl', 'moduleBonusIndustrialInvulnerability',
|
||||
'microJumpDrive', 'microJumpPortalDrive', 'emergencyHullEnergizer'
|
||||
'microJumpDrive', 'microJumpPortalDrive', 'emergencyHullEnergizer',
|
||||
'cynosuralGeneration', 'jumpPortalGeneration', 'jumpPortalGenerationBO',
|
||||
'cloneJumpAccepting', 'cloakingWarpSafe', 'cloakingPrototype', 'cloaking',
|
||||
'massEntanglerEffect5', 'electronicAttributeModifyOnline', 'targetPassively'
|
||||
}.intersection(item.effects):
|
||||
return FittingModuleState.ONLINE
|
||||
return FittingModuleState.ACTIVE
|
||||
|
||||
@@ -47,7 +47,7 @@ class ImplantTextValidor(BaseValidator):
|
||||
if len(text) == 0:
|
||||
raise ValueError("You must supply a name for the Implant Set!")
|
||||
elif text in [x.name for x in entityEditor.choices]:
|
||||
raise ValueError("Imlplant Set name already in use, please choose another.")
|
||||
raise ValueError("Implant Set name already in use, please choose another.")
|
||||
|
||||
return True
|
||||
except ValueError as e:
|
||||
@@ -106,7 +106,7 @@ class ImplantSetEditorView(BaseImplantEditorView):
|
||||
sIS = ImplantSets.getInstance()
|
||||
set_ = self.Parent.entityEditor.getActiveEntity()
|
||||
|
||||
sIS.addImplant(set_.ID, item.ID)
|
||||
sIS.addImplants(set_.ID, item.ID)
|
||||
|
||||
def removeImplantFromContext(self, implant):
|
||||
sIS = ImplantSets.getInstance()
|
||||
@@ -117,7 +117,7 @@ class ImplantSetEditorView(BaseImplantEditorView):
|
||||
|
||||
class ImplantSetEditor(AuxiliaryFrame):
|
||||
|
||||
def __init__(self, parent):
|
||||
def __init__(self, parent, dataToAdd=None):
|
||||
super().__init__(
|
||||
parent, id=wx.ID_ANY, title="Implant Set Editor", resizeable=True,
|
||||
size=wx.Size(950, 500) if "wxGTK" in wx.PlatformInfo else wx.Size(850, 420))
|
||||
@@ -166,7 +166,13 @@ class ImplantSetEditor(AuxiliaryFrame):
|
||||
self.SetSizer(mainSizer)
|
||||
self.Layout()
|
||||
|
||||
if not self.entityEditor.checkEntitiesExist():
|
||||
if dataToAdd:
|
||||
name, implants = dataToAdd
|
||||
newSet = self.entityEditor.DoNew(name)
|
||||
ImplantSets.getInstance().addImplants(newSet.ID, *[i.item.ID for i in implants])
|
||||
self.entityEditor.refreshEntityList(newSet)
|
||||
wx.PostEvent(self.entityEditor.entityChoices, wx.CommandEvent(wx.wxEVT_COMMAND_CHOICE_SELECTED))
|
||||
elif not self.entityEditor.checkEntitiesExist():
|
||||
self.Close()
|
||||
return
|
||||
|
||||
|
||||
@@ -189,7 +189,7 @@ class ShipBrowser(wx.Panel):
|
||||
|
||||
RACE_ORDER = [
|
||||
"amarr", "caldari", "gallente", "minmatar",
|
||||
"sisters", "ore",
|
||||
"sisters", "ore", "concord",
|
||||
"serpentis", "angel", "blood", "sansha", "guristas", "mordu",
|
||||
"jove", "upwell", "triglavian", None
|
||||
]
|
||||
|
||||
BIN
imgs/gui/race_concord_small.png
Normal file
BIN
imgs/gui/race_concord_small.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.8 KiB |
@@ -1,4 +1,4 @@
|
||||
wxPython == 4.0.6
|
||||
wxPython == 4.0.7.post2
|
||||
logbook >= 1.0.0
|
||||
matplotlib == 3.0.3
|
||||
numpy==1.16.4
|
||||
@@ -11,4 +11,3 @@ packaging == 16.8
|
||||
roman == 2.0.0
|
||||
beautifulsoup4 == 4.6.0
|
||||
pyyaml >= 5.1
|
||||
PyInstaller == 3.3
|
||||
|
||||
@@ -5,3 +5,4 @@ sudo python3 -m ensurepip --upgrade
|
||||
# A manual check that the correct version of Python is running.
|
||||
python3 --version
|
||||
python3 -m pip install -r requirements.txt
|
||||
python3 -m pip install PyInstaller
|
||||
|
||||
@@ -7,37 +7,17 @@ item's name. The name of the file is usually arbitrary unless it's used in logic
|
||||
elsewhere (in which case can be accessed with packs[name])
|
||||
"""
|
||||
|
||||
import pkgutil
|
||||
|
||||
from eos.utils.pyinst_support import iterNamespace
|
||||
|
||||
|
||||
# init parent dict
|
||||
all = {}
|
||||
|
||||
# init container to store the separate conversion packs in case we need them
|
||||
packs = {}
|
||||
|
||||
prefix = __name__ + "."
|
||||
|
||||
# load modules to work based with and without pyinstaller
|
||||
# from: https://github.com/webcomics/dosage/blob/master/dosagelib/loader.py
|
||||
# see: https://github.com/pyinstaller/pyinstaller/issues/1905
|
||||
|
||||
# load modules using iter_modules()
|
||||
# (should find all filters in normal build, but not pyinstaller)
|
||||
module_names = [m[1] for m in pkgutil.iter_modules(__path__, prefix)]
|
||||
|
||||
# special handling for PyInstaller
|
||||
importers = map(pkgutil.get_importer, __path__)
|
||||
toc = set()
|
||||
for i in importers:
|
||||
if hasattr(i, 'toc'):
|
||||
toc |= i.toc
|
||||
|
||||
for elm in toc:
|
||||
if elm.startswith(prefix):
|
||||
module_names.append(elm)
|
||||
|
||||
for modname in module_names:
|
||||
conversionPack = __import__(modname, fromlist="dummy")
|
||||
for modName in iterNamespace(__name__, __path__):
|
||||
conversionPack = __import__(modName, fromlist="dummy")
|
||||
all.update(conversionPack.CONVERSIONS)
|
||||
modname_tail = modname.rsplit('.', 1)[-1]
|
||||
modname_tail = modName.rsplit('.', 1)[-1]
|
||||
packs[modname_tail] = conversionPack.CONVERSIONS
|
||||
|
||||
@@ -4,5 +4,23 @@ Conversion pack for August 2019 release
|
||||
|
||||
CONVERSIONS = {
|
||||
# Renamed items
|
||||
"Gravid 1MN Afterburner MutaPlasmid": "Gravid 1MN Afterburner Mutaplasmid",
|
||||
'Gravid 1MN Afterburner MutaPlasmid': 'Gravid 1MN Afterburner Mutaplasmid',
|
||||
'Low-grade Slave Alpha': 'Low-grade Amulet Alpha',
|
||||
'Low-grade Slave Beta': 'Low-grade Amulet Beta',
|
||||
'Low-grade Slave Gamma': 'Low-grade Amulet Gamma',
|
||||
'Low-grade Slave Delta': 'Low-grade Amulet Delta',
|
||||
'Low-grade Slave Epsilon': 'Low-grade Amulet Epsilon',
|
||||
'Low-grade Slave Omega': 'Low-grade Amulet Omega',
|
||||
'Mid-grade Slave Alpha': 'Mid-grade Amulet Alpha',
|
||||
'Mid-grade Slave Beta': 'Mid-grade Amulet Beta',
|
||||
'Mid-grade Slave Gamma': 'Mid-grade Amulet Gamma',
|
||||
'Mid-grade Slave Delta': 'Mid-grade Amulet Delta',
|
||||
'Mid-grade Slave Epsilon': 'Mid-grade Amulet Epsilon',
|
||||
'Mid-grade Slave Omega': 'Mid-grade Amulet Omega',
|
||||
'High-grade Slave Alpha': 'High-grade Amulet Alpha',
|
||||
'High-grade Slave Beta': 'High-grade Amulet Beta',
|
||||
'High-grade Slave Gamma': 'High-grade Amulet Gamma',
|
||||
'High-grade Slave Delta': 'High-grade Amulet Delta',
|
||||
'High-grade Slave Epsilon': 'High-grade Amulet Epsilon',
|
||||
'High-grade Slave Omega': 'High-grade Amulet Omega'
|
||||
}
|
||||
|
||||
14
service/conversions/releaseJan2020.py
Normal file
14
service/conversions/releaseJan2020.py
Normal file
@@ -0,0 +1,14 @@
|
||||
"""
|
||||
Conversion pack for Januray 2020 release
|
||||
"""
|
||||
|
||||
CONVERSIONS = {
|
||||
'Small C5-L Emergency Shield Overload I': 'Small C5-L Compact Shield Booster',
|
||||
'Small Clarity Ward Booster I': 'Small Clarity Ward Enduring Shield Booster',
|
||||
'Medium Clarity Ward Booster I': 'Medium Clarity Ward Enduring Shield Booster',
|
||||
'Medium C5-L Emergency Shield Overload I': 'Medium C5-L Compact Shield Booster',
|
||||
'Large Clarity Ward Booster I': 'Large Clarity Ward Enduring Shield Booster',
|
||||
'Large C5-L Emergency Shield Overload I': 'Large C5-L Compact Shield Booster',
|
||||
'X-Large Clarity Ward Booster I': 'X-Large Clarity Ward Enduring Shield Booster',
|
||||
'X-Large C5-L Emergency Shield Overload I': 'X-Large C5-L Compact Shield Booster'
|
||||
}
|
||||
@@ -53,13 +53,13 @@ class DamagePattern:
|
||||
@staticmethod
|
||||
def newPattern(name):
|
||||
p = es_DamagePattern(0, 0, 0, 0)
|
||||
p.name = name
|
||||
p.rawName = name
|
||||
eos.db.save(p)
|
||||
return p
|
||||
|
||||
@staticmethod
|
||||
def renamePattern(p, newName):
|
||||
p.name = newName
|
||||
p.rawName = newName
|
||||
eos.db.save(p)
|
||||
|
||||
@staticmethod
|
||||
@@ -91,5 +91,5 @@ class DamagePattern:
|
||||
if patterns[i].name in ("Uniform", "Selected Ammo"):
|
||||
del patterns[i]
|
||||
|
||||
patterns.sort(key=lambda p: p.name)
|
||||
patterns.sort(key=lambda p: p.fullName)
|
||||
return es_DamagePattern.exportPatterns(*patterns)
|
||||
|
||||
@@ -52,11 +52,12 @@ class ImplantSets:
|
||||
return eos.db.getImplantSet(setID).implants
|
||||
|
||||
@staticmethod
|
||||
def addImplant(setID, itemID):
|
||||
def addImplants(setID, *itemIDs):
|
||||
implant_set = eos.db.getImplantSet(setID)
|
||||
implant = es_Implant(eos.db.getItem(itemID))
|
||||
implant_set.implants.makeRoom(implant)
|
||||
implant_set.implants.append(implant)
|
||||
for itemID in itemIDs:
|
||||
implant = es_Implant(eos.db.getItem(itemID))
|
||||
implant_set.implants.makeRoom(implant)
|
||||
implant_set.implants.append(implant)
|
||||
eos.db.commit()
|
||||
|
||||
@staticmethod
|
||||
|
||||
@@ -306,3 +306,4 @@ cdfe: Core Defense Field Extender
|
||||
lg: Low-grade
|
||||
mg: Mid-grade
|
||||
hg: High-grade
|
||||
slave: amulet
|
||||
|
||||
@@ -267,7 +267,9 @@ class Market:
|
||||
"Medium Nano Armor Repair Unit I": ("Tech I", "Medium Armor Repairer I"),
|
||||
"Large 'Reprieve' Vestment Reconstructer I": ("Storyline", "Large Armor Repairer I"),
|
||||
"Khanid Navy Torpedo Launcher": ("Faction", "Torpedo Launcher I"),
|
||||
"Dark Blood Tracking Disruptor": ("Faction", "Tracking Disruptor I")}
|
||||
"Dark Blood Tracking Disruptor": ("Faction", "Tracking Disruptor I"),
|
||||
"Dread Guristas Standup Variable Spectrum ECM": ("Structure Faction", "Standup Variable Spectrum ECM I"),
|
||||
"Dark Blood Standup Heavy Energy Neutralizer": ("Structure Faction", "Standup Heavy Energy Neutralizer I")}
|
||||
# Parent type name: set(item names)
|
||||
self.ITEMS_FORCEDMETAGROUP_R = {}
|
||||
for item, value in list(self.ITEMS_FORCEDMETAGROUP.items()):
|
||||
@@ -280,27 +282,18 @@ class Market:
|
||||
self.ITEMS_FORCEDMARKETGROUP = {
|
||||
"Advanced Cerebral Accelerator" : 2487, # Implants & Boosters > Booster > Cerebral Accelerators
|
||||
"Civilian Hobgoblin" : 837, # Drones > Combat Drones > Light Scout Drones
|
||||
"Civilian Light Missile Launcher" : 640,
|
||||
# Ship Equipment > Turrets & Bays > Missile Launchers > Light Missile Launchers
|
||||
"Civilian Scourge Light Missile" : 920,
|
||||
# Ammunition & Charges > Missiles > Light Missiles > Standard Light Missiles
|
||||
"Civilian Small Remote Armor Repairer" : 1059,
|
||||
# Ship Equipment > Hull & Armor > Remote Armor Repairers > Small
|
||||
"Civilian Light Missile Launcher" : 640, # Ship Equipment > Turrets & Launchers > Missile Launchers > Light Missile Launchers
|
||||
"Civilian Scourge Light Missile" : 920, # Ammunition & Charges > Missiles > Light Missiles > Standard Light Missiles
|
||||
"Civilian Small Remote Armor Repairer" : 1059, # Ship Equipment > Hull & Armor > Remote Armor Repairers > Small
|
||||
"Civilian Small Remote Shield Booster" : 603, # Ship Equipment > Shield > Remote Shield Boosters > Small
|
||||
"Hardwiring - Zainou 'Sharpshooter' ZMX10" : 1493,
|
||||
# Implants & Boosters > Implants > Skill Hardwiring > Missile Implants > Implant Slot 06
|
||||
"Hardwiring - Zainou 'Sharpshooter' ZMX100" : 1493,
|
||||
# Implants & Boosters > Implants > Skill Hardwiring > Missile Implants > Implant Slot 06
|
||||
"Hardwiring - Zainou 'Sharpshooter' ZMX1000": 1493,
|
||||
# Implants & Boosters > Implants > Skill Hardwiring > Missile Implants > Implant Slot 06
|
||||
"Hardwiring - Zainou 'Sharpshooter' ZMX11" : 1493,
|
||||
# Implants & Boosters > Implants > Skill Hardwiring > Missile Implants > Implant Slot 06
|
||||
"Hardwiring - Zainou 'Sharpshooter' ZMX110" : 1493,
|
||||
# Implants & Boosters > Implants > Skill Hardwiring > Missile Implants > Implant Slot 06
|
||||
"Hardwiring - Zainou 'Sharpshooter' ZMX1100": 1493,
|
||||
# Implants & Boosters > Implants > Skill Hardwiring > Missile Implants > Implant Slot 06
|
||||
"Hardwiring - Zainou 'Sharpshooter' ZMX10" : 1493, # Implants & Boosters > Implants > Skill Hardwiring > Missile Implants > Implant Slot 06
|
||||
"Hardwiring - Zainou 'Sharpshooter' ZMX100" : 1493, # Implants & Boosters > Implants > Skill Hardwiring > Missile Implants > Implant Slot 06
|
||||
"Hardwiring - Zainou 'Sharpshooter' ZMX1000": 1493, # Implants & Boosters > Implants > Skill Hardwiring > Missile Implants > Implant Slot 06
|
||||
"Hardwiring - Zainou 'Sharpshooter' ZMX11" : 1493, # Implants & Boosters > Implants > Skill Hardwiring > Missile Implants > Implant Slot 06
|
||||
"Hardwiring - Zainou 'Sharpshooter' ZMX110" : 1493, # Implants & Boosters > Implants > Skill Hardwiring > Missile Implants > Implant Slot 06
|
||||
"Hardwiring - Zainou 'Sharpshooter' ZMX1100": 1493, # Implants & Boosters > Implants > Skill Hardwiring > Missile Implants > Implant Slot 06
|
||||
"Prototype Cerebral Accelerator" : 2487, # Implants & Boosters > Booster > Cerebral Accelerators
|
||||
"Prototype Iris Probe Launcher" : 712, # Ship Equipment > Turrets & Bays > Scan Probe Launchers
|
||||
"Prototype Iris Probe Launcher" : 712, # Ship Equipment > Scanning Equipment > Scan Probe Launchers
|
||||
"Standard Cerebral Accelerator" : 2487, # Implants & Boosters > Booster > Cerebral Accelerators
|
||||
}
|
||||
|
||||
@@ -808,7 +801,7 @@ class Market:
|
||||
def getReplacements(self, identity):
|
||||
item = self.getItem(identity)
|
||||
# We already store needed type IDs in database
|
||||
replTypeIDs = {int(i) for i in item.replacements.split(",") if i}
|
||||
replTypeIDs = {int(i) for i in item.replacements.split(",") if i} if item.replacements is not None else {}
|
||||
if not replTypeIDs:
|
||||
return ()
|
||||
# As replacements were generated without keeping track which items were published,
|
||||
|
||||
@@ -48,13 +48,13 @@ class TargetProfile:
|
||||
@staticmethod
|
||||
def newPattern(name):
|
||||
p = es_TargetProfile()
|
||||
p.name = name
|
||||
p.rawName = name
|
||||
db.save(p)
|
||||
return p
|
||||
|
||||
@staticmethod
|
||||
def renamePattern(p, newName):
|
||||
p.name = newName
|
||||
p.rawName = newName
|
||||
db.save(p)
|
||||
|
||||
@staticmethod
|
||||
@@ -82,5 +82,5 @@ class TargetProfile:
|
||||
|
||||
def exportPatterns(self):
|
||||
patterns = self.getUserTargetProfileList()
|
||||
patterns.sort(key=lambda p: p.name)
|
||||
patterns.sort(key=lambda p: p.fullName)
|
||||
return es_TargetProfile.exportPatterns(*patterns)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,524 +0,0 @@
|
||||
[
|
||||
{
|
||||
"dataID": 16545434,
|
||||
"description": "Meter",
|
||||
"descriptionID": 77965,
|
||||
"displayName": "m",
|
||||
"displayNameID": 78005,
|
||||
"unitID": 1,
|
||||
"unitName": "Length"
|
||||
},
|
||||
{
|
||||
"dataID": 16545435,
|
||||
"description": "Kilogram",
|
||||
"descriptionID": 77966,
|
||||
"displayName": "kg",
|
||||
"displayNameID": 78006,
|
||||
"unitID": 2,
|
||||
"unitName": "Mass"
|
||||
},
|
||||
{
|
||||
"dataID": 16545436,
|
||||
"description": "Second",
|
||||
"descriptionID": 77967,
|
||||
"displayName": "sec",
|
||||
"displayNameID": 78007,
|
||||
"unitID": 3,
|
||||
"unitName": "Time"
|
||||
},
|
||||
{
|
||||
"dataID": 16545437,
|
||||
"description": "Ampere",
|
||||
"descriptionID": 77968,
|
||||
"displayName": "A",
|
||||
"displayNameID": 78008,
|
||||
"unitID": 4,
|
||||
"unitName": "Electric Current"
|
||||
},
|
||||
{
|
||||
"dataID": 16545438,
|
||||
"description": "Kelvin",
|
||||
"descriptionID": 77969,
|
||||
"displayName": "K",
|
||||
"displayNameID": 78009,
|
||||
"unitID": 5,
|
||||
"unitName": "Temperature"
|
||||
},
|
||||
{
|
||||
"dataID": 16545439,
|
||||
"description": "Mole",
|
||||
"descriptionID": 77970,
|
||||
"displayName": "mol",
|
||||
"displayNameID": 78010,
|
||||
"unitID": 6,
|
||||
"unitName": "Amount Of Substance"
|
||||
},
|
||||
{
|
||||
"dataID": 16545440,
|
||||
"description": "Candela",
|
||||
"descriptionID": 77971,
|
||||
"displayName": "cd",
|
||||
"displayNameID": 78011,
|
||||
"unitID": 7,
|
||||
"unitName": "Luminous Intensity"
|
||||
},
|
||||
{
|
||||
"dataID": 16545441,
|
||||
"description": "Square meter",
|
||||
"descriptionID": 77972,
|
||||
"displayName": "m2",
|
||||
"displayNameID": 78012,
|
||||
"unitID": 8,
|
||||
"unitName": "Area"
|
||||
},
|
||||
{
|
||||
"dataID": 16545442,
|
||||
"description": "Cubic meter",
|
||||
"descriptionID": 77973,
|
||||
"displayName": "m3",
|
||||
"displayNameID": 78013,
|
||||
"unitID": 9,
|
||||
"unitName": "Volume"
|
||||
},
|
||||
{
|
||||
"dataID": 16545443,
|
||||
"description": "Meter per second",
|
||||
"descriptionID": 77974,
|
||||
"displayName": "m/sec",
|
||||
"displayNameID": 78014,
|
||||
"unitID": 10,
|
||||
"unitName": "Speed"
|
||||
},
|
||||
{
|
||||
"dataID": 16545444,
|
||||
"description": "Meter per second squared",
|
||||
"descriptionID": 77975,
|
||||
"displayName": "m/sec",
|
||||
"displayNameID": 78015,
|
||||
"unitID": 11,
|
||||
"unitName": "Acceleration"
|
||||
},
|
||||
{
|
||||
"dataID": 16545445,
|
||||
"description": "Reciprocal meter",
|
||||
"descriptionID": 77976,
|
||||
"displayName": "m-1",
|
||||
"displayNameID": 78016,
|
||||
"unitID": 12,
|
||||
"unitName": "Wave Number"
|
||||
},
|
||||
{
|
||||
"dataID": 16545446,
|
||||
"description": "Kilogram per cubic meter",
|
||||
"descriptionID": 77977,
|
||||
"displayName": "kg/m3",
|
||||
"displayNameID": 78017,
|
||||
"unitID": 13,
|
||||
"unitName": "Mass Density"
|
||||
},
|
||||
{
|
||||
"dataID": 16545447,
|
||||
"description": "Cubic meter per kilogram",
|
||||
"descriptionID": 77978,
|
||||
"displayName": "m3/kg",
|
||||
"displayNameID": 78018,
|
||||
"unitID": 14,
|
||||
"unitName": "Specific Volume"
|
||||
},
|
||||
{
|
||||
"dataID": 16545448,
|
||||
"description": "Ampere per square meter",
|
||||
"descriptionID": 77979,
|
||||
"displayName": "A/m2",
|
||||
"displayNameID": 78019,
|
||||
"unitID": 15,
|
||||
"unitName": "Current Density"
|
||||
},
|
||||
{
|
||||
"dataID": 16545449,
|
||||
"description": "Ampere per meter",
|
||||
"descriptionID": 77980,
|
||||
"displayName": "A/m",
|
||||
"displayNameID": 78020,
|
||||
"unitID": 16,
|
||||
"unitName": "Magnetic Field Strength"
|
||||
},
|
||||
{
|
||||
"dataID": 16545450,
|
||||
"description": "Mole per cubic meter",
|
||||
"descriptionID": 77981,
|
||||
"displayName": "mol/m3",
|
||||
"displayNameID": 78021,
|
||||
"unitID": 17,
|
||||
"unitName": "Amount-Of-Substance Concentration"
|
||||
},
|
||||
{
|
||||
"dataID": 16545451,
|
||||
"description": "Candela per square meter",
|
||||
"descriptionID": 77982,
|
||||
"displayName": "cd/m2",
|
||||
"displayNameID": 78022,
|
||||
"unitID": 18,
|
||||
"unitName": "Luminance"
|
||||
},
|
||||
{
|
||||
"dataID": 16545452,
|
||||
"description": "Kilogram per kilogram, which may be represented by the number 1",
|
||||
"descriptionID": 77983,
|
||||
"displayName": "kg/kg = 1",
|
||||
"displayNameID": 78023,
|
||||
"unitID": 19,
|
||||
"unitName": "Mass Fraction"
|
||||
},
|
||||
{
|
||||
"dataID": 16545453,
|
||||
"description": "",
|
||||
"descriptionID": null,
|
||||
"displayName": "s",
|
||||
"displayNameID": 78024,
|
||||
"unitID": 101,
|
||||
"unitName": "Milliseconds"
|
||||
},
|
||||
{
|
||||
"dataID": 16545454,
|
||||
"description": "",
|
||||
"descriptionID": null,
|
||||
"displayName": "mm",
|
||||
"displayNameID": 78025,
|
||||
"unitID": 102,
|
||||
"unitName": "Millimeters"
|
||||
},
|
||||
{
|
||||
"dataID": 13353825,
|
||||
"description": "",
|
||||
"descriptionID": null,
|
||||
"displayName": "",
|
||||
"displayNameID": null,
|
||||
"unitID": 103,
|
||||
"unitName": "MegaPascals"
|
||||
},
|
||||
{
|
||||
"dataID": 16545455,
|
||||
"description": "Indicates that the unit is a multiplier.",
|
||||
"descriptionID": 77984,
|
||||
"displayName": "x",
|
||||
"displayNameID": 78026,
|
||||
"unitID": 104,
|
||||
"unitName": "Multiplier"
|
||||
},
|
||||
{
|
||||
"dataID": 16545456,
|
||||
"description": "",
|
||||
"descriptionID": null,
|
||||
"displayName": "%",
|
||||
"displayNameID": 78027,
|
||||
"unitID": 105,
|
||||
"unitName": "Percentage"
|
||||
},
|
||||
{
|
||||
"dataID": 16545457,
|
||||
"description": "",
|
||||
"descriptionID": null,
|
||||
"displayName": "tf",
|
||||
"displayNameID": 78028,
|
||||
"unitID": 106,
|
||||
"unitName": "Teraflops"
|
||||
},
|
||||
{
|
||||
"dataID": 16545458,
|
||||
"description": "",
|
||||
"descriptionID": null,
|
||||
"displayName": "MW",
|
||||
"displayNameID": 78029,
|
||||
"unitID": 107,
|
||||
"unitName": "MegaWatts"
|
||||
},
|
||||
{
|
||||
"dataID": 16545459,
|
||||
"description": "Used for resistance.\r\n0.0 = 100% 1.0 = 0%\r\n",
|
||||
"descriptionID": 77985,
|
||||
"displayName": "%",
|
||||
"displayNameID": 78030,
|
||||
"unitID": 108,
|
||||
"unitName": "Inverse Absolute Percent"
|
||||
},
|
||||
{
|
||||
"dataID": 16545460,
|
||||
"description": "Used for multipliers displayed as %\r\n1.1 = +10%\r\n0.9 = -10%",
|
||||
"descriptionID": 77986,
|
||||
"displayName": "%",
|
||||
"displayNameID": 78031,
|
||||
"unitID": 109,
|
||||
"unitName": "Modifier Percent"
|
||||
},
|
||||
{
|
||||
"dataID": 16545461,
|
||||
"description": "Used to modify damage resistance. Damage resistance bonus.\r\n0.1 = 90%\r\n0.9 = 10%",
|
||||
"descriptionID": 77987,
|
||||
"displayName": "%",
|
||||
"displayNameID": 78032,
|
||||
"unitID": 111,
|
||||
"unitName": "Inversed Modifier Percent"
|
||||
},
|
||||
{
|
||||
"dataID": 16545462,
|
||||
"description": "Rotation speed.",
|
||||
"descriptionID": 77988,
|
||||
"displayName": "rad/sec",
|
||||
"displayNameID": 78033,
|
||||
"unitID": 112,
|
||||
"unitName": "Radians/Second"
|
||||
},
|
||||
{
|
||||
"dataID": 16545463,
|
||||
"description": "",
|
||||
"descriptionID": null,
|
||||
"displayName": "HP",
|
||||
"displayNameID": 78034,
|
||||
"unitID": 113,
|
||||
"unitName": "Hitpoints"
|
||||
},
|
||||
{
|
||||
"dataID": 16545464,
|
||||
"description": "Giga Joule",
|
||||
"descriptionID": 77989,
|
||||
"displayName": "GJ",
|
||||
"displayNameID": 78035,
|
||||
"unitID": 114,
|
||||
"unitName": "capacitor units"
|
||||
},
|
||||
{
|
||||
"dataID": 16545465,
|
||||
"description": "",
|
||||
"descriptionID": null,
|
||||
"displayName": "groupID",
|
||||
"displayNameID": 78036,
|
||||
"unitID": 115,
|
||||
"unitName": "groupID"
|
||||
},
|
||||
{
|
||||
"dataID": 16545466,
|
||||
"description": "",
|
||||
"descriptionID": null,
|
||||
"displayName": "typeID",
|
||||
"displayNameID": 78037,
|
||||
"unitID": 116,
|
||||
"unitName": "typeID"
|
||||
},
|
||||
{
|
||||
"dataID": 100671817,
|
||||
"description": "1=small 2=medium 3=large 4=x-large",
|
||||
"descriptionID": 318074,
|
||||
"displayName": "1=small 2=medium 3=l",
|
||||
"displayNameID": 78038,
|
||||
"unitID": 117,
|
||||
"unitName": "Sizeclass"
|
||||
},
|
||||
{
|
||||
"dataID": 16545468,
|
||||
"description": "",
|
||||
"descriptionID": null,
|
||||
"displayName": "Ore units",
|
||||
"displayNameID": 78039,
|
||||
"unitID": 118,
|
||||
"unitName": "Ore units"
|
||||
},
|
||||
{
|
||||
"dataID": 16545469,
|
||||
"description": "",
|
||||
"descriptionID": null,
|
||||
"displayName": "attributeID",
|
||||
"displayNameID": 78040,
|
||||
"unitID": 119,
|
||||
"unitName": "attributeID"
|
||||
},
|
||||
{
|
||||
"dataID": 16545470,
|
||||
"description": "",
|
||||
"descriptionID": null,
|
||||
"displayName": "points",
|
||||
"displayNameID": 78041,
|
||||
"unitID": 120,
|
||||
"unitName": "attributePoints"
|
||||
},
|
||||
{
|
||||
"dataID": 16545471,
|
||||
"description": "Used for real percentages, i.e. the number 5 is 5%",
|
||||
"descriptionID": 77990,
|
||||
"displayName": "%",
|
||||
"displayNameID": 78042,
|
||||
"unitID": 121,
|
||||
"unitName": "realPercent"
|
||||
},
|
||||
{
|
||||
"dataID": 13353933,
|
||||
"description": "",
|
||||
"descriptionID": null,
|
||||
"displayName": "",
|
||||
"displayNameID": null,
|
||||
"unitID": 122,
|
||||
"unitName": "Fitting slots"
|
||||
},
|
||||
{
|
||||
"dataID": 16545472,
|
||||
"description": "Shows seconds directly",
|
||||
"descriptionID": 77991,
|
||||
"displayName": "sec",
|
||||
"displayNameID": 78043,
|
||||
"unitID": 123,
|
||||
"unitName": "trueTime"
|
||||
},
|
||||
{
|
||||
"dataID": 16545473,
|
||||
"description": "Used for relative percentages displayed as %",
|
||||
"descriptionID": 77992,
|
||||
"displayName": "%",
|
||||
"displayNameID": 78044,
|
||||
"unitID": 124,
|
||||
"unitName": "Modifier Relative Percent"
|
||||
},
|
||||
{
|
||||
"dataID": 16545474,
|
||||
"description": "",
|
||||
"descriptionID": null,
|
||||
"displayName": "N",
|
||||
"displayNameID": 78045,
|
||||
"unitID": 125,
|
||||
"unitName": "Newton"
|
||||
},
|
||||
{
|
||||
"dataID": 16545475,
|
||||
"description": "",
|
||||
"descriptionID": null,
|
||||
"displayName": "ly",
|
||||
"displayNameID": 78046,
|
||||
"unitID": 126,
|
||||
"unitName": "Light Year"
|
||||
},
|
||||
{
|
||||
"dataID": 16545476,
|
||||
"description": "0.0 = 0% 1.0 = 100%",
|
||||
"descriptionID": 77993,
|
||||
"displayName": "%",
|
||||
"displayNameID": 78047,
|
||||
"unitID": 127,
|
||||
"unitName": "Absolute Percent"
|
||||
},
|
||||
{
|
||||
"dataID": 16545477,
|
||||
"description": "Mega bits per second",
|
||||
"descriptionID": 77994,
|
||||
"displayName": "Mbit/sec",
|
||||
"displayNameID": 78048,
|
||||
"unitID": 128,
|
||||
"unitName": "Drone bandwidth"
|
||||
},
|
||||
{
|
||||
"dataID": 16545488,
|
||||
"description": "Hours",
|
||||
"descriptionID": 77995,
|
||||
"displayName": "",
|
||||
"displayNameID": null,
|
||||
"unitID": 129,
|
||||
"unitName": "Hours"
|
||||
},
|
||||
{
|
||||
"dataID": 16545478,
|
||||
"description": "ISK",
|
||||
"descriptionID": 77996,
|
||||
"displayName": "ISK",
|
||||
"displayNameID": 78049,
|
||||
"unitID": 133,
|
||||
"unitName": "Money"
|
||||
},
|
||||
{
|
||||
"dataID": 16545479,
|
||||
"description": "Bandwidth for PI",
|
||||
"descriptionID": 77997,
|
||||
"displayName": "m3/hour",
|
||||
"displayNameID": 78050,
|
||||
"unitID": 134,
|
||||
"unitName": "Logistical Capacity"
|
||||
},
|
||||
{
|
||||
"dataID": 16545480,
|
||||
"description": "Used to denote distance, 1AU = The distance from the Earth to the Sun.",
|
||||
"descriptionID": 77998,
|
||||
"displayName": "AU",
|
||||
"displayNameID": 78051,
|
||||
"unitID": 135,
|
||||
"unitName": "Astronomical Unit"
|
||||
},
|
||||
{
|
||||
"dataID": 16545481,
|
||||
"description": "Slot number prefix for various purposes",
|
||||
"descriptionID": 77999,
|
||||
"displayName": "Slot",
|
||||
"displayNameID": 78052,
|
||||
"unitID": 136,
|
||||
"unitName": "Slot"
|
||||
},
|
||||
{
|
||||
"dataID": 16545482,
|
||||
"description": "For displaying boolean flags 1=True 0=False",
|
||||
"descriptionID": 78000,
|
||||
"displayName": "1=True 0=False",
|
||||
"displayNameID": 78053,
|
||||
"unitID": 137,
|
||||
"unitName": "Boolean"
|
||||
},
|
||||
{
|
||||
"dataID": 16545483,
|
||||
"description": "Units of something, for example fuel",
|
||||
"descriptionID": 78001,
|
||||
"displayName": "units",
|
||||
"displayNameID": 78054,
|
||||
"unitID": 138,
|
||||
"unitName": "Units"
|
||||
},
|
||||
{
|
||||
"dataID": 16545484,
|
||||
"description": "Forces a plus sign for positive values",
|
||||
"descriptionID": 78002,
|
||||
"displayName": "+",
|
||||
"displayNameID": 78055,
|
||||
"unitID": 139,
|
||||
"unitName": "Bonus"
|
||||
},
|
||||
{
|
||||
"dataID": 16545485,
|
||||
"description": "For anything which is divided by levels",
|
||||
"descriptionID": 78003,
|
||||
"displayName": "Level",
|
||||
"displayNameID": 78056,
|
||||
"unitID": 140,
|
||||
"unitName": "Level"
|
||||
},
|
||||
{
|
||||
"dataID": 16545486,
|
||||
"description": "For various counts to do with turret, launcher and rig hardpoints",
|
||||
"descriptionID": 78004,
|
||||
"displayName": "hardpoints",
|
||||
"displayNameID": 78057,
|
||||
"unitID": 141,
|
||||
"unitName": "Hardpoints"
|
||||
},
|
||||
{
|
||||
"dataID": 16545487,
|
||||
"description": "",
|
||||
"descriptionID": null,
|
||||
"displayName": "1=Male 2=Unisex 3=Female",
|
||||
"displayNameID": 78058,
|
||||
"unitID": 142,
|
||||
"unitName": "Sex"
|
||||
},
|
||||
{
|
||||
"dataID": 97574714,
|
||||
"description": "Date and time",
|
||||
"descriptionID": 312106,
|
||||
"displayName": "",
|
||||
"displayNameID": null,
|
||||
"unitID": 143,
|
||||
"unitName": "Datetime"
|
||||
}
|
||||
]
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -64,7 +64,7 @@
|
||||
"descriptionID": 64453,
|
||||
"hasTypes": 0,
|
||||
"iconID": 365,
|
||||
"name": "Turrets & Bays",
|
||||
"name": "Turrets & Launchers",
|
||||
"nameID": 65527,
|
||||
"parentGroupID": 9
|
||||
},
|
||||
@@ -605,7 +605,7 @@
|
||||
"nameID": 65587
|
||||
},
|
||||
"157": {
|
||||
"description": "Drones are semi-autonomous robotic devices used for military and industrial purposes throughout space.",
|
||||
"description": "Drones are semi-autonomous robotic devices used for military and industrial purposes throughout space",
|
||||
"descriptionID": 64514,
|
||||
"hasTypes": 0,
|
||||
"iconID": 1084,
|
||||
@@ -16002,7 +16002,7 @@
|
||||
"description": "Capital ship entropic disintegrators, for use on dreadnoughts and titans.",
|
||||
"descriptionID": 553053,
|
||||
"hasTypes": 1,
|
||||
"iconID": 21921,
|
||||
"iconID": 24237,
|
||||
"name": "Extra Large",
|
||||
"nameID": 553052,
|
||||
"parentGroupID": 2432
|
||||
@@ -16022,5 +16022,41 @@
|
||||
"name": "Triglavian",
|
||||
"nameID": 553059,
|
||||
"parentGroupID": 1883
|
||||
},
|
||||
"2701": {
|
||||
"description": "Items used in the HyperNet Relay",
|
||||
"descriptionID": 554068,
|
||||
"hasTypes": 1,
|
||||
"iconID": 24205,
|
||||
"name": "HyperNet Relay",
|
||||
"nameID": 554066,
|
||||
"parentGroupID": 1922
|
||||
},
|
||||
"2702": {
|
||||
"description": "Corvettes that have been offered to capsuleers on occasion for limited periods.",
|
||||
"descriptionID": 554136,
|
||||
"hasTypes": 1,
|
||||
"iconID": 1443,
|
||||
"name": "Special Edition Corvettes",
|
||||
"nameID": 554135,
|
||||
"parentGroupID": 1612
|
||||
},
|
||||
"2703": {
|
||||
"description": "Precursor Dreadnoughts",
|
||||
"descriptionID": 555352,
|
||||
"hasTypes": 0,
|
||||
"iconID": 21420,
|
||||
"name": "Precursor Dreadnoughts",
|
||||
"nameID": 555351,
|
||||
"parentGroupID": 1971
|
||||
},
|
||||
"2704": {
|
||||
"description": "Triglavian Dreadnoughts",
|
||||
"descriptionID": 555354,
|
||||
"hasTypes": 1,
|
||||
"iconID": 21420,
|
||||
"name": "Triglavian",
|
||||
"nameID": 555353,
|
||||
"parentGroupID": 2703
|
||||
}
|
||||
}
|
||||
88050
staticdata/fsd_binary/requiredskillsfortypes.json
Normal file
88050
staticdata/fsd_binary/requiredskillsfortypes.json
Normal file
File diff suppressed because it is too large
Load Diff
2286318
staticdata/fsd_binary/typedogma.json
Normal file
2286318
staticdata/fsd_binary/typedogma.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -9544,6 +9544,17 @@
|
||||
"published": true,
|
||||
"useBasePrice": false
|
||||
},
|
||||
"4041": {
|
||||
"anchorable": false,
|
||||
"anchored": false,
|
||||
"categoryID": 17,
|
||||
"fittableNonSingleton": false,
|
||||
"groupID": 4041,
|
||||
"groupName": "Jump Filaments",
|
||||
"groupNameID": 553695,
|
||||
"published": true,
|
||||
"useBasePrice": false
|
||||
},
|
||||
"405": {
|
||||
"anchorable": false,
|
||||
"anchored": false,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,10 @@
|
||||
[
|
||||
{
|
||||
"field_name": "client_build",
|
||||
"field_value": 1618828
|
||||
"field_value": 1651039
|
||||
},
|
||||
{
|
||||
"field_name": "dump_time",
|
||||
"field_value": 1574856401
|
||||
"field_value": 1579607729
|
||||
}
|
||||
]
|
||||
@@ -3945,11 +3945,11 @@
|
||||
"bonuses": [
|
||||
{
|
||||
"number": "5%",
|
||||
"text": "bonus to Light Missile and Rocket Launcher explosion velocity"
|
||||
"text": "bonus to Light Missile and Rocket explosion velocity"
|
||||
},
|
||||
{
|
||||
"number": "5%",
|
||||
"text": "bonus to Light Missile and Rocket Launcher damage"
|
||||
"text": "bonus to Light Missile and Rocket damage"
|
||||
}
|
||||
],
|
||||
"header": "Assault Frigates bonuses (per skill level):"
|
||||
@@ -17728,7 +17728,7 @@
|
||||
"text": "bonus to Ultratidal Entropic Disintegrator rate of fire"
|
||||
}
|
||||
],
|
||||
"header": "Zirnitra bonuses (per skill level):"
|
||||
"header": "Precursor Dreadnought bonuses (per skill level):"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -1 +1 @@
|
||||
version: v2.15.1
|
||||
version: v2.16.0
|
||||
|
||||
Reference in New Issue
Block a user