Compare commits
65 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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.15-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
|
||||
@@ -28,6 +28,7 @@ saveInRoot = False
|
||||
evemonMinVersion = "4081"
|
||||
|
||||
minItemSearchLength = 3
|
||||
minItemSearchLengthCjk = 1
|
||||
|
||||
pyfaPath = None
|
||||
savePath = None
|
||||
|
||||
14
db_update.py
@@ -139,16 +139,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
|
||||
|
||||
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.
|
||||
545
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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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",
|
||||
]
|
||||
|
||||
@@ -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.getDestructibleBeacons()
|
||||
return data
|
||||
|
||||
def getEffectBeacons(self, *groups, extra_garbage=()):
|
||||
|
||||
@@ -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():
|
||||
|
||||
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()
|
||||
@@ -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/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/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/24497@1x.png
Normal file
|
After Width: | Height: | Size: 827 B |
BIN
imgs/icons/24497@2x.png
Normal file
|
After Width: | Height: | Size: 2.3 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 |
|
Before Width: | Height: | Size: 782 B |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 816 B |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 823 B |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 814 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 |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 6.2 KiB |
BIN
imgs/renders/1793@1x.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
imgs/renders/1793@2x.png
Normal file
|
After Width: | Height: | Size: 6.6 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 7.1 KiB |
BIN
imgs/renders/1889@1x.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
imgs/renders/1889@2x.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
BIN
imgs/renders/20228@1x.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
imgs/renders/20228@2x.png
Normal file
|
After Width: | Height: | Size: 6.9 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 6.2 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 7.2 KiB |
BIN
imgs/renders/25573@1x.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
imgs/renders/25573@2x.png
Normal file
|
After Width: | Height: | Size: 7.0 KiB |
BIN
imgs/renders/25574@1x.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
imgs/renders/25574@2x.png
Normal file
|
After Width: | Height: | Size: 6.5 KiB |
BIN
imgs/renders/25575@1x.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
imgs/renders/25575@2x.png
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
BIN
imgs/renders/25576@1x.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
imgs/renders/25576@2x.png
Normal file
|
After Width: | Height: | Size: 6.8 KiB |
BIN
imgs/renders/25578@1x.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
imgs/renders/25578@2x.png
Normal file
|
After Width: | Height: | Size: 6.8 KiB |
@@ -3,7 +3,7 @@ msgstr ""
|
||||
"Project-Id-Version: pyfa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-10-28 15:28+0300\n"
|
||||
"PO-Revision-Date: 2021-05-18 17:34\n"
|
||||
"PO-Revision-Date: 2022-06-13 10:20\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Chinese Simplified\n"
|
||||
"Language: zh_CN\n"
|
||||
@@ -19,7 +19,7 @@ msgstr ""
|
||||
|
||||
#: gui/builtinStatsViews/firepowerViewFull.py:107
|
||||
msgid " DPS: "
|
||||
msgstr ""
|
||||
msgstr " 秒伤: "
|
||||
|
||||
#: gui/builtinContextMenus/itemRemove.py:44
|
||||
msgid " Stack"
|
||||
@@ -384,7 +384,7 @@ msgstr "艾玛(护盾)"
|
||||
|
||||
#: eos/saveddata/damagePattern.py:143 eos/saveddata/targetProfile.py:95
|
||||
msgid "Amarr EDENCOM Entities"
|
||||
msgstr ""
|
||||
msgstr "艾玛EDENCOM实体"
|
||||
|
||||
#: eos/saveddata/damagePattern.py:149 eos/saveddata/targetProfile.py:72
|
||||
msgid "Amarr Empire"
|
||||
@@ -402,7 +402,7 @@ msgstr "弹药仓"
|
||||
#: eos/saveddata/targetProfile.py:220 eos/saveddata/targetProfile.py:223
|
||||
#: eos/saveddata/targetProfile.py:226 eos/saveddata/targetProfile.py:229
|
||||
msgid "Angel"
|
||||
msgstr ""
|
||||
msgstr "天使"
|
||||
|
||||
#: eos/saveddata/damagePattern.py:105 eos/saveddata/damagePattern.py:123
|
||||
#: eos/saveddata/targetProfile.py:60 eos/saveddata/targetProfile.py:66
|
||||
@@ -627,7 +627,7 @@ msgstr "统合部"
|
||||
|
||||
#: gui/builtinStatsViews/resourcesViewFull.py:153
|
||||
msgid "CPU"
|
||||
msgstr ""
|
||||
msgstr "CPU"
|
||||
|
||||
#: gui/builtinItemStatsViews/itemAttributes.py:118
|
||||
msgid "CSV files"
|
||||
@@ -644,7 +644,7 @@ msgstr "加达里(护盾)"
|
||||
#: eos/saveddata/damagePattern.py:144 eos/saveddata/damagePattern.py:145
|
||||
#: eos/saveddata/targetProfile.py:96
|
||||
msgid "Caldari EDENCOM Entities"
|
||||
msgstr ""
|
||||
msgstr "加达里EDENCOM实体"
|
||||
|
||||
#: eos/saveddata/damagePattern.py:150 eos/saveddata/targetProfile.py:73
|
||||
msgid "Caldari State"
|
||||
@@ -862,7 +862,7 @@ msgstr "对比"
|
||||
#: eos/saveddata/targetProfile.py:218 eos/saveddata/targetProfile.py:221
|
||||
#: eos/saveddata/targetProfile.py:224 eos/saveddata/targetProfile.py:227
|
||||
msgid "Concord"
|
||||
msgstr ""
|
||||
msgstr "统合部"
|
||||
|
||||
#: eos/saveddata/damagePattern.py:92
|
||||
msgid "Concussion Bomb"
|
||||
@@ -905,15 +905,15 @@ msgstr ""
|
||||
|
||||
#: gui/builtinContextMenus/envEffectAdd.py:107
|
||||
msgid "ContextMenu|ProjectedEffectManipulation|Exotic"
|
||||
msgstr ""
|
||||
msgstr "异种深渊"
|
||||
|
||||
#: gui/builtinContextMenus/envEffectAdd.py:115
|
||||
msgid "ContextMenu|ProjectedEffectManipulation|Firestorm"
|
||||
msgstr ""
|
||||
msgstr "火瀑深渊"
|
||||
|
||||
#: gui/builtinContextMenus/envEffectAdd.py:108
|
||||
msgid "ContextMenu|ProjectedEffectManipulation|Gamma"
|
||||
msgstr ""
|
||||
msgstr "伽玛深渊"
|
||||
|
||||
#: gui/builtinContextMenus/envEffectAdd.py:119
|
||||
msgid "ContextMenu|ProjectedEffectManipulation|Magnetar"
|
||||
@@ -1032,7 +1032,7 @@ msgstr "青色"
|
||||
|
||||
#: graphs/data/fitDamageStats/graph.py:83
|
||||
msgid "DPS"
|
||||
msgstr ""
|
||||
msgstr "秒伤"
|
||||
|
||||
#: gui/patternEditor.py:99
|
||||
msgid "Damage Pattern Editor"
|
||||
@@ -1134,7 +1134,7 @@ msgstr "删除所有目标属性配置"
|
||||
|
||||
#: gui/esiFittings.py:66
|
||||
msgid "Delete all from Eve"
|
||||
msgstr ""
|
||||
msgstr "从 EvE 中删除全部装配"
|
||||
|
||||
#: gui/esiFittings.py:65
|
||||
msgid "Delete from EVE"
|
||||
@@ -1271,7 +1271,7 @@ msgstr "流浪者"
|
||||
|
||||
#: eos/saveddata/damagePattern.py:159 eos/saveddata/targetProfile.py:230
|
||||
msgid "Drifter Entities"
|
||||
msgstr ""
|
||||
msgstr "流浪者实体"
|
||||
|
||||
#: gui/builtinStatsViews/firepowerViewFull.py:67
|
||||
msgid "Drone"
|
||||
@@ -1425,7 +1425,7 @@ msgstr "效果"
|
||||
#: eos/saveddata/targetProfile.py:112 eos/saveddata/targetProfile.py:194
|
||||
#: eos/saveddata/targetProfile.py:195 eos/saveddata/targetProfile.py:196
|
||||
msgid "Electrical T0/T1/T2"
|
||||
msgstr ""
|
||||
msgstr "电子深渊 T0/T1/T2"
|
||||
|
||||
#: eos/saveddata/targetProfile.py:113 eos/saveddata/targetProfile.py:114
|
||||
#: eos/saveddata/targetProfile.py:115 eos/saveddata/targetProfile.py:116
|
||||
@@ -1441,7 +1441,7 @@ msgstr "电子 T3 (含部分T5关卡)"
|
||||
#: eos/saveddata/targetProfile.py:126 eos/saveddata/targetProfile.py:200
|
||||
#: eos/saveddata/targetProfile.py:201 eos/saveddata/targetProfile.py:202
|
||||
msgid "Electrical T4/T5/T6"
|
||||
msgstr ""
|
||||
msgstr "电子深渊 T4/T5/T6"
|
||||
|
||||
#: gui/builtinStatsViews/resistancesViewFull.py:85
|
||||
msgid "Electromagnetic resistance"
|
||||
@@ -1558,7 +1558,7 @@ msgstr "异种等离子"
|
||||
#: eos/saveddata/targetProfile.py:154 eos/saveddata/targetProfile.py:212
|
||||
#: eos/saveddata/targetProfile.py:213 eos/saveddata/targetProfile.py:214
|
||||
msgid "Exotic T0/T1/T2"
|
||||
msgstr ""
|
||||
msgstr "异种深渊 T0/T1/T2"
|
||||
|
||||
#: eos/saveddata/targetProfile.py:155 eos/saveddata/targetProfile.py:156
|
||||
#: eos/saveddata/targetProfile.py:157 eos/saveddata/targetProfile.py:158
|
||||
@@ -1574,7 +1574,7 @@ msgstr "异种 T3 (含部分T5关卡)"
|
||||
#: eos/saveddata/targetProfile.py:168 eos/saveddata/targetProfile.py:218
|
||||
#: eos/saveddata/targetProfile.py:219 eos/saveddata/targetProfile.py:220
|
||||
msgid "Exotic T4/T5/T6"
|
||||
msgstr ""
|
||||
msgstr "异种深渊 T4/T5/T6"
|
||||
|
||||
#: gui/builtinItemStatsViews/itemAffectedBy.py:67
|
||||
msgid "Expand All"
|
||||
@@ -1764,7 +1764,7 @@ msgstr "火力"
|
||||
#: eos/saveddata/targetProfile.py:133 eos/saveddata/targetProfile.py:203
|
||||
#: eos/saveddata/targetProfile.py:204 eos/saveddata/targetProfile.py:205
|
||||
msgid "Firestorm T0/T1/T2"
|
||||
msgstr ""
|
||||
msgstr "火瀑深渊 T0/T1/T2"
|
||||
|
||||
#: eos/saveddata/targetProfile.py:134 eos/saveddata/targetProfile.py:135
|
||||
#: eos/saveddata/targetProfile.py:136 eos/saveddata/targetProfile.py:137
|
||||
@@ -1780,7 +1780,7 @@ msgstr "火瀑 T3 (含部分T5关卡)"
|
||||
#: eos/saveddata/targetProfile.py:147 eos/saveddata/targetProfile.py:209
|
||||
#: eos/saveddata/targetProfile.py:210 eos/saveddata/targetProfile.py:211
|
||||
msgid "Firestorm T4/T5/T6"
|
||||
msgstr ""
|
||||
msgstr "火瀑深渊 T4/T5/T6"
|
||||
|
||||
#: graphs/gui/lists.py:306
|
||||
msgid "Fit"
|
||||
@@ -1853,7 +1853,7 @@ msgstr "盖伦特(护盾)"
|
||||
|
||||
#: eos/saveddata/damagePattern.py:146 eos/saveddata/targetProfile.py:97
|
||||
msgid "Gallente EDENCOM Entities"
|
||||
msgstr ""
|
||||
msgstr "盖伦特EDENCOM实体"
|
||||
|
||||
#: eos/saveddata/damagePattern.py:152 eos/saveddata/targetProfile.py:75
|
||||
msgid "Gallente Federation"
|
||||
@@ -1873,7 +1873,7 @@ msgstr "伽玛"
|
||||
#: eos/saveddata/targetProfile.py:175 eos/saveddata/targetProfile.py:221
|
||||
#: eos/saveddata/targetProfile.py:222 eos/saveddata/targetProfile.py:223
|
||||
msgid "Gamma T0/T1/T2"
|
||||
msgstr ""
|
||||
msgstr "伽玛深渊 T0/T1/T2"
|
||||
|
||||
#: eos/saveddata/targetProfile.py:176 eos/saveddata/targetProfile.py:177
|
||||
#: eos/saveddata/targetProfile.py:178 eos/saveddata/targetProfile.py:179
|
||||
@@ -1889,7 +1889,7 @@ msgstr "伽玛 T3 (含部分T5关卡)"
|
||||
#: eos/saveddata/targetProfile.py:189 eos/saveddata/targetProfile.py:227
|
||||
#: eos/saveddata/targetProfile.py:228 eos/saveddata/targetProfile.py:229
|
||||
msgid "Gamma T4/T5/T6"
|
||||
msgstr ""
|
||||
msgstr "伽玛深渊 T4/T5/T6"
|
||||
|
||||
#: gui/builtinStatsViews/targetingMiscViewMinimal.py:125
|
||||
msgid "Gas hold"
|
||||
@@ -1948,7 +1948,7 @@ msgstr "古斯塔斯"
|
||||
#: gui/builtinStatsViews/resistancesViewFull.py:172
|
||||
#: gui/builtinStatsViews/resistancesViewFull.py:187
|
||||
msgid "HP"
|
||||
msgstr ""
|
||||
msgstr "生命值"
|
||||
|
||||
#: gui/builtinPreferenceViews/pyfaHTMLExportPreferences.py:19
|
||||
msgid "HTML Export"
|
||||
@@ -2019,7 +2019,7 @@ msgstr "混合弹药"
|
||||
|
||||
#: gui/builtinItemStatsViews/itemEffects.py:35
|
||||
msgid "ID"
|
||||
msgstr ""
|
||||
msgstr "ID"
|
||||
|
||||
#: eos/saveddata/targetProfile.py:293
|
||||
msgid "Ideal Target"
|
||||
@@ -2465,7 +2465,7 @@ msgstr "米玛塔尔(护盾)"
|
||||
#: eos/saveddata/damagePattern.py:147 eos/saveddata/damagePattern.py:148
|
||||
#: eos/saveddata/targetProfile.py:98
|
||||
msgid "Minmatar EDENCOM Entities"
|
||||
msgstr ""
|
||||
msgstr "米玛塔尔EDENCOM实体"
|
||||
|
||||
#: eos/saveddata/damagePattern.py:154 eos/saveddata/targetProfile.py:77
|
||||
msgid "Minmatar Republic"
|
||||
@@ -2664,7 +2664,7 @@ msgstr "变质"
|
||||
#: eos/saveddata/targetProfile.py:230 eos/saveddata/targetProfile.py:231
|
||||
#: eos/saveddata/targetProfile.py:232
|
||||
msgid "NPC"
|
||||
msgstr ""
|
||||
msgstr "NPC"
|
||||
|
||||
#: gui/builtinItemStatsViews/itemEffects.py:30
|
||||
#: gui/builtinViewColumns/baseName.py:55
|
||||
@@ -3012,7 +3012,8 @@ msgstr "Pyfa可以自动检查更新并提示。这个功能可在网络设置
|
||||
#: gui/builtinPreferenceViews/pyfaGeneralPreferences.py:69
|
||||
msgid "Pyfa language selection disabled. Please check if .mo files have been generated.\n"
|
||||
"Refer to locale/README.md for info."
|
||||
msgstr ""
|
||||
msgstr "Pyfa语言选择已禁用。请检查.mo 文件是否已生成。\n"
|
||||
"请参阅locale/README.md获取信息。"
|
||||
|
||||
#: gui/builtinStatsViews/targetingMiscViewMinimal.py:129
|
||||
msgid "Quafe hold"
|
||||
@@ -3189,7 +3190,7 @@ msgstr "自由无人机"
|
||||
|
||||
#: eos/saveddata/damagePattern.py:160 eos/saveddata/targetProfile.py:231
|
||||
msgid "Rogue Drone Entities"
|
||||
msgstr ""
|
||||
msgstr "自由无人机实体"
|
||||
|
||||
#: eos/saveddata/targetProfile.py:63 eos/saveddata/targetProfile.py:69
|
||||
msgid "Rogue Drones"
|
||||
@@ -3227,7 +3228,7 @@ msgstr ""
|
||||
#: eos/saveddata/targetProfile.py:219 eos/saveddata/targetProfile.py:222
|
||||
#: eos/saveddata/targetProfile.py:225 eos/saveddata/targetProfile.py:228
|
||||
msgid "Sansha"
|
||||
msgstr ""
|
||||
msgstr "萨沙"
|
||||
|
||||
#: eos/saveddata/damagePattern.py:157 eos/saveddata/targetProfile.py:80
|
||||
#: gui/builtinContextMenus/envEffectAdd.py:124
|
||||
@@ -3497,7 +3498,7 @@ msgstr "冬眠者"
|
||||
|
||||
#: eos/saveddata/damagePattern.py:161 eos/saveddata/targetProfile.py:232
|
||||
msgid "Sleeper Entities"
|
||||
msgstr ""
|
||||
msgstr "冬眠者实体"
|
||||
|
||||
#: eos/saveddata/damagePattern.py:158
|
||||
msgid "Sleepers"
|
||||
@@ -3859,7 +3860,7 @@ msgstr "三神裔"
|
||||
#: eos/saveddata/damagePattern.py:134 eos/saveddata/damagePattern.py:137
|
||||
#: eos/saveddata/damagePattern.py:140 eos/saveddata/targetProfile.py:94
|
||||
msgid "Triglavian Entities"
|
||||
msgstr ""
|
||||
msgstr "三神裔实体"
|
||||
|
||||
#: gui/builtinContextMenus/envEffectAdd.py:126
|
||||
#: gui/builtinContextMenus/envEffectAdd.py:128
|
||||
@@ -4191,11 +4192,11 @@ msgstr "Pyfa属性自定义文件"
|
||||
|
||||
#: gui/builtinPreferenceViews/pyfaEsiPreferences.py:46
|
||||
msgid "pyfa.io"
|
||||
msgstr ""
|
||||
msgstr "pyfa.io"
|
||||
|
||||
#: gui/builtinPreferenceViews/pyfaGeneralPreferences.py:47
|
||||
msgid "pyfa:"
|
||||
msgstr ""
|
||||
msgstr "pyfa:"
|
||||
|
||||
#: eos/utils/stats.py:123
|
||||
msgid "th"
|
||||
|
||||
9
service/conversions/releaseAug2022.py
Normal file
@@ -0,0 +1,9 @@
|
||||
"""
|
||||
Conversion pack for August 2022 release
|
||||
"""
|
||||
|
||||
CONVERSIONS = {
|
||||
# Renamed items
|
||||
"Basic Reactor Control Unit": "'Basic' Reactor Control Unit",
|
||||
"Basic Co-Processor": "'Basic' Co-Processor",
|
||||
}
|
||||
@@ -35,6 +35,7 @@ from eos.gamedata import Category as types_Category, Group as types_Group, Item
|
||||
from service import conversions
|
||||
from service.jargon import JargonLoader
|
||||
from service.settings import SettingsProvider
|
||||
from utils.cjk import isStringCjk
|
||||
|
||||
pyfalog = Logger(__name__)
|
||||
_t = wx.GetTranslation
|
||||
@@ -152,7 +153,11 @@ class SearchWorkerThread(threading.Thread):
|
||||
requestTokens = self.jargonLoader.get_jargon().apply(requestTokens)
|
||||
|
||||
all_results = set()
|
||||
if len(' '.join(requestTokens)) >= config.minItemSearchLength:
|
||||
joinedTokens = ' '.join(requestTokens)
|
||||
if (
|
||||
(isStringCjk(joinedTokens) and len(joinedTokens) >= config.minItemSearchLengthCjk)
|
||||
or len(joinedTokens) >= config.minItemSearchLength
|
||||
):
|
||||
for filter_ in filters:
|
||||
filtered_results = eos.db.searchItemsRegex(
|
||||
requestTokens, where=filter_,
|
||||
|
||||
@@ -28,7 +28,7 @@ pyfaVersion = getVersion()
|
||||
|
||||
class EfsPort:
|
||||
wepTestSet = {}
|
||||
version = 0.05
|
||||
version = 0.06
|
||||
|
||||
@staticmethod
|
||||
def attrDirectMap(values, target, source):
|
||||
@@ -207,6 +207,9 @@ class EfsPort:
|
||||
]:
|
||||
stats["type"] = "Remote Armor Repairer"
|
||||
EfsPort.attrDirectMap(["armorDamageAmount"], stats, mod)
|
||||
elif mod.item.group.name in ["Remote Capacitor Transmitter"]:
|
||||
stats["type"] = "Remote Capacitor Transmitter"
|
||||
EfsPort.attrDirectMap(["powerTransferAmount"], stats, mod)
|
||||
elif mod.item.group.name == "Warp Scrambler":
|
||||
stats["type"] = "Warp Scrambler"
|
||||
EfsPort.attrDirectMap(["activationBlockedStrenght", "warpScrambleStrength"], stats, mod)
|
||||
@@ -243,7 +246,10 @@ class EfsPort:
|
||||
pyfalog.error("Projected module {0} lacks efs export implementation".format(mod.item.typeName))
|
||||
if mod.getModifiedItemAttr("maxRange", None) is None:
|
||||
pyfalog.error("Projected module {0} has no maxRange".format(mod.item.typeName))
|
||||
stats["optimal"] = mod.getModifiedItemAttr("maxRange", maxRangeDefault)
|
||||
|
||||
# Burst jammer maxRange is 0 if the value is retrieved using mod.getModifiedItemAttr("maxRange")
|
||||
# Despite it is correct, it still pulls 0.0.
|
||||
stats["optimal"] = mod.getModifiedItemAttr("maxRange", maxRangeDefault) if mod.item.group.name != "Burst Jammer" else mod.maxRange
|
||||
stats["falloff"] = mod.getModifiedItemAttr("falloffEffectiveness", falloffDefault)
|
||||
EfsPort.attrDirectMap(["duration", "capacitorNeed"], stats, mod)
|
||||
projections.append(stats)
|
||||
|
||||
@@ -165,16 +165,25 @@ def exportModules(modules, options, mutaData=None):
|
||||
|
||||
def exportDrones(drones, exportMutants=True, mutaData=None, standAlone=True):
|
||||
|
||||
# Same as in drone additions panel
|
||||
DRONE_ORDER = ('Light Scout Drones', 'Medium Scout Drones',
|
||||
'Heavy Attack Drones', 'Sentry Drones', 'Combat Utility Drones',
|
||||
'Electronic Warfare Drones', 'Logistic Drones', 'Mining Drones', 'Salvage Drones')
|
||||
|
||||
def getDroneName(drone):
|
||||
if drone.isMutated:
|
||||
return drone.baseItem.typeName
|
||||
return drone.item.typeName
|
||||
|
||||
def droneSorter(drone):
|
||||
groupName = Market.getInstance().getMarketGroupByItem(drone.item).marketGroupName
|
||||
return (DRONE_ORDER.index(groupName), drone.isMutated, drone.fullName)
|
||||
|
||||
if mutaData is None:
|
||||
mutaData = MutationExportData()
|
||||
sections = []
|
||||
droneLines = []
|
||||
for drone in sorted(drones, key=getDroneName):
|
||||
for drone in sorted(drones, key=droneSorter):
|
||||
if drone.isMutated and exportMutants:
|
||||
mutaData.mutants[mutaData.reference] = drone
|
||||
mutationSuffix = ' [{}]'.format(mutaData.reference)
|
||||
@@ -190,8 +199,15 @@ def exportDrones(drones, exportMutants=True, mutaData=None, standAlone=True):
|
||||
|
||||
|
||||
def exportFighters(fighters):
|
||||
# Same as in drone additions panel
|
||||
FIGHTER_ORDER = ('Light Fighter', 'Heavy Fighter', 'Support Fighter')
|
||||
|
||||
def fighterSorter(fighter):
|
||||
groupName = Market.getInstance().getGroupByItem(fighter.item).name
|
||||
return (FIGHTER_ORDER.index(groupName), fighter.fullName)
|
||||
|
||||
fighterLines = []
|
||||
for fighter in sorted(fighters, key=lambda f: f.item.typeName):
|
||||
for fighter in sorted(fighters, key=fighterSorter):
|
||||
fighterLines.append('{} x{}'.format(fighter.item.typeName, fighter.amount))
|
||||
return '\n'.join(fighterLines)
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ def tankSection(fit):
|
||||
ehp.append(sum(ehp))
|
||||
ehpStr = [formatAmount(ehpVal, 3, 0, 9) for ehpVal in ehp]
|
||||
resists = {tankType: [1 - fit.ship.getModifiedItemAttr(s) for s in resonanceNames[tankType]] for tankType in tankTypes}
|
||||
ehpAgainstDamageType = [sum(pattern.calculateEhp(fit).values()) for pattern in damagePatterns]
|
||||
ehpAgainstDamageType = [sum(pattern.calculateEhp(fit.ship).values()) for pattern in damagePatterns]
|
||||
ehpAgainstDamageTypeStr = [formatAmount(ehpVal, 3, 0, 9) for ehpVal in ehpAgainstDamageType]
|
||||
|
||||
# not used for now. maybe will be improved later
|
||||
|
||||