Skip to content

Updating for new EVE expansions

Ryan Holmes edited this page Aug 7, 2014 · 26 revisions

Note: this document is meant for developers. If you have no interest in pyfa development, then this doesn't offer you much

Each time EVE is updated, pyfa may need to be updated too. This document covers only the most basic activities. Please remember that sometimes more work is needed to update pyfa properly.

Extract data from the client

Launch EVE client, make sure it is updated. Log in, open market window, tab with market tree to cache it. Use Phobos for actual data extraction: (if dumping from Singularity client, add --server=singularity to options)

$ python dumpToJson.py --eve="/.wine_eve/drive_c/Program Files/CCP/EVE/" --cache="/.wine_eve/drive_c/users/"$USER"/Local Settings/Application Data/CCP/EVE/c_program_files_ccp_eve_tranquility/" --json=~/Desktop/phobos_dump_tq --tables="dgmattribs|dgmeffects|dgmtypeattribs|dgmtypeeffects|dgmunits|icons|invcategories|invgroups|invmetagroups|invmetatypes|invtypes|marketProxy()_GetMarketGroups()"

For now, additional step is needed to extract traits data:

$ python dumpTraits.py --eve="/.wine_eve/drive_c/Program Files/CCP/EVE/" --cache="/.wine_eve/drive_c/users/"$USER"/Local Settings/Application Data/CCP/EVE/c_program_files_ccp_eve_tranquility/" --json=~/Desktop/phobos_dump_tq

Convert data to sqlite database

Using eos/utils/scripts/jsonToSql.py script, convert data into suitable to pyfa format:

$ python jsonToSql.py --json=~/Desktop/phobos_dump_tq/ --db=sqlite:////home/$USER/Desktop/eve.db

Find out what has been changed

Using eos/utils/scripts/itemDiff.py script, compare existing and new databases:

$ python3 itemDiff.py --old=../../../staticdata/eve.db --new=~/Desktop/eve.db > ~/Desktop/diff

If output file is empty, then pyfa update is not needed at all. Else, use output file as your guidance for updating pyfa.

Actual pyfa update

Database

Copy eve.db into staticdata folder of pyfa.

Effects

Go through diff file. For each item with added effects, you should verify already implemented effects or implement missing ones. Let's take Rubicon 1.3's Breacher change as example:

[*] Breacher
  [-|y] shipSmallMissileEMDmgMF2
  [-|y] shipSmallMissileExpDmgMF2
  [-|y] shipSmallMissileKinDmgMF2
  [-|y] shipSmallMissileThermDmgMF2
  [+|n] shipMissileRoFMF2
  [*] agility: 3.16 => 3.18
  [*] maxVelocity: 350.0 => 360.0
  [*] powerOutput: 35.0 => 37.0
  [*] shipBonusMF2: 5.0 => -5.0

Here damage bonus was replaced with rate of fire bonus. So, what exactly does new effect do? To find it out, you can use trait description, but translating words into filter is ambiguous. Thus, i prefer to use small script for new Eos:

if __name__ == "__main__":

    import argparse
    import json

    from eos import Eos
    from eos.const.eos import *
    from eos.data.data_handler import JsonDataHandler

    parser = argparse.ArgumentParser(description="Figure out what actually effect does")
    parser.add_argument("-e", "--effect", type=str, required=True, help="effect name")
    args = parser.parse_args()


    with open('/home/dfx/src/eve/eos/data_folder/phobos/dgmattribs.json', mode='r') as file:
        dgmattribs = json.load(file)

    with open('/home/dfx/src/eve/eos/data_folder/phobos/dgmeffects.json', mode='r') as file:
        dgmeffects = json.load(file)

    with open('/home/dfx/src/eve/eos/data_folder/phobos/invtypes.json', mode='r') as file:
        invtypes = json.load(file)

    with open('/home/dfx/src/eve/eos/data_folder/phobos/invgroups.json', mode='r') as file:
        invgroups = json.load(file)

    attr_id_name = {}
    attr_id_penalized = {}
    for row in dgmattribs:
        attr_id_name[row['attributeID']] = row['attributeName']
        attr_id_penalized[row['attributeID']] = 'not penalized' if row['stackable'] else 'penalized'

    effect_id_name = {}
    for row in dgmeffects:
        effect_id_name[row['effectID']] = row['effectName']
        if row['effectName'] == args.effect:
            effect_id = row['effectID']
            break

    type_id_name = {}
    for row in invtypes:
        type_id_name[row['typeID']] = row['typeName']

    group_id_name = {}
    for row in invgroups:
        group_id_name[row['groupID']] = row['groupName']

    dataHandler = JsonDataHandler('/home/dfx/src/eve/eos/data_folder/phobos/')
    engine = Eos(dataHandler, name='eos', storage_path='~/src/eve/eos/data_folder/', make_default=True)

    effect = engine._cache_handler.get_effect(effect_id)
    modifiers = effect.modifiers
    mod_counter = 1
    indent = '  '
    print('effect {}, build status is {}'.format(args.effect, EffectBuildStatus._get_name(effect.build_status)))
    for modifier in modifiers:
        print('{}Modifier {}:'.format(indent, mod_counter))
        print('{0}{0}state: {1}'.format(indent, State._get_name(modifier.state)))
        print('{0}{0}context: {1}'.format(indent, Context._get_name(modifier.context)))
        print('{0}{0}srcattr: {1}'.format(indent, attr_id_name[modifier.source_attribute_id]))
        print('{0}{0}operator: {1}'.format(indent, Operator._get_name(modifier.operator)))
        print('{0}{0}tgtattr: {1} ({2})'.format(
            indent,
            attr_id_name[modifier.target_attribute_id],
            attr_id_penalized[modifier.target_attribute_id])
        )
        print('{0}{0}location: {1}'.format(indent, Location._get_name(modifier.location)))
        print('{0}{0}filter type: {1}'.format(indent, FilterType._get_name(modifier.filter_type)))
        if modifier.filter_type is None or modifier.filter_type in (FilterType.all_, FilterType.skill_self):
            pass
        elif modifier.filter_type == FilterType.skill:
            print('{0}{0}filter value: {1}'.format(indent, type_id_name[modifier.filter_value]))
        elif modifier.filter_type == FilterType.group:
            print('{0}{0}filter value: {1}'.format(indent, group_id_name[modifier.filter_value]))
        mod_counter += 1

