Compare commits
140 Commits
v2.43.0
...
v2.55.0dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3ed85112c6 | ||
|
|
fed39b75e3 | ||
|
|
8a3defded5 | ||
|
|
88970c7a95 | ||
|
|
fddaf27055 | ||
|
|
dd575bd3a0 | ||
|
|
0c9b73727b | ||
|
|
ade9fc389a | ||
|
|
b6c5f67085 | ||
|
|
7d86d58993 | ||
|
|
a7ab046bc6 | ||
|
|
c94693a72d | ||
|
|
ea335b7d41 | ||
|
|
4838f69c40 | ||
|
|
fb81e6c043 | ||
|
|
84716af82b | ||
|
|
30dd77d462 | ||
|
|
9148611a8e | ||
|
|
e7be51b70e | ||
|
|
194e4657eb | ||
|
|
b08986ba74 | ||
|
|
57d8a672d9 | ||
|
|
47dbfbd6d5 | ||
|
|
cbbf4863fb | ||
|
|
369f62bd68 | ||
|
|
885ad4deb3 | ||
|
|
0ce3b861a4 | ||
|
|
48ee543c00 | ||
|
|
e07e2bc4f7 | ||
|
|
17dec4d732 | ||
|
|
effb7e6429 | ||
|
|
63f7762e34 | ||
|
|
76ff52aea8 | ||
|
|
cd12279404 | ||
|
|
263929b6e3 | ||
|
|
759135d3fe | ||
|
|
d240f547cc | ||
|
|
0a4f3481da | ||
|
|
b248cdefdd | ||
|
|
6172ceda0f | ||
|
|
ba236bcb54 | ||
|
|
b4e115eb7b | ||
|
|
52b567a06d | ||
|
|
dd1f7e224c | ||
|
|
338b298077 | ||
|
|
512b370e3e | ||
|
|
a14210f356 | ||
|
|
f81cf4ee7b | ||
|
|
87b072b567 | ||
|
|
e21789d29c | ||
|
|
dd93f348e6 | ||
|
|
cae8088ad3 | ||
|
|
a92cbe92f1 | ||
|
|
52fd0bb13f | ||
|
|
afcddeea70 | ||
|
|
e5eb001cf3 | ||
|
|
0d186ba56b | ||
|
|
e2273f90b4 | ||
|
|
d6501df509 | ||
|
|
96d639996a | ||
|
|
625c52720d | ||
|
|
69221eac24 | ||
|
|
74daf99aed | ||
|
|
eaf637d1d9 | ||
|
|
c262ea6e35 | ||
|
|
1c541c82bf | ||
|
|
1824d1b866 | ||
|
|
90025f22e5 | ||
|
|
9e71ed88e9 | ||
|
|
be07d8e338 | ||
|
|
242fbba6d6 | ||
|
|
7f1e0fcc58 | ||
|
|
072a53eabc | ||
|
|
3115268fb8 | ||
|
|
0631bd65e1 | ||
|
|
6b7a4b3f9d | ||
|
|
0ba65cab1f | ||
|
|
d75419d858 | ||
|
|
771dfca1c8 | ||
|
|
73a5f62d90 | ||
|
|
3982670dff | ||
|
|
79d2ded836 | ||
|
|
55bc0cd40f | ||
|
|
9da09a279e | ||
|
|
889047f891 | ||
|
|
8f645fa425 | ||
|
|
e3e7f92b8d | ||
|
|
22f37995cf | ||
|
|
92119c01f6 | ||
|
|
95841c44dc | ||
|
|
e7b3040c0f | ||
|
|
78af68cac2 | ||
|
|
3e5eb989f9 | ||
|
|
975d6f8776 | ||
|
|
4e89a87ec1 | ||
|
|
eef644fb4c | ||
|
|
8131dd4ace | ||
|
|
c8059d6132 | ||
|
|
cc008a57e1 | ||
|
|
ce6910fd63 | ||
|
|
7892e637b2 | ||
|
|
6543a2c225 | ||
|
|
1e59d3d6ac | ||
|
|
11d0566433 | ||
|
|
b8d84d3af2 | ||
|
|
1831fea819 | ||
|
|
d15322a57c | ||
|
|
48981460ab | ||
|
|
eaca4a179f | ||
|
|
e249cf917b | ||
|
|
1de7a4ea82 | ||
|
|
289acc099c | ||
|
|
ce3678debb | ||
|
|
0e36794578 | ||
|
|
6d67b23a7e | ||
|
|
a95d69623b | ||
|
|
7578532949 | ||
|
|
a067c77c4c | ||
|
|
c6dd22f04f | ||
|
|
2e1f53184a | ||
|
|
3159d399a6 | ||
|
|
357dab2964 | ||
|
|
41c93efd83 | ||
|
|
628aa9d905 | ||
|
|
f9248dec6f | ||
|
|
9d5ea487d5 | ||
|
|
e76ce71701 | ||
|
|
5a91e01746 | ||
|
|
355e6dd0fe | ||
|
|
49da362dc3 | ||
|
|
460cf26236 | ||
|
|
cceaed8d61 | ||
|
|
d9df4958a6 | ||
|
|
e43e7ba51e | ||
|
|
50e76deab7 | ||
|
|
e109cce36b | ||
|
|
2731e9962b | ||
|
|
76536a5dcc | ||
|
|
41d6828024 | ||
|
|
bf4b4ab3c0 |
@@ -11,7 +11,7 @@ for:
|
||||
environment:
|
||||
APPVEYOR_SSH_KEY: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDJDW/+oYNGOiPvwuwAL9tc/LQgg58aosIVpMYfepQZ20V+VZnHpZh8IRDA8Jo5xht19p2PksA+hFgqA0kpKtrSkuiWdE8rATQItfk4gf7yB0yGasJGGQZYazy9k/9XtmYkq2HHOOeEqdxvrICddJQ88MLCLT9lJENSUP/YS/yGcjZFXVxE11pTeIcqlCRU+3eYa1v7BeNvXIKNhZoK5orXWrtuH3cy8jrSns/u70aYfJ6B2jA8CnWnDbuvpeQtEY61SQqlKUsSArNa8NAsXj41wr3Ar9gAG9330w7EMTqlutk8HZO35uHI0q5qinUhaQYufPPrVkb2L/N+ZCfu0fnh appveyor"
|
||||
APPIMAGE_TOOL: appimagetool-x86_64.AppImage
|
||||
PYTHON_APPIMAGE: python3.7.13-cp37-cp37m-manylinux2014_x86_64.AppImage
|
||||
PYTHON_APPIMAGE: python3.7.17-cp37-cp37m-manylinux2014_x86_64.AppImage
|
||||
DEPLOY_DIR: AppDir/opt/pyfa
|
||||
# APPVEYOR_SSH_BLOCK: true
|
||||
cache:
|
||||
@@ -33,11 +33,14 @@ for:
|
||||
- sh: rm AppDir/python*.desktop
|
||||
- sh: rm AppDir/usr/share/applications/*.desktop
|
||||
- sh: rm AppDir/usr/share/metainfo/*.appdata.xml
|
||||
- sh: unlink AppDir/AppRun
|
||||
- sh: mkdir -p $DEPLOY_DIR
|
||||
# run install pyfa packages and any other requirements
|
||||
|
||||
- sh: AppDir/usr/bin/python -s -m pip install -U pip setuptools==41.6.0 wheel pathlib2
|
||||
- sh: AppDir/usr/bin/python -s -m pip install -r ../requirements.txt
|
||||
# Speedup, but causes runtime incompatiblities
|
||||
#- sh: AppDir/usr/bin/python -s -m pip install -f https://extras.wxpython.org/wxPython4/extras/linux/gtk3/ubuntu-18.04 -r ../requirements.txt
|
||||
|
||||
# Run scripts to prep pyfa data and build database
|
||||
- sh: cd ../
|
||||
@@ -53,9 +56,10 @@ for:
|
||||
|
||||
# Copy static AppImage files
|
||||
- sh: cd dist_assets/linux
|
||||
- sh: chmod +x AppRun
|
||||
- sh: cp AppRun pyfa.desktop ../../build/AppDir/
|
||||
- sh: cp pyfa.desktop ../../build/AppDir/usr/share/applications/
|
||||
- sh: cp org.pyfa.pyfa.appdata.xml ../../build/AppDir/usr/share/metainfo/
|
||||
- sh: cp pyfa.appdata.xml ../../build/AppDir/usr/share/metainfo/
|
||||
- sh: chmod +x pyfa && cp pyfa ../../build/AppDir/usr/bin
|
||||
- sh: cd ../../
|
||||
|
||||
@@ -211,4 +215,4 @@ for:
|
||||
force_update: false
|
||||
# deploy on tag push only
|
||||
on:
|
||||
APPVEYOR_REPO_TAG: true
|
||||
APPVEYOR_REPO_TAG: true
|
||||
|
||||
4
.gitignore
vendored
@@ -90,6 +90,7 @@ target/
|
||||
|
||||
# pyenv
|
||||
.python-version
|
||||
PyfaEnv/
|
||||
|
||||
# celery beat schedule file
|
||||
celerybeat-schedule
|
||||
@@ -123,3 +124,6 @@ gitversion
|
||||
|
||||
*.fsdbinary
|
||||
/locale/progress.json
|
||||
|
||||
# vscode settings
|
||||
.vscode
|
||||
@@ -1,6 +1,6 @@
|
||||
# pyfa
|
||||
|
||||
[](https://pyfainvite.azurewebsites.net/) [](https://travis-ci.org/pyfa-org/Pyfa)
|
||||
[]([https://travis-ci.org/pyfa-org/Pyfa](https://ci.appveyor.com/project/pyfa-org/pyfa))
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ saveInRoot = False
|
||||
evemonMinVersion = "4081"
|
||||
|
||||
minItemSearchLength = 3
|
||||
minItemSearchLengthCjk = 1
|
||||
|
||||
pyfaPath = None
|
||||
savePath = None
|
||||
|
||||
175
db_update.py
@@ -117,8 +117,7 @@ def update_db():
|
||||
for k, v in compiled_data.items():
|
||||
row = {}
|
||||
row.update(v)
|
||||
if keyIdName not in row:
|
||||
row[keyIdName] = int(k)
|
||||
row[keyIdName] = int(k)
|
||||
data.append(row)
|
||||
return data
|
||||
|
||||
@@ -139,16 +138,18 @@ def update_db():
|
||||
for row in data:
|
||||
if (
|
||||
# Apparently people really want Civilian modules available
|
||||
(row['typeName_en-us'].startswith('Civilian') and "Shuttle" not in row['typeName_en-us']) or
|
||||
row['typeName_en-us'] == 'Capsule' or
|
||||
row['groupID'] == 4033 # destructible effect beacons
|
||||
(row['typeName_en-us'].startswith('Civilian') and "Shuttle" not in row['typeName_en-us'])
|
||||
or row['typeName_en-us'] == 'Capsule'
|
||||
or row['groupID'] == 4033 # destructible effect beacons
|
||||
or re.match('AIR .+Booster.*', row['typeName_en-us'])
|
||||
):
|
||||
row['published'] = True
|
||||
# Nearly useless and clutter search results too much
|
||||
elif (
|
||||
row['typeName_en-us'].startswith('Limited Synth ') or
|
||||
row['typeName_en-us'].startswith('Expired ') or
|
||||
row['typeName_en-us'].endswith(' Filament') and (
|
||||
row['typeName_en-us'].startswith('Limited Synth ')
|
||||
or row['typeName_en-us'].startswith('Expired ')
|
||||
or re.match('Mining Blitz .+ Booster Dose .+', row['typeName_en-us'])
|
||||
or row['typeName_en-us'].endswith(' Filament') and (
|
||||
"'Needlejack'" not in row['typeName_en-us'] and
|
||||
"'Devana'" not in row['typeName_en-us'] and
|
||||
"'Pochven'" not in row['typeName_en-us'] and
|
||||
@@ -616,6 +617,16 @@ def update_db():
|
||||
eos.db.gamedata_session.delete(cat)
|
||||
|
||||
# Unused normally, can be useful for customizing items
|
||||
def _copyItem(srcName, tgtTypeID, tgtName):
|
||||
eveType = eos.db.gamedata_session.query(eos.gamedata.Item).filter(eos.gamedata.Item.name == srcName).one()
|
||||
eos.db.gamedata_session.expunge(eveType)
|
||||
sqlalchemy.orm.make_transient(eveType)
|
||||
eveType.ID = tgtTypeID
|
||||
for suffix in eos.config.translation_mapping.values():
|
||||
setattr(eveType, f'typeName{suffix}', tgtName)
|
||||
eos.db.gamedata_session.add(eveType)
|
||||
eos.db.gamedata_session.flush()
|
||||
|
||||
def _hardcodeAttribs(typeID, attrMap):
|
||||
for attrName, value in attrMap.items():
|
||||
try:
|
||||
@@ -624,7 +635,7 @@ def update_db():
|
||||
except sqlalchemy.orm.exc.NoResultFound:
|
||||
attrInfo = eos.db.gamedata_session.query(eos.gamedata.AttributeInfo).filter(eos.gamedata.AttributeInfo.name == attrName).one()
|
||||
attr = eos.gamedata.Attribute()
|
||||
attr.ID = attrInfo.ID
|
||||
attr.attributeID = attrInfo.ID
|
||||
attr.typeID = typeID
|
||||
attr.value = value
|
||||
eos.db.gamedata_session.add(attr)
|
||||
@@ -640,6 +651,152 @@ def update_db():
|
||||
effect.effectName = effectName
|
||||
item.effects[effectName] = effect
|
||||
|
||||
def hardcodeShapash():
|
||||
shapashTypeID = 1000000
|
||||
_copyItem(srcName='Utu', tgtTypeID=shapashTypeID, tgtName='Shapash')
|
||||
attrMap = {
|
||||
# Fitting
|
||||
'powerOutput': 50,
|
||||
'cpuOutput': 225,
|
||||
'capacitorCapacity': 420,
|
||||
'rechargeRate': 187500,
|
||||
# Slots
|
||||
'hiSlots': 3,
|
||||
'medSlots': 4,
|
||||
'lowSlots': 4,
|
||||
'launcherSlotsLeft': 0,
|
||||
'turretSlotsLeft': 3,
|
||||
# Rigs
|
||||
'rigSlots': 2,
|
||||
'rigSize': 1,
|
||||
'upgradeCapacity': 400,
|
||||
# Shield
|
||||
'shieldCapacity': 575,
|
||||
'shieldRechargeRate': 625000,
|
||||
'shieldEmDamageResonance': 1 - 0.0,
|
||||
'shieldThermalDamageResonance': 1 - 0.6,
|
||||
'shieldKineticDamageResonance': 1 - 0.85,
|
||||
'shieldExplosiveDamageResonance': 1 - 0.5,
|
||||
# Armor
|
||||
'armorHP': 1015,
|
||||
'armorEmDamageResonance': 1 - 0.5,
|
||||
'armorThermalDamageResonance': 1 - 0.675,
|
||||
'armorKineticDamageResonance': 1 - 0.8375,
|
||||
'armorExplosiveDamageResonance': 1 - 0.1,
|
||||
# Structure
|
||||
'hp': 1274,
|
||||
'emDamageResonance': 1 - 0.33,
|
||||
'thermalDamageResonance': 1 - 0.33,
|
||||
'kineticDamageResonance': 1 - 0.33,
|
||||
'explosiveDamageResonance': 1 - 0.33,
|
||||
'mass': 1215000,
|
||||
'volume': 29500,
|
||||
'capacity': 165,
|
||||
# Navigation
|
||||
'maxVelocity': 325,
|
||||
'agility': 3.467,
|
||||
'warpSpeedMultiplier': 5.5,
|
||||
# Drones
|
||||
'droneCapacity': 75,
|
||||
'droneBandwidth': 25,
|
||||
# Targeting
|
||||
'maxTargetRange': 49000,
|
||||
'maxLockedTargets': 6,
|
||||
'scanRadarStrength': 0,
|
||||
'scanLadarStrength': 0,
|
||||
'scanMagnetometricStrength': 9,
|
||||
'scanGravimetricStrength': 0,
|
||||
'signatureRadius': 39,
|
||||
'scanResolution': 550,
|
||||
# Misc
|
||||
'energyWarfareResistance': 0,
|
||||
'stasisWebifierResistance': 0,
|
||||
'weaponDisruptionResistance': 0}
|
||||
effectMap = {
|
||||
100100: 'pyfaCustomShapashAfArAmount',
|
||||
100101: 'pyfaCustomShapashAfShtTrackingOptimal',
|
||||
100102: 'pyfaCustomShapashGfShtDamage',
|
||||
100103: 'pyfaCustomShapashGfPointRange',
|
||||
100104: 'pyfaCustomShapashGfPropOverheat',
|
||||
100105: 'pyfaCustomShapashRolePlateMass',
|
||||
100106: 'pyfaCustomShapashRoleHeat'}
|
||||
_hardcodeAttribs(shapashTypeID, attrMap)
|
||||
_hardcodeEffects(shapashTypeID, effectMap)
|
||||
|
||||
def hardcodeCybele():
|
||||
cybeleTypeID = 1000001
|
||||
_copyItem(srcName='Adrestia', tgtTypeID=cybeleTypeID, tgtName='Cybele')
|
||||
attrMap = {
|
||||
# Fitting
|
||||
'powerOutput': 1284,
|
||||
'cpuOutput': 400,
|
||||
'capacitorCapacity': 2400,
|
||||
'rechargeRate': 334000,
|
||||
'hiSlots': 5,
|
||||
'medSlots': 4,
|
||||
'lowSlots': 6,
|
||||
'launcherSlotsLeft': 0,
|
||||
'turretSlotsLeft': 5,
|
||||
# Rigs
|
||||
'rigSlots': 2,
|
||||
'rigSize': 2,
|
||||
'upgradeCapacity': 400,
|
||||
# Shield
|
||||
'shieldCapacity': 1200,
|
||||
'shieldRechargeRate': 1250000,
|
||||
'shieldEmDamageResonance': 1 - 0.0,
|
||||
'shieldThermalDamageResonance': 1 - 0.5,
|
||||
'shieldKineticDamageResonance': 1 - 0.9,
|
||||
'shieldExplosiveDamageResonance': 1 - 0.5,
|
||||
# Armor
|
||||
'armorHP': 1900,
|
||||
'armorEmDamageResonance': 1 - 0.5,
|
||||
'armorThermalDamageResonance': 1 - 0.69,
|
||||
'armorKineticDamageResonance': 1 - 0.85,
|
||||
'armorExplosiveDamageResonance': 1 - 0.1,
|
||||
# Structure
|
||||
'hp': 2300,
|
||||
'emDamageResonance': 1 - 0.33,
|
||||
'thermalDamageResonance': 1 - 0.33,
|
||||
'kineticDamageResonance': 1 - 0.33,
|
||||
'explosiveDamageResonance': 1 - 0.33,
|
||||
'mass': 11100000,
|
||||
'volume': 112000,
|
||||
'capacity': 450,
|
||||
# Navigation
|
||||
'maxVelocity': 235,
|
||||
'agility': 0.457,
|
||||
'warpSpeedMultiplier': 4.5,
|
||||
# Drones
|
||||
'droneCapacity': 100,
|
||||
'droneBandwidth': 50,
|
||||
# Targeting
|
||||
'maxTargetRange': 60000,
|
||||
'maxLockedTargets': 6,
|
||||
'scanRadarStrength': 0,
|
||||
'scanLadarStrength': 0,
|
||||
'scanMagnetometricStrength': 15,
|
||||
'scanGravimetricStrength': 0,
|
||||
'signatureRadius': 115,
|
||||
'scanResolution': 330,
|
||||
# Misc
|
||||
'energyWarfareResistance': 0,
|
||||
'stasisWebifierResistance': 0,
|
||||
'weaponDisruptionResistance': 0}
|
||||
effectMap = {
|
||||
100200: 'pyfaCustomCybeleHacMhtFalloff',
|
||||
100201: 'pyfaCustomCybeleHacMhtTracking',
|
||||
100202: 'pyfaCustomCybeleGcMhtDamage',
|
||||
100203: 'pyfaCustomCybeleGcArAmount',
|
||||
100204: 'pyfaCustomCybeleGcPointRange',
|
||||
100205: 'pyfaCustomCybeleRoleVelocity',
|
||||
100206: 'pyfaCustomCybeleRolePlateMass'}
|
||||
_hardcodeAttribs(cybeleTypeID, attrMap)
|
||||
_hardcodeEffects(cybeleTypeID, effectMap)
|
||||
|
||||
hardcodeShapash()
|
||||
hardcodeCybele()
|
||||
|
||||
eos.db.gamedata_session.commit()
|
||||
eos.db.gamedata_engine.execute('VACUUM')
|
||||
|
||||
|
||||
0
dist_assets/linux/AppRun
Normal file → Executable file
1
docs/_config.yml
Normal file
@@ -0,0 +1 @@
|
||||
theme: jekyll-theme-midnight
|
||||
104
docs/callback.html
Normal file
@@ -0,0 +1,104 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
|
||||
<title>pyfa Authentication Proxy</title>
|
||||
<style type="text/css">
|
||||
|
||||
|
||||
body { width: 700px; margin: 150px auto; }
|
||||
h1 { font-size: 40px; }
|
||||
h2 { font-size: 32px; }
|
||||
body { font: 20px Helvetica, sans-serif; color: #333; }
|
||||
#article { display: block; text-align: left; width: 650px; margin: 0 auto; }
|
||||
.hidden { display:none; }
|
||||
.success { color: #28a745; }
|
||||
.error { color: #dc3545; }
|
||||
textarea { width: 100%; height: 100px; }
|
||||
hr { border-width: 1px 0 0 0; border-style: solid; border-color: #333; }
|
||||
button { cursor: pointer; background-color: white; border: 1px solid #333; color: #333; padding: 8px 11px; text-align: center; text-decoration: none; display: inline-block; }
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body { background-color: #333; color: white; }
|
||||
textarea { width: 100%; height: 100px; background-color: #aaa;}
|
||||
button { background-color: #333; border: 1px solid white; color: white; }
|
||||
hr { border-color: white; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- Layout from Short Circuit's CREST login. Shout out! https://github.com/farshield/shortcircuit -->
|
||||
<h1>pyfa</h1>
|
||||
<div id="mode0" class="hidden">
|
||||
<p id="mode0-msg">Processing request...</p>
|
||||
<button id="showBtn" onClick="showCode()">Show Code</button>
|
||||
</div>
|
||||
<div id="mode1" class="hidden">
|
||||
<p id="mode1-p">Please copy and paste the token below into pyfa.</p>
|
||||
<textarea id="authCodeText" readonly></textarea>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<script>
|
||||
debugger;
|
||||
function showCode() {
|
||||
var element = document.getElementById(`mode1`);
|
||||
element.classList.remove("hidden");
|
||||
element = document.getElementById(`showBtn`);
|
||||
element.classList.add("hidden");
|
||||
}
|
||||
|
||||
function httpPostAsync(url, callback)
|
||||
{
|
||||
var xmlHttp = new XMLHttpRequest();
|
||||
xmlHttp.onreadystatechange = function() {
|
||||
if (xmlHttp.readyState == XMLHttpRequest.DONE)
|
||||
callback(xmlHttp);
|
||||
}
|
||||
xmlHttp.open("GET", url, true); // true for asynchronous
|
||||
xmlHttp.send(null);
|
||||
}
|
||||
|
||||
const urlSearchParams = new URLSearchParams(window.location.search);
|
||||
const params = Object.fromEntries(urlSearchParams.entries());
|
||||
let stateInfo;
|
||||
try {
|
||||
stateInfo = JSON.parse(atob(params.state))
|
||||
} catch (err) {
|
||||
// something has happened and we cannot continue.
|
||||
// todo: show a simple message and exit.
|
||||
throw err;
|
||||
}
|
||||
|
||||
// we always want to show the text box for manual.
|
||||
var element = document.getElementById(`mode${stateInfo.mode}`);
|
||||
element.classList.remove("hidden");
|
||||
|
||||
if (stateInfo.mode === 0) {
|
||||
let p = document.getElementById(`mode1-p`);
|
||||
p.prepend(document.createElement("hr"))
|
||||
}
|
||||
debugger;
|
||||
document.getElementById(`authCodeText`).value = btoa(JSON.stringify(params))
|
||||
|
||||
if (stateInfo.mode == 0) { // auto / server mode
|
||||
httpPostAsync(stateInfo.redirect + window.location.search, (req)=>{
|
||||
debugger;
|
||||
const msgDiv = document.getElementById(`mode0-msg`);
|
||||
if (req.status === 200) {
|
||||
msgDiv.innerHTML ="<span class='success'>Success!</span> You may close this window and return to the application.";
|
||||
return;
|
||||
} else if (req.status === 0){
|
||||
msgDiv.innerHTML = "<span class='error'>Error!</span> Server response not received.<p><small>The local pyfa server may have timed out, or may not have started correctly.</small></p>";
|
||||
} else if (req.status === 400){
|
||||
msgDiv.innerHTML = `<span class='error'>Error!</span> <p><small>${req.responseText}</small></p>`
|
||||
} else {
|
||||
msgDiv.innerHTML = `<span class='error'>Error!</span> <p><small>There was an unknown error. Please report this to the pyfa issues page.</p><p><textarea readdonly>${req.responseText}</textarea></small></p>`
|
||||
}
|
||||
showCode()
|
||||
// todo: bad request error when it's not an error itself, but rather
|
||||
})
|
||||
// todo: post message to local EVE server
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
37
docs/index.md
Normal file
@@ -0,0 +1,37 @@
|
||||
## Welcome to GitHub Pages
|
||||
|
||||
You can use the [editor on GitHub](https://github.com/pyfa-org/Pyfa/edit/gh-pages/index.md) to maintain and preview the content for your website in Markdown files.
|
||||
|
||||
Whenever you commit to this repository, GitHub Pages will run [Jekyll](https://jekyllrb.com/) to rebuild the pages in your site, from the content in your Markdown files.
|
||||
|
||||
### Markdown
|
||||
|
||||
Markdown is a lightweight and easy-to-use syntax for styling your writing. It includes conventions for
|
||||
|
||||
```markdown
|
||||
Syntax highlighted code block
|
||||
|
||||
# Header 1
|
||||
## Header 2
|
||||
### Header 3
|
||||
|
||||
- Bulleted
|
||||
- List
|
||||
|
||||
1. Numbered
|
||||
2. List
|
||||
|
||||
**Bold** and _Italic_ and `Code` text
|
||||
|
||||
[Link](url) and 
|
||||
```
|
||||
|
||||
For more details see [GitHub Flavored Markdown](https://guides.github.com/features/mastering-markdown/).
|
||||
|
||||
### Jekyll Themes
|
||||
|
||||
Your Pages site will use the layout and styles from the Jekyll theme you have selected in your [repository settings](https://github.com/pyfa-org/Pyfa/settings/pages). The name of this theme is saved in the Jekyll `_config.yml` configuration file.
|
||||
|
||||
### Support or Contact
|
||||
|
||||
Having trouble with Pages? Check out our [documentation](https://docs.github.com/categories/github-pages-basics/) or [contact support](https://support.github.com/contact) and we’ll help you sort it out.
|
||||
2910
eos/effects.py
@@ -66,7 +66,7 @@ BUILTINS = OrderedDict([
|
||||
(-25, (_c(_t('Condenser Packs')) + _t('SlamBolt'), 23376, 0, 76624, 0)),
|
||||
(-26, (_c(_t('Condenser Packs')) + _t('BlastShot'), 19820, 0, 80180, 0)),
|
||||
(-27, (_c(_t('Condenser Packs')) + _t('GalvaSurge'), 80206, 0, 19794, 0)),
|
||||
(-28, (_c(_t('Condenser Packs')) + '|' + _t('[T2] ElectroPunch'), 0, 50547, 0, 49453)),
|
||||
(-28, (_c(_t('Condenser Packs')) + '|' + _t('[T2] ElectroPunch'), 50547, 0, 49453, 0)),
|
||||
|
||||
(-29, (_c(_t('Hybrid Charges')) + '|' + _t('[T2] Spike'), 0, 4, 4, 0)),
|
||||
(-30, (_c(_t('Hybrid Charges')) + '|' + _t('[T2] Null'), 0, 6, 5, 0)),
|
||||
@@ -216,11 +216,11 @@ class DamagePattern:
|
||||
pattern.builtin = True
|
||||
cls._builtins[id] = pattern
|
||||
|
||||
def calculateEhp(self, fit):
|
||||
def calculateEhp(self, item):
|
||||
ehp = {}
|
||||
for (type, attr) in (('shield', 'shieldCapacity'), ('armor', 'armorHP'), ('hull', 'hp')):
|
||||
rawCapacity = fit.ship.getModifiedItemAttr(attr)
|
||||
ehp[type] = self.effectivify(fit, rawCapacity, type)
|
||||
rawCapacity = item.getModifiedItemAttr(attr)
|
||||
ehp[type] = self.effectivify(item, rawCapacity, type)
|
||||
|
||||
return ehp
|
||||
|
||||
@@ -236,10 +236,10 @@ class DamagePattern:
|
||||
ereps = {}
|
||||
for field in tankInfo:
|
||||
if field in typeMap:
|
||||
ereps[field] = self.effectivify(fit, tankInfo[field], typeMap[field])
|
||||
ereps[field] = self.effectivify(fit.ship, tankInfo[field], typeMap[field])
|
||||
return ereps
|
||||
|
||||
def effectivify(self, fit, amount, type):
|
||||
def effectivify(self, item, amount, type):
|
||||
type = type if type != "hull" else ""
|
||||
totalDamage = sum((self.emAmount, self.thermalAmount, self.kineticAmount, self.explosiveAmount))
|
||||
specificDivider = 0
|
||||
@@ -248,7 +248,7 @@ class DamagePattern:
|
||||
attrName = "%s%sDamageResonance" % (type, damageType.capitalize())
|
||||
attrName = attrName[0].lower() + attrName[1:]
|
||||
|
||||
resonance = fit.ship.getModifiedItemAttr(attrName)
|
||||
resonance = item.getModifiedItemAttr(attrName)
|
||||
damage = getattr(self, "%sAmount" % damageType)
|
||||
|
||||
specificDivider += damage / float(totalDamage or 1) * resonance
|
||||
|
||||
@@ -82,6 +82,7 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut, Mu
|
||||
self.__baseRRAmount = None
|
||||
self.__miningYield = None
|
||||
self.__miningWaste = None
|
||||
self.__ehp = None
|
||||
self.__itemModifiedAttributes = ModifiedAttributeDict()
|
||||
self.__itemModifiedAttributes.original = self._item.attributes
|
||||
self.__itemModifiedAttributes.overrides = self._item.overrides
|
||||
@@ -287,6 +288,29 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut, Mu
|
||||
if delay is not None and speed is not None:
|
||||
return delay / 1000.0 * speed
|
||||
|
||||
@property
|
||||
def hp(self):
|
||||
hp = {}
|
||||
for (type, attr) in (('shield', 'shieldCapacity'), ('armor', 'armorHP'), ('hull', 'hp')):
|
||||
hp[type] = self.getModifiedItemAttr(attr)
|
||||
|
||||
return hp
|
||||
|
||||
@property
|
||||
def ehp(self):
|
||||
if self.__ehp is None:
|
||||
if self.owner is None or self.owner.damagePattern is None:
|
||||
ehp = self.hp
|
||||
else:
|
||||
ehp = self.owner.damagePattern.calculateEhp(self)
|
||||
self.__ehp = ehp
|
||||
return self.__ehp
|
||||
|
||||
def calculateShieldRecharge(self):
|
||||
capacity = self.getModifiedItemAttr("shieldCapacity")
|
||||
rechargeRate = self.getModifiedItemAttr("shieldRechargeRate") / 1000.0
|
||||
return 10 / rechargeRate * math.sqrt(0.25) * (1 - math.sqrt(0.25)) * capacity
|
||||
|
||||
# Had to add this to match the falloff property in modules.py
|
||||
# Fscking ship scanners. If you find any other falloff attributes,
|
||||
# Put them in the attrs tuple.
|
||||
@@ -318,6 +342,7 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut, Mu
|
||||
self.__baseRRAmount = None
|
||||
self.__miningYield = None
|
||||
self.__miningWaste = None
|
||||
self.__ehp = None
|
||||
self.itemModifiedAttributes.clear()
|
||||
self.chargeModifiedAttributes.clear()
|
||||
|
||||
|
||||
@@ -96,6 +96,7 @@ class Fighter(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
self.__charge = None
|
||||
self.__baseVolley = None
|
||||
self.__miningyield = None
|
||||
self.__ehp = None
|
||||
self.__itemModifiedAttributes = ModifiedAttributeDict()
|
||||
self.__chargeModifiedAttributes = ModifiedAttributeDict()
|
||||
|
||||
@@ -345,6 +346,29 @@ class Fighter(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
if falloff is not None:
|
||||
return falloff
|
||||
|
||||
@property
|
||||
def hp(self):
|
||||
hp = {}
|
||||
for (type, attr) in (('shield', 'shieldCapacity'), ('armor', 'armorHP'), ('hull', 'hp')):
|
||||
hp[type] = self.getModifiedItemAttr(attr)
|
||||
|
||||
return hp
|
||||
|
||||
@property
|
||||
def ehp(self):
|
||||
if self.__ehp is None:
|
||||
if self.owner is None or self.owner.damagePattern is None:
|
||||
ehp = self.hp
|
||||
else:
|
||||
ehp = self.owner.damagePattern.calculateEhp(self)
|
||||
self.__ehp = ehp
|
||||
return self.__ehp
|
||||
|
||||
def calculateShieldRecharge(self):
|
||||
capacity = self.getModifiedItemAttr("shieldCapacity")
|
||||
rechargeRate = self.getModifiedItemAttr("shieldRechargeRate") / 1000.0
|
||||
return 10 / rechargeRate * math.sqrt(0.25) * (1 - math.sqrt(0.25)) * capacity
|
||||
|
||||
@validates("ID", "itemID", "chargeID", "amount")
|
||||
def validator(self, key, val):
|
||||
map = {
|
||||
@@ -361,6 +385,7 @@ class Fighter(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
def clear(self):
|
||||
self.__baseVolley = None
|
||||
self.__miningyield = None
|
||||
self.__ehp = None
|
||||
self.itemModifiedAttributes.clear()
|
||||
self.chargeModifiedAttributes.clear()
|
||||
[x.clear() for x in self.abilities]
|
||||
|
||||
@@ -1469,7 +1469,7 @@ class Fit:
|
||||
if self.damagePattern is None:
|
||||
ehp = self.hp
|
||||
else:
|
||||
ehp = self.damagePattern.calculateEhp(self)
|
||||
ehp = self.damagePattern.calculateEhp(self.ship)
|
||||
self.__ehp = ehp
|
||||
|
||||
return self.__ehp
|
||||
|
||||
@@ -477,7 +477,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut, M
|
||||
# Some delay attributes have non-0 default value, so we have to pick according to effects
|
||||
if {'superWeaponAmarr', 'superWeaponCaldari', 'superWeaponGallente', 'superWeaponMinmatar', 'lightningWeapon'}.intersection(self.item.effects):
|
||||
dmgDelay = self.getModifiedItemAttr("damageDelayDuration", 0)
|
||||
elif {'doomsdayBeamDOT', 'doomsdaySlash', 'doomsdayConeDOT'}.intersection(self.item.effects):
|
||||
elif {'doomsdayBeamDOT', 'doomsdaySlash', 'doomsdayConeDOT', 'debuffLance'}.intersection(self.item.effects):
|
||||
dmgDelay = self.getModifiedItemAttr("doomsdayWarningDuration", 0)
|
||||
else:
|
||||
dmgDelay = 0
|
||||
@@ -696,16 +696,22 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut, M
|
||||
return False
|
||||
|
||||
# Check max group fitted
|
||||
max = self.getModifiedItemAttr("maxGroupFitted")
|
||||
if max:
|
||||
current = 0 # if self.owner != fit else -1 # Disabled, see #1278
|
||||
for mod in fit.modules:
|
||||
if (mod.item and mod.item.groupID == self.item.groupID and
|
||||
self.getModPosition(fit) != mod.getModPosition(fit)):
|
||||
current += 1
|
||||
# use raw value, since it seems what EVE uses. Example is FAXes with their capacitor boosters,
|
||||
# which have unmodified value of 10, and modified of 1, and you can actually fit multiples
|
||||
try:
|
||||
max = self.item.attributes.get('maxGroupFitted').value
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
if max:
|
||||
current = 0 # if self.owner != fit else -1 # Disabled, see #1278
|
||||
for mod in fit.modules:
|
||||
if (mod.item and mod.item.groupID == self.item.groupID and
|
||||
self.getModPosition(fit) != mod.getModPosition(fit)):
|
||||
current += 1
|
||||
|
||||
if current >= max:
|
||||
return False
|
||||
if current >= max:
|
||||
return False
|
||||
|
||||
# Check this only if we're told to do so
|
||||
if hardpointLimit:
|
||||
|
||||
@@ -211,7 +211,7 @@ def getDoomsdayMult(mod, tgt, distance, tgtSigRadius):
|
||||
# Disallow only against subcaps, allow against caps and tgt profiles
|
||||
if tgt.isFit and not tgt.item.ship.item.requiresSkill('Capital Ships'):
|
||||
return 0
|
||||
damageSig = mod.getModifiedItemAttr('doomsdayDamageRadius') or mod.getModifiedItemAttr('signatureRadius')
|
||||
damageSig = mod.getModifiedItemAttr('signatureRadius')
|
||||
if not damageSig:
|
||||
return 1
|
||||
return min(1, tgtSigRadius / damageSig)
|
||||
|
||||
@@ -66,7 +66,7 @@ class FitShieldRegenGraph(FitGraph):
|
||||
('shieldAmount', '%'): lambda v, src, tgt: v / 100 * src.item.ship.getModifiedItemAttr('shieldCapacity'),
|
||||
('shieldAmountT0', '%'): lambda v, src, tgt: None if v is None else v / 100 * src.item.ship.getModifiedItemAttr('shieldCapacity'),
|
||||
# Needed only for "x mark" support, to convert EHP x into normalized value
|
||||
('shieldAmount', 'EHP'): lambda v, src, tgt: v / src.item.damagePattern.effectivify(src.item, 1, 'shield')}
|
||||
('shieldAmount', 'EHP'): lambda v, src, tgt: v / src.item.damagePattern.effectivify(src.item.ship, 1, 'shield')}
|
||||
_limiters = {
|
||||
'shieldAmount': lambda src, tgt: (0, src.item.ship.getModifiedItemAttr('shieldCapacity')),
|
||||
'shieldAmountT0': lambda src, tgt: (0, src.item.ship.getModifiedItemAttr('shieldCapacity'))}
|
||||
@@ -77,5 +77,5 @@ class FitShieldRegenGraph(FitGraph):
|
||||
('shieldAmount', 'shieldRegen'): ShieldAmount2ShieldRegenGetter}
|
||||
_denormalizers = {
|
||||
('shieldAmount', '%'): lambda v, src, tgt: v * 100 / src.item.ship.getModifiedItemAttr('shieldCapacity'),
|
||||
('shieldAmount', 'EHP'): lambda v, src, tgt: src.item.damagePattern.effectivify(src.item, v, 'shield'),
|
||||
('shieldRegen', 'EHP/s'): lambda v, src, tgt: src.item.damagePattern.effectivify(src.item, v, 'shield')}
|
||||
('shieldAmount', 'EHP'): lambda v, src, tgt: src.item.damagePattern.effectivify(src.item.ship, v, 'shield'),
|
||||
('shieldRegen', 'EHP/s'): lambda v, src, tgt: src.item.damagePattern.effectivify(src.item.ship, v, 'shield')}
|
||||
|
||||
@@ -199,7 +199,7 @@ def _getAutoResists(fit):
|
||||
armorHp = hpData['armor']
|
||||
hullHp = hpData['hull']
|
||||
uniformDamagePattern = DamagePattern(emAmount=25, thermalAmount=25, kineticAmount=25, explosiveAmount=25)
|
||||
ehpData = uniformDamagePattern.calculateEhp(fit)
|
||||
ehpData = uniformDamagePattern.calculateEhp(fit.ship)
|
||||
shieldEhp = ehpData['shield']
|
||||
armorEhp = ehpData['armor']
|
||||
hullEhp = ehpData['hull']
|
||||
|
||||
@@ -66,6 +66,8 @@ class DroneView(Display):
|
||||
"Max Range",
|
||||
"Miscellanea",
|
||||
"attr:maxVelocity",
|
||||
"Drone HP",
|
||||
"Drone Regen",
|
||||
"Price",
|
||||
]
|
||||
|
||||
|
||||
@@ -151,6 +151,8 @@ class FighterDisplay(d.Display):
|
||||
# "Max Range",
|
||||
# "Miscellanea",
|
||||
"attr:maxVelocity",
|
||||
"Drone HP",
|
||||
"Drone Regen",
|
||||
"Fighter Abilities",
|
||||
"Price",
|
||||
]
|
||||
|
||||
@@ -44,7 +44,6 @@ class AddCommandFit(ContextMenuUnconditional):
|
||||
def display(self, callingWindow, srcContext):
|
||||
if self.mainFrame.getActiveFit() is None or len(self.__class__.commandFits) == 0 or srcContext != "commandView":
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def getText(self, callingWindow, itmContext):
|
||||
@@ -52,6 +51,8 @@ class AddCommandFit(ContextMenuUnconditional):
|
||||
|
||||
def addFit(self, menu, fit, includeShip=False):
|
||||
label = fit.name if not includeShip else "({}) {}".format(fit.ship.item.name, fit.name)
|
||||
if not label:
|
||||
label = ' '
|
||||
id = ContextMenuUnconditional.nextID()
|
||||
self.fitMenuItemIds[id] = fit
|
||||
menuItem = wx.MenuItem(menu, id, label)
|
||||
|
||||
@@ -123,9 +123,7 @@ class AddEnvironmentEffect(ContextMenuUnconditional):
|
||||
data.groups[_t('Abyssal Weather')] = self.getAbyssalWeather()
|
||||
data.groups[_t('Sansha Incursion')] = self.getEffectBeacons(
|
||||
_t('ContextMenu|ProjectedEffectManipulation|Sansha Incursion'))
|
||||
data.groups[_t('Triglavian Invasion')] = self.getEffectBeacons(
|
||||
_t('ContextMenu|ProjectedEffectManipulation|Triglavian Invasion'))
|
||||
data.groups[_t('Triglavian Invasion')].groups[_t('Destructible Beacons')] = self.getDestructibleBeacons()
|
||||
data.groups[_t('Triglavian Invasion')] = self.getInvasionBeacons()
|
||||
return data
|
||||
|
||||
def getEffectBeacons(self, *groups, extra_garbage=()):
|
||||
@@ -233,5 +231,12 @@ class AddEnvironmentEffect(ContextMenuUnconditional):
|
||||
data.sort()
|
||||
return data
|
||||
|
||||
def getInvasionBeacons(self):
|
||||
data = self.getDestructibleBeacons()
|
||||
# Turnur weather
|
||||
item = Market.getInstance().getItem(74002)
|
||||
data.items.append(Entry(item.ID, item.name, item.name))
|
||||
return data
|
||||
|
||||
|
||||
AddEnvironmentEffect.register()
|
||||
|
||||
@@ -36,6 +36,8 @@ class ItemCompare(wx.Panel):
|
||||
self.item = item
|
||||
self.items = sorted(items, key=defaultSort)
|
||||
self.attrs = {}
|
||||
self.HighlightOn = wx.Colour(255, 255, 0, wx.ALPHA_OPAQUE)
|
||||
self.highlightedNames = []
|
||||
|
||||
# get a dict of attrName: attrInfo of all unique attributes across all items
|
||||
for item in self.items:
|
||||
@@ -88,6 +90,21 @@ class ItemCompare(wx.Panel):
|
||||
self.toggleViewBtn.Bind(wx.EVT_TOGGLEBUTTON, self.ToggleViewMode)
|
||||
self.Bind(wx.EVT_LIST_COL_CLICK, self.SortCompareCols)
|
||||
|
||||
self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.HighlightRow)
|
||||
|
||||
def HighlightRow(self, event):
|
||||
itemIdx = event.GetIndex()
|
||||
name = self.paramList.GetItem(itemIdx).Text
|
||||
if name in self.highlightedNames:
|
||||
self.highlightedNames.remove(name)
|
||||
else:
|
||||
self.highlightedNames.append(name)
|
||||
self.Freeze()
|
||||
self.paramList.ClearAll()
|
||||
self.PopulateList()
|
||||
self.Thaw()
|
||||
event.Skip()
|
||||
|
||||
def SortCompareCols(self, event):
|
||||
self.Freeze()
|
||||
self.paramList.ClearAll()
|
||||
@@ -155,6 +172,8 @@ class ItemCompare(wx.Panel):
|
||||
self.paramList.InsertColumn(len(self.attrs) + 1, _t("Price"))
|
||||
self.paramList.SetColumnWidth(len(self.attrs) + 1, 60)
|
||||
|
||||
toHighlight = []
|
||||
|
||||
for item in self.items:
|
||||
i = self.paramList.InsertItem(self.paramList.GetItemCount(), item.name)
|
||||
for x, attr in enumerate(self.attrs.keys()):
|
||||
@@ -172,10 +191,19 @@ class ItemCompare(wx.Panel):
|
||||
|
||||
# Add prices
|
||||
self.paramList.SetItem(i, len(self.attrs) + 1, formatAmount(item.price.price, 3, 3, 9, currency=True) if item.price.price else "")
|
||||
if item.name in self.highlightedNames:
|
||||
toHighlight.append(i)
|
||||
|
||||
self.paramList.RefreshRows()
|
||||
self.Layout()
|
||||
|
||||
# Highlight after layout, otherwise colors are getting overwritten
|
||||
for itemIdx in toHighlight:
|
||||
listItem = self.paramList.GetItem(itemIdx)
|
||||
listItem.SetBackgroundColour(self.HighlightOn)
|
||||
listItem.SetFont(listItem.GetFont().MakeBold())
|
||||
self.paramList.SetItem(listItem)
|
||||
|
||||
@staticmethod
|
||||
def TranslateValueUnit(value, unitName, unitDisplayName):
|
||||
def itemIDCallback():
|
||||
|
||||
@@ -127,7 +127,9 @@ class TargetingMiscViewMinimal(StatsView):
|
||||
("specialSalvageHoldCapacity", _t("Salvage hold")),
|
||||
("specialCommandCenterHoldCapacity", _t("Command center hold")),
|
||||
("specialPlanetaryCommoditiesHoldCapacity", _t("Planetary goods hold")),
|
||||
("specialQuafeHoldCapacity", _t("Quafe hold"))))
|
||||
("specialQuafeHoldCapacity", _t("Quafe hold")),
|
||||
("specialMobileDepotHoldCapacity", _t("Mobile depot hold")),
|
||||
))
|
||||
|
||||
cargoValues = {
|
||||
"main": lambda: fit.ship.getModifiedItemAttr("capacity"),
|
||||
@@ -148,7 +150,8 @@ class TargetingMiscViewMinimal(StatsView):
|
||||
"specialSalvageHoldCapacity": lambda: fit.ship.getModifiedItemAttr("specialSalvageHoldCapacity"),
|
||||
"specialCommandCenterHoldCapacity": lambda: fit.ship.getModifiedItemAttr("specialCommandCenterHoldCapacity"),
|
||||
"specialPlanetaryCommoditiesHoldCapacity": lambda: fit.ship.getModifiedItemAttr("specialPlanetaryCommoditiesHoldCapacity"),
|
||||
"specialQuafeHoldCapacity": lambda: fit.ship.getModifiedItemAttr("specialQuafeHoldCapacity")
|
||||
"specialQuafeHoldCapacity": lambda: fit.ship.getModifiedItemAttr("specialQuafeHoldCapacity"),
|
||||
"specialMobileDepotHoldCapacity": lambda: fit.ship.getModifiedItemAttr("specialMobileDepotHoldCapacity"),
|
||||
}
|
||||
|
||||
stats = (("labelTargets", {"main": lambda: fit.maxTargets}, 3, 0, 0, ""),
|
||||
|
||||
87
gui/builtinViewColumns/droneEhp.py
Normal file
@@ -0,0 +1,87 @@
|
||||
# =============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of pyfa.
|
||||
#
|
||||
# pyfa is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# pyfa is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
|
||||
# =============================================================================
|
||||
|
||||
# noinspection PyPackageRequirements
|
||||
import wx
|
||||
|
||||
import gui.mainFrame
|
||||
from eos.saveddata.drone import Drone
|
||||
from eos.saveddata.fighter import Fighter
|
||||
from service.attribute import Attribute
|
||||
from gui.viewColumn import ViewColumn
|
||||
from gui.bitmap_loader import BitmapLoader
|
||||
from gui.utils.numberFormatter import formatAmount
|
||||
|
||||
|
||||
_t = wx.GetTranslation
|
||||
|
||||
|
||||
class DroneEhpColumn(ViewColumn):
|
||||
name = "Drone HP"
|
||||
|
||||
def __init__(self, fittingView, params=None):
|
||||
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
|
||||
if params is None:
|
||||
params = {"showIcon": True, "displayName": False}
|
||||
|
||||
ViewColumn.__init__(self, fittingView)
|
||||
|
||||
sAttr = Attribute.getInstance()
|
||||
info = sAttr.getAttributeInfo("shieldCapacity")
|
||||
self.info = info
|
||||
if params["showIcon"]:
|
||||
iconFile = info.iconID
|
||||
if iconFile:
|
||||
self.imageId = fittingView.imageList.GetImageIndex(iconFile, "icons")
|
||||
self.bitmap = BitmapLoader.getBitmap(iconFile, "icons")
|
||||
else:
|
||||
self.imageId = -1
|
||||
self.mask = wx.LIST_MASK_IMAGE
|
||||
else:
|
||||
self.imageId = -1
|
||||
|
||||
if params["displayName"] or self.imageId == -1:
|
||||
self.columnText = info.displayName if info.displayName != "" else info.name
|
||||
self.mask |= wx.LIST_MASK_TEXT
|
||||
|
||||
def getText(self, stuff):
|
||||
if not isinstance(stuff, (Drone, Fighter)):
|
||||
return ""
|
||||
if self.mainFrame.statsPane.nameViewMap["resistancesViewFull"].showEffective:
|
||||
ehp = sum(stuff.ehp.values())
|
||||
else:
|
||||
ehp = sum(stuff.hp.values())
|
||||
return formatAmount(ehp, 3, 0, 9)
|
||||
|
||||
def getImageId(self, mod):
|
||||
return -1
|
||||
|
||||
def getParameters(self):
|
||||
return ("displayName", bool, False), ("showIcon", bool, True)
|
||||
|
||||
def getToolTip(self, stuff):
|
||||
if not isinstance(stuff, (Drone, Fighter)):
|
||||
return ""
|
||||
if self.mainFrame.statsPane.nameViewMap["resistancesViewFull"].showEffective:
|
||||
return _t("Effective HP")
|
||||
else:
|
||||
return _t("HP")
|
||||
|
||||
|
||||
DroneEhpColumn.register()
|
||||
81
gui/builtinViewColumns/droneRegen.py
Normal file
@@ -0,0 +1,81 @@
|
||||
# =============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of pyfa.
|
||||
#
|
||||
# pyfa is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# pyfa is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
|
||||
# =============================================================================
|
||||
|
||||
# noinspection PyPackageRequirements
|
||||
import wx
|
||||
|
||||
import gui.mainFrame
|
||||
from eos.saveddata.drone import Drone
|
||||
from eos.saveddata.fighter import Fighter
|
||||
from gui.viewColumn import ViewColumn
|
||||
from gui.bitmap_loader import BitmapLoader
|
||||
from gui.utils.numberFormatter import formatAmount
|
||||
|
||||
|
||||
_t = wx.GetTranslation
|
||||
|
||||
|
||||
class DroneRegenColumn(ViewColumn):
|
||||
name = "Drone Regen"
|
||||
|
||||
def __init__(self, fittingView, params=None):
|
||||
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
|
||||
if params is None:
|
||||
params = {"showIcon": True, "displayName": False}
|
||||
|
||||
ViewColumn.__init__(self, fittingView)
|
||||
|
||||
if params["showIcon"]:
|
||||
self.imageId = fittingView.imageList.GetImageIndex("shieldPassive_small", "gui")
|
||||
self.bitmap = BitmapLoader.getBitmap("shieldPassive_small", "gui")
|
||||
self.mask = wx.LIST_MASK_IMAGE
|
||||
else:
|
||||
self.imageId = -1
|
||||
|
||||
if params["displayName"] or self.imageId == -1:
|
||||
self.columnText = _("Misc data")
|
||||
self.mask |= wx.LIST_MASK_TEXT
|
||||
|
||||
def getText(self, stuff):
|
||||
if not isinstance(stuff, (Drone, Fighter)):
|
||||
return ""
|
||||
regen = stuff.calculateShieldRecharge()
|
||||
if (
|
||||
self.mainFrame.statsPane.nameViewMap["resistancesViewFull"].showEffective
|
||||
and stuff.owner and stuff.owner.damagePattern is not None
|
||||
):
|
||||
regen = stuff.owner.damagePattern.effectivify(stuff, regen, 'shield')
|
||||
return '{}/s'.format(formatAmount(regen, 3, 0, 9))
|
||||
|
||||
def getImageId(self, mod):
|
||||
return -1
|
||||
|
||||
def getParameters(self):
|
||||
return ("displayName", bool, False), ("showIcon", bool, True)
|
||||
|
||||
def getToolTip(self, stuff):
|
||||
if not isinstance(stuff, (Drone, Fighter)):
|
||||
return ""
|
||||
if self.mainFrame.statsPane.nameViewMap["resistancesViewFull"].showEffective:
|
||||
return _t("Effective Shield Regeneration")
|
||||
else:
|
||||
return _t("Shield Regeneration")
|
||||
|
||||
|
||||
DroneRegenColumn.register()
|
||||
@@ -182,6 +182,13 @@ class Miscellanea(ViewColumn):
|
||||
text = "{0} | {1}".format(formatAmount(strength, 3, 0, 3), formatAmount(coherence, 3, 0, 3))
|
||||
tooltip = "Virus strength and coherence"
|
||||
return text, tooltip
|
||||
elif itemGroup == "Damage Control":
|
||||
duration = stuff.getModifiedItemAttr("duration")
|
||||
if not duration:
|
||||
return "", None
|
||||
text = "{0}s".format(formatAmount(duration / 1000, 3, 0, 0))
|
||||
tooltip = "Assault ability duration"
|
||||
return text, tooltip
|
||||
elif itemGroup in ("Warp Scrambler", "Warp Core Stabilizer", "Structure Warp Scrambler"):
|
||||
scramStr = stuff.getModifiedItemAttr("warpScrambleStrength")
|
||||
if not scramStr:
|
||||
|
||||
@@ -22,6 +22,7 @@ import traceback
|
||||
|
||||
# noinspection PyPackageRequirements
|
||||
import wx
|
||||
import roman
|
||||
from logbook import Logger
|
||||
|
||||
import config
|
||||
@@ -105,6 +106,9 @@ class CharacterSelection(wx.Panel):
|
||||
exportItem = menu.Append(wx.ID_ANY, _t("Copy Missing Skills"))
|
||||
self.Bind(wx.EVT_MENU, self.exportSkills, exportItem)
|
||||
|
||||
exportItem = menu.Append(wx.ID_ANY, _t("Copy Missing Skills (EVEMon)"))
|
||||
self.Bind(wx.EVT_MENU, self.exportSkillsEveMon, exportItem)
|
||||
|
||||
self.PopupMenu(menu, pos)
|
||||
|
||||
event.Skip()
|
||||
@@ -264,6 +268,15 @@ class CharacterSelection(wx.Panel):
|
||||
|
||||
toClipboard(list)
|
||||
|
||||
def exportSkillsEveMon(self, evt):
|
||||
skillsMap = self._buildSkillsTooltipCondensed(self.reqs, skillsMap={})
|
||||
|
||||
list = ""
|
||||
for key in sorted(skillsMap):
|
||||
list += "%s %s\n" % (key, roman.toRoman(skillsMap[key][0]))
|
||||
|
||||
toClipboard(list)
|
||||
|
||||
def _buildSkillsTooltip(self, reqs, currItem="", tabulationLevel=0):
|
||||
tip = ""
|
||||
sCharacter = Character.getInstance()
|
||||
|
||||
@@ -78,6 +78,8 @@ from gui.builtinViewColumns import ( # noqa: E402, F401
|
||||
baseName,
|
||||
capacitorUse,
|
||||
dampScanRes,
|
||||
droneEhp,
|
||||
droneRegen,
|
||||
graphColor,
|
||||
graphLightness,
|
||||
graphLineStyle,
|
||||
|
||||
BIN
imgs/gui/shieldPassive_small.png
Normal file
|
After Width: | Height: | Size: 662 B |
BIN
imgs/icons/1168@1x.png
Normal file
|
After Width: | Height: | Size: 857 B |
BIN
imgs/icons/1168@2x.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
imgs/icons/21831@1x.png
Normal file
|
After Width: | Height: | Size: 812 B |
BIN
imgs/icons/21831@2x.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
imgs/icons/21894@1x.png
Normal file
|
After Width: | Height: | Size: 808 B |
BIN
imgs/icons/21894@2x.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
imgs/icons/24296@1x.png
Normal file
|
After Width: | Height: | Size: 667 B |
BIN
imgs/icons/24296@2x.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
imgs/icons/24404@1x.png
Normal file
|
After Width: | Height: | Size: 676 B |
BIN
imgs/icons/24404@2x.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
imgs/icons/24411@1x.png
Normal file
|
After Width: | Height: | Size: 849 B |
BIN
imgs/icons/24411@2x.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
imgs/icons/24419@1x.png
Normal file
|
After Width: | Height: | Size: 640 B |
BIN
imgs/icons/24419@2x.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
imgs/icons/24585@1x.png
Normal file
|
After Width: | Height: | Size: 878 B |
BIN
imgs/icons/24585@2x.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 780 B |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 829 B |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 821 B |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 824 B |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 783 B |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 814 B |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 825 B |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 821 B |
|
Before Width: | Height: | Size: 2.3 KiB |
BIN
imgs/icons/25328@1x.png
Normal file
|
After Width: | Height: | Size: 791 B |
BIN
imgs/icons/25328@2x.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
imgs/icons/25329@1x.png
Normal file
|
After Width: | Height: | Size: 769 B |
BIN
imgs/icons/25329@2x.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
imgs/icons/25330@1x.png
Normal file
|
After Width: | Height: | Size: 799 B |
BIN
imgs/icons/25330@2x.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
imgs/icons/25331@1x.png
Normal file
|
After Width: | Height: | Size: 802 B |
BIN
imgs/icons/25331@2x.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
imgs/icons/25355@1x.png
Normal file
|
After Width: | Height: | Size: 796 B |
BIN
imgs/icons/25355@2x.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
imgs/icons/25356@1x.png
Normal file
|
After Width: | Height: | Size: 603 B |
BIN
imgs/icons/25356@2x.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
imgs/icons/25467@1x.png
Normal file
|
After Width: | Height: | Size: 605 B |
BIN
imgs/icons/25467@2x.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
imgs/icons/25468@1x.png
Normal file
|
After Width: | Height: | Size: 625 B |
BIN
imgs/icons/25468@2x.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
imgs/icons/25621@1x.png
Normal file
|
After Width: | Height: | Size: 825 B |
BIN
imgs/icons/25621@2x.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
imgs/icons/25622@1x.png
Normal file
|
After Width: | Height: | Size: 834 B |
BIN
imgs/icons/25622@2x.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
imgs/icons/25624@1x.png
Normal file
|
After Width: | Height: | Size: 810 B |
BIN
imgs/icons/25624@2x.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
imgs/icons/25625@1x.png
Normal file
|
After Width: | Height: | Size: 833 B |
BIN
imgs/icons/25625@2x.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
imgs/icons/25629@1x.png
Normal file
|
After Width: | Height: | Size: 952 B |
BIN
imgs/icons/25629@2x.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
imgs/icons/25631@1x.png
Normal file
|
After Width: | Height: | Size: 771 B |
BIN
imgs/icons/25631@2x.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
imgs/icons/25632@1x.png
Normal file
|
After Width: | Height: | Size: 783 B |
BIN
imgs/icons/25632@2x.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
imgs/icons/25633@1x.png
Normal file
|
After Width: | Height: | Size: 768 B |
BIN
imgs/icons/25633@2x.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
imgs/icons/25634@1x.png
Normal file
|
After Width: | Height: | Size: 961 B |
BIN
imgs/icons/25634@2x.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
imgs/icons/25803@1x.png
Normal file
|
After Width: | Height: | Size: 894 B |
BIN
imgs/icons/25803@2x.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
imgs/icons/25833@1x.png
Normal file
|
After Width: | Height: | Size: 795 B |