Compare commits
172 Commits
v2.53.0
...
v2.57.0dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7120000202 | ||
|
|
c3f7078053 | ||
|
|
b70f02fa3e | ||
|
|
8d893ce648 | ||
|
|
c230480464 | ||
|
|
da7a4a2df0 | ||
|
|
62bde4b8c9 | ||
|
|
43967b70ae | ||
|
|
782c007200 | ||
|
|
5812d333d9 | ||
|
|
c461bf469e | ||
|
|
d5c8c92b48 | ||
|
|
1abffd6c5d | ||
|
|
a824cc5e48 | ||
|
|
db7afffd65 | ||
|
|
4d02a1292f | ||
|
|
00f72294d4 | ||
|
|
0d45be0597 | ||
|
|
f60090fc79 | ||
|
|
713807df13 | ||
|
|
c020bd8898 | ||
|
|
39ee8586d4 | ||
|
|
653a1585dc | ||
|
|
2dcf011020 | ||
|
|
555e72a27a | ||
|
|
85e740d75a | ||
|
|
d604ed300a | ||
|
|
3aea4e5f23 | ||
|
|
a54adddc74 | ||
|
|
dda397fea3 | ||
|
|
3cd718350e | ||
|
|
e87860a700 | ||
|
|
451d21eaa0 | ||
|
|
718f9ef859 | ||
|
|
193adc4ba5 | ||
|
|
cdfa52e9ed | ||
|
|
2752b288ad | ||
|
|
8dce968780 | ||
|
|
b889da7e68 | ||
|
|
0dd7dea708 | ||
|
|
8af1c8da7d | ||
|
|
8d4f83156d | ||
|
|
798bdf3fe0 | ||
|
|
a7cf4aab76 | ||
|
|
d910e324f3 | ||
|
|
d800db5ccb | ||
|
|
6c5d0a3e4f | ||
|
|
9389a0421f | ||
|
|
6f3ab6cee8 | ||
|
|
258dcd49a0 | ||
|
|
5f0320d1e3 | ||
|
|
54052899f9 | ||
|
|
eda53e9318 | ||
|
|
4d8a891fd8 | ||
|
|
2d4b97afe6 | ||
|
|
49d1ec17e8 | ||
|
|
cfecacacf9 | ||
|
|
a9112c04a3 | ||
|
|
5f2a74691c | ||
|
|
17c22df0f4 | ||
|
|
c53bc82929 | ||
|
|
7113f41b9a | ||
|
|
aa66d63085 | ||
|
|
140ee70dc3 | ||
|
|
5023a6cbae | ||
|
|
aafa77baed | ||
|
|
16dabd57ca | ||
|
|
8668d2dd55 | ||
|
|
5c5f37a9ae | ||
|
|
621c36f1cd | ||
|
|
be2cc523c2 | ||
|
|
bd83c403a1 | ||
|
|
043f533a10 | ||
|
|
57a23affd0 | ||
|
|
b678152ac6 | ||
|
|
747bbc8200 | ||
|
|
871cf42d88 | ||
|
|
28533d60d3 | ||
|
|
ca12b3c94f | ||
|
|
81e449dd83 | ||
|
|
368f2c33a9 | ||
|
|
c445bb4423 | ||
|
|
9b216b5d48 | ||
|
|
4b932d210f | ||
|
|
a1ca29fb30 | ||
|
|
876c85ee19 | ||
|
|
ac1d935712 | ||
|
|
2ccc829d3b | ||
|
|
061ab27286 | ||
|
|
d127dd9a7e | ||
|
|
6d13ab8bcb | ||
|
|
e5d95dd4d8 | ||
|
|
08c5c9a4b7 | ||
|
|
115ea9a36c | ||
|
|
a484698a9d | ||
|
|
bafaed1d81 | ||
|
|
c56f274a5f | ||
|
|
02f7fbf1b1 | ||
|
|
96214eaa27 | ||
|
|
3ed85112c6 | ||
|
|
fed39b75e3 | ||
|
|
8a3defded5 | ||
|
|
2fef60eaaa | ||
|
|
88970c7a95 | ||
|
|
fddaf27055 | ||
|
|
dd575bd3a0 | ||
|
|
0c9b73727b | ||
|
|
807622a1ec | ||
|
|
ade9fc389a | ||
|
|
b6c5f67085 | ||
|
|
7d86d58993 | ||
|
|
a7ab046bc6 | ||
|
|
d126b62d63 | ||
|
|
c94693a72d | ||
|
|
9e50de96f3 | ||
|
|
ea335b7d41 | ||
|
|
4838f69c40 | ||
|
|
e67083a79b | ||
|
|
b103e576d2 | ||
|
|
fb81e6c043 | ||
|
|
84716af82b | ||
|
|
30dd77d462 | ||
|
|
9148611a8e | ||
|
|
e7be51b70e | ||
|
|
194e4657eb | ||
|
|
b472adb404 | ||
|
|
b08986ba74 | ||
|
|
7e5150be8c | ||
|
|
57d8a672d9 | ||
|
|
261d510ccb | ||
|
|
858b0b243a | ||
|
|
53385f2458 | ||
|
|
7d3371c379 | ||
|
|
d94116ea1c | ||
|
|
b21b756fa6 | ||
|
|
492adb4dfd | ||
|
|
5fa7b2c86a | ||
|
|
f6120f09ac | ||
|
|
4995c7994f | ||
|
|
620ce89a05 | ||
|
|
73dc056e61 | ||
|
|
97625d11ab | ||
|
|
21bd4272d9 | ||
|
|
332c91d661 | ||
|
|
719125657f | ||
|
|
9621a54257 | ||
|
|
bfc580cf7c | ||
|
|
fd2f76ee41 | ||
|
|
9e01d15e60 | ||
|
|
23ee164a76 | ||
|
|
99ddc36027 | ||
|
|
a33f48a83b | ||
|
|
11c060103a | ||
|
|
ac6b6f70eb | ||
|
|
baf10b24d6 | ||
|
|
0ab485115c | ||
|
|
f8895a14c5 | ||
|
|
22eabcea8d | ||
|
|
ccd3498594 | ||
|
|
71d088b90a | ||
|
|
17712d8b7d | ||
|
|
4a224ea9a5 | ||
|
|
6664b5620a | ||
|
|
a98e898bd8 | ||
|
|
e98ae5de39 | ||
|
|
a51fbbc238 | ||
|
|
f9b4c7b5ea | ||
|
|
4e83f52532 | ||
|
|
ec0b543393 | ||
|
|
cff94a12ee | ||
|
|
da39975ba8 | ||
|
|
82515343ee |
104
.appveyor.yml
@@ -1,75 +1,48 @@
|
||||
image:
|
||||
- Visual Studio 2019
|
||||
- Ubuntu
|
||||
- macos
|
||||
clone_depth: 1
|
||||
- Ubuntu2204
|
||||
- Visual Studio 2022
|
||||
- macos-catalina
|
||||
for:
|
||||
-
|
||||
matrix:
|
||||
only:
|
||||
- image: Ubuntu
|
||||
- image: Ubuntu2204
|
||||
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.16-cp37-cp37m-manylinux2014_x86_64.AppImage
|
||||
APPVEYOR_SSH_KEY: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDhb96UEXy8yOy/f+riX/8kKbNx/lOfIZ4pP4Cw3Gj3DmnTwEnxtRtyc+xtaxOsKbt+7+EAXFpCzYX+jHMhtd0QtWB7dbey8DBg31g0f8C5EPquqROibVbhzr/F3f6/d52FFfq6Y/CWaAvLjezvipr+zOOsIFcVusqtXdPJQ/LtUJ0LS5d4lFiw5ELHSxHIpqwGwyb7PbR3ufEFoqbr8eYiCH+vlBob72ArPfo2f3u0sMvpGYmjVVu2jj4FEY2h89sLrGyFdNWBoyumRhkb38+WSAuyPa/Y21+g+S8sRzIlkwbxicGNMtrMIi6zHEIGAgA06Sw2psP807h730PPOVaWjUcU3ojNW8hH3nPizF74pT82+iP7/fFC4PXLP+tBa+8OoHC5yiO7QKUKprMSqVa1qOm8fHbrzglplKJXfzSfUtSE+AQ+HtHhuUWKI+0LBLDrsOJwI5hbsPOAuiZ5I3VfqfAOck6SH9TcmlapVmQEypc7d7oeeUtZSOuIWKXp068= dfx@aw"
|
||||
APPIMAGE_TOOL: appimage-builder-x86_64.AppImage
|
||||
DEPLOY_DIR: AppDir/opt/pyfa
|
||||
# APPVEYOR_SSH_BLOCK: true
|
||||
# APPVEYOR_SSH_BLOCK: true
|
||||
cache:
|
||||
- /home/appveyor/.cache/pip -> requirements.txt
|
||||
init:
|
||||
- sh: curl -sflL 'https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-ssh.sh' | bash -e -
|
||||
# init:
|
||||
# - sh: curl -sflL 'https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-ssh.sh' | bash -e -
|
||||
install:
|
||||
- sh: git fetch --prune --unshallow # to fix the version dump issues
|
||||
- sh: sudo DEBIAN_FRONTEND=noninteractive apt-get -y update
|
||||
- sh: sudo DEBIAN_FRONTEND=noninteractive apt-get -y install python3.7-dev libgtk-3-dev python3-pip libwebkit2gtk-4.0-dev
|
||||
# AppImage dependencies
|
||||
- sh: sudo DEBIAN_FRONTEND=noninteractive apt-get -y install libfuse2
|
||||
# Preparation script dependencies
|
||||
- sh: sudo DEBIAN_FRONTEND=noninteractive apt-get -y install python3-wxgtk4.0 python3-sqlalchemy python3-logbook
|
||||
before_build:
|
||||
- sh: mkdir build && cd build
|
||||
- sh: curl -LO https://github.com/AppImage/AppImageKit/releases/download/13/$APPIMAGE_TOOL && chmod +x $APPIMAGE_TOOL
|
||||
- sh: curl -LO https://github.com/niess/python-appimage/releases/download/python3.7/$PYTHON_APPIMAGE && chmod +x $PYTHON_APPIMAGE
|
||||
build_script:
|
||||
# Prepare Python base AppImage, stripping Python metadata
|
||||
- sh: ./$PYTHON_APPIMAGE --appimage-extract
|
||||
- sh: mv squashfs-root AppDir
|
||||
- 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 ../
|
||||
# Prepare pyfa data
|
||||
- sh: find locale/ -type f -name "*.po" -exec msgen "{}" -o "{}" \;
|
||||
- sh: build/AppDir/usr/bin/python scripts/compile_lang.py
|
||||
- sh: build/AppDir/usr/bin/python scripts/dump_crowdin_progress.py
|
||||
- sh: build/AppDir/usr/bin/python db_update.py
|
||||
- sh: export PYFA_VERSION="$(python3.7 scripts/dump_version.py)"
|
||||
|
||||
# Copy pyfa files to host
|
||||
- sh: cp -r eos graphs gui imgs locale service utils eve.db config.py pyfa.py db_update.py README.md LICENSE version.yml ./build/$DEPLOY_DIR
|
||||
- sh: find ./build/$DEPLOY_DIR | grep -E "(__pycache__|\.pyc|\.pyo$)" | xargs rm -rf
|
||||
|
||||
# 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 pyfa.appdata.xml ../../build/AppDir/usr/share/metainfo/
|
||||
- sh: chmod +x pyfa && cp pyfa ../../build/AppDir/usr/bin
|
||||
- sh: cd ../../
|
||||
|
||||
# Package it all up
|
||||
- sh: mkdir dist
|
||||
- sh: ./build/$APPIMAGE_TOOL build/AppDir dist/pyfa-$PYFA_VERSION-linux.AppImage
|
||||
- sh: python3 -B scripts/compile_lang.py
|
||||
- sh: python3 -B scripts/dump_crowdin_progress.py
|
||||
- sh: python3 -B db_update.py
|
||||
- sh: export PYFA_VERSION="$(python3 -B scripts/dump_version.py)"
|
||||
- sh: mkdir build
|
||||
# Download packaging tool
|
||||
- sh: curl -o $APPIMAGE_TOOL -L https://github.com/AppImageCrafters/appimage-builder/releases/download/v1.1.0/appimage-builder-1.1.0-x86_64.AppImage
|
||||
- sh: chmod +x $APPIMAGE_TOOL
|
||||
build_script:
|
||||
- sh: mkdir -p AppDir/opt/pyfa
|
||||
- sh: cp -r eos graphs gui imgs locale service utils eve.db config.py pyfa.py db_update.py README.md LICENSE version.yml AppDir/opt/pyfa/
|
||||
- sh: mkdir -p AppDir/usr/share/icons/hicolor/64x64/apps/
|
||||
- sh: cp imgs/gui/pyfa64.png AppDir/usr/share/icons/hicolor/64x64/apps/pyfa.png
|
||||
- sh: ./$APPIMAGE_TOOL --recipe dist_assets/linux/AppImageBuilder.yml
|
||||
after_build:
|
||||
- sh: ls -la build
|
||||
- sh: ls -la
|
||||
artifacts:
|
||||
- path: dist/pyfa-$PYFA_VERSION-linux.AppImage
|
||||
- path: pyfa-$PYFA_VERSION-linux.AppImage
|
||||
deploy:
|
||||
tag: $PYFA_VERSION
|
||||
release: pyfa $PYFA_VERSION
|
||||
@@ -85,17 +58,15 @@ for:
|
||||
-
|
||||
matrix:
|
||||
only:
|
||||
- image: Visual Studio 2019
|
||||
- image: Visual Studio 2022
|
||||
environment:
|
||||
PYTHON: "C:\\Python37-x64"
|
||||
PYTHON: "C:\\Python311-x64"
|
||||
# Should be enabled only for build process debugging
|
||||
# init:
|
||||
# - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
cache:
|
||||
- C:\users\appveyor\appdata\local\pip\cache\ -> requirements.txt
|
||||
install:
|
||||
- cmd: git fetch --prune --unshallow # to fix the version dump issues
|
||||
|
||||
- ps: echo("OS version:")
|
||||
- ps: "[System.Environment]::OSVersion.Version"
|
||||
|
||||
@@ -131,10 +102,8 @@ for:
|
||||
# pip will build them from source using the MSVC compiler matching the
|
||||
# target Python version and architecture
|
||||
- ps: echo("Install pip requirements:")
|
||||
# This one is needed to build wxpython 4.0.6 on windows
|
||||
- cmd: "python -m pip install pathlib2"
|
||||
- cmd: "python -m pip install -r requirements.txt"
|
||||
- cmd: "python -m pip install PyInstaller==3.6"
|
||||
- cmd: "python -m pip install PyInstaller"
|
||||
before_build:
|
||||
# directory that will contain the built files
|
||||
- ps: $env:PYFA_DIST_DIR = "c:\projects\$env:APPVEYOR_PROJECT_SLUG\dist"
|
||||
@@ -150,7 +119,7 @@ for:
|
||||
# Build gamedata DB
|
||||
- cmd: "python db_update.py"
|
||||
# Build command for PyInstaller
|
||||
- cmd: "python -m PyInstaller --noupx --clean --windowed --noconsole -y pyfa.spec"
|
||||
- cmd: "python -m PyInstaller --clean -y pyfa.spec"
|
||||
# Copy over manifest (See pyfa-org/pyfa#1622)
|
||||
- ps: xcopy /y dist_assets\win\pyfa.exe.manifest $env:PYFA_DIST_DIR\pyfa\
|
||||
# InnoScript EXE building. This is in a separate script because I don't feel like copying over the logic to AppVeyor script right now...
|
||||
@@ -177,16 +146,15 @@ for:
|
||||
-
|
||||
matrix:
|
||||
only:
|
||||
- image: macos
|
||||
- image: macos-catalina
|
||||
environment:
|
||||
APPVEYOR_SSH_KEY: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDJDW/+oYNGOiPvwuwAL9tc/LQgg58aosIVpMYfepQZ20V+VZnHpZh8IRDA8Jo5xht19p2PksA+hFgqA0kpKtrSkuiWdE8rATQItfk4gf7yB0yGasJGGQZYazy9k/9XtmYkq2HHOOeEqdxvrICddJQ88MLCLT9lJENSUP/YS/yGcjZFXVxE11pTeIcqlCRU+3eYa1v7BeNvXIKNhZoK5orXWrtuH3cy8jrSns/u70aYfJ6B2jA8CnWnDbuvpeQtEY61SQqlKUsSArNa8NAsXj41wr3Ar9gAG9330w7EMTqlutk8HZO35uHI0q5qinUhaQYufPPrVkb2L/N+ZCfu0fnh appveyor"
|
||||
cache:
|
||||
- /Users/appveyor/Library/Caches/pip/ -> requirements.txt
|
||||
init:
|
||||
# - sh: curl -sflL 'https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-ssh.sh' | bash -e -
|
||||
- sh: source ~/venv3.7/bin/activate
|
||||
- sh: source ~/venv3.11/bin/activate
|
||||
install:
|
||||
- sh: git fetch --prune --unshallow # to fix the version dump issues
|
||||
- sh: bash scripts/osx-setup.sh
|
||||
build_script:
|
||||
- sh: bash scripts/osx-translations.sh
|
||||
|
||||
183
db_update.py
@@ -617,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:
|
||||
@@ -625,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)
|
||||
@@ -641,138 +651,151 @@ def update_db():
|
||||
effect.effectName = effectName
|
||||
item.effects[effectName] = effect
|
||||
|
||||
def hardcodeGeri():
|
||||
def hardcodeShapash():
|
||||
shapashTypeID = 1000000
|
||||
_copyItem(srcName='Utu', tgtTypeID=shapashTypeID, tgtName='Shapash')
|
||||
attrMap = {
|
||||
# Fitting
|
||||
'powerOutput': 50,
|
||||
'cpuOutput': 200,
|
||||
'capacitorCapacity': 325,
|
||||
'rechargeRate': 130000,
|
||||
'cpuOutput': 225,
|
||||
'capacitorCapacity': 420,
|
||||
'rechargeRate': 187500,
|
||||
# Slots
|
||||
'hiSlots': 5,
|
||||
'hiSlots': 3,
|
||||
'medSlots': 4,
|
||||
'lowSlots': 4,
|
||||
'launcherSlotsLeft': 3,
|
||||
'turretSlotsLeft': 2,
|
||||
'launcherSlotsLeft': 0,
|
||||
'turretSlotsLeft': 3,
|
||||
# Rigs
|
||||
'rigSlots': 2,
|
||||
'rigSize': 1,
|
||||
'upgradeCapacity': 400,
|
||||
# Shield
|
||||
'shieldCapacity': 1000,
|
||||
'shieldEmDamageResonance': 1 - 0.75,
|
||||
'shieldCapacity': 575,
|
||||
'shieldRechargeRate': 625000,
|
||||
'shieldEmDamageResonance': 1 - 0.0,
|
||||
'shieldThermalDamageResonance': 1 - 0.6,
|
||||
'shieldKineticDamageResonance': 1 - 0.4,
|
||||
'shieldKineticDamageResonance': 1 - 0.85,
|
||||
'shieldExplosiveDamageResonance': 1 - 0.5,
|
||||
# Armor
|
||||
'armorHP': 1000,
|
||||
'armorEmDamageResonance': 1 - 0.9,
|
||||
'armorHP': 1015,
|
||||
'armorEmDamageResonance': 1 - 0.5,
|
||||
'armorThermalDamageResonance': 1 - 0.675,
|
||||
'armorKineticDamageResonance': 1 - 0.25,
|
||||
'armorKineticDamageResonance': 1 - 0.8375,
|
||||
'armorExplosiveDamageResonance': 1 - 0.1,
|
||||
# Structure
|
||||
'hp': 700,
|
||||
'hp': 1274,
|
||||
'emDamageResonance': 1 - 0.33,
|
||||
'thermalDamageResonance': 1 - 0.33,
|
||||
'kineticDamageResonance': 1 - 0.33,
|
||||
'explosiveDamageResonance': 1 - 0.33,
|
||||
'mass': 1309000,
|
||||
'volume': 27289,
|
||||
'capacity': 260,
|
||||
'mass': 1215000,
|
||||
'volume': 29500,
|
||||
'capacity': 165,
|
||||
# Navigation
|
||||
'maxVelocity': 440,
|
||||
'agility': 2.5,
|
||||
'maxVelocity': 325,
|
||||
'agility': 3.467,
|
||||
'warpSpeedMultiplier': 5.5,
|
||||
# Drones
|
||||
'droneCapacity': 50,
|
||||
'droneBandwidth': 10,
|
||||
'droneCapacity': 75,
|
||||
'droneBandwidth': 25,
|
||||
# Targeting
|
||||
'maxTargetRange': 42000,
|
||||
'maxTargetRange': 49000,
|
||||
'maxLockedTargets': 6,
|
||||
'scanRadarStrength': 0,
|
||||
'scanLadarStrength': 12,
|
||||
'scanMagnetometricStrength': 0,
|
||||
'scanLadarStrength': 0,
|
||||
'scanMagnetometricStrength': 9,
|
||||
'scanGravimetricStrength': 0,
|
||||
'signatureRadius': 33,
|
||||
'scanResolution': 770}
|
||||
'signatureRadius': 39,
|
||||
'scanResolution': 550,
|
||||
# Misc
|
||||
'energyWarfareResistance': 0,
|
||||
'stasisWebifierResistance': 0,
|
||||
'weaponDisruptionResistance': 0}
|
||||
effectMap = {
|
||||
100100: 'pyfaCustomGeriAfExploVel',
|
||||
100101: 'pyfaCustomGeriAfRof',
|
||||
100102: 'pyfaCustomGeriMfDmg',
|
||||
100103: 'pyfaCustomGeriMfRep',
|
||||
100104: 'pyfaCustomGeriRoleWebDroneStr',
|
||||
100105: 'pyfaCustomGeriRoleWebDroneHP',
|
||||
100106: 'pyfaCustomGeriRoleWebDroneSpeed',
|
||||
100107: 'pyfaCustomGeriRoleMWDSigBloom'}
|
||||
_hardcodeAttribs(74141, attrMap)
|
||||
_hardcodeEffects(74141, effectMap)
|
||||
100100: 'pyfaCustomShapashAfArAmount',
|
||||
100101: 'pyfaCustomShapashAfShtTrackingOptimal',
|
||||
100102: 'pyfaCustomShapashGfShtDamage',
|
||||
100103: 'pyfaCustomShapashGfPointRange',
|
||||
100104: 'pyfaCustomShapashGfPropOverheat',
|
||||
100105: 'pyfaCustomShapashRolePlateMass',
|
||||
100106: 'pyfaCustomShapashRoleHeat'}
|
||||
_hardcodeAttribs(shapashTypeID, attrMap)
|
||||
_hardcodeEffects(shapashTypeID, effectMap)
|
||||
|
||||
def hardcodeBestla():
|
||||
def hardcodeCybele():
|
||||
cybeleTypeID = 1000001
|
||||
_copyItem(srcName='Adrestia', tgtTypeID=cybeleTypeID, tgtName='Cybele')
|
||||
attrMap = {
|
||||
# Fitting
|
||||
'powerOutput': 1300,
|
||||
'cpuOutput': 500,
|
||||
'capacitorCapacity': 1500,
|
||||
'rechargeRate': 200000,
|
||||
'hiSlots': 6,
|
||||
'medSlots': 5,
|
||||
'lowSlots': 5,
|
||||
'launcherSlotsLeft': 4,
|
||||
'turretSlotsLeft': 2,
|
||||
'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': 3000,
|
||||
'shieldEmDamageResonance': 1 - 0.75,
|
||||
'shieldThermalDamageResonance': 1 - 0.6,
|
||||
'shieldKineticDamageResonance': 1 - 0.4,
|
||||
'shieldCapacity': 1200,
|
||||
'shieldRechargeRate': 1250000,
|
||||
'shieldEmDamageResonance': 1 - 0.0,
|
||||
'shieldThermalDamageResonance': 1 - 0.5,
|
||||
'shieldKineticDamageResonance': 1 - 0.9,
|
||||
'shieldExplosiveDamageResonance': 1 - 0.5,
|
||||
# Armor
|
||||
'armorHP': 3000,
|
||||
'armorEmDamageResonance': 1 - 0.9,
|
||||
'armorThermalDamageResonance': 1 - 0.675,
|
||||
'armorKineticDamageResonance': 1 - 0.25,
|
||||
'armorHP': 1900,
|
||||
'armorEmDamageResonance': 1 - 0.5,
|
||||
'armorThermalDamageResonance': 1 - 0.69,
|
||||
'armorKineticDamageResonance': 1 - 0.85,
|
||||
'armorExplosiveDamageResonance': 1 - 0.1,
|
||||
# Structure
|
||||
'hp': 1600,
|
||||
'hp': 2300,
|
||||
'emDamageResonance': 1 - 0.33,
|
||||
'thermalDamageResonance': 1 - 0.33,
|
||||
'kineticDamageResonance': 1 - 0.33,
|
||||
'explosiveDamageResonance': 1 - 0.33,
|
||||
'mass': 11650000,
|
||||
'volume': 96000,
|
||||
'capacity': 660,
|
||||
'mass': 11100000,
|
||||
'volume': 112000,
|
||||
'capacity': 450,
|
||||
# Navigation
|
||||
'maxVelocity': 300,
|
||||
'agility': 0.47,
|
||||
'maxVelocity': 235,
|
||||
'agility': 0.457,
|
||||
'warpSpeedMultiplier': 4.5,
|
||||
# Drones
|
||||
'droneCapacity': 125,
|
||||
'droneBandwidth': 20,
|
||||
'droneCapacity': 100,
|
||||
'droneBandwidth': 50,
|
||||
# Targeting
|
||||
'maxTargetRange': 80000,
|
||||
'maxLockedTargets': 7,
|
||||
'maxTargetRange': 60000,
|
||||
'maxLockedTargets': 6,
|
||||
'scanRadarStrength': 0,
|
||||
'scanLadarStrength': 22,
|
||||
'scanMagnetometricStrength': 0,
|
||||
'scanLadarStrength': 0,
|
||||
'scanMagnetometricStrength': 15,
|
||||
'scanGravimetricStrength': 0,
|
||||
'signatureRadius': 120,
|
||||
'scanResolution': 340}
|
||||
'signatureRadius': 115,
|
||||
'scanResolution': 330,
|
||||
# Misc
|
||||
'energyWarfareResistance': 0,
|
||||
'stasisWebifierResistance': 0,
|
||||
'weaponDisruptionResistance': 0}
|
||||
effectMap = {
|
||||
100200: 'pyfaCustomBestlaHacExploVel',
|
||||
100201: 'pyfaCustomBestlaHacRof',
|
||||
100202: 'pyfaCustomBestlaMcDmg',
|
||||
100203: 'pyfaCustomBestlaMcRep',
|
||||
100204: 'pyfaCustomBestlaRoleWebDroneStr',
|
||||
100205: 'pyfaCustomBestlaRoleWebDroneHP',
|
||||
100206: 'pyfaCustomBestlaRoleWebDroneSpeed'}
|
||||
_hardcodeAttribs(74316, attrMap)
|
||||
_hardcodeEffects(74316, effectMap)
|
||||
100200: 'pyfaCustomCybeleHacMhtFalloff',
|
||||
100201: 'pyfaCustomCybeleHacMhtTracking',
|
||||
100202: 'pyfaCustomCybeleGcMhtDamage',
|
||||
100203: 'pyfaCustomCybeleGcArAmount',
|
||||
100204: 'pyfaCustomCybeleGcPointRange',
|
||||
100205: 'pyfaCustomCybeleRoleVelocity',
|
||||
100206: 'pyfaCustomCybeleRolePlateMass'}
|
||||
_hardcodeAttribs(cybeleTypeID, attrMap)
|
||||
_hardcodeEffects(cybeleTypeID, effectMap)
|
||||
|
||||
# hardcodeGeri()
|
||||
# hardcodeBestla()
|
||||
# hardcodeShapash()
|
||||
# hardcodeCybele()
|
||||
|
||||
eos.db.gamedata_session.commit()
|
||||
eos.db.gamedata_engine.execute('VACUUM')
|
||||
|
||||
55
dist_assets/linux/AppImageBuilder.yml
Normal file
@@ -0,0 +1,55 @@
|
||||
version: 1
|
||||
|
||||
AppDir:
|
||||
path: ./AppDir
|
||||
|
||||
app_info:
|
||||
id: pyfa
|
||||
name: pyfa
|
||||
icon: pyfa
|
||||
version: '{{PYFA_VERSION}}'
|
||||
exec: usr/bin/python3.11
|
||||
exec_args: "-s $APPDIR/opt/pyfa/pyfa.py $@"
|
||||
|
||||
apt:
|
||||
arch: [ amd64 ]
|
||||
sources:
|
||||
- sourceline: 'deb http://us.archive.ubuntu.com/ubuntu jammy main restricted universe multiverse'
|
||||
key_url: 'http://keyserver.ubuntu.com/pks/lookup?op=get&search=0x871920d1991bc93c'
|
||||
- sourceline: 'deb http://us.archive.ubuntu.com/ubuntu jammy-updates main restricted universe multiverse'
|
||||
key_url: 'http://keyserver.ubuntu.com/pks/lookup?op=get&search=0x871920d1991bc93c'
|
||||
- sourceline: 'deb http://us.archive.ubuntu.com/ubuntu jammy-backports main restricted universe multiverse'
|
||||
key_url: 'http://keyserver.ubuntu.com/pks/lookup?op=get&search=0x871920d1991bc93c'
|
||||
- sourceline: 'deb http://us.archive.ubuntu.com/ubuntu jammy-security main restricted universe multiverse'
|
||||
key_url: 'http://keyserver.ubuntu.com/pks/lookup?op=get&search=0x871920d1991bc93c'
|
||||
- sourceline: 'deb https://ppa.launchpadcontent.net/deadsnakes/ppa/ubuntu jammy main'
|
||||
key_url: 'http://keyserver.ubuntu.com/pks/lookup?op=get&search=0xf23c5a6cf475977595c89f51ba6932366a755776'
|
||||
|
||||
include:
|
||||
- python3.11
|
||||
# wx dependencies
|
||||
- libgtk-3-0
|
||||
- libwebkit2gtk-4.0-37 # Needed for wx's HTML lib
|
||||
- librsvg2-common # Without it, search in char editor crashes due to inability to load some images
|
||||
exclude: []
|
||||
|
||||
after_bundle:
|
||||
# Install python dependencies to bundled interpreter
|
||||
- export PYTHONHOME="AppDir/usr"
|
||||
- export PYTHONPATH="AppDir/usr/lib/python3.11/site-packages"
|
||||
- curl -L https://bootstrap.pypa.io/get-pip.py -o get-pip.py
|
||||
- AppDir/usr/bin/python3.11 get-pip.py
|
||||
# Just to bundle certificates with AppImage
|
||||
- AppDir/usr/bin/python3.11 -s -m pip install certifi
|
||||
- AppDir/usr/bin/python3.11 -s -m pip install -f https://extras.wxpython.org/wxPython4/extras/linux/gtk3/ubuntu-22.04 -r requirements.txt
|
||||
|
||||
runtime:
|
||||
env:
|
||||
PYTHONHOME: '${APPDIR}/usr'
|
||||
PYTHONPATH: '${APPDIR}/usr/lib/python3.11/site-packages'
|
||||
SSL_CERT_FILE: '${APPDIR}/usr/lib/python3.11/site-packages/certifi/cacert.pem'
|
||||
|
||||
AppImage:
|
||||
sign-key: None
|
||||
arch: x86_64
|
||||
file_name: 'pyfa-{{PYFA_VERSION}}-linux.AppImage'
|
||||
@@ -1,3 +1,3 @@
|
||||
#! /bin/bash
|
||||
|
||||
${APPDIR}/usr/bin/python3.7 -s "${APPDIR}/opt/pyfa/pyfa.py" "$@"
|
||||
${APPDIR}/usr/bin/python3 -s "${APPDIR}/opt/pyfa/pyfa.py" "$@"
|
||||
|
||||
@@ -80,6 +80,7 @@ exe = EXE(pyz,
|
||||
app = BUNDLE(
|
||||
exe,
|
||||
name='pyfa.app',
|
||||
version=os.getenv('PYFA_VERSION'),
|
||||
icon=icon,
|
||||
bundle_identifier=None,
|
||||
info_plist={
|
||||
@@ -88,5 +89,7 @@ app = BUNDLE(
|
||||
'CFBundleName': 'pyfa',
|
||||
'CFBundleDisplayName': 'pyfa',
|
||||
'CFBundleIdentifier': 'org.pyfaorg.pyfa',
|
||||
'CFBundleVersion': os.getenv('PYFA_VERSION'),
|
||||
'CFBundleShortVersionString': os.getenv('PYFA_VERSION'),
|
||||
}
|
||||
)
|
||||
|
||||
@@ -42,10 +42,10 @@ CloseApplications=yes
|
||||
DefaultDirName={pf}\{#MyAppName}
|
||||
DefaultGroupName={#MyAppName}
|
||||
AllowNoIcons=yes
|
||||
LicenseFile={#MyAppDir}\LICENSE
|
||||
LicenseFile={#MyAppDir}\app\LICENSE
|
||||
OutputDir={#MyOutputDir}
|
||||
OutputBaseFilename={#MyOutputFile}
|
||||
SetupIconFile={#MyAppDir}\pyfa.ico
|
||||
SetupIconFile={#MyAppDir}\app\pyfa.ico
|
||||
SolidCompression=yes
|
||||
|
||||
[Languages]
|
||||
|
||||
@@ -51,7 +51,7 @@ mapper(DynamicItemAttribute, dynamicAttributes_table,
|
||||
properties={"info": relation(AttributeInfo, lazy=False)})
|
||||
|
||||
mapper(DynamicItemItem, dynamicApplicable_table, properties={
|
||||
"mutaplasmid": relation(DynamicItem),
|
||||
"mutaplasmid": relation(DynamicItem, viewonly=True),
|
||||
})
|
||||
|
||||
DynamicItemAttribute.ID = association_proxy("info", "attributeID")
|
||||
|
||||
@@ -69,7 +69,8 @@ props = {
|
||||
primaryjoin=dynamicApplicable_table.c.applicableTypeID == items_table.c.typeID,
|
||||
secondaryjoin=dynamicApplicable_table.c.typeID == DynamicItem.typeID,
|
||||
secondary=dynamicApplicable_table,
|
||||
backref="applicableItems"
|
||||
backref="applicableItems",
|
||||
viewonly=True
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -175,12 +175,13 @@ mapper(es_Fit, fits_table,
|
||||
collection_class=HandledModuleList,
|
||||
primaryjoin=and_(modules_table.c.fitID == fits_table.c.ID, modules_table.c.projected == False), # noqa
|
||||
order_by=modules_table.c.position,
|
||||
overlaps='owner',
|
||||
cascade='all, delete, delete-orphan'),
|
||||
"_Fit__projectedModules": relation(
|
||||
Module,
|
||||
collection_class=HandledProjectedModList,
|
||||
overlaps='owner, _Fit__modules',
|
||||
cascade='all, delete, delete-orphan',
|
||||
single_parent=True,
|
||||
primaryjoin=and_(modules_table.c.fitID == fits_table.c.ID, modules_table.c.projected == True)), # noqa
|
||||
"owner": relation(
|
||||
User,
|
||||
@@ -190,37 +191,37 @@ mapper(es_Fit, fits_table,
|
||||
"_Fit__boosters": relation(
|
||||
Booster,
|
||||
collection_class=HandledBoosterList,
|
||||
cascade='all, delete, delete-orphan',
|
||||
single_parent=True),
|
||||
overlaps='owner',
|
||||
cascade='all, delete, delete-orphan'),
|
||||
"_Fit__drones": relation(
|
||||
Drone,
|
||||
collection_class=HandledDroneCargoList,
|
||||
overlaps='owner',
|
||||
cascade='all, delete, delete-orphan',
|
||||
single_parent=True,
|
||||
primaryjoin=and_(drones_table.c.fitID == fits_table.c.ID, drones_table.c.projected == False)), # noqa
|
||||
"_Fit__fighters": relation(
|
||||
Fighter,
|
||||
collection_class=HandledDroneCargoList,
|
||||
overlaps='owner',
|
||||
cascade='all, delete, delete-orphan',
|
||||
single_parent=True,
|
||||
primaryjoin=and_(fighters_table.c.fitID == fits_table.c.ID, fighters_table.c.projected == False)), # noqa
|
||||
"_Fit__cargo": relation(
|
||||
Cargo,
|
||||
collection_class=HandledDroneCargoList,
|
||||
overlaps='owner',
|
||||
cascade='all, delete, delete-orphan',
|
||||
single_parent=True,
|
||||
primaryjoin=and_(cargo_table.c.fitID == fits_table.c.ID)),
|
||||
"_Fit__projectedDrones": relation(
|
||||
Drone,
|
||||
collection_class=HandledProjectedDroneList,
|
||||
overlaps='owner, _Fit__drones',
|
||||
cascade='all, delete, delete-orphan',
|
||||
single_parent=True,
|
||||
primaryjoin=and_(drones_table.c.fitID == fits_table.c.ID, drones_table.c.projected == True)), # noqa
|
||||
"_Fit__projectedFighters": relation(
|
||||
Fighter,
|
||||
collection_class=HandledProjectedDroneList,
|
||||
overlaps='owner, _Fit__fighters',
|
||||
cascade='all, delete, delete-orphan',
|
||||
single_parent=True,
|
||||
primaryjoin=and_(fighters_table.c.fitID == fits_table.c.ID, fighters_table.c.projected == True)), # noqa
|
||||
"_Fit__implants": relation(
|
||||
Implant,
|
||||
|
||||
901
eos/effects.py
@@ -159,6 +159,12 @@ class Fit:
|
||||
self.gangBoosts = None
|
||||
self.__ecmProjectedList = []
|
||||
self.commandBonuses = {}
|
||||
# Reps received, as a list of (amount, cycle time in seconds)
|
||||
self._hullRr = []
|
||||
self._armorRr = []
|
||||
self._armorRrPreSpool = []
|
||||
self._armorRrFullSpool = []
|
||||
self._shieldRr = []
|
||||
|
||||
def clearFactorReloadDependentData(self):
|
||||
# Here we clear all data known to rely on cycle parameters
|
||||
@@ -550,6 +556,12 @@ class Fit:
|
||||
if stuff is not None and stuff != self:
|
||||
stuff.clear()
|
||||
|
||||
self._hullRr.clear()
|
||||
self._armorRr.clear()
|
||||
self._armorRrPreSpool.clear()
|
||||
self._armorRrFullSpool.clear()
|
||||
self._shieldRr.clear()
|
||||
|
||||
# If this is the active fit that we are clearing, not a projected fit,
|
||||
# then this will run and clear the projected ships and flag the next
|
||||
# iteration to skip this part to prevent recursion.
|
||||
@@ -621,7 +633,7 @@ class Fit:
|
||||
"duration", value)
|
||||
|
||||
if warfareBuffID == 12: # Shield Burst: Shield Extension: Shield HP
|
||||
self.ship.boostItemAttr("shieldCapacity", value, stackingPenalties=True)
|
||||
self.ship.boostItemAttr("shieldCapacity", value)
|
||||
|
||||
if warfareBuffID == 13: # Armor Burst: Armor Energizing: Armor Resistance
|
||||
for damageType in ("Em", "Thermal", "Explosive", "Kinetic"):
|
||||
@@ -640,7 +652,7 @@ class Fit:
|
||||
"duration", value)
|
||||
|
||||
if warfareBuffID == 15: # Armor Burst: Armor Reinforcement: Armor HP
|
||||
self.ship.boostItemAttr("armorHP", value, stackingPenalties=True)
|
||||
self.ship.boostItemAttr("armorHP", value)
|
||||
|
||||
if warfareBuffID == 16: # Information Burst: Sensor Optimization: Scan Resolution
|
||||
self.ship.boostItemAttr("scanResolution", value, stackingPenalties=True)
|
||||
@@ -734,7 +746,7 @@ class Fit:
|
||||
self.ship.boostItemAttr(attr, value, stackingPenalties=True)
|
||||
|
||||
if warfareBuffID == 42: # Erebus Effect Generator : Armor HP bonus
|
||||
self.ship.boostItemAttr("armorHP", value, stackingPenalties=True)
|
||||
self.ship.boostItemAttr("armorHP", value)
|
||||
|
||||
if warfareBuffID == 43: # Erebus Effect Generator : Explosive resistance bonus
|
||||
for attr in ("armorExplosiveDamageResonance", "shieldExplosiveDamageResonance", "explosiveDamageResonance"):
|
||||
@@ -756,7 +768,7 @@ class Fit:
|
||||
self.ship.boostItemAttr(attr, value, stackingPenalties=True)
|
||||
|
||||
if warfareBuffID == 48: # Leviathan Effect Generator : Shield HP bonus
|
||||
self.ship.boostItemAttr("shieldCapacity", value, stackingPenalties=True)
|
||||
self.ship.boostItemAttr("shieldCapacity", value)
|
||||
|
||||
if warfareBuffID == 49: # Leviathan Effect Generator : EM resistance bonus
|
||||
for attr in ("armorEmDamageResonance", "shieldEmDamageResonance", "emDamageResonance"):
|
||||
@@ -870,6 +882,14 @@ class Fit:
|
||||
if warfareBuffID == 100: # Weather_caustic_toxin_scan_resolution_bonus
|
||||
self.ship.boostItemAttr("scanResolution", value, stackingPenalties=True)
|
||||
|
||||
if warfareBuffID == 2405: # Insurgency Suppression Bonus: Interdiction Range
|
||||
self.modules.filteredItemBoost(
|
||||
lambda mod: mod.item.requiresSkill("Navigation"),
|
||||
"maxRange", value, stackingPenalties=True)
|
||||
self.modules.filteredItemBoost(
|
||||
lambda mod: mod.item.group.name == "Stasis Web",
|
||||
"maxRange", value, stackingPenalties=True)
|
||||
|
||||
del self.commandBonuses[warfareBuffID]
|
||||
|
||||
def __resetDependentCalcs(self):
|
||||
@@ -1478,11 +1498,11 @@ class Fit:
|
||||
def tank(self):
|
||||
reps = {
|
||||
"passiveShield": self.calculateShieldRecharge(),
|
||||
"shieldRepair": self.extraAttributes["shieldRepair"],
|
||||
"armorRepair": self.extraAttributes["armorRepair"],
|
||||
"armorRepairPreSpool": self.extraAttributes["armorRepairPreSpool"],
|
||||
"armorRepairFullSpool": self.extraAttributes["armorRepairFullSpool"],
|
||||
"hullRepair": self.extraAttributes["hullRepair"]
|
||||
"shieldRepair": self.extraAttributes["shieldRepair"] + self._getAppliedShieldRr(),
|
||||
"armorRepair": self.extraAttributes["armorRepair"] + self._getAppliedArmorRr(),
|
||||
"armorRepairPreSpool": self.extraAttributes["armorRepairPreSpool"] + self._getAppliedArmorPreSpoolRr(),
|
||||
"armorRepairFullSpool": self.extraAttributes["armorRepairFullSpool"] + self._getAppliedArmorFullSpoolRr(),
|
||||
"hullRepair": self.extraAttributes["hullRepair"] + self._getAppliedHullRr()
|
||||
}
|
||||
return reps
|
||||
|
||||
@@ -1519,11 +1539,11 @@ class Fit:
|
||||
if self.__sustainableTank is None:
|
||||
sustainable = {
|
||||
"passiveShield": self.calculateShieldRecharge(),
|
||||
"shieldRepair": self.extraAttributes["shieldRepair"],
|
||||
"armorRepair": self.extraAttributes["armorRepair"],
|
||||
"armorRepairPreSpool": self.extraAttributes["armorRepairPreSpool"],
|
||||
"armorRepairFullSpool": self.extraAttributes["armorRepairFullSpool"],
|
||||
"hullRepair": self.extraAttributes["hullRepair"]
|
||||
"shieldRepair": self.extraAttributes["shieldRepair"] + self._getAppliedShieldRr(),
|
||||
"armorRepair": self.extraAttributes["armorRepair"] + self._getAppliedArmorRr(),
|
||||
"armorRepairPreSpool": self.extraAttributes["armorRepairPreSpool"] + self._getAppliedArmorPreSpoolRr(),
|
||||
"armorRepairFullSpool": self.extraAttributes["armorRepairFullSpool"] + self._getAppliedArmorFullSpoolRr(),
|
||||
"hullRepair": self.extraAttributes["hullRepair"] + self._getAppliedHullRr()
|
||||
}
|
||||
if not self.capStable or self.factorReload:
|
||||
# Map a local repairer type to the attribute it uses
|
||||
@@ -1760,6 +1780,38 @@ class Fit:
|
||||
mults.setdefault(stackingGroup, []).append((1 + strength / 100, None))
|
||||
return calculateMultiplier(mults)
|
||||
|
||||
def _getAppliedHullRr(self):
|
||||
return self.__getAppliedRr(self._hullRr)
|
||||
|
||||
def _getAppliedArmorRr(self):
|
||||
return self.__getAppliedRr(self._armorRr)
|
||||
|
||||
def _getAppliedArmorPreSpoolRr(self):
|
||||
return self.__getAppliedRr(self._armorRrPreSpool)
|
||||
|
||||
def _getAppliedArmorFullSpoolRr(self):
|
||||
return self.__getAppliedRr(self._armorRrFullSpool)
|
||||
|
||||
def _getAppliedShieldRr(self):
|
||||
return self.__getAppliedRr(self._shieldRr)
|
||||
|
||||
@staticmethod
|
||||
def __getAppliedRr(rrList):
|
||||
totalRaw = 0
|
||||
for amount, cycleTime in rrList:
|
||||
# That's right, for considerations of RR diminishing returns cycle time is rounded this way
|
||||
totalRaw += amount / int(cycleTime)
|
||||
RR_ADDITION = 7000
|
||||
RR_MULTIPLIER = 10
|
||||
appliedRr = 0
|
||||
for amount, cycleTime in rrList:
|
||||
rrps = amount / int(cycleTime)
|
||||
modified_rrps = RR_ADDITION + (rrps * RR_MULTIPLIER)
|
||||
rrps_mult = 1 - (((rrps + modified_rrps) / (totalRaw + modified_rrps)) - 1) ** 2
|
||||
appliedRr += rrps_mult * amount / cycleTime
|
||||
return appliedRr
|
||||
|
||||
|
||||
def __deepcopy__(self, memo=None):
|
||||
fitCopy = Fit()
|
||||
# Character and owner are not copied
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -114,7 +114,7 @@ class GraphFrame(AuxiliaryFrame):
|
||||
newW = max(curW, bestW)
|
||||
newH = max(curH, bestH)
|
||||
if newW > curW or newH > curH:
|
||||
newSize = wx.Size(newW, newH)
|
||||
newSize = wx.Size(round(newW), round(newH))
|
||||
self.SetSize(newSize)
|
||||
self.SetMinSize(newSize)
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ class VectorPicker(wx.Window):
|
||||
self._directionOnly = kwargs.pop('directionOnly', False)
|
||||
super().__init__(*args, **kwargs)
|
||||
self._fontsize = max(1, float(kwargs.pop('fontsize', 8 / self.GetContentScaleFactor())))
|
||||
self._font = wx.Font(self._fontsize, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False)
|
||||
self._font = wx.Font(round(self._fontsize), wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False)
|
||||
self._angle = 0
|
||||
self.__length = 1
|
||||
self._left = False
|
||||
@@ -76,7 +76,7 @@ class VectorPicker(wx.Window):
|
||||
self.__length = newLength
|
||||
|
||||
def DoGetBestSize(self):
|
||||
return wx.Size(self._size, self._size)
|
||||
return wx.Size(round(self._size), round(self._size))
|
||||
|
||||
def AcceptsFocusFromKeyboard(self):
|
||||
return False
|
||||
@@ -121,35 +121,37 @@ class VectorPicker(wx.Window):
|
||||
|
||||
radius = min(width, height) / 2 - 2
|
||||
dc.SetBrush(wx.WHITE_BRUSH)
|
||||
dc.DrawCircle(radius + 2, radius + 2, radius)
|
||||
dc.DrawCircle(round(radius + 2), round(radius + 2), round(radius))
|
||||
a = math.radians(self._angle + self._offset)
|
||||
x = math.cos(a) * radius
|
||||
y = math.sin(a) * radius
|
||||
# See PR #2260 on why this is needed
|
||||
pointRadius = 2 / self.GetContentScaleFactor() if 'wxGTK' in wx.PlatformInfo else 2
|
||||
dc.DrawLine(radius + 2, radius + 2, radius + 2 + x * self._length, radius + 2 - y * self._length)
|
||||
dc.DrawLine(
|
||||
round(radius + 2), round(radius + 2),
|
||||
round(radius + 2 + x * self._length), round(radius + 2 - y * self._length))
|
||||
dc.SetBrush(wx.BLACK_BRUSH)
|
||||
dc.DrawCircle(radius + 2 + x * self._length, radius + 2 - y * self._length, pointRadius)
|
||||
dc.DrawCircle(round(radius + 2 + x * self._length), round(radius + 2 - y * self._length), round(pointRadius))
|
||||
|
||||
if self._label:
|
||||
labelText = self._label
|
||||
labelTextW, labelTextH = dc.GetTextExtent(labelText)
|
||||
labelTextX = (radius * 2 + 4 - labelTextW) if (self._labelpos & 1) else 0
|
||||
labelTextY = (radius * 2 + 4 - labelTextH) if (self._labelpos & 2) else 0
|
||||
dc.DrawText(labelText, labelTextX, labelTextY)
|
||||
dc.DrawText(labelText, round(labelTextX), round(labelTextY))
|
||||
|
||||
if not self._directionOnly:
|
||||
lengthText = '%d%%' % (100 * self._length,)
|
||||
lengthTextW, lengthTextH = dc.GetTextExtent(lengthText)
|
||||
lengthTextX = radius + 2 + x / 2 - y / 3 - lengthTextW / 2
|
||||
lengthTextY = radius + 2 - y / 2 - x / 3 - lengthTextH / 2
|
||||
dc.DrawText(lengthText, lengthTextX, lengthTextY)
|
||||
dc.DrawText(lengthText, round(lengthTextX), round(lengthTextY))
|
||||
|
||||
angleText = '%d\u00B0' % (self._angle,)
|
||||
angleTextW, angleTextH = dc.GetTextExtent(angleText)
|
||||
angleTextX = radius + 2 - x / 2 - angleTextW / 2
|
||||
angleTextY = radius + 2 + y / 2 - angleTextH / 2
|
||||
dc.DrawText(angleText, angleTextX, angleTextY)
|
||||
dc.DrawText(angleText, round(angleTextX), round(angleTextY))
|
||||
|
||||
def OnEraseBackground(self, event):
|
||||
pass
|
||||
|
||||
@@ -212,7 +212,7 @@ class AttributeGauge(wx.Window):
|
||||
for x in range(1, 20):
|
||||
dc.SetBrush(wx.Brush(wx.LIGHT_GREY))
|
||||
dc.SetPen(wx.Pen(wx.LIGHT_GREY))
|
||||
dc.DrawRectangle(x * 10, 1, 1, rect.height)
|
||||
dc.DrawRectangle(round(x * 10), 1, 1, round(rect.height))
|
||||
|
||||
dc.SetBrush(wx.Brush(colour))
|
||||
dc.SetPen(wx.Pen(colour))
|
||||
@@ -222,19 +222,19 @@ class AttributeGauge(wx.Window):
|
||||
|
||||
if value >= 0:
|
||||
padding = (half if is_even else math.ceil(half - 1)) + 1
|
||||
dc.DrawRectangle(padding, 1, w, rect.height)
|
||||
dc.DrawRectangle(round(padding), 1, round(w), round(rect.height))
|
||||
else:
|
||||
padding = half - w + 1 if is_even else math.ceil(half) - (w - 1)
|
||||
dc.DrawRectangle(padding, 1, w, rect.height)
|
||||
dc.DrawRectangle(round(padding), 1, round(w), round(rect.height))
|
||||
|
||||
if self.leading_edge and (self.edge_on_neutral or value != 0):
|
||||
dc.SetPen(wx.Pen(wx.WHITE))
|
||||
dc.SetBrush(wx.Brush(wx.WHITE))
|
||||
|
||||
if value > 0:
|
||||
dc.DrawRectangle(min(padding + w, rect.width), 1, 1, rect.height)
|
||||
dc.DrawRectangle(round(min(padding + w, rect.width)), 1, 1, round(rect.height))
|
||||
else:
|
||||
dc.DrawRectangle(max(padding - 1, 1), 1, 1, rect.height)
|
||||
dc.DrawRectangle(round(max(padding - 1, 1)), 1, 1, round(rect.height))
|
||||
|
||||
def OnTimer(self, event):
|
||||
old_value = self._old_percentage
|
||||
|
||||
@@ -103,10 +103,9 @@ class BitmapLoader:
|
||||
pyfalog.warning("Missing icon file: {0}/{1}".format(location, filename))
|
||||
return None
|
||||
|
||||
bmp: wx.Bitmap = img.ConvertToBitmap()
|
||||
if scale > 1:
|
||||
bmp.SetSize((bmp.GetWidth() // scale, bmp.GetHeight() // scale))
|
||||
return bmp
|
||||
return img.Scale(img.GetWidth() // scale, img.GetHeight() // scale).ConvertToBitmap()
|
||||
return img.ConvertToBitmap()
|
||||
|
||||
@classmethod
|
||||
def loadScaledBitmap(cls, name, location, scale=0):
|
||||
|
||||
@@ -124,6 +124,8 @@ class AddEnvironmentEffect(ContextMenuUnconditional):
|
||||
data.groups[_t('Sansha Incursion')] = self.getEffectBeacons(
|
||||
_t('ContextMenu|ProjectedEffectManipulation|Sansha Incursion'))
|
||||
data.groups[_t('Triglavian Invasion')] = self.getInvasionBeacons()
|
||||
# data.groups[_t('Pirate Insurgency')] = self.getEffectBeacons(
|
||||
# _t('ContextMenu|ProjectedEffectManipulation|Insurgency'))
|
||||
return data
|
||||
|
||||
def getEffectBeacons(self, *groups, extra_garbage=()):
|
||||
@@ -238,5 +240,12 @@ class AddEnvironmentEffect(ContextMenuUnconditional):
|
||||
data.items.append(Entry(item.ID, item.name, item.name))
|
||||
return data
|
||||
|
||||
def getInsurgencyBeacons(self):
|
||||
data = self.getDestructibleBeacons()
|
||||
# Suppression Interdiction Range Beacon
|
||||
item = Market.getInstance().getItem(79839)
|
||||
data.items.append(Entry(item.ID, item.name, item.name))
|
||||
return data
|
||||
|
||||
|
||||
AddEnvironmentEffect.register()
|
||||
|
||||
@@ -253,8 +253,8 @@ class PFSearchBox(wx.Window):
|
||||
else:
|
||||
spad = 0
|
||||
|
||||
dc.DrawBitmap(self.searchBitmapShadow, self.searchButtonX + 1, self.searchButtonY + 1)
|
||||
dc.DrawBitmap(self.searchBitmap, self.searchButtonX + spad, self.searchButtonY + spad)
|
||||
dc.DrawBitmap(self.searchBitmapShadow, round(self.searchButtonX + 1), round(self.searchButtonY + 1))
|
||||
dc.DrawBitmap(self.searchBitmap, round(self.searchButtonX + spad), round(self.searchButtonY + spad))
|
||||
|
||||
if self.isCancelButtonVisible:
|
||||
if self.cancelBitmap:
|
||||
@@ -262,8 +262,8 @@ class PFSearchBox(wx.Window):
|
||||
cpad = 1
|
||||
else:
|
||||
cpad = 0
|
||||
dc.DrawBitmap(self.cancelBitmapShadow, self.cancelButtonX + 1, self.cancelButtonY + 1)
|
||||
dc.DrawBitmap(self.cancelBitmap, self.cancelButtonX + cpad, self.cancelButtonY + cpad)
|
||||
dc.DrawBitmap(self.cancelBitmapShadow, round(self.cancelButtonX + 1), round(self.cancelButtonY + 1))
|
||||
dc.DrawBitmap(self.cancelBitmap, round(self.cancelButtonX + cpad), round(self.cancelButtonY + cpad))
|
||||
|
||||
dc.SetPen(wx.Pen(sepColor, 1))
|
||||
dc.DrawLine(0, rect.height - 1, rect.width, rect.height - 1)
|
||||
|
||||
@@ -64,7 +64,7 @@ class PFGeneralPref(PreferenceView):
|
||||
langBox.Add(hl.HyperLinkCtrl(panel, -1,
|
||||
_t("Interested in helping with translations?"),
|
||||
URL="https://github.com/pyfa-org/Pyfa/blob/master/locale/README.md"
|
||||
), 0, wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 15)
|
||||
), 0, wx.LEFT, 15)
|
||||
else:
|
||||
self.stLangLabel = wx.StaticText(panel, wx.ID_ANY, _t("Pyfa language selection disabled. Please check if .mo files have been generated.\nRefer to locale/README.md for info."), wx.DefaultPosition, wx.DefaultSize, 0)
|
||||
self.stLangLabel.Wrap(-1)
|
||||
@@ -93,7 +93,7 @@ class PFGeneralPref(PreferenceView):
|
||||
langBox.Add(wx.StaticText(panel, wx.ID_ANY,
|
||||
_t("Auto will use the same language pyfa uses if available, otherwise English"),
|
||||
wx.DefaultPosition,
|
||||
wx.DefaultSize, 0), 0, wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 15)
|
||||
wx.DefaultSize, 0), 0, wx.LEFT, 15)
|
||||
|
||||
self.cbGlobalChar = wx.CheckBox(panel, wx.ID_ANY, _t("Use global character"), wx.DefaultPosition, wx.DefaultSize,
|
||||
0)
|
||||
|
||||
@@ -104,14 +104,14 @@ class CategoryItem(SFBrowserItem):
|
||||
textColor = colorUtils.GetSuitable(windowColor, 1)
|
||||
|
||||
mdc.SetTextForeground(textColor)
|
||||
mdc.DrawBitmap(self.dropShadowBitmap, self.shipBmpx + 1, self.shipBmpy + 1)
|
||||
mdc.DrawBitmap(self.shipBmp, self.shipBmpx, self.shipBmpy, 0)
|
||||
mdc.DrawBitmap(self.dropShadowBitmap, round(self.shipBmpx + 1), round(self.shipBmpy + 1))
|
||||
mdc.DrawBitmap(self.shipBmp, round(self.shipBmpx), round(self.shipBmpy), 0)
|
||||
|
||||
mdc.SetFont(self.fontBig)
|
||||
|
||||
categoryName, fittings = self.fittingInfo
|
||||
|
||||
mdc.DrawText(categoryName, self.catx, self.caty)
|
||||
mdc.DrawText(categoryName, round(self.catx), round(self.caty))
|
||||
|
||||
|
||||
# =============================================================================
|
||||
|
||||
@@ -416,9 +416,18 @@ class FitItem(SFItem.SFBrowserItem):
|
||||
if self.dragging:
|
||||
if not self.dragged:
|
||||
if self.dragMotionTrigger < 0:
|
||||
if not self.dragTLFBmp:
|
||||
tdc = wx.MemoryDC()
|
||||
bmpWidth = self.toolbarx if self.toolbarx < 200 else 200
|
||||
self.dragTLFBmp = wx.Bitmap(bmpWidth, self.GetRect().height)
|
||||
tdc.SelectObject(self.dragTLFBmp)
|
||||
tdc.SetBrush(wx.Brush(wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW)))
|
||||
tdc.DrawRectangle(0, 0, bmpWidth, self.GetRect().height)
|
||||
self.DrawItem(tdc)
|
||||
tdc.SelectObject(wx.NullBitmap)
|
||||
if not self.HasCapture():
|
||||
self.CaptureMouse()
|
||||
self.dragWindow = PFBitmapFrame(self, pos, self.dragTLFBmp)
|
||||
self.dragWindow = PFBitmapFrame(self, pos, self.dragTLFBmp)
|
||||
self.dragWindow.Show()
|
||||
self.dragged = True
|
||||
self.dragMotionTrigger = self.dragMotionTrail
|
||||
@@ -493,9 +502,9 @@ class FitItem(SFItem.SFBrowserItem):
|
||||
else:
|
||||
shipEffBk = self.shipEffBk
|
||||
|
||||
mdc.DrawBitmap(shipEffBk, self.shipEffx, self.shipEffy, 0)
|
||||
mdc.DrawBitmap(shipEffBk, round(self.shipEffx), round(self.shipEffy), 0)
|
||||
|
||||
mdc.DrawBitmap(self.shipBmp, self.shipBmpx, self.shipBmpy, 0)
|
||||
mdc.DrawBitmap(self.shipBmp, round(self.shipBmpx), round(self.shipBmpy), 0)
|
||||
|
||||
mdc.SetFont(self.fontNormal)
|
||||
|
||||
@@ -504,26 +513,21 @@ class FitItem(SFItem.SFBrowserItem):
|
||||
pfdate = drawUtils.GetPartialText(mdc, fitLocalDate,
|
||||
self.toolbarx - self.textStartx - self.padding * 2 - self.thoverw)
|
||||
|
||||
mdc.DrawText(pfdate, self.textStartx, self.timestampy)
|
||||
mdc.DrawText(pfdate, round(self.textStartx), round(self.timestampy))
|
||||
|
||||
mdc.SetFont(self.fontSmall)
|
||||
mdc.DrawText(self.toolbar.hoverLabel, self.thoverx, self.thovery)
|
||||
mdc.DrawText(self.toolbar.hoverLabel, round(self.thoverx), round(self.thovery))
|
||||
|
||||
mdc.SetFont(self.fontBig)
|
||||
|
||||
psname = drawUtils.GetPartialText(mdc, self.fitName,
|
||||
self.toolbarx - self.textStartx - self.padding * 2 - self.thoverw)
|
||||
|
||||
mdc.DrawText(psname, self.textStartx, self.fitNamey)
|
||||
mdc.DrawText(psname, round(self.textStartx), round(self.fitNamey))
|
||||
|
||||
if self.tcFitName.IsShown():
|
||||
self.AdjustControlSizePos(self.tcFitName, self.textStartx, self.toolbarx - self.editWidth - self.padding)
|
||||
|
||||
tdc = wx.MemoryDC()
|
||||
self.dragTLFBmp = wx.Bitmap((self.toolbarx if self.toolbarx < 200 else 200), rect.height, 24)
|
||||
tdc.SelectObject(self.dragTLFBmp)
|
||||
tdc.Blit(0, 0, (self.toolbarx if self.toolbarx < 200 else 200), rect.height, mdc, 0, 0, wx.COPY)
|
||||
tdc.SelectObject(wx.NullBitmap)
|
||||
|
||||
def AdjustControlSizePos(self, editCtl, start, end):
|
||||
fnEditSize = editCtl.GetSize()
|
||||
|
||||
@@ -231,7 +231,7 @@ class NavigationPanel(SFItem.SFBrowserItem):
|
||||
|
||||
self.toolbar.SetPosition((self.toolbarx, self.toolbary))
|
||||
mdc.SetFont(self.fontSmall)
|
||||
mdc.DrawText(self.toolbar.hoverLabel, self.thoverx, self.thovery)
|
||||
mdc.DrawText(self.toolbar.hoverLabel, round(self.thoverx), round(self.thovery))
|
||||
mdc.SetPen(wx.Pen(sepColor, 1))
|
||||
mdc.DrawLine(0, rect.height - 1, rect.width, rect.height - 1)
|
||||
|
||||
|
||||
@@ -63,4 +63,4 @@ class PFBitmapFrame(wx.Frame):
|
||||
mdc.DrawBitmap(self.bitmap, 0, 0)
|
||||
mdc.SetPen(wx.Pen("#000000", width=1))
|
||||
mdc.SetBrush(wx.TRANSPARENT_BRUSH)
|
||||
mdc.DrawRectangle(0, 0, rect.width, rect.height)
|
||||
mdc.DrawRectangle(0, 0, round(rect.width), round(rect.height))
|
||||
|
||||
@@ -57,7 +57,7 @@ class PFListPane(wx.ScrolledWindow):
|
||||
|
||||
posy = self.GetScrollPos(wx.VERTICAL)
|
||||
posy -= self.itemsHeight
|
||||
self.Scroll(0, posy)
|
||||
self.Scroll(0, round(posy))
|
||||
|
||||
event.Skip()
|
||||
|
||||
@@ -65,7 +65,7 @@ class PFListPane(wx.ScrolledWindow):
|
||||
|
||||
posy = self.GetScrollPos(wx.VERTICAL)
|
||||
posy += self.itemsHeight
|
||||
self.Scroll(0, posy)
|
||||
self.Scroll(0, round(posy))
|
||||
|
||||
event.Skip()
|
||||
|
||||
@@ -109,7 +109,7 @@ class PFListPane(wx.ScrolledWindow):
|
||||
|
||||
# if we need to adjust
|
||||
if new_vs_x != -1 or new_vs_y != -1:
|
||||
self.Scroll(new_vs_x, new_vs_y)
|
||||
self.Scroll(round(new_vs_x), round(new_vs_y))
|
||||
|
||||
def AddWidget(self, widget):
|
||||
widget.Reparent(self)
|
||||
|
||||
@@ -194,25 +194,25 @@ class RaceSelector(wx.Window):
|
||||
bmp = wx.Bitmap(img)
|
||||
|
||||
if self.layout == wx.VERTICAL:
|
||||
mdc.DrawBitmap(dropShadow, rect.width - self.buttonsPadding - bmp.GetWidth() + 1, y + 1)
|
||||
mdc.DrawBitmap(bmp, rect.width - self.buttonsPadding - bmp.GetWidth(), y)
|
||||
mdc.DrawBitmap(dropShadow, round(rect.width - self.buttonsPadding - bmp.GetWidth() + 1), round(y + 1))
|
||||
mdc.DrawBitmap(bmp, round(rect.width - self.buttonsPadding - bmp.GetWidth()), round(y))
|
||||
y += raceBmp.GetHeight() + self.buttonsPadding
|
||||
mdc.SetPen(wx.Pen(sepColor, 1))
|
||||
mdc.DrawLine(rect.width - 1, 0, rect.width - 1, rect.height)
|
||||
else:
|
||||
mdc.DrawBitmap(dropShadow, x + 1, self.buttonsPadding + 1)
|
||||
mdc.DrawBitmap(bmp, x, self.buttonsPadding)
|
||||
mdc.DrawBitmap(dropShadow, round(x + 1), round(self.buttonsPadding + 1))
|
||||
mdc.DrawBitmap(bmp, round(x), round(self.buttonsPadding))
|
||||
x += raceBmp.GetWidth() + self.buttonsPadding
|
||||
mdc.SetPen(wx.Pen(sepColor, 1))
|
||||
mdc.DrawLine(0, 0, rect.width, 0)
|
||||
|
||||
if self.direction < 1:
|
||||
if self.layout == wx.VERTICAL:
|
||||
mdc.DrawBitmap(self.bmpArrow, -2, (rect.height - self.bmpArrow.GetHeight()) / 2)
|
||||
mdc.DrawBitmap(self.bmpArrow, -2, round((rect.height - self.bmpArrow.GetHeight()) / 2))
|
||||
else:
|
||||
mdc.SetPen(wx.Pen(sepColor, 1))
|
||||
mdc.DrawLine(0, 0, rect.width, 0)
|
||||
mdc.DrawBitmap(self.bmpArrow, (rect.width - self.bmpArrow.GetWidth()) / 2, -2)
|
||||
mdc.DrawBitmap(self.bmpArrow, round((rect.width - self.bmpArrow.GetWidth()) / 2), -2)
|
||||
|
||||
def OnTimer(self, event):
|
||||
if event.GetId() == self.animTimerID:
|
||||
|
||||
@@ -233,8 +233,8 @@ class PFToolbar:
|
||||
|
||||
bmpWidth = bmp.GetWidth()
|
||||
|
||||
pdc.DrawBitmap(dropShadowBmp, bx + self.padding / 2, self.toolbarY + self.padding / 2)
|
||||
pdc.DrawBitmap(bmp, tbx, by)
|
||||
pdc.DrawBitmap(dropShadowBmp, round(bx + self.padding / 2), round(self.toolbarY + self.padding / 2))
|
||||
pdc.DrawBitmap(bmp, round(tbx), round(by))
|
||||
|
||||
bx += bmpWidth + self.padding
|
||||
|
||||
|
||||
@@ -247,12 +247,12 @@ class ShipItem(SFItem.SFBrowserItem):
|
||||
else:
|
||||
shipEffBk = self.shipEffBk
|
||||
|
||||
mdc.DrawBitmap(shipEffBk, self.shipEffx, self.shipEffy, 0)
|
||||
mdc.DrawBitmap(shipEffBk, round(self.shipEffx), round(self.shipEffy), 0)
|
||||
|
||||
mdc.DrawBitmap(self.shipBmp, self.shipBmpx, self.shipBmpy, 0)
|
||||
mdc.DrawBitmap(self.shipBmp, round(self.shipBmpx), round(self.shipBmpy), 0)
|
||||
|
||||
mdc.DrawBitmap(self.raceDropShadowBmp, self.raceBmpx + 1, self.raceBmpy + 1)
|
||||
mdc.DrawBitmap(self.raceBmp, self.raceBmpx, self.raceBmpy)
|
||||
mdc.DrawBitmap(self.raceDropShadowBmp, round(self.raceBmpx + 1), round(self.raceBmpy + 1))
|
||||
mdc.DrawBitmap(self.raceBmp, round(self.raceBmpx), round(self.raceBmpy))
|
||||
|
||||
shipName, shipTrait, fittings = self.shipFittingInfo
|
||||
|
||||
@@ -264,17 +264,17 @@ class ShipItem(SFItem.SFBrowserItem):
|
||||
fformat = "%d fits"
|
||||
|
||||
mdc.SetFont(self.fontNormal)
|
||||
mdc.DrawText(fformat % fittings if fittings > 0 else fformat, self.textStartx, self.fittingsy)
|
||||
mdc.DrawText(fformat % fittings if fittings > 0 else fformat, round(self.textStartx), round(self.fittingsy))
|
||||
|
||||
mdc.SetFont(self.fontSmall)
|
||||
mdc.DrawText(self.toolbar.hoverLabel, self.thoverx, self.thovery)
|
||||
mdc.DrawText(self.toolbar.hoverLabel, round(self.thoverx), round(self.thovery))
|
||||
|
||||
mdc.SetFont(self.fontBig)
|
||||
|
||||
psname = drawUtils.GetPartialText(mdc, shipName,
|
||||
self.toolbarx - self.textStartx - self.padding * 2 - self.thoverw)
|
||||
|
||||
mdc.DrawText(psname, self.textStartx, self.shipNamey)
|
||||
mdc.DrawText(psname, round(self.textStartx), round(self.shipNamey))
|
||||
|
||||
if self.tcFitName.IsShown():
|
||||
self.AdjustControlSizePos(self.tcFitName, self.textStartx, self.toolbarx - self.editWidth - self.padding)
|
||||
|
||||
@@ -146,8 +146,8 @@ class ResistancesViewFull(StatsView):
|
||||
|
||||
lbl = PyGauge(contentPanel, font, 100)
|
||||
lbl.SetMinSize((48, 16))
|
||||
lbl.SetBackgroundColour(wx.Colour(bc[0], bc[1], bc[2]))
|
||||
lbl.SetBarColour(wx.Colour(fc[0], fc[1], fc[2]))
|
||||
lbl.SetBackgroundColour(wx.Colour(round(bc[0]), round(bc[1]), round(bc[2])))
|
||||
lbl.SetBarColour(wx.Colour(round(fc[0]), round(fc[1]), round(fc[2])))
|
||||
lbl.SetBarGradient()
|
||||
lbl.SetFractionDigits(1)
|
||||
|
||||
|
||||
@@ -956,7 +956,7 @@ class FittingView(d.Display):
|
||||
cx = padding
|
||||
|
||||
if slotMap[st.slot]:
|
||||
mdc.DrawRectangle(cx, cy, maxWidth - cx, maxRowHeight)
|
||||
mdc.DrawRectangle(round(cx), round(cy), round(maxWidth - cx), round(maxRowHeight))
|
||||
|
||||
for i, col in enumerate(self.activeColumns):
|
||||
if i > maxColumns:
|
||||
|
||||
@@ -516,7 +516,10 @@ class SkillTreeView(wx.Panel):
|
||||
def populateSkillTreeSkillSearch(self, event=None):
|
||||
sChar = Character.getInstance()
|
||||
char = self.charEditor.entityEditor.getActiveEntity()
|
||||
search = self.searchInput.GetLineText(0)
|
||||
try:
|
||||
search = self.searchInput.GetLineText(0)
|
||||
except AttributeError:
|
||||
search = self.searchInput.GetValue()
|
||||
|
||||
root = self.root
|
||||
tree = self.skillTreeListCtrl
|
||||
@@ -530,7 +533,7 @@ class SkillTreeView(wx.Panel):
|
||||
iconId = self.skillBookDirtyImageId
|
||||
|
||||
childId = tree.AppendItem(root, name, iconId, data=('skill', id))
|
||||
tree.SetItemText(childId, 1, _t("Level {}d").format(int(level)) if isinstance(level, float) else level)
|
||||
tree.SetItemText(childId, 1, _t("Level {}").format(int(level)) if isinstance(level, float) else level)
|
||||
|
||||
def populateSkillTree(self, event=None):
|
||||
sChar = Character.getInstance()
|
||||
@@ -588,7 +591,6 @@ class SkillTreeView(wx.Panel):
|
||||
iconId = self.skillBookDirtyImageId
|
||||
|
||||
childId = tree.AppendItem(root, name, iconId, data=('skill', id))
|
||||
|
||||
tree.SetItemText(childId, 1, _t("Level {}").format(int(level)) if isinstance(level, float) else level)
|
||||
|
||||
def spawnMenu(self, event):
|
||||
|
||||
@@ -530,11 +530,11 @@ class _TabRenderer:
|
||||
mbmp = wx.Bitmap(mimg)
|
||||
|
||||
# draw middle bitmap, offset by left
|
||||
mdc.DrawBitmap(mbmp, self.left_width, 0)
|
||||
mdc.DrawBitmap(mbmp, round(self.left_width), 0)
|
||||
|
||||
# draw right bitmap offset by left + middle
|
||||
mdc.DrawBitmap(self.ctab_right_bmp,
|
||||
self.content_width + self.left_width, 0)
|
||||
round(self.content_width + self.left_width), 0)
|
||||
|
||||
mdc.SelectObject(wx.NullBitmap)
|
||||
|
||||
@@ -555,7 +555,7 @@ class _TabRenderer:
|
||||
+ self.left_width \
|
||||
- self.ctab_close_bmp.GetWidth() / 2
|
||||
y_offset = (self.tab_height - self.ctab_close_bmp.GetHeight()) / 2
|
||||
self.close_region.Offset(x_offset, y_offset)
|
||||
self.close_region.Offset(round(x_offset), round(y_offset))
|
||||
|
||||
def InitColors(self):
|
||||
"""Determines colors used for tab, based on system settings"""
|
||||
@@ -590,8 +590,8 @@ class _TabRenderer:
|
||||
# Draw tab icon
|
||||
mdc.DrawBitmap(
|
||||
bmp,
|
||||
self.left_width + self.padding - bmp.GetWidth() / 2,
|
||||
(height - bmp.GetHeight()) / 2)
|
||||
round(self.left_width + self.padding - bmp.GetWidth() / 2),
|
||||
round((height - bmp.GetHeight()) / 2))
|
||||
|
||||
# draw close button
|
||||
if self.closeable:
|
||||
@@ -604,8 +604,8 @@ class _TabRenderer:
|
||||
|
||||
mdc.DrawBitmap(
|
||||
cbmp,
|
||||
self.content_width + self.left_width - cbmp.GetWidth() / 2,
|
||||
(height - cbmp.GetHeight()) / 2)
|
||||
round(self.content_width + self.left_width - cbmp.GetWidth() / 2),
|
||||
round((height - cbmp.GetHeight()) / 2))
|
||||
|
||||
mdc.SelectObject(wx.NullBitmap)
|
||||
|
||||
@@ -640,7 +640,7 @@ class _TabRenderer:
|
||||
# draw text (with no ellipses)
|
||||
text = draw.GetPartialText(dc, self.text, maxsize, "")
|
||||
tx, ty = dc.GetTextExtent(text)
|
||||
dc.DrawText(text, text_start + self.padding, height / 2 - ty / 2)
|
||||
dc.DrawText(text, round(text_start + self.padding), round(height / 2 - ty / 2))
|
||||
|
||||
def __repr__(self):
|
||||
return "_TabRenderer(text={}, disabled={}) at {}".format(
|
||||
@@ -1005,7 +1005,7 @@ class _TabsContainer(wx.Panel):
|
||||
|
||||
region = tab.GetCloseButtonRegion()
|
||||
posx, posy = tab.GetPosition()
|
||||
region.Offset(posx, posy)
|
||||
region.Offset(round(posx), round(posy))
|
||||
|
||||
if region.Contains(x, y):
|
||||
index = self.tabs.index(tab)
|
||||
@@ -1036,7 +1036,7 @@ class _TabsContainer(wx.Panel):
|
||||
|
||||
region = self.add_button.GetRegion()
|
||||
ax, ay = self.add_button.GetPosition()
|
||||
region.Offset(ax, ay)
|
||||
region.Offset(round(ax), round(ay))
|
||||
|
||||
if region.Contains(x, y):
|
||||
ev = PageAdding()
|
||||
@@ -1058,7 +1058,7 @@ class _TabsContainer(wx.Panel):
|
||||
for tab in self.tabs:
|
||||
region = tab.GetCloseButtonRegion()
|
||||
posx, posy = tab.GetPosition()
|
||||
region.Offset(posx, posy)
|
||||
region.Offset(round(posx), round(posy))
|
||||
|
||||
if region.Contains(x, y):
|
||||
if not tab.GetCloseButtonHoverStatus():
|
||||
@@ -1093,7 +1093,7 @@ class _TabsContainer(wx.Panel):
|
||||
tabRegion = tab.GetTabRegion()
|
||||
tabPos = tab.GetPosition()
|
||||
tabPosX, tabPosY = tabPos
|
||||
tabRegion.Offset(tabPosX, tabPosY)
|
||||
tabRegion.Offset(round(tabPosX), round(tabPosY))
|
||||
|
||||
if tabRegion.Contains(x, y):
|
||||
return True
|
||||
@@ -1166,7 +1166,7 @@ class _TabsContainer(wx.Panel):
|
||||
|
||||
region = self.add_button.GetRegion()
|
||||
ax, ay = self.add_button.GetPosition()
|
||||
region.Offset(ax, ay)
|
||||
region.Offset(round(ax), round(ay))
|
||||
|
||||
if region.Contains(x, y):
|
||||
if not self.add_button.IsHighlighted():
|
||||
@@ -1198,7 +1198,7 @@ class _TabsContainer(wx.Panel):
|
||||
|
||||
if self.show_add_button:
|
||||
ax, ay = self.add_button.GetPosition()
|
||||
mdc.DrawBitmap(self.add_button.Render(), ax, ay, True)
|
||||
mdc.DrawBitmap(self.add_button.Render(), round(ax), round(ay), True)
|
||||
|
||||
for i in range(len(self.tabs) - 1, -1, -1):
|
||||
tab = self.tabs[i]
|
||||
@@ -1206,12 +1206,12 @@ class _TabsContainer(wx.Panel):
|
||||
|
||||
if not tab.IsSelected():
|
||||
# drop shadow first
|
||||
mdc.DrawBitmap(self.fxBmps[tab], posx, posy, True)
|
||||
mdc.DrawBitmap(self.fxBmps[tab], round(posx), (posy), True)
|
||||
bmp = tab.Render()
|
||||
img = bmp.ConvertToImage()
|
||||
img = img.AdjustChannels(1, 1, 1, 0.85)
|
||||
bmp = wx.Bitmap(img)
|
||||
mdc.DrawBitmap(bmp, posx, posy, True)
|
||||
mdc.DrawBitmap(bmp, round(posx), (posy), True)
|
||||
|
||||
mdc.SetDeviceOrigin(posx, posy)
|
||||
tab.DrawText(mdc)
|
||||
@@ -1224,7 +1224,7 @@ class _TabsContainer(wx.Panel):
|
||||
if selected:
|
||||
posx, posy = selected.GetPosition()
|
||||
# drop shadow first
|
||||
mdc.DrawBitmap(self.fxBmps[selected], posx, posy, True)
|
||||
mdc.DrawBitmap(self.fxBmps[selected], round(posx), round(posy), True)
|
||||
|
||||
bmp = selected.Render()
|
||||
|
||||
@@ -1233,7 +1233,7 @@ class _TabsContainer(wx.Panel):
|
||||
img = img.AdjustChannels(1.2, 1.2, 1.2, 0.7)
|
||||
bmp = wx.Bitmap(img)
|
||||
|
||||
mdc.DrawBitmap(bmp, posx, posy, True)
|
||||
mdc.DrawBitmap(bmp, round(posx), round(posy), True)
|
||||
|
||||
mdc.SetDeviceOrigin(posx, posy)
|
||||
selected.DrawText(mdc)
|
||||
@@ -1514,7 +1514,7 @@ class PFNotebookPagePreview(wx.Frame):
|
||||
x, y = mdc.GetTextExtent(self.title)
|
||||
|
||||
mdc.SetBrush(wx.Brush(wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOWTEXT)))
|
||||
mdc.DrawRectangle(0, 0, rect.width, 16)
|
||||
mdc.DrawRectangle(0, 0, round(rect.width), 16)
|
||||
|
||||
mdc.SetTextForeground(wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW))
|
||||
|
||||
@@ -1523,4 +1523,4 @@ class PFNotebookPagePreview(wx.Frame):
|
||||
mdc.SetPen(wx.Pen("#000000", width=1))
|
||||
mdc.SetBrush(wx.TRANSPARENT_BRUSH)
|
||||
|
||||
mdc.DrawRectangle(0, 16, rect.width, rect.height - 16)
|
||||
mdc.DrawRectangle(0, 16, round(rect.width), round(rect.height - 16))
|
||||
|
||||
@@ -193,7 +193,7 @@ class CopySelectDialog(wx.Dialog):
|
||||
|
||||
def exportEsi(self, options, callback):
|
||||
fit = getFit(self.mainFrame.getActiveFit())
|
||||
Port.exportESI(fit, True, callback)
|
||||
Port.exportESI(fit, False, False, False, callback)
|
||||
|
||||
def exportXml(self, options, callback):
|
||||
fit = getFit(self.mainFrame.getActiveFit())
|
||||
|
||||
@@ -283,7 +283,7 @@ class ExportToEve(AuxiliaryFrame):
|
||||
def __init__(self, parent):
|
||||
super().__init__(
|
||||
parent, id=wx.ID_ANY, title=_t("Export fit to EVE"), pos=wx.DefaultPosition,
|
||||
size=wx.Size(400, 140) if "wxGTK" in wx.PlatformInfo else wx.Size(350, 115), resizeable=True)
|
||||
size=wx.Size(400, 175) if "wxGTK" in wx.PlatformInfo else wx.Size(350, 145), resizeable=True)
|
||||
|
||||
self.mainFrame = parent
|
||||
|
||||
@@ -305,6 +305,16 @@ class ExportToEve(AuxiliaryFrame):
|
||||
self.exportChargesCb.Bind(wx.EVT_CHECKBOX, self.OnChargeExportChange)
|
||||
mainSizer.Add(self.exportChargesCb, 0, 0, 5)
|
||||
|
||||
self.exportImplantsCb = wx.CheckBox(self, wx.ID_ANY, _t('Export Implants'), wx.DefaultPosition, wx.DefaultSize, 0)
|
||||
self.exportImplantsCb.SetValue(EsiSettings.getInstance().get('exportImplants'))
|
||||
self.exportImplantsCb.Bind(wx.EVT_CHECKBOX, self.OnImplantsExportChange)
|
||||
mainSizer.Add(self.exportImplantsCb, 0, 0, 5)
|
||||
|
||||
self.exportBoostersCb = wx.CheckBox(self, wx.ID_ANY, _t('Export Boosters'), wx.DefaultPosition, wx.DefaultSize, 0)
|
||||
self.exportBoostersCb.SetValue(EsiSettings.getInstance().get('exportBoosters'))
|
||||
self.exportBoostersCb.Bind(wx.EVT_CHECKBOX, self.OnBoostersExportChange)
|
||||
mainSizer.Add(self.exportBoostersCb, 0, 0, 5)
|
||||
|
||||
self.exportBtn.Bind(wx.EVT_BUTTON, self.exportFitting)
|
||||
|
||||
self.statusbar = wx.StatusBar(self)
|
||||
@@ -324,6 +334,14 @@ class ExportToEve(AuxiliaryFrame):
|
||||
EsiSettings.getInstance().set('exportCharges', self.exportChargesCb.GetValue())
|
||||
event.Skip()
|
||||
|
||||
def OnImplantsExportChange(self, event):
|
||||
EsiSettings.getInstance().set('exportImplants', self.exportImplantsCb.GetValue())
|
||||
event.Skip()
|
||||
|
||||
def OnBoostersExportChange(self, event):
|
||||
EsiSettings.getInstance().set('exportBoosters', self.exportBoostersCb.GetValue())
|
||||
event.Skip()
|
||||
|
||||
def updateCharList(self):
|
||||
sEsi = Esi.getInstance()
|
||||
chars = sEsi.getSsoCharacters()
|
||||
@@ -360,8 +378,10 @@ class ExportToEve(AuxiliaryFrame):
|
||||
|
||||
sFit = Fit.getInstance()
|
||||
exportCharges = self.exportChargesCb.GetValue()
|
||||
exportImplants = self.exportImplantsCb.GetValue()
|
||||
exportBoosters = self.exportBoostersCb.GetValue()
|
||||
try:
|
||||
data = sPort.exportESI(sFit.getFit(fitID), exportCharges)
|
||||
data = sPort.exportESI(sFit.getFit(fitID), exportCharges, exportImplants, exportBoosters)
|
||||
except ESIExportException as e:
|
||||
msg = str(e)
|
||||
if not msg:
|
||||
|
||||
@@ -42,7 +42,7 @@ class DmgPatternNameValidator(BaseValidator):
|
||||
return DmgPatternNameValidator()
|
||||
|
||||
def Validate(self, win):
|
||||
entityEditor = win.parent
|
||||
entityEditor = win.Parent.parent
|
||||
textCtrl = self.GetWindow()
|
||||
text = textCtrl.GetValue().strip()
|
||||
|
||||
|
||||
@@ -257,7 +257,7 @@ class PyGauge(wx.Window):
|
||||
else:
|
||||
w = rect.width * (float(value) / 100)
|
||||
r = copy.copy(rect)
|
||||
r.width = w
|
||||
r.width = round(w)
|
||||
dc.DrawRectangle(r)
|
||||
else:
|
||||
# if bar color is not set, then we use pre-defined transitions
|
||||
@@ -269,7 +269,7 @@ class PyGauge(wx.Window):
|
||||
else:
|
||||
w = rect.width * (float(value) / 100)
|
||||
r = copy.copy(rect)
|
||||
r.width = w
|
||||
r.width = round(w)
|
||||
|
||||
# determine transition range number and calculate xv (which is the
|
||||
# progress between the two transition ranges)
|
||||
@@ -317,7 +317,7 @@ class PyGauge(wx.Window):
|
||||
gradient_color
|
||||
)
|
||||
if gradient_bitmap is not None:
|
||||
dc.DrawBitmap(gradient_bitmap, r.left, r.top)
|
||||
dc.DrawBitmap(gradient_bitmap, round(r.left), round(r.top))
|
||||
|
||||
# font stuff begins here
|
||||
dc.SetFont(self.font)
|
||||
|
||||
@@ -39,7 +39,7 @@ class ImplantTextValidor(BaseValidator):
|
||||
return ImplantTextValidor()
|
||||
|
||||
def Validate(self, win):
|
||||
entityEditor = win.parent
|
||||
entityEditor = win.Parent.parent
|
||||
textCtrl = self.GetWindow()
|
||||
text = textCtrl.GetValue().strip()
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ class TargetProfileNameValidator(BaseValidator):
|
||||
return TargetProfileNameValidator()
|
||||
|
||||
def Validate(self, win):
|
||||
entityEditor = win.parent
|
||||
entityEditor = win.Parent.parent
|
||||
textCtrl = self.GetWindow()
|
||||
text = textCtrl.GetValue().strip()
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ class LoadAnimation(wx.Window):
|
||||
bh = rect.height
|
||||
y = 0
|
||||
|
||||
dc.DrawRectangle(x, y, barWidth, bh)
|
||||
dc.DrawRectangle(round(x), round(y), round(barWidth), round(bh))
|
||||
x += barWidth
|
||||
|
||||
textColor = wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOWTEXT)
|
||||
|
||||
@@ -12,7 +12,7 @@ def Brighten(color, factor):
|
||||
b += (255 - b) * factor
|
||||
g += (255 - g) * factor
|
||||
|
||||
return wx.Colour(r, g, b, a)
|
||||
return wx.Colour(round(r), round(g), round(b), round(a))
|
||||
|
||||
|
||||
def Darken(color, factor):
|
||||
@@ -30,7 +30,7 @@ def Darken(color, factor):
|
||||
b = min(max(b, 0), 255)
|
||||
g = min(max(g, 0), 255)
|
||||
|
||||
return wx.Colour(r, g, b, a)
|
||||
return wx.Colour(round(r), round(g), round(b), round(a))
|
||||
|
||||
|
||||
def _getBrightness(color):
|
||||
@@ -70,4 +70,4 @@ def CalculateTransition(s_color, e_color, delta):
|
||||
tG = sG + (eG - sG) * delta
|
||||
tB = sB + (eB - sB) * delta
|
||||
|
||||
return wx.Colour(tR, tG, tB, (sA + eA) / 2)
|
||||
return wx.Colour(round(tR), round(tG), round(tB), round((sA + eA) / 2))
|
||||
|
||||
@@ -43,14 +43,14 @@ def DrawGradientBar(width, height, gStart, gEnd, gMid=None, fillRatio=4):
|
||||
mdc.SelectObject(canvas)
|
||||
|
||||
r = wx.Rect(0, 0, width, height)
|
||||
r.SetHeight(height / fillRatio)
|
||||
r.SetHeight(round(height / fillRatio))
|
||||
|
||||
if gMid is None:
|
||||
gMid = gStart
|
||||
|
||||
mdc.GradientFillLinear(r, gStart, gMid, wx.SOUTH)
|
||||
r.SetTop(r.GetHeight())
|
||||
r.SetHeight(height * (fillRatio - 1) / fillRatio + (1 if height % fillRatio != 0 else 0))
|
||||
r.SetHeight(round(height * (fillRatio - 1) / fillRatio + (1 if height % fillRatio != 0 else 0)))
|
||||
|
||||
mdc.GradientFillLinear(r, gMid, gEnd, wx.SOUTH)
|
||||
|
||||
|
||||
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/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 |
|
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/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 |
BIN
imgs/icons/25833@2x.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 7.4 KiB |
|
Before Width: | Height: | Size: 2.2 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/24531@1x.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
imgs/renders/24531@2x.png
Normal file
|
After Width: | Height: | Size: 7.1 KiB |
BIN
imgs/renders/26204@1x.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
imgs/renders/26204@2x.png
Normal file
|
After Width: | Height: | Size: 7.3 KiB |
BIN
imgs/renders/26216@1x.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
imgs/renders/26216@2x.png
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
BIN
imgs/renders/26378@1x.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
imgs/renders/26378@2x.png
Normal file
|
After Width: | Height: | Size: 6.3 KiB |
BIN
imgs/renders/26445@1x.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
imgs/renders/26445@2x.png
Normal file
|
After Width: | Height: | Size: 6.0 KiB |
BIN
imgs/renders/26515@1x.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
imgs/renders/26515@2x.png
Normal file
|
After Width: | Height: | Size: 7.4 KiB |
BIN
imgs/renders/26516@1x.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
imgs/renders/26516@2x.png
Normal file
|
After Width: | Height: | Size: 7.6 KiB |
@@ -92,7 +92,8 @@ exe = EXE(
|
||||
upx=upx,
|
||||
icon= icon,
|
||||
# version='win-version-info.txt',
|
||||
console=False
|
||||
console=False,
|
||||
contents_directory='app',
|
||||
)
|
||||
|
||||
coll = COLLECT(
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
wxPython == 4.0.6
|
||||
logbook >= 1.0.0
|
||||
numpy == 1.19.2
|
||||
matplotlib == 3.2.2
|
||||
wxPython
|
||||
logbook
|
||||
numpy
|
||||
matplotlib
|
||||
python-dateutil
|
||||
requests == 2.28.1
|
||||
sqlalchemy == 1.3.23
|
||||
cryptography >= 2.3
|
||||
markdown2 >= 2.3.5
|
||||
packaging >= 16.8
|
||||
roman >= 2.0.0
|
||||
beautifulsoup4 >= 4.6.0
|
||||
pyyaml >= 5.1
|
||||
python-jose==3.0.1
|
||||
requests-cache==0.8.1
|
||||
requests
|
||||
sqlalchemy==1.4.50
|
||||
cryptography
|
||||
markdown2
|
||||
packaging
|
||||
roman
|
||||
beautifulsoup4
|
||||
pyyaml
|
||||
python-jose
|
||||
requests-cache
|
||||
|
||||
@@ -19,7 +19,7 @@ params = {
|
||||
resp = requests.get('https://api.crowdin.com/api/project/pyfa/status', params=params)
|
||||
data = resp.json()
|
||||
|
||||
if resp.status_code is not 200:
|
||||
if resp.status_code != 200:
|
||||
print("Error fetching Crowdin progress. Error: {}; {}".format(data['error']['message']))
|
||||
sys.exit()
|
||||
|
||||
@@ -36,4 +36,4 @@ data = {x['canonical_name']: x for x in data}
|
||||
with open("locale/progress.json", 'w') as file:
|
||||
file.seek(0)
|
||||
file.truncate()
|
||||
json.dump(data, file)
|
||||
json.dump(data, file)
|
||||
|
||||
@@ -4,10 +4,8 @@ echo "${PYFA_VERSION}"
|
||||
echo "Pyfa version (YAML):"
|
||||
cat version.yml
|
||||
echo "Building distributive..."
|
||||
python3 -m PyInstaller -y --clean --windowed dist_assets/mac/pyfa.spec
|
||||
python3 -m PyInstaller -y --clean dist_assets/mac/pyfa.spec
|
||||
echo "Compressing distributive..."
|
||||
cd dist
|
||||
/usr/libexec/PlistBuddy -c "Add :CFBundleVersion string ${PYFA_VERSION}" "pyfa.app/Contents/Info.plist" # Add missing
|
||||
/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString ${PYFA_VERSION}" "pyfa.app/Contents/Info.plist" # Modify existing
|
||||
zip -r "pyfa-$PYFA_VERSION-mac.zip" pyfa.app
|
||||
md5 -r "pyfa-$PYFA_VERSION-mac.zip"
|
||||
|
||||
@@ -3,9 +3,7 @@ echo "Python version:"
|
||||
python3 --version
|
||||
echo "Upgrading pip..."
|
||||
python3 -m pip install --upgrade pip
|
||||
echo "Installing pathlib2 (wxpython issue workaround)..."
|
||||
python3 -m pip install pathlib2
|
||||
echo "Installing app requirements..."
|
||||
python3 -m pip install -r requirements.txt
|
||||
echo "Installing packaging tools..."
|
||||
python3 -m pip install PyInstaller==3.6
|
||||
python3 -m pip install PyInstaller
|
||||
|
||||
10
service/conversions/releaseSep2023.py
Normal file
@@ -0,0 +1,10 @@
|
||||
"""
|
||||
Actually renamed somewhere during summer, but updated only in september
|
||||
"""
|
||||
|
||||
CONVERSIONS = {
|
||||
# Renamed items
|
||||
"‘Atgeir’ Explosive Disruptive Lance": "'Atgeir' Explosive Disruptive Lance",
|
||||
"‘Steel Yari’ Kinetic Disruptive Lance": "'Steel Yari' Kinetic Disruptive Lance",
|
||||
"‘Sarissa’ Thermal Disruptive Lance": "'Sarissa' Thermal Disruptive Lance",
|
||||
}
|
||||
@@ -88,7 +88,7 @@ class Fit:
|
||||
"enableGaugeAnimation": True,
|
||||
"openFitInNew": False,
|
||||
"priceSystem": "Jita",
|
||||
"priceSource": "evemarketer",
|
||||
"priceSource": "fuzzwork market",
|
||||
"showShipBrowserTooltip": True,
|
||||
"marketSearchDelay": 250,
|
||||
"ammoChangeAll": False,
|
||||
|
||||
@@ -322,6 +322,8 @@ class Market:
|
||||
"Geri" : self.les_grp, # AT18 prize
|
||||
"Bestla" : self.les_grp, # AT18 prize
|
||||
"Metamorphosis" : self.les_grp, # Seems to be anniversary gift
|
||||
"Shapash" : self.les_grp, # AT19 prize
|
||||
"Cybele" : self.les_grp, # AT19 prize
|
||||
}
|
||||
|
||||
self.ITEMS_FORCEGROUP_R = self.__makeRevDict(self.ITEMS_FORCEGROUP)
|
||||
|
||||
@@ -1 +1 @@
|
||||
__all__ = ['evemarketer', 'evepraisal', 'evemarketdata', 'fuzzwork', 'cevemarket']
|
||||
__all__ = ['evetycoon', 'evemarketdata', 'fuzzwork', 'cevemarket']
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
# =============================================================================
|
||||
# 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/>.
|
||||
# =============================================================================
|
||||
|
||||
|
||||
from xml.dom import minidom
|
||||
|
||||
from logbook import Logger
|
||||
|
||||
from eos.saveddata.price import PriceStatus
|
||||
from service.network import Network
|
||||
from service.price import Price
|
||||
|
||||
pyfalog = Logger(__name__)
|
||||
|
||||
|
||||
class EveMarketer:
|
||||
|
||||
name = 'evemarketer'
|
||||
group = 'tranquility'
|
||||
|
||||
def __init__(self, priceMap, system, fetchTimeout):
|
||||
# Try selected system first
|
||||
self.fetchPrices(priceMap, max(2 * fetchTimeout / 3, 2), system)
|
||||
# If price was not available - try globally
|
||||
if priceMap:
|
||||
self.fetchPrices(priceMap, max(fetchTimeout / 3, 2))
|
||||
|
||||
@staticmethod
|
||||
def fetchPrices(priceMap, fetchTimeout, system=None):
|
||||
params = {'typeid': {typeID for typeID in priceMap}}
|
||||
if system is not None:
|
||||
params['usesystem'] = system
|
||||
baseurl = 'https://api.evemarketer.com/ec/marketstat'
|
||||
network = Network.getInstance()
|
||||
data = network.get(url=baseurl, type=network.PRICES, params=params, timeout=fetchTimeout)
|
||||
xml = minidom.parseString(data.text)
|
||||
types = xml.getElementsByTagName('marketstat').item(0).getElementsByTagName('type')
|
||||
# Cycle through all types we've got from request
|
||||
for type_ in types:
|
||||
# Get data out of each typeID details tree
|
||||
typeID = int(type_.getAttribute('id'))
|
||||
sell = type_.getElementsByTagName('sell').item(0)
|
||||
# If price data wasn't there, skip the item
|
||||
try:
|
||||
percprice = float(sell.getElementsByTagName('percentile').item(0).firstChild.data)
|
||||
except (TypeError, ValueError):
|
||||
pyfalog.warning('Failed to get price for: {0}', type_)
|
||||
continue
|
||||
|
||||
# Price is 0 if evemarketer has info on this item, but it is not available
|
||||
# for current scope limit. If we provided scope limit - make sure to skip
|
||||
# such items to check globally, and do not skip if requested globally
|
||||
if percprice == 0 and system is not None:
|
||||
continue
|
||||
priceMap[typeID].update(PriceStatus.fetchSuccess, percprice)
|
||||
del priceMap[typeID]
|
||||
|
||||
|
||||
Price.register(EveMarketer)
|
||||
@@ -18,6 +18,8 @@
|
||||
# =============================================================================
|
||||
|
||||
|
||||
from xml.dom import minidom
|
||||
|
||||
from logbook import Logger
|
||||
|
||||
from eos.saveddata.price import PriceStatus
|
||||
@@ -26,58 +28,41 @@ from service.price import Price
|
||||
|
||||
pyfalog = Logger(__name__)
|
||||
|
||||
systemAliases = {
|
||||
None: 'universe',
|
||||
30000142: 'jita',
|
||||
30002187: 'amarr',
|
||||
30002659: 'dodixie',
|
||||
30002510: 'rens',
|
||||
30002053: 'hek'}
|
||||
locations = {
|
||||
30000142: (10000002, 60003760), # Jita 4-4 CNAP
|
||||
30002187: (10000043, 60008494), # Amarr VIII
|
||||
30002659: (10000032, 60011866), # Dodixie
|
||||
30002510: (10000030, 60004588), # Rens
|
||||
30002053: (10000042, 60005686)} # Hek
|
||||
|
||||
|
||||
class EvePraisal:
|
||||
class EveTycoon:
|
||||
|
||||
name = 'evepraisal'
|
||||
name = 'evetycoon'
|
||||
group = 'tranquility'
|
||||
|
||||
def __init__(self, priceMap, system, fetchTimeout):
|
||||
# Try selected system first
|
||||
self.fetchPrices(priceMap, max(2 * fetchTimeout / 3, 2), system)
|
||||
# If price was not available - try globally
|
||||
if priceMap:
|
||||
self.fetchPrices(priceMap, max(fetchTimeout / 3, 2))
|
||||
|
||||
@staticmethod
|
||||
def fetchPrices(priceMap, fetchTimeout, system=None):
|
||||
if system not in systemAliases:
|
||||
return
|
||||
jsonData = {
|
||||
'market_name': systemAliases[system],
|
||||
'items': [{'type_id': typeID} for typeID in priceMap]}
|
||||
baseurl = 'https://evepraisal.com/appraisal/structured.json'
|
||||
# Default to jita when system is not found
|
||||
regionID, stationID = locations.get(system, locations[30000142])
|
||||
baseurl = 'https://evetycoon.com/api/v1/market/stats'
|
||||
network = Network.getInstance()
|
||||
resp = network.post(baseurl, network.PRICES, jsonData=jsonData, timeout=fetchTimeout)
|
||||
data = resp.json()
|
||||
try:
|
||||
itemsData = data['appraisal']['items']
|
||||
except (KeyError, TypeError):
|
||||
return
|
||||
# Cycle through all types we've got from request
|
||||
for itemData in itemsData:
|
||||
try:
|
||||
typeID = int(itemData['typeID'])
|
||||
price = itemData['prices']['sell']['min']
|
||||
orderCount = itemData['prices']['sell']['order_count']
|
||||
except (KeyError, TypeError):
|
||||
for typeID in tuple(priceMap):
|
||||
url = f'{baseurl}/{regionID}/{typeID}'
|
||||
resp = network.get(url=url, params={'locationId': stationID}, type=network.PRICES, timeout=fetchTimeout)
|
||||
if resp.status_code != 200:
|
||||
continue
|
||||
# evepraisal returns 0 if price data doesn't even exist for the item
|
||||
price = resp.json()['sellAvgFivePercent']
|
||||
# Price is 0 - no data
|
||||
if price == 0:
|
||||
continue
|
||||
# evepraisal seems to provide price for some items despite having no orders up
|
||||
if orderCount < 1:
|
||||
continue
|
||||
priceMap[typeID].update(PriceStatus.fetchSuccess, price)
|
||||
del priceMap[typeID]
|
||||
|
||||
|
||||
Price.register(EvePraisal)
|
||||
Price.register(EveTycoon)
|
||||
@@ -56,7 +56,7 @@ INV_FLAG_DRONEBAY = 87
|
||||
INV_FLAG_FIGHTER = 158
|
||||
|
||||
|
||||
def exportESI(ofit, exportCharges, callback):
|
||||
def exportESI(ofit, exportCharges, exportImplants, exportBoosters, callback):
|
||||
# A few notes:
|
||||
# max fit name length is 50 characters
|
||||
# Most keys are created simply because they are required, but bogus data is okay
|
||||
@@ -133,6 +133,22 @@ def exportESI(ofit, exportCharges, callback):
|
||||
item['type_id'] = fighter.item.ID
|
||||
fit['items'].append(item)
|
||||
|
||||
if exportImplants:
|
||||
for implant in ofit.implants:
|
||||
item = nested_dict()
|
||||
item['flag'] = INV_FLAG_CARGOBAY
|
||||
item['quantity'] = 1
|
||||
item['type_id'] = implant.item.ID
|
||||
fit['items'].append(item)
|
||||
|
||||
if exportBoosters:
|
||||
for booster in ofit.boosters:
|
||||
item = nested_dict()
|
||||
item['flag'] = INV_FLAG_CARGOBAY
|
||||
item['quantity'] = 1
|
||||
item['type_id'] = booster.item.ID
|
||||
fit['items'].append(item)
|
||||
|
||||
if len(fit['items']) == 0:
|
||||
raise ESIExportException("Cannot export fitting: module list cannot be empty.")
|
||||
|
||||
|
||||
@@ -323,8 +323,8 @@ class Port:
|
||||
return importESI(string)
|
||||
|
||||
@staticmethod
|
||||
def exportESI(fit, exportCharges, callback=None):
|
||||
return exportESI(fit, exportCharges, callback=callback)
|
||||
def exportESI(fit, exportCharges, exportImplants, exportBoosters, callback=None):
|
||||
return exportESI(fit, exportCharges, exportImplants, exportBoosters, callback=callback)
|
||||
|
||||
# XML-related methods
|
||||
@staticmethod
|
||||
|
||||
@@ -276,4 +276,4 @@ class PriceWorkerThread(threading.Thread):
|
||||
|
||||
|
||||
# Import market sources only to initialize price source modules, they register on their own
|
||||
from service.marketSources import evemarketer, evemarketdata, evepraisal, fuzzwork, cevemarket # noqa: E402
|
||||
from service.marketSources import evemarketdata, fuzzwork, cevemarket, evetycoon # noqa: E402
|
||||
|
||||
@@ -376,6 +376,8 @@ class EsiSettings:
|
||||
"timeout": 60,
|
||||
"server": "Tranquility",
|
||||
"exportCharges": True,
|
||||
"exportImplants": True,
|
||||
"exportBoosters": True,
|
||||
"enforceJwtExpiration": True
|
||||
}
|
||||
|
||||
|
||||
@@ -7756,26 +7756,24 @@
|
||||
},
|
||||
"462": {
|
||||
"attributeID": 462,
|
||||
"categoryID": 9,
|
||||
"categoryID": 37,
|
||||
"dataType": 5,
|
||||
"defaultValue": 0.0,
|
||||
"description": "",
|
||||
"displayWhenZero": 0,
|
||||
"highIsGood": 1,
|
||||
"iconID": 0,
|
||||
"name": "shipBonusGF",
|
||||
"published": 0,
|
||||
"stackable": 1
|
||||
},
|
||||
"463": {
|
||||
"attributeID": 463,
|
||||
"categoryID": 9,
|
||||
"categoryID": 37,
|
||||
"dataType": 5,
|
||||
"defaultValue": 0.0,
|
||||
"description": "",
|
||||
"displayWhenZero": 0,
|
||||
"highIsGood": 1,
|
||||
"iconID": 0,
|
||||
"name": "shipBonusCF",
|
||||
"published": 0,
|
||||
"stackable": 1
|
||||
@@ -12102,13 +12100,12 @@
|
||||
},
|
||||
"729": {
|
||||
"attributeID": 729,
|
||||
"categoryID": 9,
|
||||
"categoryID": 37,
|
||||
"dataType": 5,
|
||||
"defaultValue": 0.0,
|
||||
"description": "",
|
||||
"displayWhenZero": 0,
|
||||
"highIsGood": 1,
|
||||
"iconID": 0,
|
||||
"name": "shipBonusMD1",
|
||||
"published": 0,
|
||||
"stackable": 1
|
||||
@@ -12141,39 +12138,36 @@
|
||||
},
|
||||
"734": {
|
||||
"attributeID": 734,
|
||||
"categoryID": 9,
|
||||
"categoryID": 37,
|
||||
"dataType": 5,
|
||||
"defaultValue": 0.0,
|
||||
"description": "",
|
||||
"displayWhenZero": 0,
|
||||
"highIsGood": 1,
|
||||
"iconID": 0,
|
||||
"name": "shipBonusCD1",
|
||||
"published": 0,
|
||||
"stackable": 1
|
||||
},
|
||||
"735": {
|
||||
"attributeID": 735,
|
||||
"categoryID": 9,
|
||||
"categoryID": 37,
|
||||
"dataType": 5,
|
||||
"defaultValue": 0.0,
|
||||
"description": "",
|
||||
"displayWhenZero": 0,
|
||||
"highIsGood": 1,
|
||||
"iconID": 0,
|
||||
"name": "shipBonusCD2",
|
||||
"published": 0,
|
||||
"stackable": 1
|
||||
},
|
||||
"738": {
|
||||
"attributeID": 738,
|
||||
"categoryID": 9,
|
||||
"categoryID": 37,
|
||||
"dataType": 5,
|
||||
"defaultValue": 0.0,
|
||||
"description": "",
|
||||
"displayWhenZero": 0,
|
||||
"highIsGood": 1,
|
||||
"iconID": 0,
|
||||
"name": "shipBonusGD1",
|
||||
"published": 0,
|
||||
"stackable": 1
|
||||
@@ -12193,13 +12187,12 @@
|
||||
},
|
||||
"740": {
|
||||
"attributeID": 740,
|
||||
"categoryID": 9,
|
||||
"categoryID": 37,
|
||||
"dataType": 5,
|
||||
"defaultValue": 0.0,
|
||||
"description": "",
|
||||
"displayWhenZero": 0,
|
||||
"highIsGood": 1,
|
||||
"iconID": 0,
|
||||
"name": "shipBonusMD2",
|
||||
"published": 0,
|
||||
"stackable": 1
|
||||
@@ -46760,7 +46753,7 @@
|
||||
"stackable": 1
|
||||
},
|
||||
"5214": {
|
||||
"attributeID": 2285,
|
||||
"attributeID": 5214,
|
||||
"categoryID": 37,
|
||||
"dataType": 5,
|
||||
"defaultValue": 0.0,
|
||||
@@ -46772,7 +46765,7 @@
|
||||
"stackable": 1
|
||||
},
|
||||
"5215": {
|
||||
"attributeID": 2291,
|
||||
"attributeID": 5215,
|
||||
"categoryID": 37,
|
||||
"dataType": 5,
|
||||
"defaultValue": 0.0,
|
||||
@@ -46784,7 +46777,7 @@
|
||||
"stackable": 1
|
||||
},
|
||||
"5216": {
|
||||
"attributeID": 2291,
|
||||
"attributeID": 5216,
|
||||
"categoryID": 37,
|
||||
"dataType": 5,
|
||||
"defaultValue": 0.0,
|
||||
@@ -46796,7 +46789,7 @@
|
||||
"stackable": 1
|
||||
},
|
||||
"5218": {
|
||||
"attributeID": 1986,
|
||||
"attributeID": 5218,
|
||||
"categoryID": 37,
|
||||
"dataType": 5,
|
||||
"defaultValue": 0.0,
|
||||
@@ -46808,7 +46801,7 @@
|
||||
"stackable": 1
|
||||
},
|
||||
"5219": {
|
||||
"attributeID": 1986,
|
||||
"attributeID": 5219,
|
||||
"categoryID": 37,
|
||||
"dataType": 5,
|
||||
"defaultValue": 0.0,
|
||||
@@ -46820,7 +46813,7 @@
|
||||
"stackable": 1
|
||||
},
|
||||
"5220": {
|
||||
"attributeID": 1986,
|
||||
"attributeID": 5220,
|
||||
"categoryID": 37,
|
||||
"dataType": 5,
|
||||
"defaultValue": 0.0,
|
||||
@@ -46832,7 +46825,7 @@
|
||||
"stackable": 1
|
||||
},
|
||||
"5221": {
|
||||
"attributeID": 1986,
|
||||
"attributeID": 5221,
|
||||
"categoryID": 37,
|
||||
"dataType": 5,
|
||||
"defaultValue": 0.0,
|
||||
@@ -46844,7 +46837,7 @@
|
||||
"stackable": 1
|
||||
},
|
||||
"5222": {
|
||||
"attributeID": 1986,
|
||||
"attributeID": 5222,
|
||||
"categoryID": 37,
|
||||
"dataType": 5,
|
||||
"defaultValue": 0.0,
|
||||
@@ -46856,7 +46849,7 @@
|
||||
"stackable": 1
|
||||
},
|
||||
"5223": {
|
||||
"attributeID": 1986,
|
||||
"attributeID": 5223,
|
||||
"categoryID": 37,
|
||||
"dataType": 5,
|
||||
"defaultValue": 0.0,
|
||||
@@ -46868,7 +46861,7 @@
|
||||
"stackable": 1
|
||||
},
|
||||
"5224": {
|
||||
"attributeID": 1986,
|
||||
"attributeID": 5224,
|
||||
"categoryID": 37,
|
||||
"dataType": 5,
|
||||
"defaultValue": 0.0,
|
||||
@@ -46880,7 +46873,7 @@
|
||||
"stackable": 1
|
||||
},
|
||||
"5225": {
|
||||
"attributeID": 2015,
|
||||
"attributeID": 5225,
|
||||
"categoryID": 37,
|
||||
"dataType": 5,
|
||||
"defaultValue": 0.0,
|
||||
@@ -46892,7 +46885,7 @@
|
||||
"stackable": 1
|
||||
},
|
||||
"5226": {
|
||||
"attributeID": 2015,
|
||||
"attributeID": 5226,
|
||||
"categoryID": 37,
|
||||
"dataType": 5,
|
||||
"defaultValue": 0.0,
|
||||
@@ -46904,7 +46897,7 @@
|
||||
"stackable": 1
|
||||
},
|
||||
"5227": {
|
||||
"attributeID": 2015,
|
||||
"attributeID": 5227,
|
||||
"categoryID": 37,
|
||||
"dataType": 5,
|
||||
"defaultValue": 0.0,
|
||||
@@ -46916,7 +46909,7 @@
|
||||
"stackable": 1
|
||||
},
|
||||
"5228": {
|
||||
"attributeID": 2015,
|
||||
"attributeID": 5228,
|
||||
"categoryID": 37,
|
||||
"dataType": 5,
|
||||
"defaultValue": 0.0,
|
||||
@@ -46928,7 +46921,7 @@
|
||||
"stackable": 1
|
||||
},
|
||||
"5229": {
|
||||
"attributeID": 2015,
|
||||
"attributeID": 5229,
|
||||
"categoryID": 37,
|
||||
"dataType": 5,
|
||||
"defaultValue": 0.0,
|
||||
@@ -46940,7 +46933,7 @@
|
||||
"stackable": 1
|
||||
},
|
||||
"5230": {
|
||||
"attributeID": 2027,
|
||||
"attributeID": 5230,
|
||||
"categoryID": 37,
|
||||
"dataType": 5,
|
||||
"defaultValue": 0.0,
|
||||
@@ -46952,7 +46945,7 @@
|
||||
"stackable": 1
|
||||
},
|
||||
"5231": {
|
||||
"attributeID": 2027,
|
||||
"attributeID": 5231,
|
||||
"categoryID": 37,
|
||||
"dataType": 5,
|
||||
"defaultValue": 0.0,
|
||||
@@ -46964,7 +46957,7 @@
|
||||
"stackable": 1
|
||||
},
|
||||
"5232": {
|
||||
"attributeID": 2027,
|
||||
"attributeID": 5232,
|
||||
"categoryID": 37,
|
||||
"dataType": 5,
|
||||
"defaultValue": 0.0,
|
||||
@@ -46976,7 +46969,7 @@
|
||||
"stackable": 1
|
||||
},
|
||||
"5233": {
|
||||
"attributeID": 2027,
|
||||
"attributeID": 5233,
|
||||
"categoryID": 37,
|
||||
"dataType": 5,
|
||||
"defaultValue": 0.0,
|
||||
@@ -46988,7 +46981,7 @@
|
||||
"stackable": 1
|
||||
},
|
||||
"5234": {
|
||||
"attributeID": 2027,
|
||||
"attributeID": 5234,
|
||||
"categoryID": 37,
|
||||
"dataType": 5,
|
||||
"defaultValue": 0.0,
|
||||
@@ -47000,7 +46993,7 @@
|
||||
"stackable": 1
|
||||
},
|
||||
"5235": {
|
||||
"attributeID": 2004,
|
||||
"attributeID": 5235,
|
||||
"categoryID": 37,
|
||||
"dataType": 5,
|
||||
"defaultValue": 0.0,
|
||||
@@ -47012,7 +47005,7 @@
|
||||
"stackable": 1
|
||||
},
|
||||
"5236": {
|
||||
"attributeID": 2004,
|
||||
"attributeID": 5236,
|
||||
"categoryID": 37,
|
||||
"dataType": 5,
|
||||
"defaultValue": 0.0,
|
||||
@@ -47024,7 +47017,7 @@
|
||||
"stackable": 1
|
||||
},
|
||||
"5237": {
|
||||
"attributeID": 2004,
|
||||
"attributeID": 5237,
|
||||
"categoryID": 37,
|
||||
"dataType": 5,
|
||||
"defaultValue": 0.0,
|
||||
@@ -47036,7 +47029,7 @@
|
||||
"stackable": 1
|
||||
},
|
||||
"5238": {
|
||||
"attributeID": 2004,
|
||||
"attributeID": 5238,
|
||||
"categoryID": 37,
|
||||
"dataType": 5,
|
||||
"defaultValue": 0.0,
|
||||
@@ -47048,7 +47041,7 @@
|
||||
"stackable": 1
|
||||
},
|
||||
"5239": {
|
||||
"attributeID": 2004,
|
||||
"attributeID": 5239,
|
||||
"categoryID": 37,
|
||||
"dataType": 5,
|
||||
"defaultValue": 0.0,
|
||||
@@ -47216,15 +47209,15 @@
|
||||
"categoryID": 39,
|
||||
"dataType": 0,
|
||||
"defaultValue": 0.0,
|
||||
"displayName_de": "Disallow Cloaking While Fit",
|
||||
"displayName_de": "Verweigert Tarnung, solange ausgerüstet",
|
||||
"displayName_en-us": "Disallow Cloaking While Fit",
|
||||
"displayName_es": "Disallow Cloaking While Fit",
|
||||
"displayName_fr": "Disallow Cloaking While Fit",
|
||||
"displayName_es": "Desautorizar camuflaje mientras esté equipado",
|
||||
"displayName_fr": "Désactive le camouflage si équipé",
|
||||
"displayName_it": "Disallow Cloaking While Fit",
|
||||
"displayName_ja": "Disallow Cloaking While Fit",
|
||||
"displayName_ko": "Disallow Cloaking While Fit",
|
||||
"displayName_ru": "Disallow Cloaking While Fit",
|
||||
"displayName_zh": "Disallow Cloaking While Fit",
|
||||
"displayName_ja": "装備中は遮蔽使用不可",
|
||||
"displayName_ko": "해당 모듈 피팅 시 클로킹 불가",
|
||||
"displayName_ru": "Маскировка не работает, если модуль установлен",
|
||||
"displayName_zh": "装配时不允许隐形",
|
||||
"displayNameID": 662925,
|
||||
"displayWhenZero": 0,
|
||||
"highIsGood": 1,
|
||||
@@ -47240,15 +47233,15 @@
|
||||
"dataType": 3,
|
||||
"defaultValue": 0.0,
|
||||
"description": "An effect can check this to indicate that module activation requires ship to have an active Industrial Core module.",
|
||||
"displayName_de": "Requires Active Siege Module",
|
||||
"displayName_de": "Erfordert aktives Belagerungsmodul",
|
||||
"displayName_en-us": "Requires Active Siege Module",
|
||||
"displayName_es": "Requires Active Siege Module",
|
||||
"displayName_fr": "Requires Active Siege Module",
|
||||
"displayName_es": "Requiere módulo de asedio activo",
|
||||
"displayName_fr": "Nécessite un module de siège actif",
|
||||
"displayName_it": "Requires Active Siege Module",
|
||||
"displayName_ja": "Requires Active Siege Module",
|
||||
"displayName_ko": "Requires Active Siege Module",
|
||||
"displayName_ru": "Requires Active Siege Module",
|
||||
"displayName_zh": "Requires Active Siege Module",
|
||||
"displayName_ja": "起動状態のシージモジュールが必要",
|
||||
"displayName_ko": "시즈 모듈 활성화 필요",
|
||||
"displayName_ru": "Требуется активный осадный модуль",
|
||||
"displayName_zh": "需要主动会战装备",
|
||||
"displayNameID": 662927,
|
||||
"displayWhenZero": 0,
|
||||
"highIsGood": 0,
|
||||
@@ -47257,5 +47250,233 @@
|
||||
"published": 1,
|
||||
"stackable": 0,
|
||||
"unitID": 137
|
||||
},
|
||||
"5429": {
|
||||
"attributeID": 5429,
|
||||
"dataType": 5,
|
||||
"defaultValue": 0.0,
|
||||
"displayWhenZero": 0,
|
||||
"highIsGood": 0,
|
||||
"name": "warpDistanceXAxis",
|
||||
"published": 0,
|
||||
"stackable": 0
|
||||
},
|
||||
"5430": {
|
||||
"attributeID": 5430,
|
||||
"dataType": 5,
|
||||
"defaultValue": 0.0,
|
||||
"displayWhenZero": 0,
|
||||
"highIsGood": 0,
|
||||
"name": "warpDistanceYAxis",
|
||||
"published": 0,
|
||||
"stackable": 0
|
||||
},
|
||||
"5431": {
|
||||
"attributeID": 5431,
|
||||
"dataType": 5,
|
||||
"defaultValue": 0.0,
|
||||
"displayWhenZero": 0,
|
||||
"highIsGood": 0,
|
||||
"name": "warpDistanceZAxis",
|
||||
"published": 0,
|
||||
"stackable": 0
|
||||
},
|
||||
"5432": {
|
||||
"attributeID": 5432,
|
||||
"dataType": 5,
|
||||
"defaultValue": 149599993856.0,
|
||||
"displayWhenZero": 0,
|
||||
"highIsGood": 0,
|
||||
"name": "warpItemActivationLimit",
|
||||
"published": 0,
|
||||
"stackable": 0
|
||||
},
|
||||
"5469": {
|
||||
"attributeID": 5469,
|
||||
"categoryID": 52,
|
||||
"dataType": 5,
|
||||
"defaultValue": 0.0,
|
||||
"description": "Alliance Tournament Ship Overheat Bonus",
|
||||
"displayName_de": "Überhitzungsbonus",
|
||||
"displayName_en-us": "Overheat Bonus",
|
||||
"displayName_es": "Bonificación de sobrecalentamiento",
|
||||
"displayName_fr": "Bonus de surchauffe",
|
||||
"displayName_it": "Overheat Bonus",
|
||||
"displayName_ja": "Overheat Bonus",
|
||||
"displayName_ko": "과부하 보너스",
|
||||
"displayName_ru": "Повышение эффективности при перегрузке",
|
||||
"displayName_zh": "过载损伤降低",
|
||||
"displayNameID": 665013,
|
||||
"displayWhenZero": 1,
|
||||
"highIsGood": 1,
|
||||
"name": "roleBonusOverheatATHAC",
|
||||
"published": 0,
|
||||
"stackable": 1,
|
||||
"unitID": 105
|
||||
},
|
||||
"5470": {
|
||||
"attributeID": 5470,
|
||||
"categoryID": 6,
|
||||
"dataType": 0,
|
||||
"defaultValue": 0.0,
|
||||
"description": "Tracking Speed Bonus",
|
||||
"displayName_de": "Zielverfolgungsgeschwindigkeit-Bonus",
|
||||
"displayName_en-us": "Tracking Speed Bonus",
|
||||
"displayName_es": "Bonificación de velocidad de rastreo",
|
||||
"displayName_fr": "Bonus de vitesse de poursuite",
|
||||
"displayName_it": "Tracking Speed Bonus",
|
||||
"displayName_ja": "Tracking Speed Bonus",
|
||||
"displayName_ko": "트래킹 속도 보너스",
|
||||
"displayName_ru": "Влияние на скорость слежения",
|
||||
"displayName_zh": "跟踪速度加成",
|
||||
"displayNameID": 665059,
|
||||
"displayWhenZero": 0,
|
||||
"highIsGood": 1,
|
||||
"iconID": 1398,
|
||||
"name": "shipBonusTrackingATC1",
|
||||
"published": 1,
|
||||
"stackable": 1,
|
||||
"unitID": 105
|
||||
},
|
||||
"5561": {
|
||||
"attributeID": 5561,
|
||||
"categoryID": 9,
|
||||
"dataType": 4,
|
||||
"defaultValue": 0.0,
|
||||
"description": "If set on a charge or module type, will prevent it from being activated in hazard system",
|
||||
"displayName_de": "Kann nicht in Zarzakh verwendet werden ",
|
||||
"displayName_en-us": "Unusable in Zarzakh ",
|
||||
"displayName_es": "Inutilizable en Zarzakh ",
|
||||
"displayName_fr": "Inutilisable à Zarzakh ",
|
||||
"displayName_it": "Unusable in Zarzakh ",
|
||||
"displayName_ja": "ザルザクでは使用不可 ",
|
||||
"displayName_ko": "자르자크에서 사용 불가 ",
|
||||
"displayName_ru": "Нельзя использовать в Zarzakh ",
|
||||
"displayName_zh": "无法在扎尔扎克使用 ",
|
||||
"displayNameID": 669819,
|
||||
"displayWhenZero": 0,
|
||||
"highIsGood": 0,
|
||||
"iconID": 25803,
|
||||
"name": "disallowInHazardSystem",
|
||||
"published": 1,
|
||||
"stackable": 1,
|
||||
"unitID": 137
|
||||
},
|
||||
"5592": {
|
||||
"attributeID": 5592,
|
||||
"categoryID": 42,
|
||||
"dataType": 5,
|
||||
"defaultValue": 0.0,
|
||||
"displayWhenZero": 0,
|
||||
"highIsGood": 1,
|
||||
"name": "behaviorTargetRepairImpedanceRange",
|
||||
"published": 0,
|
||||
"stackable": 1,
|
||||
"unitID": 1
|
||||
},
|
||||
"5593": {
|
||||
"attributeID": 5593,
|
||||
"categoryID": 42,
|
||||
"dataType": 5,
|
||||
"defaultValue": 0.0,
|
||||
"displayWhenZero": 0,
|
||||
"highIsGood": 1,
|
||||
"name": " behaviorTargetRepairImpedanceDuration",
|
||||
"published": 0,
|
||||
"stackable": 1,
|
||||
"unitID": 101
|
||||
},
|
||||
"5594": {
|
||||
"attributeID": 5594,
|
||||
"categoryID": 42,
|
||||
"dataType": 5,
|
||||
"defaultValue": 0.0,
|
||||
"displayWhenZero": 0,
|
||||
"highIsGood": 1,
|
||||
"name": "behaviorTargetInertiaRange",
|
||||
"published": 0,
|
||||
"stackable": 1,
|
||||
"unitID": 1
|
||||
},
|
||||
"5595": {
|
||||
"attributeID": 5595,
|
||||
"categoryID": 42,
|
||||
"dataType": 5,
|
||||
"defaultValue": 0.0,
|
||||
"displayWhenZero": 0,
|
||||
"highIsGood": 1,
|
||||
"name": " behaviorTargetInertiaDuration",
|
||||
"published": 0,
|
||||
"stackable": 1,
|
||||
"unitID": 101
|
||||
},
|
||||
"5599": {
|
||||
"attributeID": 5599,
|
||||
"dataType": 0,
|
||||
"defaultValue": 0.0,
|
||||
"description": "if the module is disallowed in low sec (empire space), if it also have this attribute, it will allow that module to be used in low sec system if the systems is fully corrupted",
|
||||
"displayWhenZero": 0,
|
||||
"highIsGood": 0,
|
||||
"name": "allowInFullyCorruptedLowSec",
|
||||
"published": 0,
|
||||
"stackable": 0
|
||||
},
|
||||
"5600": {
|
||||
"attributeID": 5600,
|
||||
"dataType": 0,
|
||||
"defaultValue": 0.0,
|
||||
"description": "if the module is disallowed in high sec (by disallowInEmpireSpace or disallowInHighSec), if it also have this attribute, the module can be used in high sec system ONLY WHEN the systems is fully corrupted",
|
||||
"displayWhenZero": 0,
|
||||
"highIsGood": 0,
|
||||
"name": "allowInFullyCorruptedHighSec",
|
||||
"published": 1,
|
||||
"stackable": 0
|
||||
},
|
||||
"5602": {
|
||||
"attributeID": 5602,
|
||||
"categoryID": 9,
|
||||
"dataType": 0,
|
||||
"defaultValue": 1.0,
|
||||
"description": "to allow capture point proximity sensors to also detect non-interactives (like NPCs/entities) ",
|
||||
"displayWhenZero": 0,
|
||||
"highIsGood": 0,
|
||||
"name": "captureProximityInteractivesOnly",
|
||||
"published": 0,
|
||||
"stackable": 0
|
||||
},
|
||||
"5603": {
|
||||
"attributeID": 5603,
|
||||
"categoryID": 9,
|
||||
"dataType": 5,
|
||||
"defaultValue": 0.0,
|
||||
"description": "used for alliance tournament ships 2023, plate mass reduction",
|
||||
"displayWhenZero": 0,
|
||||
"highIsGood": 1,
|
||||
"name": "shipBonusATF3",
|
||||
"published": 0,
|
||||
"stackable": 1
|
||||
},
|
||||
"5604": {
|
||||
"attributeID": 5604,
|
||||
"categoryID": 7,
|
||||
"dataType": 0,
|
||||
"defaultValue": 0.0,
|
||||
"description": "Alliance Tournament Ship Bonus",
|
||||
"displayName_de": "Bonus für besondere Fähigkeit",
|
||||
"displayName_en-us": "Special Ability Bonus",
|
||||
"displayName_es": "Bonificación de capacidad especial",
|
||||
"displayName_fr": "Bonus d'aptitude particulière",
|
||||
"displayName_it": "Special Ability Bonus",
|
||||
"displayName_ja": "Special Ability Bonus",
|
||||
"displayName_ko": "특수 능력 보너스",
|
||||
"displayName_ru": "Усиление особого умения",
|
||||
"displayName_zh": "特殊能力加成",
|
||||
"displayNameID": 696793,
|
||||
"displayWhenZero": 0,
|
||||
"highIsGood": 1,
|
||||
"name": "shipBonusATC3",
|
||||
"published": 0,
|
||||
"stackable": 1,
|
||||
"unitID": 105
|
||||
}
|
||||
}
|
||||
@@ -7481,5 +7481,89 @@
|
||||
"resultingType": 60483
|
||||
}
|
||||
]
|
||||
},
|
||||
"78622": {
|
||||
"attributeIDs": {
|
||||
"50": {
|
||||
"max": 1.2999999523162842,
|
||||
"min": 0.8500000238418579
|
||||
},
|
||||
"64": {
|
||||
"max": 1.0140000581741333,
|
||||
"min": 0.9890000224113464
|
||||
},
|
||||
"204": {
|
||||
"max": 1.0149999856948853,
|
||||
"min": 0.9800000190734863
|
||||
}
|
||||
},
|
||||
"inputOutputMapping": [
|
||||
{
|
||||
"applicableTypes": [
|
||||
54973,
|
||||
54975,
|
||||
54974,
|
||||
78740,
|
||||
78741
|
||||
],
|
||||
"resultingType": 78621
|
||||
}
|
||||
]
|
||||
},
|
||||
"78623": {
|
||||
"attributeIDs": {
|
||||
"50": {
|
||||
"max": 1.25,
|
||||
"min": 0.949999988079071
|
||||
},
|
||||
"64": {
|
||||
"max": 1.0080000162124634,
|
||||
"min": 0.9950000047683716
|
||||
},
|
||||
"204": {
|
||||
"max": 1.0099999904632568,
|
||||
"min": 0.9850000143051147
|
||||
}
|
||||
},
|
||||
"inputOutputMapping": [
|
||||
{
|
||||
"applicableTypes": [
|
||||
54973,
|
||||
54975,
|
||||
54974,
|
||||
78740,
|
||||
78741
|
||||
],
|
||||
"resultingType": 78621
|
||||
}
|
||||
]
|
||||
},
|
||||
"78624": {
|
||||
"attributeIDs": {
|
||||
"50": {
|
||||
"max": 1.5,
|
||||
"min": 0.800000011920929
|
||||
},
|
||||
"64": {
|
||||
"max": 1.0199999809265137,
|
||||
"min": 0.9800000190734863
|
||||
},
|
||||
"204": {
|
||||
"max": 1.024999976158142,
|
||||
"min": 0.9750000238418579
|
||||
}
|
||||
},
|
||||
"inputOutputMapping": [
|
||||
{
|
||||
"applicableTypes": [
|
||||
54973,
|
||||
54975,
|
||||
54974,
|
||||
78741,
|
||||
78740
|
||||
],
|
||||
"resultingType": 78621
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||