Just make full phobos data dump for it and fix paths, and you should be fine. Now, let's run it:

$ python3 getmods.py -e shipMissileRoFMF2
effect shipMissileRoFMF2, build status is ok_full
  Modifier 1:
    state: offline
    context: local
    srcattr: shipBonusMF2
    operator: post_percent
    tgtattr: speed (penalized)
    location: ship
    filter type: skill
    filter value: Missile Launcher Operation

It shows that this effect is completely passive (applied regardless of item state), it takes value of shipBonusMF2 attribute and boosts (multiplies by 1 + value/100) attribute speed of all items which have skill Missile Launcher Operation in its skill requirements (as root node of skill requirement tree). Target attribute is stacking penalizable, but here it doesn't make any difference, because attribute modifications coming from ship are immune to stacking penalty. Now, let's implement an effect:

$ cat eos/effects/shipmissilerofmf2.py
type = "passive"
def handler(fit, ship, context):
    level = fit.character.getSkill("Minmatar Frigate").level
    fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Missile Launcher Operation"),
                                  "speed", ship.getModifiedItemAttr("shipBonusMF2") * level)

After you've finished writing new effects, remove effects which are no longer used. You can identify them using eos/utils/scripts/effectUsedBy.py script:

$ python3 effectUsedBy.py --database=../../../staticdata/eve.db

It also goes through effects' .py files and prints by which items this effect is used, which eases maintenance and testing.

Market overrides

Pyfa does not show vanity variations of ships. This time, few were added, e.g. Incursus Aliastra Edition. Open service/market.py and add it to ITEMS_FORCEPUBLISHED dictionary as key with False value. Pyfa won't see them this way. There're multiple other settings to control what's shown and where, but they are pretty much self-explanatory.

Versioning

Open config.py and update version, tag, expansionName nad expansionVersion variables according to versioning guidelines.

Distributives

Clean copies of resources

To make distributives for all 3 platforms, you will need clean version of pyfa and its skeletons. It might be good idea to store them in separate folder:

$ git clone https://github.com/DarkFenX/Pyfa.git

$ git clone https://github.com/DarkFenX/Pyfa-skel.git

Each time before you're going to make distributive, make sure these copies are updated, are on correct branch, and run git clean -fdx in both.

Generating distributives

Switch current working directory to eos/utils/scripts/ of your main working copy (not the read-only clean variants), and run following commands: (not that windows will strip permissions from Mac build and break the package, it's best to do this in Linux or Mac)

$ python nighty.py --base=/src/eve/github/pyfa_ro/ --skeleton=/src/eve/github/pyfa_skeletons/win/ --destination=~/Desktop/

$ python nighty.py --base=/src/eve/github/pyfa_ro/ --skeleton=/src/eve/github/pyfa_skeletons/mac/ --destination=~/Desktop/

$ python nighty.py --base=/src/eve/github/pyfa_ro/ --skeleton=/src/eve/github/pyfa_skeletons/src/ --destination=~/Desktop/

Repack them into zip files for maximum flexibility. Make sure to put pyfa's folder into archive, not its contents, as some decompressors may produce undesirable results (e.g. put all these files on the desktop if it was target directory). Naming conventions are pyfa-<version>-<lowercased expansionName>-<expansionVersion>-<platform>.zip. You can check already released versions for examples.

Generating distributives

Use Inno Setup with this script to generate an installer for eve. You will need windows machine for this - put script in your current folder, put 'pyfa' folder there too, bump version in script itself and run it. Rename generated file according to conventions which were described earlier.