Compare commits
464 Commits
v2.28.2dev
...
v2.38.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fe809ed86b | ||
|
|
de4466b037 | ||
|
|
8ebf478cf7 | ||
|
|
530a12ea4f | ||
|
|
b94f6e8d0a | ||
|
|
4b83169070 | ||
|
|
a7da9e20a5 | ||
|
|
0020dcdf0a | ||
|
|
066f697186 | ||
|
|
b2217bb6cd | ||
|
|
4669b4813c | ||
|
|
a71701932c | ||
|
|
1be0d306bb | ||
|
|
85f63e237d | ||
|
|
acab787a7b | ||
|
|
da50c7dcfc | ||
|
|
b0d3469f01 | ||
|
|
148093f6ad | ||
|
|
fab58bdb57 | ||
|
|
34b2fdbd1b | ||
|
|
ea7a5b3c70 | ||
|
|
056685ded5 | ||
|
|
60f9e96b19 | ||
|
|
341950cb42 | ||
|
|
641e982614 | ||
|
|
1e534e087a | ||
|
|
0b7b80d0f6 | ||
|
|
27bd9fc55b | ||
|
|
533f6f3b24 | ||
|
|
c18cbe5e59 | ||
|
|
adba55eb7d | ||
|
|
03c6f7c894 | ||
|
|
478b2bfe4c | ||
|
|
7e4d8a3074 | ||
|
|
8497d1f1bb | ||
|
|
1b5acc36d3 | ||
|
|
2a94dcebf8 | ||
|
|
7b9e196ca8 | ||
|
|
f3f7d688ab | ||
|
|
17391f119c | ||
|
|
abd138a015 | ||
|
|
33aa208513 | ||
|
|
1874cbe0c5 | ||
|
|
028fb42e18 | ||
|
|
d9b0d2e72a | ||
|
|
e0234c343e | ||
|
|
b5816a312c | ||
|
|
86cc025812 | ||
|
|
8072f7e618 | ||
|
|
c34b12d806 | ||
|
|
67760fa2ab | ||
|
|
9a28dd17be | ||
|
|
6e4d1876ad | ||
|
|
40b0b27176 | ||
|
|
b238422f29 | ||
|
|
4e20583b81 | ||
|
|
f730cdb86a | ||
|
|
e05471fa6f | ||
|
|
45b517e097 | ||
|
|
f27274c9e5 | ||
|
|
d32a8f0b61 | ||
|
|
6a01086cf5 | ||
|
|
e0f65c2370 | ||
|
|
e7c2f4cff7 | ||
|
|
93cce50d00 | ||
|
|
d1a2cdc586 | ||
|
|
9dab6b0f92 | ||
|
|
33e3ea6030 | ||
|
|
9d97b27c3a | ||
|
|
05d156c7f4 | ||
|
|
2ddc4924cc | ||
|
|
e3fef6f1a7 | ||
|
|
fbd8d04f68 | ||
|
|
23916165bb | ||
|
|
3cca6a6c95 | ||
|
|
a52172a3c6 | ||
|
|
8a2bfb48ce | ||
|
|
b42254cb61 | ||
|
|
91fbcd4eb4 | ||
|
|
bdc52da05d | ||
|
|
2bbe17722b | ||
|
|
3ef07b9153 | ||
|
|
5af904ca18 | ||
|
|
d3cdc67472 | ||
|
|
0991124d5f | ||
|
|
83ea548c4d | ||
|
|
4752eee09d | ||
|
|
53d2d1fabe | ||
|
|
f600868eb2 | ||
|
|
f6a489fa22 | ||
|
|
2962a89919 | ||
|
|
c3d53f56a9 | ||
|
|
3257abbeff | ||
|
|
5858d96deb | ||
|
|
94d1eae464 | ||
|
|
b7e2b782c9 | ||
|
|
05e5958d36 | ||
|
|
e9364fe65a | ||
|
|
b3b71896ae | ||
|
|
00d20f53d0 | ||
|
|
88e4f7a77e | ||
|
|
5763954f51 | ||
|
|
4fbfbcc84e | ||
|
|
1f2c20e95b | ||
|
|
d7aa744bc1 | ||
|
|
1117c786ff | ||
|
|
6a715f6678 | ||
|
|
5e93235b02 | ||
|
|
271b915ce6 | ||
|
|
52667da64a | ||
|
|
82f0fea1bf | ||
|
|
751823177b | ||
|
|
ac7e8a1efa | ||
|
|
066a12e912 | ||
|
|
ea64657fba | ||
|
|
17b94001e0 | ||
|
|
cc481f9f29 | ||
|
|
f73bb14990 | ||
|
|
a5ed992cd2 | ||
|
|
f7e792411a | ||
|
|
fc71d7b706 | ||
|
|
162055d5ce | ||
|
|
5cc87a439f | ||
|
|
d2d3a42adf | ||
|
|
e43cb74906 | ||
|
|
ace00d495a | ||
|
|
729b39e351 | ||
|
|
5ae1e64a76 | ||
|
|
88a9ce03ba | ||
|
|
cbd3d8cc1b | ||
|
|
65a126b4c5 | ||
|
|
241c744d40 | ||
|
|
8ee900a90e | ||
|
|
1c415fbe06 | ||
|
|
304aebbccf | ||
|
|
18d9f6a542 | ||
|
|
cdc6e046b0 | ||
|
|
59bb9670b6 | ||
|
|
9321a78a61 | ||
|
|
53191714f2 | ||
|
|
b17347156c | ||
|
|
66ace06194 | ||
|
|
e8697c6131 | ||
|
|
7a6e87330d | ||
|
|
2acf92160e | ||
|
|
6e49f6fd7a | ||
|
|
6e56230a0e | ||
|
|
01282d103a | ||
|
|
a0317d5b3c | ||
|
|
a697c1890a | ||
|
|
aaf719437f | ||
|
|
3d6e703b7c | ||
|
|
ce26b22752 | ||
|
|
6b30b2859e | ||
|
|
961258618a | ||
|
|
f07684875f | ||
|
|
538954f4a6 | ||
|
|
30e73ed795 | ||
|
|
d216eb3e55 | ||
|
|
c25fa0f632 | ||
|
|
8a115be0bd | ||
|
|
b897ee5146 | ||
|
|
7b3bda5816 | ||
|
|
f62e16288d | ||
|
|
9aad8860a9 | ||
|
|
f8dd1f27a9 | ||
|
|
09bc2da863 | ||
|
|
f531c144af | ||
|
|
dfd08fa8e2 | ||
|
|
e430848be9 | ||
|
|
2d645b8f91 | ||
|
|
e33cb80608 | ||
|
|
fcc8c3eeb9 | ||
|
|
c29d567255 | ||
|
|
e85b618cbc | ||
|
|
008b6a887d | ||
|
|
05ab2d47c7 | ||
|
|
75b611c94a | ||
|
|
356d594637 | ||
|
|
03f4bc1d75 | ||
|
|
226c5d7fad | ||
|
|
0c3998b640 | ||
|
|
942f9a35ee | ||
|
|
031a3c2d3e | ||
|
|
ed7df2f1a7 | ||
|
|
fb2ad2cc10 | ||
|
|
34bce4e083 | ||
|
|
fc45b43295 | ||
|
|
4160b08388 | ||
|
|
95c25b274c | ||
|
|
690e5caf52 | ||
|
|
95ada5d61d | ||
|
|
976820a7c0 | ||
|
|
8ab14bcfcc | ||
|
|
6e8798eb08 | ||
|
|
15af830dca | ||
|
|
ce728243b0 | ||
|
|
2696b480fa | ||
|
|
ca7a3cae9c | ||
|
|
10613c9070 | ||
|
|
a692b1fe74 | ||
|
|
0592d2c3f4 | ||
|
|
301a3473cc | ||
|
|
4887852de4 | ||
|
|
6b3bf1f7a8 | ||
|
|
a4d163fc89 | ||
|
|
e88e3996a8 | ||
|
|
a36dd20890 | ||
|
|
c9f37457ab | ||
|
|
4709cd78f3 | ||
|
|
5ac5b3f5e4 | ||
|
|
da78c24d9b | ||
|
|
566c87fa59 | ||
|
|
e6d7a140cf | ||
|
|
89e496f3af | ||
|
|
d650284ae1 | ||
|
|
b41d7d2603 | ||
|
|
33c20bfc3b | ||
|
|
6f0778ad94 | ||
|
|
7ce39a0dac | ||
|
|
7de7a17bae | ||
|
|
50b8c3fc61 | ||
|
|
dab5d1f211 | ||
|
|
5141a30e22 | ||
|
|
1172e5011e | ||
|
|
ea2141b719 | ||
|
|
9f7fdfc800 | ||
|
|
de63b11a80 | ||
|
|
514d11e6f2 | ||
|
|
9d759054ca | ||
|
|
c162d96cc0 | ||
|
|
3c22397377 | ||
|
|
20e605c30f | ||
|
|
9601887855 | ||
|
|
0a7f5b6092 | ||
|
|
e27ea79bc6 | ||
|
|
adb0609eb8 | ||
|
|
39b08baff0 | ||
|
|
e4388bf835 | ||
|
|
b9cae5165b | ||
|
|
06e6589209 | ||
|
|
9f21b251ff | ||
|
|
7d7a499070 | ||
|
|
e18a3bfab5 | ||
|
|
a80b7c098a | ||
|
|
1580a8ddc9 | ||
|
|
385215b717 | ||
|
|
d09913d61b | ||
|
|
b9059835ce | ||
|
|
7af28b497c | ||
|
|
5cf555b8ce | ||
|
|
a25bb1aaa3 | ||
|
|
24a54c9cec | ||
|
|
0b9e6bf55d | ||
|
|
41070ce22e | ||
|
|
7b5aab8a35 | ||
|
|
c9fe6c959d | ||
|
|
67cf3a3a26 | ||
|
|
c644d528e9 | ||
|
|
cca5781ca8 | ||
|
|
c08216252e | ||
|
|
02219846a7 | ||
|
|
ff0af7cce7 | ||
|
|
0e8316192b | ||
|
|
c0f8099f49 | ||
|
|
32a03dedaa | ||
|
|
5ae43fc648 | ||
|
|
d1f26dd4db | ||
|
|
c595e4426e | ||
|
|
abe7fa4ac1 | ||
|
|
fd5d6ffca5 | ||
|
|
abaa7f395d | ||
|
|
8e3893d6c6 | ||
|
|
5de808456e | ||
|
|
362d081338 | ||
|
|
7bc4e5b34c | ||
|
|
9450f4a915 | ||
|
|
1a9ebf0772 | ||
|
|
1c7036e612 | ||
|
|
87cb9713f9 | ||
|
|
d3f0d9d41a | ||
|
|
b0d088ab31 | ||
|
|
47bda45516 | ||
|
|
95d18dc3ab | ||
|
|
be5f8ce37d | ||
|
|
107856ab0e | ||
|
|
c1f9b1d0d7 | ||
|
|
469c255bbf | ||
|
|
bec9eb2224 | ||
|
|
7dc362fef9 | ||
|
|
80781c7eff | ||
|
|
fca78a72e4 | ||
|
|
7438fb72bc | ||
|
|
b6f24ec4c2 | ||
|
|
db2bd22ddc | ||
|
|
bbcedbf2cb | ||
|
|
937adb68d7 | ||
|
|
1fe83ddcdf | ||
|
|
ac1e6fe5b7 | ||
|
|
cb99151f69 | ||
|
|
0b850808cb | ||
|
|
ffb14a2393 | ||
|
|
f1feb8cebe | ||
|
|
507cc09a2f | ||
|
|
6990a71d14 | ||
|
|
2239428b71 | ||
|
|
ce755e393c | ||
|
|
d07e46099b | ||
|
|
d11e9c52c0 | ||
|
|
57aaed4140 | ||
|
|
af76103957 | ||
|
|
fdaf682dbd | ||
|
|
26e1ab47f2 | ||
|
|
f1ffd369d0 | ||
|
|
9ac8969d43 | ||
|
|
7bc4a1d334 | ||
|
|
bb9866e175 | ||
|
|
d81e25fc50 | ||
|
|
6b11fd0a91 | ||
|
|
8a5b2b3e48 | ||
|
|
99d1655c20 | ||
|
|
91c30832b3 | ||
|
|
390f198310 | ||
|
|
316265e19d | ||
|
|
8754326446 | ||
|
|
443769badd | ||
|
|
0cee45e33d | ||
|
|
9d02845875 | ||
|
|
5f97ba6931 | ||
|
|
ca7358d2fc | ||
|
|
dcdd50a91b | ||
|
|
9895339c13 | ||
|
|
04f9c1c9f8 | ||
|
|
e536aa5f1c | ||
|
|
b82030090c | ||
|
|
9868b219d7 | ||
|
|
f9b3defd4b | ||
|
|
7451ce147e | ||
|
|
2203767fde | ||
|
|
067f60bfcd | ||
|
|
d4c9423c77 | ||
|
|
ffbae4826d | ||
|
|
da2ec4d759 | ||
|
|
5a45863432 | ||
|
|
605addd0d6 | ||
|
|
5f45709118 | ||
|
|
76674435c9 | ||
|
|
dcdf69d658 | ||
|
|
47e428d57e | ||
|
|
95af9660b6 | ||
|
|
6e7b8cca24 | ||
|
|
af62a7273f | ||
|
|
6cdb4a7dc1 | ||
|
|
469f0a9be7 | ||
|
|
832ad5bc6b | ||
|
|
bc77f24471 | ||
|
|
5d95877d2c | ||
|
|
3642ff8cee | ||
|
|
8cc770467e | ||
|
|
85e779469f | ||
|
|
29f6ac0d99 | ||
|
|
4d49512a7e | ||
|
|
dae13f934e | ||
|
|
bf99132f2f | ||
|
|
25a694bd69 | ||
|
|
038b7ce931 | ||
|
|
8625dea833 | ||
|
|
6f3049f39b | ||
|
|
52b74d9950 | ||
|
|
dc60c3d68b | ||
|
|
6612724beb | ||
|
|
c242a18a34 | ||
|
|
732634fefa | ||
|
|
10a4f62b78 | ||
|
|
c39ae080fb | ||
|
|
e5e8a570db | ||
|
|
eaea671f4e | ||
|
|
1145a27e04 | ||
|
|
b18205a184 | ||
|
|
9703ce70d9 | ||
|
|
47dd6f7bba | ||
|
|
3db9c637e0 | ||
|
|
77d233ca1c | ||
|
|
b225093b1f | ||
|
|
4a6a3fc6ea | ||
|
|
2fd4168ab7 | ||
|
|
22498e5605 | ||
|
|
f515536d1a | ||
|
|
5c7e3fe782 | ||
|
|
546a3b6e01 | ||
|
|
1d0c890c23 | ||
|
|
427b1189f7 | ||
|
|
19da89a467 | ||
|
|
be4f6241a9 | ||
|
|
03e29e02b1 | ||
|
|
853b65d6aa | ||
|
|
45dae7a031 | ||
|
|
4130852e76 | ||
|
|
3d238a1cc1 | ||
|
|
977ae98ea6 | ||
|
|
dac35597ea | ||
|
|
0a1489719b | ||
|
|
4ff63e5fc4 | ||
|
|
c3389fb19b | ||
|
|
42706f35c6 | ||
|
|
c7ec87b979 | ||
|
|
66140f092b | ||
|
|
8be4b0dd91 | ||
|
|
a2f65e9d46 | ||
|
|
c040ff26c0 | ||
|
|
92ecd8c844 | ||
|
|
60c8a66bea | ||
|
|
b1ff13e370 | ||
|
|
50b0df7d6d | ||
|
|
281e30f78a | ||
|
|
821378e2c3 | ||
|
|
d4106a7229 | ||
|
|
079256a99f | ||
|
|
bcd7e6d56d | ||
|
|
e56db0d129 | ||
|
|
6035d26dd0 | ||
|
|
61127dc4d3 | ||
|
|
f4f0dc775c | ||
|
|
d33976a2ad | ||
|
|
1c4de8b259 | ||
|
|
1079371ecf | ||
|
|
85c3158e98 | ||
|
|
2d97f0952e | ||
|
|
396640e5b1 | ||
|
|
aa8a03b18b | ||
|
|
889e901cbd | ||
|
|
07696ce0ed | ||
|
|
ffdbab87e9 | ||
|
|
4eda1a1d66 | ||
|
|
29ec297acb | ||
|
|
7cd7d475db | ||
|
|
02aa4eb2b4 | ||
|
|
7cf9326311 | ||
|
|
2214269cca | ||
|
|
9b73f1c221 | ||
|
|
339367f730 | ||
|
|
68f7e6c709 | ||
|
|
eb657e804c | ||
|
|
413bc5d46c | ||
|
|
e4e49cef54 | ||
|
|
49cf03759b | ||
|
|
a05e7dbad1 | ||
|
|
d28665f172 | ||
|
|
1848acc1ba | ||
|
|
d9e5349edd | ||
|
|
d939b0e565 | ||
|
|
c290e9e23a | ||
|
|
ce0d8b1247 | ||
|
|
834e4a3d6e | ||
|
|
3d9b4c11d4 | ||
|
|
2d3a661442 | ||
|
|
343f4a5196 | ||
|
|
31fd480fb0 | ||
|
|
8e83adf7db | ||
|
|
7fa638f62b | ||
|
|
2490d3de92 | ||
|
|
c3ceebcec7 | ||
|
|
5177768962 | ||
|
|
fdd06ed3d6 |
197
.appveyor.yml
197
.appveyor.yml
@@ -1,88 +1,129 @@
|
||||
image: Visual Studio 2019
|
||||
image:
|
||||
- Visual Studio 2019
|
||||
- macos
|
||||
clone_depth: 400
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- PYTHON: "C:\\Python37-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'))
|
||||
install:
|
||||
- ps: echo("OS version:")
|
||||
- ps: "[System.Environment]::OSVersion.Version"
|
||||
for:
|
||||
-
|
||||
matrix:
|
||||
only:
|
||||
- image: Visual Studio 2019
|
||||
environment:
|
||||
PYTHON: "C:\\Python37-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'))
|
||||
install:
|
||||
- ps: echo("OS version:")
|
||||
- ps: "[System.Environment]::OSVersion.Version"
|
||||
|
||||
- ps: echo("Filesystem - root:")
|
||||
- ps: "ls \"C:\\\""
|
||||
- ps: echo("Filesystem - root:")
|
||||
- ps: "ls \"C:\\\""
|
||||
|
||||
- ps: echo("Filesystem - projects root:")
|
||||
- ps: "ls \"C:\\projects\\\""
|
||||
- ps: echo("Filesystem - projects root:")
|
||||
- ps: "ls \"C:\\projects\\\""
|
||||
|
||||
- ps: echo("Filesystem - pyfa root:")
|
||||
- ps: "ls \"C:\\projects\\$env:APPVEYOR_PROJECT_SLUG\\\""
|
||||
- ps: echo("Filesystem - pyfa root:")
|
||||
- ps: "ls \"C:\\projects\\$env:APPVEYOR_PROJECT_SLUG\\\""
|
||||
|
||||
- ps: echo("Filesystem - installed SDKs:")
|
||||
- ps: "ls \"C:\\Program Files (x86)\\Windows Kits\\\""
|
||||
- ps: echo("Filesystem - installed SDKs:")
|
||||
- ps: "ls \"C:\\Program Files (x86)\\Windows Kits\\\""
|
||||
|
||||
# Prepend newly installed Python to the PATH of this build (this cannot be
|
||||
# done from inside the powershell script as it would require to restart
|
||||
# the parent CMD process).
|
||||
- cmd: "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%"
|
||||
# Prepend newly installed Python to the PATH of this build (this cannot be
|
||||
# done from inside the powershell script as it would require to restart
|
||||
# the parent CMD process).
|
||||
- cmd: "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%"
|
||||
- cmd: "appveyor DownloadFile https://github.com/mlocati/gettext-iconv-windows/releases/download/v0.20.2-v1.16/gettext0.20.2-iconv1.16-shared-64.zip"
|
||||
- cmd: "7z x gettext0.20.2-iconv1.16-shared-64.zip -ogettext"
|
||||
- cmd: "SET PATH=gettext;%PATH%"
|
||||
|
||||
- cmd: "python --version"
|
||||
- cmd: "python -c \"import struct; print(struct.calcsize('P') * 8)\""
|
||||
- cmd: "python --version"
|
||||
- cmd: "python -c \"import struct; print(struct.calcsize('P') * 8)\""
|
||||
|
||||
# Upgrade to the latest version of pip to avoid it displaying warnings
|
||||
# about it being out of date.
|
||||
- cmd: "python -m pip install --upgrade pip"
|
||||
# Upgrade to the latest version of pip to avoid it displaying warnings
|
||||
# about it being out of date.
|
||||
- cmd: "python -m pip install --upgrade pip"
|
||||
|
||||
# Install the build dependencies of the project. If some dependencies contain
|
||||
# compiled extensions and are not provided as pre-built wheel packages,
|
||||
# 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"
|
||||
|
||||
before_build:
|
||||
# directory that will contain the built files
|
||||
- ps: $env:PYFA_DIST_DIR = "c:\projects\$env:APPVEYOR_PROJECT_SLUG\dist"
|
||||
- ps: $env:PYFA_VERSION = (python ./scripts/dump_version.py)
|
||||
- ps: echo("pyfa version $env:PYFA_VERSION")
|
||||
|
||||
build_script:
|
||||
- ps: echo("Build pyfa:")
|
||||
# Build gamedata DB
|
||||
- cmd: "python db_update.py"
|
||||
# Build command for PyInstaller
|
||||
- cmd: "python -m PyInstaller --noupx --clean --windowed --noconsole -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...
|
||||
- cmd: "python dist_assets/win/dist.py"
|
||||
- ps: dir $env:PYFA_DIST_DIR/
|
||||
|
||||
after_build:
|
||||
- ps: "ls \"./\""
|
||||
- ps: 7z a "pyfa-$env:PYFA_VERSION-win.zip" -r "$env:PYFA_DIST_DIR\pyfa\*"
|
||||
|
||||
test_script:
|
||||
# Ha... we're just building
|
||||
|
||||
artifacts:
|
||||
- path: pyfa*-win.zip
|
||||
- path: pyfa*-win.exe
|
||||
|
||||
deploy:
|
||||
tag: $(pyfa_version)
|
||||
release: pyfa $(pyfa_version)
|
||||
description: 'Release description'
|
||||
provider: GitHub
|
||||
auth_token:
|
||||
secure: X+U3hOAMTt7HGXCR/LXaGNF6qyhUXetrjz5+xlWiNJQ3XEdzhZZmHK75m0Hm6qre
|
||||
draft: true
|
||||
force_update: false
|
||||
# deploy on tag push only
|
||||
on:
|
||||
APPVEYOR_REPO_TAG: true
|
||||
# Install the build dependencies of the project. If some dependencies contain
|
||||
# compiled extensions and are not provided as pre-built wheel packages,
|
||||
# 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"
|
||||
before_build:
|
||||
# directory that will contain the built files
|
||||
- ps: $env:PYFA_DIST_DIR = "c:\projects\$env:APPVEYOR_PROJECT_SLUG\dist"
|
||||
- ps: $env:PYFA_VERSION = (python ./scripts/dump_version.py)
|
||||
- ps: echo("pyfa version $env:PYFA_VERSION")
|
||||
build_script:
|
||||
- ps: echo("Build pyfa:")
|
||||
- ps: Get-ChildItem locale/*.po -Recurse -File| Foreach {msgen $_.fullname -o $_.fullname}
|
||||
# Build language files
|
||||
- cmd: "python scripts/compile_lang.py"
|
||||
# Dump language progress
|
||||
- cmd: "python scripts/dump_crowdin_progress.py"
|
||||
# Build gamedata DB
|
||||
- cmd: "python db_update.py"
|
||||
# Build command for PyInstaller
|
||||
- cmd: "python -m PyInstaller --noupx --clean --windowed --noconsole -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...
|
||||
- cmd: "python dist_assets/win/dist.py"
|
||||
- ps: dir $env:PYFA_DIST_DIR/
|
||||
after_build:
|
||||
- ps: "ls \"./\""
|
||||
- ps: 7z a "pyfa-$env:PYFA_VERSION-win.zip" -r "$env:PYFA_DIST_DIR\pyfa\*"
|
||||
artifacts:
|
||||
- path: pyfa*-win.zip
|
||||
- path: pyfa*-win.exe
|
||||
deploy:
|
||||
tag: $(pyfa_version)
|
||||
release: pyfa $(pyfa_version)
|
||||
description: 'Release description'
|
||||
provider: GitHub
|
||||
auth_token:
|
||||
secure: M94o0xMtzxrvlKpqMcXU2KfbJdd3aYJ3UxWzePUz/pkT1/Ojiis052CiLsLVyzJg
|
||||
draft: true
|
||||
force_update: false
|
||||
# deploy on tag push only
|
||||
on:
|
||||
APPVEYOR_REPO_TAG: true
|
||||
-
|
||||
matrix:
|
||||
only:
|
||||
- image: macos
|
||||
# Should be enabled only for build process debugging
|
||||
init:
|
||||
# - sh: curl -sflL 'https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-ssh.sh' | bash -e -
|
||||
- sh: source ~/venv3.7/bin/activate
|
||||
install:
|
||||
- sh: bash scripts/osx-setup.sh
|
||||
build_script:
|
||||
- sh: bash scripts/osx-translations.sh
|
||||
- sh: python3 scripts/compile_lang.py
|
||||
- sh: python3 scripts/dump_crowdin_progress.py
|
||||
- sh: python3 db_update.py
|
||||
after_build:
|
||||
- sh: export PYFA_VERSION="$(python3 scripts/dump_version.py)"
|
||||
- sh: bash scripts/osx-package.sh
|
||||
artifacts:
|
||||
- path: dist/pyfa*-mac.zip
|
||||
before_deploy:
|
||||
- sh: export RELEASE_PKG_FILE=$(ls *.deb)
|
||||
- sh: echo "deploying $RELEASE_PKG_FILE to GitHub releases"
|
||||
deploy:
|
||||
tag: $PYFA_VERSION
|
||||
release: pyfa $PYFA_VERSION
|
||||
description: 'Release description'
|
||||
provider: GitHub
|
||||
auth_token:
|
||||
secure: M94o0xMtzxrvlKpqMcXU2KfbJdd3aYJ3UxWzePUz/pkT1/Ojiis052CiLsLVyzJg
|
||||
draft: true
|
||||
force_update: false
|
||||
# deploy on tag push only
|
||||
on:
|
||||
APPVEYOR_REPO_TAG: true
|
||||
|
||||
6
.gitattributes
vendored
6
.gitattributes
vendored
@@ -1,11 +1,9 @@
|
||||
# Set the default behavior, in case people don't have core.autocrlf set.
|
||||
* text=auto
|
||||
|
||||
# Explicitly declare text files you want to always be normalized and converted
|
||||
# to native line endings on checkout.
|
||||
# *.c text
|
||||
# *.h text
|
||||
|
||||
# Declare files that will always have CRLF line endings on checkout.
|
||||
# Source files
|
||||
# ============
|
||||
@@ -15,7 +13,6 @@
|
||||
*.pyw text eol=crlf
|
||||
*.pyx text eol=crlf
|
||||
pyfa.py text eol=lf
|
||||
|
||||
# Denote all files that are truly binary and should not be modified.
|
||||
# Binary files
|
||||
# ============
|
||||
@@ -25,12 +22,10 @@ pyfa.py text eol=lf
|
||||
*.pyc binary
|
||||
*.pyd binary
|
||||
*.pyo binary
|
||||
|
||||
# Note: .db, .p, and .pkl files are associated
|
||||
# with the python modules ``pickle``, ``dbm.*``,
|
||||
# ``shelve``, ``marshal``, ``anydbm``, & ``bsddb``
|
||||
# (among others).
|
||||
|
||||
# Denote all files that are truly binary and should not be modified.
|
||||
# Image files
|
||||
# ============
|
||||
@@ -38,3 +33,4 @@ pyfa.py text eol=lf
|
||||
*.jpg binary
|
||||
*.icns binary
|
||||
*.ico binary
|
||||
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -67,7 +67,6 @@ coverage.xml
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
@@ -123,3 +122,4 @@ gitversion
|
||||
*.swp
|
||||
|
||||
*.fsdbinary
|
||||
/locale/progress.json
|
||||
|
||||
31
.travis.yml
31
.travis.yml
@@ -1,31 +0,0 @@
|
||||
os: linux
|
||||
language: python
|
||||
git:
|
||||
depth: 400
|
||||
python:
|
||||
- 3.8
|
||||
matrix:
|
||||
include:
|
||||
- os: osx
|
||||
osx_image: xcode11.3
|
||||
language: generic
|
||||
before_install:
|
||||
- bash scripts/setup-osx.sh
|
||||
install:
|
||||
- python3 db_update.py
|
||||
- export PYFA_VERSION="$(python3 scripts/dump_version.py)"
|
||||
- bash scripts/package-osx.sh
|
||||
before_deploy:
|
||||
- export RELEASE_PKG_FILE=$(ls *.deb)
|
||||
- echo "deploying $RELEASE_PKG_FILE to GitHub releases"
|
||||
deploy:
|
||||
provider: releases
|
||||
api_key:
|
||||
secure: D8tBW0kyHlKf/sXS69aIuexsYTx9auY2DzudKFlfcvdzqat4N2XZqZbZCTVd7YVvptQ8Dj0oZ/p3KUxEGpnJZmlTeJL142rpM/qaNd6wOIMy2yUde/aZl+W9JLFNQp7KHutM+MxObYLzJGihx/8YsupmFx6lxgdngGDXtXYZe/ruDIWDs92ShoKJ4vlce9Csm7eGKv7wv6Z6V9sD5FS3E9J8xdWStHxsbrkPBOflmG+uHU09dpEqzUm+ZYROIoTwig1Xbw3fw+gfjmNrfdSU4fAJcVZI1hrgoenZyJbMfhI2Ej/nZdbZgaXcZNF/eUpqOGgbPe1JljqFnHTbexcE+LPBVyAToScsGMpByHhig67DrZ0nk9gSZoC6CPNl5YS6xub+5dncMJ3P5L03DOGYRu4SL9NczbeuQyKuea7+JPP/8VLwfFDSEqbNEAmgzABAzrdfano+VXtuBuE/Tiy5eE7le9hJu6aSQoKW1SA3cUhMsmr2amzdO96sh+PN8FA1oNr45Yuy0pqOj4SUIkb8JUy4th7vgdhljEkSxrHDK1UcHpxUTp+IIUZkZVVk50aH68dQZxGwSTVOeRxpjrTcEf7VCGaM98qxi/ZK4RW6Ewiq0eo0AxwEeB2Zm841lycGPR/406vM9/ZBzv5IhELIdDdVWTk+dGjJBXB8z5hPJOg=
|
||||
file_glob: true
|
||||
file: "dist/pyfa-*.zip"
|
||||
skip_cleanup: true
|
||||
draft: true
|
||||
on:
|
||||
tags: true
|
||||
repo: pyfa-org/Pyfa
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
## Requirements
|
||||
|
||||
- Python 3.6
|
||||
- Python 3.7
|
||||
- Git CLI installed
|
||||
- Python, pip and git are all available as command-line commands (add to the path if needed)
|
||||
|
||||
@@ -41,13 +41,18 @@ Check that the libs from *requirements.txt* are installed
|
||||
pip list
|
||||
```
|
||||
|
||||
Build translations and database:
|
||||
```
|
||||
python scripts\compile_lang.py
|
||||
python db_update.py
|
||||
```
|
||||
|
||||
Test that the project is starting properly
|
||||
```
|
||||
python PyfaDEV\pyfa.py
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Setting up the project with PyCharm/IntelliJ
|
||||
|
||||
Install PyCharm / Other IntelliJ product with Python plugin
|
||||
@@ -99,4 +104,4 @@ python -m pytest
|
||||
py.test
|
||||
```
|
||||
|
||||
More information on tests can be found on appropriate [Wiki page](https://github.com/pyfa-org/Pyfa/wiki/Developers:-Writing-Tests-for-Pyfa).
|
||||
More information on tests can be found on appropriate [Wiki page](https://github.com/pyfa-org/Pyfa/wiki/Developers:-Writing-Tests-for-Pyfa).
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
<option name="RIGHT_MARGIN" value="165" />
|
||||
<Python>
|
||||
<option name="NEW_LINE_AFTER_COLON" value="true" />
|
||||
<option name="DICT_ALIGNMENT" value="2" />
|
||||
<option name="DICT_NEW_LINE_AFTER_LEFT_BRACE" value="true" />
|
||||
<option name="DICT_NEW_LINE_BEFORE_RIGHT_BRACE" value="true" />
|
||||
<option name="USE_CONTINUATION_INDENT_FOR_ARGUMENTS" value="true" />
|
||||
|
||||
@@ -1,54 +1,61 @@
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Pyfa" />
|
||||
<inspection_tool class="IgnoreUnusedEntry" enabled="false" level="UNUSED ENTRY" enabled_by_default="false" />
|
||||
<inspection_tool class="InconsistentLineSeparators" enabled="true" level="ERROR" enabled_by_default="true" />
|
||||
<inspection_tool class="ProblematicWhitespace" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PyBehaveInspection" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PyClassicStyleClassInspection" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PyCompatibilityInspection" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="ourVersions">
|
||||
<value>
|
||||
<list size="1">
|
||||
<item index="0" class="java.lang.String" itemvalue="2.7" />
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Pyfa" />
|
||||
<inspection_tool class="IgnoreUnusedEntry" enabled="false" level="UNUSED ENTRY" enabled_by_default="false" />
|
||||
<inspection_tool class="InconsistentLineSeparators" enabled="true" level="ERROR" enabled_by_default="true" />
|
||||
<inspection_tool class="ProblematicWhitespace" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PyBehaveInspection" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PyClassicStyleClassInspection" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PyCompatibilityInspection" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="ourVersions">
|
||||
<value>
|
||||
<list size="1">
|
||||
<item index="0" class="java.lang.String" itemvalue="2.7" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
</inspection_tool>
|
||||
<inspection_tool class="PyMissingTypeHintsInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PyPackageRequirementsInspection" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="ignoredPackages">
|
||||
<value>
|
||||
<list size="1">
|
||||
<item index="0" class="java.lang.String" itemvalue="wxPython" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
</inspection_tool>
|
||||
<inspection_tool class="PyPep8Inspection" enabled="true" level="TYPO" enabled_by_default="true">
|
||||
<option name="ignoredErrors">
|
||||
<list>
|
||||
<option value="E203" />
|
||||
<option value="E127" />
|
||||
<option value="E128" />
|
||||
<option value="E126" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
</inspection_tool>
|
||||
<inspection_tool class="PyMissingTypeHintsInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PyPackageRequirementsInspection" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="ignoredPackages">
|
||||
<value>
|
||||
<list size="1">
|
||||
<item index="0" class="java.lang.String" itemvalue="wxPython" />
|
||||
</option>
|
||||
</inspection_tool>
|
||||
<inspection_tool class="PyPep8NamingInspection" enabled="true" level="TYPO" enabled_by_default="true">
|
||||
<option name="ignoredErrors">
|
||||
<list>
|
||||
<option value="N802" />
|
||||
<option value="N806" />
|
||||
<option value="N803" />
|
||||
<option value="N814" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
</inspection_tool>
|
||||
<inspection_tool class="PyPep8Inspection" enabled="true" level="TYPO" enabled_by_default="true">
|
||||
<option name="ignoredErrors">
|
||||
<list>
|
||||
<option value="E203" />
|
||||
<option value="E127" />
|
||||
<option value="E128" />
|
||||
<option value="E126" />
|
||||
</list>
|
||||
</option>
|
||||
</inspection_tool>
|
||||
<inspection_tool class="PyPep8NamingInspection" enabled="true" level="TYPO" enabled_by_default="true">
|
||||
<option name="ignoredErrors">
|
||||
<list>
|
||||
<option value="N802" />
|
||||
<option value="N806" />
|
||||
<option value="N803" />
|
||||
<option value="N814" />
|
||||
</list>
|
||||
</option>
|
||||
</inspection_tool>
|
||||
<inspection_tool class="PyShadowingBuiltinsInspection" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PyShadowingNamesInspection" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
|
||||
<option name="processCode" value="true" />
|
||||
<option name="processLiterals" value="true" />
|
||||
<option name="processComments" value="true" />
|
||||
</inspection_tool>
|
||||
</profile>
|
||||
</option>
|
||||
</inspection_tool>
|
||||
<inspection_tool class="PyShadowingBuiltinsInspection" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PyShadowingNamesInspection" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PyUnresolvedReferencesInspection" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="ignoredIdentifiers">
|
||||
<list>
|
||||
<option value="_" />
|
||||
</list>
|
||||
</option>
|
||||
</inspection_tool>
|
||||
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
|
||||
<option name="processCode" value="true" />
|
||||
<option name="processLiterals" value="true" />
|
||||
<option name="processComments" value="true" />
|
||||
</inspection_tool>
|
||||
</profile>
|
||||
|
||||
14
config.py
14
config.py
@@ -41,8 +41,11 @@ cipher = None
|
||||
clientHash = None
|
||||
experimentalFeatures = None
|
||||
version = None
|
||||
language = None
|
||||
|
||||
API_CLIENT_ID = '095d8cd841ac40b581330919b49fe746'
|
||||
ESI_CACHE = 'esi_cache'
|
||||
SSO_CALLBACK = 'https://pyfa-org.github.io/Pyfa/callback'
|
||||
|
||||
LOGLEVEL_MAP = {
|
||||
"critical": CRITICAL,
|
||||
@@ -52,6 +55,8 @@ LOGLEVEL_MAP = {
|
||||
"debug": DEBUG,
|
||||
}
|
||||
|
||||
CATALOG = 'lang'
|
||||
|
||||
slotColourMap = {
|
||||
FittingSlot.LOW: wx.Colour(250, 235, 204), # yellow = low slots
|
||||
FittingSlot.MED: wx.Colour(188, 215, 241), # blue = mid slots
|
||||
@@ -106,6 +111,7 @@ def defPaths(customSavePath=None):
|
||||
global clientHash
|
||||
global version
|
||||
global experimentalFeatures
|
||||
global language
|
||||
|
||||
pyfalog.debug("Configuring Pyfa")
|
||||
|
||||
@@ -185,9 +191,15 @@ def defPaths(customSavePath=None):
|
||||
eos.config.gamedata_connectionstring = "sqlite:///" + gameDB + "?check_same_thread=False"
|
||||
|
||||
# initialize the settings
|
||||
from service.settings import EOSSettings
|
||||
from service.settings import EOSSettings, LocaleSettings
|
||||
eos.config.settings = EOSSettings.getInstance().EOSSettings # this is kind of confusing, but whatever
|
||||
|
||||
# set langauge, taking the passed argument or falling back to what's saved in the settings
|
||||
localeSettings = LocaleSettings.getInstance()
|
||||
language = language or localeSettings.get('locale')
|
||||
|
||||
# sets the lang for eos, using the mapped langauge.
|
||||
eos.config.set_lang(localeSettings.get_eos_locale())
|
||||
|
||||
def defLogging():
|
||||
global debug
|
||||
|
||||
3
crowdin.yml
Normal file
3
crowdin.yml
Normal file
@@ -0,0 +1,3 @@
|
||||
files:
|
||||
- source: /locale/*.pot
|
||||
translation: /locale/%locale_with_underscore%/LC_MESSAGES/lang.po
|
||||
121
db_update.py
121
db_update.py
@@ -27,7 +27,11 @@ import re
|
||||
import sqlite3
|
||||
import sys
|
||||
|
||||
from sqlalchemy import or_
|
||||
|
||||
|
||||
# todo: need to set the EOS language to en, becasuse this assumes it's being run within an English context
|
||||
# Need to know what that would do if called from pyfa
|
||||
ROOT_DIR = os.path.realpath(os.path.dirname(__file__))
|
||||
DB_PATH = os.path.join(ROOT_DIR, 'eve.db')
|
||||
JSON_DIR = os.path.join(ROOT_DIR, 'staticdata')
|
||||
@@ -39,7 +43,7 @@ GAMEDATA_SCHEMA_VERSION = 4
|
||||
def db_needs_update():
|
||||
"""True if needs, false if it does not, none if we cannot check it."""
|
||||
try:
|
||||
with open(os.path.join(JSON_DIR, 'phobos', 'metadata.json')) as f:
|
||||
with open(os.path.join(JSON_DIR, 'phobos', 'metadata.0.json')) as f:
|
||||
data_version = next((r['field_value'] for r in json.load(f) if r['field_name'] == 'client_build'))
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
@@ -85,18 +89,31 @@ def update_db():
|
||||
|
||||
import eos.db
|
||||
import eos.gamedata
|
||||
import eos.config
|
||||
|
||||
# Create the database tables
|
||||
eos.db.gamedata_meta.create_all()
|
||||
|
||||
def _readData(minerName, jsonName, keyIdName=None):
|
||||
with open(os.path.join(JSON_DIR, minerName, '{}.json'.format(jsonName)), encoding='utf-8') as f:
|
||||
rawData = json.load(f)
|
||||
compiled_data = None
|
||||
for i in itertools.count(0):
|
||||
try:
|
||||
with open(os.path.join(JSON_DIR, minerName, '{}.{}.json'.format(jsonName, i)), encoding='utf-8') as f:
|
||||
rawData = json.load(f)
|
||||
if i == 0:
|
||||
compiled_data = {} if type(rawData) == dict else []
|
||||
if type(rawData) == dict:
|
||||
compiled_data.update(rawData)
|
||||
else:
|
||||
compiled_data.extend(rawData)
|
||||
except FileNotFoundError:
|
||||
break
|
||||
|
||||
if not keyIdName:
|
||||
return rawData
|
||||
return compiled_data
|
||||
# IDs in keys, rows in values
|
||||
data = []
|
||||
for k, v in rawData.items():
|
||||
for k, v in compiled_data.items():
|
||||
row = {}
|
||||
row.update(v)
|
||||
if keyIdName not in row:
|
||||
@@ -121,13 +138,24 @@ def update_db():
|
||||
for row in data:
|
||||
if (
|
||||
# Apparently people really want Civilian modules available
|
||||
(row['typeName'].startswith('Civilian') and "Shuttle" not in row['typeName']) or
|
||||
row['typeName'] == 'Capsule' or
|
||||
(row['typeName_en-us'].startswith('Civilian') and "Shuttle" not in row['typeName_en-us']) or
|
||||
row['typeName_en-us'] == 'Capsule' or
|
||||
row['groupID'] == 4033 # destructible effect beacons
|
||||
):
|
||||
row['published'] = True
|
||||
# Nearly useless and clutter search results too much
|
||||
elif row['typeName'].startswith('Limited Synth '):
|
||||
elif (
|
||||
row['typeName_en-us'].startswith('Limited Synth ') or
|
||||
row['typeName_en-us'].endswith(' Filament') and (
|
||||
"'Needlejack'" not in row['typeName_en-us'] and
|
||||
"'Devana'" not in row['typeName_en-us'] and
|
||||
"'Pochven'" not in row['typeName_en-us'] and
|
||||
"'Extraction'" not in row['typeName_en-us'] and
|
||||
"'Krai Veles'" not in row['typeName_en-us'] and
|
||||
"'Krai Perun'" not in row['typeName_en-us'] and
|
||||
"'Krai Svarog'" not in row['typeName_en-us']
|
||||
)
|
||||
):
|
||||
row['published'] = False
|
||||
|
||||
newData = []
|
||||
@@ -146,25 +174,34 @@ def update_db():
|
||||
1983) # the "container" for the abyssal environments
|
||||
):
|
||||
newData.append(row)
|
||||
|
||||
_addRows(newData, eos.gamedata.Item)
|
||||
map = {'typeName_en-us': 'typeName', 'description_en-us': '_description'}
|
||||
map.update({'description'+v: '_description'+v for (k, v) in eos.config.translation_mapping.items() if k != 'en'})
|
||||
_addRows(newData, eos.gamedata.Item, fieldMap=map)
|
||||
return newData
|
||||
|
||||
def processEveGroups():
|
||||
print('processing evegroups')
|
||||
data = _readData('fsd_lite', 'evegroups', keyIdName='groupID')
|
||||
_addRows(data, eos.gamedata.Group)
|
||||
map = {'groupName_en-us': 'name'}
|
||||
map.update({'groupName'+v: 'name'+v for (k, v) in eos.config.translation_mapping.items() if k != 'en'})
|
||||
_addRows(data, eos.gamedata.Group, fieldMap=map)
|
||||
return data
|
||||
|
||||
def processEveCategories():
|
||||
print('processing evecategories')
|
||||
data = _readData('fsd_lite', 'evecategories', keyIdName='categoryID')
|
||||
_addRows(data, eos.gamedata.Category)
|
||||
map = { 'categoryName_en-us': 'name' }
|
||||
map.update({'categoryName'+v: 'name'+v for (k, v) in eos.config.translation_mapping.items() if k != 'en'})
|
||||
_addRows(data, eos.gamedata.Category, fieldMap=map)
|
||||
|
||||
def processDogmaAttributes():
|
||||
print('processing dogmaattributes')
|
||||
data = _readData('fsd_binary', 'dogmaattributes', keyIdName='attributeID')
|
||||
_addRows(data, eos.gamedata.AttributeInfo)
|
||||
map = {
|
||||
'displayName_en-us': 'displayName',
|
||||
# 'tooltipDescription_en-us': 'tooltipDescription'
|
||||
}
|
||||
_addRows(data, eos.gamedata.AttributeInfo, fieldMap=map)
|
||||
|
||||
def processDogmaTypeAttributes(eveTypesData):
|
||||
print('processing dogmatypeattributes')
|
||||
@@ -239,17 +276,28 @@ def update_db():
|
||||
def processDogmaUnits():
|
||||
print('processing dogmaunits')
|
||||
data = _readData('fsd_binary', 'dogmaunits', keyIdName='unitID')
|
||||
_addRows(data, eos.gamedata.Unit, fieldMap={'name': 'unitName'})
|
||||
_addRows(data, eos.gamedata.Unit, fieldMap={
|
||||
'name': 'unitName',
|
||||
'displayName_en-us': 'displayName'
|
||||
})
|
||||
|
||||
def processMarketGroups():
|
||||
print('processing marketgroups')
|
||||
data = _readData('fsd_binary', 'marketgroups', keyIdName='marketGroupID')
|
||||
_addRows(data, eos.gamedata.MarketGroup, fieldMap={'name': 'marketGroupName'})
|
||||
map = {
|
||||
'name_en-us': 'marketGroupName',
|
||||
'description_en-us': '_description',
|
||||
}
|
||||
map.update({'name'+v: 'marketGroupName'+v for (k, v) in eos.config.translation_mapping.items() if k != 'en'})
|
||||
map.update({'description' + v: '_description' + v for (k, v) in eos.config.translation_mapping.items() if k != 'en'})
|
||||
_addRows(data, eos.gamedata.MarketGroup, fieldMap=map)
|
||||
|
||||
def processMetaGroups():
|
||||
print('processing metagroups')
|
||||
data = _readData('fsd_binary', 'metagroups', keyIdName='metaGroupID')
|
||||
_addRows(data, eos.gamedata.MetaGroup)
|
||||
map = {'name_en-us': 'metaGroupName'}
|
||||
map.update({'name' + v: 'metaGroupName' + v for (k, v) in eos.config.translation_mapping.items() if k != 'en'})
|
||||
_addRows(data, eos.gamedata.MetaGroup, fieldMap=map)
|
||||
|
||||
def processCloneGrades():
|
||||
print('processing clonegrades')
|
||||
@@ -303,20 +351,28 @@ def update_db():
|
||||
|
||||
newData = []
|
||||
for row in data:
|
||||
typeLines = []
|
||||
typeId = row['typeID']
|
||||
traitData = row['traits']
|
||||
for skillData in sorted(traitData.get('skills', ()), key=lambda i: i['header']):
|
||||
typeLines.append(convertSection(skillData))
|
||||
if 'role' in traitData:
|
||||
typeLines.append(convertSection(traitData['role']))
|
||||
if 'misc' in traitData:
|
||||
typeLines.append(convertSection(traitData['misc']))
|
||||
traitLine = '<br />\n<br />\n'.join(typeLines)
|
||||
newRow = {'typeID': typeId, 'traitText': traitLine}
|
||||
newData.append(newRow)
|
||||
try:
|
||||
newRow = {
|
||||
'typeID': row['typeID'],
|
||||
}
|
||||
for (k, v) in eos.config.translation_mapping.items():
|
||||
if v == '':
|
||||
v = '_en-us'
|
||||
typeLines = []
|
||||
traitData = row['traits{}'.format(v)]
|
||||
for skillData in sorted(traitData.get('skills', ()), key=lambda i: i['header']):
|
||||
typeLines.append(convertSection(skillData))
|
||||
if 'role' in traitData:
|
||||
typeLines.append(convertSection(traitData['role']))
|
||||
if 'misc' in traitData:
|
||||
typeLines.append(convertSection(traitData['misc']))
|
||||
traitLine = '<br />\n<br />\n'.join(typeLines)
|
||||
newRow['traitText{}'.format(v)] = traitLine
|
||||
|
||||
_addRows(newData, eos.gamedata.Traits)
|
||||
newData.append(newRow)
|
||||
except:
|
||||
pass
|
||||
_addRows(newData, eos.gamedata.Traits, fieldMap={'traitText_en-us': 'traitText'})
|
||||
|
||||
def processMetadata():
|
||||
print('processing metadata')
|
||||
@@ -483,7 +539,7 @@ def update_db():
|
||||
continue
|
||||
if row.get('groupID') not in implant_groups:
|
||||
continue
|
||||
typeName = row.get('typeName', '')
|
||||
typeName = row.get('typeName_en-us', '')
|
||||
# Regular sets matching
|
||||
m = re.match('(?P<grade>(High|Mid|Low)-grade) (?P<set>\w+) (?P<implant>(Alpha|Beta|Gamma|Delta|Epsilon|Omega))', typeName, re.IGNORECASE)
|
||||
if m:
|
||||
@@ -537,7 +593,10 @@ def update_db():
|
||||
# pyfa, we can do it here as a post-processing step
|
||||
for attr in eos.db.gamedata_session.query(eos.gamedata.Attribute).filter(eos.gamedata.Attribute.ID == 1367).all():
|
||||
attr.value = 4.0
|
||||
for item in eos.db.gamedata_session.query(eos.gamedata.Item).filter(eos.gamedata.Item.name.like('%abyssal%')).all():
|
||||
for item in eos.db.gamedata_session.query(eos.gamedata.Item).filter(or_(
|
||||
eos.gamedata.Item.name.like('%abyssal%'),
|
||||
eos.gamedata.Item.name.like('%mutated%')
|
||||
)).all():
|
||||
item.published = False
|
||||
|
||||
for x in [
|
||||
|
||||
@@ -20,6 +20,7 @@ added_files = [
|
||||
('../../imgs/renders/*.png', 'imgs/renders'),
|
||||
('../../dist_assets/win/pyfa.ico', '.'),
|
||||
('../../service/jargon/*.yaml', 'service/jargon'),
|
||||
('../../locale', 'locale'),
|
||||
(requests.certs.where(), '.'), # is this needed anymore?
|
||||
('../../eve.db', '.'),
|
||||
('../../README.md', '.'),
|
||||
|
||||
@@ -119,7 +119,7 @@ function PrepareToInstall(var NeedsRestart: Boolean): String;
|
||||
begin
|
||||
if(IsAppRunning( 'pyfa.exe' )) then
|
||||
begin
|
||||
Result := 'Please close pyfa before continuing. When closed, please go back to the previous step and continue.';
|
||||
Result := 'Please close pyfa before continuing. When closed, please go back to the previous step and continue. If you have named this installer pyfa.exe, please rename it and restart installation';
|
||||
end
|
||||
else
|
||||
begin
|
||||
|
||||
@@ -13,6 +13,24 @@ saveddataCache = True
|
||||
gamedata_version = ""
|
||||
gamedata_date = ""
|
||||
gamedata_connectionstring = 'sqlite:///' + realpath(join(dirname(abspath(__file__)), "..", "eve.db"))
|
||||
|
||||
lang = ""
|
||||
|
||||
# Maps supported langauges to their suffix in the database
|
||||
translation_mapping = {
|
||||
"en": "",
|
||||
"fr": "_fr",
|
||||
# "it": "_it",
|
||||
"ja": "_ja",
|
||||
"ko": "_ko",
|
||||
"ru": "_ru",
|
||||
"zh": "_zh",
|
||||
}
|
||||
|
||||
def set_lang(i18n_lang):
|
||||
global lang
|
||||
lang = translation_mapping.get(i18n_lang, translation_mapping.get("en"))
|
||||
|
||||
pyfalog.debug("Gamedata connection string: {0}", gamedata_connectionstring)
|
||||
|
||||
if istravis is True or hasattr(sys, '_called_from_test'):
|
||||
|
||||
@@ -118,7 +118,7 @@ from eos.db.gamedata import alphaClones, attribute, category, effect, group, ite
|
||||
pyfalog.debug('Importing saveddata DB scheme')
|
||||
# noinspection PyPep8
|
||||
from eos.db.saveddata import booster, cargo, character, damagePattern, databaseRepair, drone, fighter, fit, implant, implantSet, \
|
||||
miscData, mutator, module, override, price, queries, skill, targetProfile, user
|
||||
miscData, mutatorMod, mutatorDrone, module, override, price, queries, skill, targetProfile, user
|
||||
|
||||
pyfalog.debug('Importing gamedata queries')
|
||||
# noinspection PyPep8
|
||||
|
||||
@@ -23,7 +23,7 @@ from sqlalchemy.orm import relation, mapper, synonym, deferred
|
||||
|
||||
from eos.db import gamedata_meta
|
||||
from eos.gamedata import Attribute, AttributeInfo, Unit
|
||||
|
||||
import eos.config
|
||||
typeattributes_table = Table("dgmtypeattribs", gamedata_meta,
|
||||
Column("value", Float),
|
||||
Column("typeID", Integer, ForeignKey("invtypes.typeID"), primary_key=True, index=True),
|
||||
@@ -36,11 +36,11 @@ attributes_table = Table("dgmattribs", gamedata_meta,
|
||||
Column("maxAttributeID", Integer, ForeignKey("dgmattribs.attributeID")),
|
||||
Column("description", Unicode),
|
||||
Column("published", Boolean),
|
||||
Column("displayName", String),
|
||||
*[Column("displayName{}".format(lang), String) for lang in eos.config.translation_mapping.values()],
|
||||
Column("highIsGood", Boolean),
|
||||
Column("iconID", Integer),
|
||||
Column("attributeCategory", Integer),
|
||||
Column("tooltipDescription", Integer),
|
||||
# Column("tooltipDescription", Integer), # deprecated...?
|
||||
Column("unitID", Integer, ForeignKey("dgmunits.unitID")))
|
||||
|
||||
mapper(Attribute, typeattributes_table,
|
||||
@@ -51,14 +51,14 @@ mapper(AttributeInfo, attributes_table,
|
||||
"unit" : relation(Unit),
|
||||
"ID" : synonym("attributeID"),
|
||||
"name" : synonym("attributeName"),
|
||||
"description": deferred(attributes_table.c.description)
|
||||
"description": deferred(attributes_table.c.description),
|
||||
})
|
||||
|
||||
Attribute.ID = association_proxy("info", "attributeID")
|
||||
Attribute.name = association_proxy("info", "attributeName")
|
||||
Attribute.description = association_proxy("info", "description")
|
||||
Attribute.published = association_proxy("info", "published")
|
||||
Attribute.displayName = association_proxy("info", "displayName")
|
||||
Attribute.displayName = association_proxy("info", "displayName{}".format(eos.config.lang))
|
||||
Attribute.highIsGood = association_proxy("info", "highIsGood")
|
||||
Attribute.iconID = association_proxy("info", "iconID")
|
||||
Attribute.icon = association_proxy("info", "icon")
|
||||
|
||||
@@ -22,17 +22,18 @@ from sqlalchemy.orm import deferred, mapper, synonym
|
||||
|
||||
from eos.db import gamedata_meta
|
||||
from eos.gamedata import Category
|
||||
import eos.config
|
||||
|
||||
categories_table = Table("invcategories", gamedata_meta,
|
||||
Column("categoryID", Integer, primary_key=True),
|
||||
Column("categoryName", String),
|
||||
Column("description", String),
|
||||
*[Column("name{}".format(lang), String) for lang in eos.config.translation_mapping.values()],
|
||||
# Column("description", String), # deprecated
|
||||
Column("published", Boolean),
|
||||
Column("iconID", Integer))
|
||||
|
||||
mapper(Category, categories_table,
|
||||
properties={
|
||||
"ID" : synonym("categoryID"),
|
||||
"name" : synonym("categoryName"),
|
||||
"description": deferred(categories_table.c.description)
|
||||
"displayName": synonym("name{}".format(eos.config.lang)),
|
||||
# "description": deferred(categories_table.c.description) # deprecated
|
||||
})
|
||||
|
||||
@@ -22,11 +22,12 @@ from sqlalchemy.orm import relation, mapper, synonym, deferred, backref
|
||||
|
||||
from eos.db import gamedata_meta
|
||||
from eos.gamedata import Category, Group
|
||||
import eos.config
|
||||
|
||||
groups_table = Table("invgroups", gamedata_meta,
|
||||
Column("groupID", Integer, primary_key=True),
|
||||
Column("groupName", String),
|
||||
Column("description", String),
|
||||
*[Column("name{}".format(lang), String) for lang in eos.config.translation_mapping.values()],
|
||||
# Column("description", String), # deprecated
|
||||
Column("published", Boolean),
|
||||
Column("categoryID", Integer, ForeignKey("invcategories.categoryID")),
|
||||
Column("iconID", Integer))
|
||||
@@ -35,6 +36,6 @@ mapper(Group, groups_table,
|
||||
properties={
|
||||
"category" : relation(Category, backref=backref("groups", cascade="all,delete")),
|
||||
"ID" : synonym("groupID"),
|
||||
"name" : synonym("groupName"),
|
||||
"description": deferred(groups_table.c.description)
|
||||
"displayName" : synonym("name{}".format(eos.config.lang)),
|
||||
# "description": deferred(groups_table.c.description) # deprecated
|
||||
})
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
# ===============================================================================
|
||||
|
||||
from sqlalchemy import Boolean, Column, Float, ForeignKey, Integer, String, Table
|
||||
from sqlalchemy import Boolean, Column, ForeignKey, Integer, String, Table
|
||||
from sqlalchemy.ext.associationproxy import association_proxy
|
||||
from sqlalchemy.orm import backref, deferred, mapper, relation, synonym
|
||||
from sqlalchemy.orm.collections import attribute_mapped_collection
|
||||
@@ -27,10 +27,12 @@ from eos.db.gamedata.dynamicAttributes import dynamicApplicable_table
|
||||
from eos.db.gamedata.effect import typeeffects_table
|
||||
from eos.gamedata import Attribute, DynamicItem, Effect, Group, Item, Traits, MetaGroup
|
||||
|
||||
import eos.config
|
||||
|
||||
items_table = Table("invtypes", gamedata_meta,
|
||||
Column("typeID", Integer, primary_key=True),
|
||||
Column("typeName", String, index=True),
|
||||
Column("description", String),
|
||||
*[Column("typeName{}".format(lang), String, index=True) for lang in eos.config.translation_mapping.values()],
|
||||
*[Column("typeDescription{}".format(lang), String) for lang in eos.config.translation_mapping.values()],
|
||||
Column("raceID", Integer),
|
||||
Column("factionID", Integer),
|
||||
Column("published", Boolean),
|
||||
@@ -43,27 +45,38 @@ items_table = Table("invtypes", gamedata_meta,
|
||||
Column("variationParentTypeID", Integer, ForeignKey("invtypes.typeID"), index=True),
|
||||
Column("replacements", String),
|
||||
Column("reqskills", String),
|
||||
Column("requiredfor", String))
|
||||
Column("requiredfor", String),
|
||||
)
|
||||
|
||||
from .traits import traits_table # noqa
|
||||
|
||||
mapper(Item, items_table,
|
||||
properties={
|
||||
"group" : relation(Group, backref=backref("items", cascade="all,delete")),
|
||||
props = {
|
||||
"group": relation(Group, backref=backref("items", cascade="all,delete")),
|
||||
"_Item__attributes": relation(Attribute, cascade='all, delete, delete-orphan', collection_class=attribute_mapped_collection('name')),
|
||||
"effects": relation(Effect, secondary=typeeffects_table, collection_class=attribute_mapped_collection('name')),
|
||||
"metaGroup" : relation(MetaGroup, backref=backref("items", cascade="all,delete")),
|
||||
"varParent" : relation(Item, backref=backref("varChildren", cascade="all,delete"), remote_side=items_table.c.typeID),
|
||||
"ID" : synonym("typeID"),
|
||||
"name" : synonym("typeName"),
|
||||
"description" : deferred(items_table.c.description),
|
||||
"traits" : relation(Traits,
|
||||
primaryjoin=traits_table.c.typeID == items_table.c.typeID,
|
||||
uselist=False),
|
||||
"mutaplasmids": relation(DynamicItem,
|
||||
primaryjoin=dynamicApplicable_table.c.applicableTypeID == items_table.c.typeID,
|
||||
secondaryjoin=dynamicApplicable_table.c.typeID == DynamicItem.typeID,
|
||||
secondary=dynamicApplicable_table,
|
||||
backref="applicableItems")})
|
||||
"metaGroup": relation(MetaGroup, backref=backref("items", cascade="all,delete")),
|
||||
"varParent": relation(Item, backref=backref("varChildren", cascade="all,delete"), remote_side=items_table.c.typeID),
|
||||
"ID": synonym("typeID"),
|
||||
"name": synonym("typeName{}".format(eos.config.lang)),
|
||||
"description" : synonym("_description{}".format(eos.config.lang)),
|
||||
"traits": relation(
|
||||
Traits,
|
||||
primaryjoin=traits_table.c.typeID == items_table.c.typeID,
|
||||
uselist=False
|
||||
),
|
||||
"mutaplasmids": relation(
|
||||
DynamicItem,
|
||||
primaryjoin=dynamicApplicable_table.c.applicableTypeID == items_table.c.typeID,
|
||||
secondaryjoin=dynamicApplicable_table.c.typeID == DynamicItem.typeID,
|
||||
secondary=dynamicApplicable_table,
|
||||
backref="applicableItems"
|
||||
)
|
||||
}
|
||||
|
||||
# Create deferred columns shadowing all the description fields. The literal `description` property will dynamically
|
||||
# be assigned as synonym to one of these
|
||||
props.update({'_description' + v: deferred(items_table.c['typeDescription' + v]) for (k, v) in eos.config.translation_mapping.items()})
|
||||
|
||||
mapper(Item, items_table, properties=props)
|
||||
|
||||
Item.category = association_proxy("group", "category")
|
||||
|
||||
@@ -22,22 +22,34 @@ from sqlalchemy.orm import relation, mapper, synonym, deferred
|
||||
|
||||
from eos.db import gamedata_meta
|
||||
from eos.gamedata import Item, MarketGroup
|
||||
import eos.config
|
||||
|
||||
marketgroups_table = Table("invmarketgroups", gamedata_meta,
|
||||
Column("marketGroupID", Integer, primary_key=True),
|
||||
Column("marketGroupName", String),
|
||||
Column("description", String),
|
||||
*[Column("marketGroupName{}".format(lang), String) for lang in eos.config.translation_mapping.values()],
|
||||
*[Column("marketGroupDescription{}".format(lang), String) for lang in eos.config.translation_mapping.values()],
|
||||
Column("hasTypes", Boolean),
|
||||
Column("parentGroupID", Integer,
|
||||
ForeignKey("invmarketgroups.marketGroupID", initially="DEFERRED", deferrable=True)),
|
||||
ForeignKey("invmarketgroups.marketGroupID", initially="DEFERRED", deferrable=True)),
|
||||
Column("iconID", Integer))
|
||||
|
||||
mapper(MarketGroup, marketgroups_table,
|
||||
properties={
|
||||
"items" : relation(Item, backref="marketGroup"),
|
||||
"parent" : relation(MarketGroup, backref="children",
|
||||
remote_side=[marketgroups_table.c.marketGroupID]),
|
||||
"ID" : synonym("marketGroupID"),
|
||||
"name" : synonym("marketGroupName"),
|
||||
"description": deferred(marketgroups_table.c.description)
|
||||
})
|
||||
props = {
|
||||
"items": relation(Item, backref="marketGroup"),
|
||||
"parent": relation(MarketGroup, backref="children", remote_side=[marketgroups_table.c.marketGroupID]),
|
||||
"ID": synonym("marketGroupID"),
|
||||
"name": synonym("marketGroupName{}".format(eos.config.lang)),
|
||||
"description": synonym("_description{}".format(eos.config.lang)),
|
||||
}
|
||||
|
||||
# Create deferred columns shadowing all the description fields. The literal `description` property will dynamically
|
||||
# be assigned as synonym to one of these
|
||||
# this is mostly here to allow the db_update to be language-agnostic
|
||||
# todo: determine if we ever use market group descriptions... can we just get with of these?
|
||||
props.update({'_description' + v: deferred(marketgroups_table.c['marketGroupDescription' + v]) for (k, v) in eos.config.translation_mapping.items()})
|
||||
|
||||
mapper(
|
||||
MarketGroup,
|
||||
marketgroups_table,
|
||||
properties=props
|
||||
)
|
||||
|
||||
|
||||
@@ -22,12 +22,20 @@ from sqlalchemy.orm import mapper, synonym
|
||||
|
||||
from eos.db import gamedata_meta
|
||||
from eos.gamedata import MetaGroup
|
||||
import eos.config
|
||||
|
||||
metagroups_table = Table("invmetagroups", gamedata_meta,
|
||||
Column("metaGroupID", Integer, primary_key=True),
|
||||
Column("metaGroupName", String))
|
||||
metagroups_table = Table(
|
||||
"invmetagroups",
|
||||
gamedata_meta,
|
||||
Column("metaGroupID", Integer, primary_key=True),
|
||||
*[Column("metaGroupName{}".format(lang), String) for lang in eos.config.translation_mapping.values()],
|
||||
)
|
||||
|
||||
mapper(MetaGroup, metagroups_table,
|
||||
properties={
|
||||
"ID" : synonym("metaGroupID"),
|
||||
"name": synonym("metaGroupName")})
|
||||
mapper(
|
||||
MetaGroup,
|
||||
metagroups_table,
|
||||
properties={
|
||||
"ID" : synonym("metaGroupID"),
|
||||
"name": synonym("metaGroupName{}".format(eos.config.lang))
|
||||
}
|
||||
)
|
||||
|
||||
@@ -91,7 +91,7 @@ def getItem(lookfor, eager=None):
|
||||
item = get_gamedata_session().query(Item).options(*processEager(eager)).filter(Item.ID == id).first()
|
||||
else:
|
||||
# Item names are unique, so we can use first() instead of one()
|
||||
item = get_gamedata_session().query(Item).options(*processEager(eager)).filter(Item.name == lookfor).first()
|
||||
item = get_gamedata_session().query(Item).options(*processEager(eager)).filter(Item.typeName == lookfor).first()
|
||||
if item is not None:
|
||||
itemNameMap[lookfor] = item.ID
|
||||
else:
|
||||
@@ -265,7 +265,7 @@ def getMetaGroup(lookfor, eager=None):
|
||||
else:
|
||||
# MetaGroup names are unique, so we can use first() instead of one()
|
||||
metaGroup = get_gamedata_session().query(MetaGroup).options(*processEager(eager)).filter(
|
||||
MetaGroup.name == lookfor).first()
|
||||
MetaGroup.metaGroupName == lookfor).first()
|
||||
if metaGroup is not None:
|
||||
metaGroupNameMap[lookfor] = metaGroup.ID
|
||||
else:
|
||||
|
||||
@@ -1,11 +1,21 @@
|
||||
from sqlalchemy import Column, Table, Integer, String, ForeignKey
|
||||
from sqlalchemy.orm import mapper
|
||||
from sqlalchemy.orm import mapper, synonym
|
||||
|
||||
from eos.db import gamedata_meta
|
||||
from eos.gamedata import Traits
|
||||
import eos.config
|
||||
|
||||
traits_table = Table("invtraits", gamedata_meta,
|
||||
Column("typeID", Integer, ForeignKey("invtypes.typeID"), primary_key=True),
|
||||
Column("traitText", String))
|
||||
traits_table = Table(
|
||||
"invtraits",
|
||||
gamedata_meta,
|
||||
Column("typeID", Integer, ForeignKey("invtypes.typeID"), primary_key=True),
|
||||
*[Column("traitText{}".format(lang), String) for lang in eos.config.translation_mapping.values()],
|
||||
)
|
||||
|
||||
mapper(Traits, traits_table)
|
||||
mapper(
|
||||
Traits,
|
||||
traits_table,
|
||||
properties={
|
||||
"display": synonym("traitText{}".format(eos.config.lang)),
|
||||
}
|
||||
)
|
||||
|
||||
@@ -22,11 +22,13 @@ from sqlalchemy.orm import mapper, synonym
|
||||
|
||||
from eos.db import gamedata_meta
|
||||
from eos.gamedata import Unit
|
||||
import eos.config
|
||||
|
||||
groups_table = Table("dgmunits", gamedata_meta,
|
||||
Column("unitID", Integer, primary_key=True),
|
||||
Column("unitName", String),
|
||||
Column("displayName", String))
|
||||
*[Column("displayName{}".format(lang), String) for lang in eos.config.translation_mapping.values()],
|
||||
)
|
||||
|
||||
mapper(Unit, groups_table,
|
||||
properties={
|
||||
|
||||
25
eos/db/migrations/upgrade44.py
Normal file
25
eos/db/migrations/upgrade44.py
Normal file
@@ -0,0 +1,25 @@
|
||||
"""
|
||||
Migration 44
|
||||
|
||||
- Signal distortion amplifier tiericide
|
||||
"""
|
||||
|
||||
CONVERSIONS = {
|
||||
25565: ( # Hypnos Compact Signal Distortion Amplifier I
|
||||
25571, # Initiated Signal Distortion Amplifier I
|
||||
25569, # Induced Signal Distortion Amplifier I
|
||||
25567, # Compulsive Signal Distortion Amplifier I
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
def upgrade(saveddata_engine):
|
||||
# Convert modules
|
||||
for replacement_item, list in CONVERSIONS.items():
|
||||
for retired_item in list:
|
||||
saveddata_engine.execute('UPDATE "modules" SET "itemID" = ? WHERE "itemID" = ?',
|
||||
(replacement_item, retired_item))
|
||||
saveddata_engine.execute('UPDATE "modules" SET "baseItemID" = ? WHERE "baseItemID" = ?',
|
||||
(replacement_item, retired_item))
|
||||
saveddata_engine.execute('UPDATE "cargo" SET "itemID" = ? WHERE "itemID" = ?',
|
||||
(replacement_item, retired_item))
|
||||
18
eos/db/migrations/upgrade45.py
Normal file
18
eos/db/migrations/upgrade45.py
Normal file
@@ -0,0 +1,18 @@
|
||||
"""
|
||||
Migration 45
|
||||
|
||||
- Drone mutaplasmid support
|
||||
"""
|
||||
|
||||
import sqlalchemy
|
||||
|
||||
|
||||
def upgrade(saveddata_engine):
|
||||
try:
|
||||
saveddata_engine.execute("SELECT baseItemID FROM drones LIMIT 1")
|
||||
except sqlalchemy.exc.DatabaseError:
|
||||
saveddata_engine.execute("ALTER TABLE drones ADD COLUMN baseItemID INTEGER;")
|
||||
try:
|
||||
saveddata_engine.execute("SELECT mutaplasmidID FROM drones LIMIT 1")
|
||||
except sqlalchemy.exc.DatabaseError:
|
||||
saveddata_engine.execute("ALTER TABLE drones ADD COLUMN mutaplasmidID INTEGER;")
|
||||
@@ -1,7 +1,8 @@
|
||||
__all__ = [
|
||||
"character",
|
||||
"fit",
|
||||
"mutator",
|
||||
"mutatorMod",
|
||||
"mutatorDrone",
|
||||
"module",
|
||||
"user",
|
||||
"skill",
|
||||
|
||||
@@ -24,11 +24,12 @@ import datetime
|
||||
from eos.db import saveddata_meta
|
||||
from eos.saveddata.booster import Booster
|
||||
from eos.saveddata.boosterSideEffect import BoosterSideEffect
|
||||
from eos.saveddata.fit import Fit
|
||||
|
||||
boosters_table = Table("boosters", saveddata_meta,
|
||||
Column("ID", Integer, primary_key=True),
|
||||
Column("itemID", Integer),
|
||||
Column("fitID", Integer, ForeignKey("fits.ID"), nullable=False),
|
||||
Column("fitID", Integer, ForeignKey("fits.ID"), nullable=False, index=True),
|
||||
Column("active", Boolean),
|
||||
Column("created", DateTime, nullable=True, default=datetime.datetime.now),
|
||||
Column("modified", DateTime, nullable=True, onupdate=datetime.datetime.now),
|
||||
@@ -44,6 +45,7 @@ booster_side_effect_table = Table("boosterSideEffects", saveddata_meta,
|
||||
|
||||
mapper(Booster, boosters_table,
|
||||
properties={
|
||||
"owner": relation(Fit),
|
||||
"_Booster__sideEffects": relation(
|
||||
BoosterSideEffect,
|
||||
backref="booster",
|
||||
|
||||
@@ -18,27 +18,35 @@
|
||||
# ===============================================================================
|
||||
|
||||
from sqlalchemy import Table, Column, Integer, Float, ForeignKey, Boolean, DateTime
|
||||
from sqlalchemy.orm import mapper, relation
|
||||
from sqlalchemy.orm import mapper, relation, synonym
|
||||
from sqlalchemy.orm.collections import attribute_mapped_collection
|
||||
import datetime
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.saveddata.drone import Drone
|
||||
from eos.saveddata.fit import Fit
|
||||
from eos.saveddata.mutator import MutatorDrone
|
||||
|
||||
drones_table = Table("drones", saveddata_meta,
|
||||
Column("groupID", Integer, primary_key=True),
|
||||
Column("fitID", Integer, ForeignKey("fits.ID"), nullable=False, index=True),
|
||||
Column("itemID", Integer, nullable=False),
|
||||
Column("baseItemID", Integer, nullable=True),
|
||||
Column("mutaplasmidID", Integer, nullable=True),
|
||||
Column("amount", Integer, nullable=False),
|
||||
Column("amountActive", Integer, nullable=False),
|
||||
Column("projected", Boolean, default=False),
|
||||
Column("created", DateTime, nullable=True, default=datetime.datetime.now),
|
||||
Column("modified", DateTime, nullable=True, onupdate=datetime.datetime.now),
|
||||
Column("projectionRange", Float, nullable=True)
|
||||
)
|
||||
Column("projectionRange", Float, nullable=True))
|
||||
|
||||
|
||||
mapper(Drone, drones_table,
|
||||
properties={
|
||||
"owner": relation(Fit)
|
||||
}
|
||||
)
|
||||
"ID": synonym("groupID"),
|
||||
"owner": relation(Fit),
|
||||
"mutators": relation(
|
||||
MutatorDrone,
|
||||
backref="item",
|
||||
cascade="all,delete-orphan",
|
||||
collection_class=attribute_mapped_collection('attrID'))})
|
||||
|
||||
@@ -191,7 +191,6 @@ mapper(es_Fit, fits_table,
|
||||
Booster,
|
||||
collection_class=HandledBoosterList,
|
||||
cascade='all, delete, delete-orphan',
|
||||
backref='owner',
|
||||
single_parent=True),
|
||||
"_Fit__drones": relation(
|
||||
Drone,
|
||||
|
||||
@@ -18,14 +18,14 @@
|
||||
# ===============================================================================
|
||||
|
||||
from sqlalchemy import Table, Column, Integer, Float, ForeignKey, CheckConstraint, Boolean, DateTime
|
||||
from sqlalchemy.orm.collections import attribute_mapped_collection
|
||||
from sqlalchemy.orm import relation, mapper
|
||||
from sqlalchemy.orm.collections import attribute_mapped_collection
|
||||
import datetime
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.saveddata.module import Module
|
||||
from eos.saveddata.mutator import Mutator
|
||||
from eos.saveddata.fit import Fit
|
||||
from eos.saveddata.mutator import MutatorModule
|
||||
|
||||
modules_table = Table("modules", saveddata_meta,
|
||||
Column("ID", Integer, primary_key=True),
|
||||
@@ -45,13 +45,12 @@ modules_table = Table("modules", saveddata_meta,
|
||||
Column("projectionRange", Float, nullable=True),
|
||||
CheckConstraint('("dummySlot" = NULL OR "itemID" = NULL) AND "dummySlot" != "itemID"'))
|
||||
|
||||
|
||||
mapper(Module, modules_table,
|
||||
properties={
|
||||
"owner": relation(Fit),
|
||||
"mutators": relation(
|
||||
Mutator,
|
||||
backref="module",
|
||||
MutatorModule,
|
||||
backref="item",
|
||||
cascade="all,delete-orphan",
|
||||
collection_class=attribute_mapped_collection('attrID')
|
||||
)
|
||||
})
|
||||
collection_class=attribute_mapped_collection('attrID'))})
|
||||
|
||||
@@ -23,13 +23,14 @@ from sqlalchemy import Column, DateTime, Float, ForeignKey, Integer, Table
|
||||
from sqlalchemy.orm import mapper
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.saveddata.mutator import Mutator
|
||||
from eos.saveddata.mutator import MutatorDrone
|
||||
|
||||
mutator_table = Table("mutators", saveddata_meta,
|
||||
Column("moduleID", Integer, ForeignKey("modules.ID"), primary_key=True, index=True),
|
||||
Column("attrID", Integer, primary_key=True, index=True),
|
||||
Column("value", Float, nullable=False),
|
||||
Column("created", DateTime, nullable=True, default=datetime.datetime.now),
|
||||
Column("modified", DateTime, nullable=True, onupdate=datetime.datetime.now))
|
||||
mutatorDrones_table = Table(
|
||||
"mutatorsDrones", saveddata_meta,
|
||||
Column("groupID", Integer, ForeignKey("drones.groupID"), primary_key=True, index=True),
|
||||
Column("attrID", Integer, primary_key=True, index=True),
|
||||
Column("value", Float, nullable=False),
|
||||
Column("created", DateTime, nullable=True, default=datetime.datetime.now),
|
||||
Column("modified", DateTime, nullable=True, onupdate=datetime.datetime.now))
|
||||
|
||||
mapper(Mutator, mutator_table)
|
||||
mapper(MutatorDrone, mutatorDrones_table)
|
||||
36
eos/db/saveddata/mutatorMod.py
Normal file
36
eos/db/saveddata/mutatorMod.py
Normal file
@@ -0,0 +1,36 @@
|
||||
# ===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
#
|
||||
# eos is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# eos 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
# ===============================================================================
|
||||
|
||||
import datetime
|
||||
|
||||
from sqlalchemy import Column, DateTime, Float, ForeignKey, Integer, Table
|
||||
from sqlalchemy.orm import mapper
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.saveddata.mutator import MutatorModule
|
||||
|
||||
mutatorMods_table = Table(
|
||||
"mutators", saveddata_meta,
|
||||
Column("moduleID", Integer, ForeignKey("modules.ID"), primary_key=True, index=True),
|
||||
Column("attrID", Integer, primary_key=True, index=True),
|
||||
Column("value", Float, nullable=False),
|
||||
Column("created", DateTime, nullable=True, default=datetime.datetime.now),
|
||||
Column("modified", DateTime, nullable=True, onupdate=datetime.datetime.now))
|
||||
|
||||
mapper(MutatorModule, mutatorMods_table)
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
|
||||
from logbook import Logger
|
||||
from sqlalchemy.orm.attributes import flag_dirty
|
||||
from sqlalchemy.orm.collections import collection
|
||||
|
||||
|
||||
@@ -108,10 +109,7 @@ class HandledList(list):
|
||||
|
||||
def remove(self, thing):
|
||||
# We must flag it as modified, otherwise it not be removed from the database
|
||||
# @todo: flag_modified isn't in os x skel. need to rebuild to include
|
||||
# flag_modified(thing, "itemID")
|
||||
if thing.isInvalid: # see GH issue #324
|
||||
thing.itemID = 0
|
||||
flag_dirty(thing)
|
||||
list.remove(self, thing)
|
||||
|
||||
def sort(self, *args, **kwargs):
|
||||
|
||||
1808
eos/effects.py
1808
eos/effects.py
File diff suppressed because it is too large
Load Diff
@@ -19,7 +19,7 @@
|
||||
|
||||
|
||||
import json
|
||||
from collections import OrderedDict
|
||||
import re
|
||||
|
||||
from logbook import Logger
|
||||
from sqlalchemy.orm import reconstructor
|
||||
@@ -33,6 +33,10 @@ from .eqBase import EqBase
|
||||
pyfalog = Logger(__name__)
|
||||
|
||||
|
||||
def _t(x):
|
||||
return x
|
||||
|
||||
|
||||
class Effect(EqBase):
|
||||
"""
|
||||
The effect handling class, it is used to proxy and load effect handler code,
|
||||
@@ -245,6 +249,10 @@ class Item(EqBase):
|
||||
pass
|
||||
return shortName
|
||||
|
||||
@property
|
||||
def customName(self):
|
||||
return re.sub(_t('Caustic'), _t('Tachyon'), self.name)
|
||||
|
||||
@property
|
||||
def attributes(self):
|
||||
return self.__attributes
|
||||
@@ -344,7 +352,7 @@ class Item(EqBase):
|
||||
|
||||
try:
|
||||
if (
|
||||
self.category.categoryName == 'Structure' or
|
||||
self.category.name == 'Structure' or
|
||||
# Here until CCP puts their shit together
|
||||
self.name in ("Thunderchild", "Stormbringer", "Skybreaker")
|
||||
):
|
||||
@@ -423,7 +431,7 @@ class Item(EqBase):
|
||||
def requiresSkill(self, skill, level=None):
|
||||
for s, l in self.requiredSkills.items():
|
||||
if isinstance(skill, str):
|
||||
if s.name == skill and (level is None or l == level):
|
||||
if s.typeName == skill and (level is None or l == level):
|
||||
return True
|
||||
|
||||
elif isinstance(skill, int) and (level is None or l == level):
|
||||
@@ -481,6 +489,10 @@ class Item(EqBase):
|
||||
def isCharge(self):
|
||||
return self.category.name == 'Charge'
|
||||
|
||||
@property
|
||||
def isCommodity(self):
|
||||
return self.category.name == 'Commodity'
|
||||
|
||||
@property
|
||||
def isDrone(self):
|
||||
return self.category.name == 'Drone'
|
||||
@@ -506,8 +518,8 @@ class Item(EqBase):
|
||||
return False
|
||||
|
||||
def __repr__(self):
|
||||
return "Item(ID={}, name={}) at {}".format(
|
||||
self.ID, self.name, hex(id(self))
|
||||
return "Item(ID={}, name={}, display={}) at {}".format(
|
||||
self.ID, self.typeName, self.name, hex(id(self))
|
||||
)
|
||||
|
||||
|
||||
@@ -555,7 +567,18 @@ class Group(EqBase):
|
||||
|
||||
|
||||
class DynamicItem(EqBase):
|
||||
pass
|
||||
|
||||
@property
|
||||
def shortName(self):
|
||||
name = self.item.customName
|
||||
keywords = ('Decayed', 'Gravid', 'Unstable', 'Radical')
|
||||
for kw in keywords:
|
||||
if name.startswith(f'{kw} '):
|
||||
name = kw
|
||||
m = re.match('(?P<mutagrade>\S+) (?P<dronetype>\S+) Drone (?P<mutatype>\S+) Mutaplasmid', name)
|
||||
if m:
|
||||
name = '{} {}'.format(m.group('mutagrade'), m.group('mutatype'))
|
||||
return name
|
||||
|
||||
|
||||
class DynamicItemAttribute(EqBase):
|
||||
|
||||
@@ -159,6 +159,6 @@ class Booster(HandledItem, ItemAttrShortcut):
|
||||
sideEffect.active = sideEffectStates[sideEffect.effectID]
|
||||
|
||||
def __repr__(self):
|
||||
return "Booster(ID={}, name={}) at {}".format(
|
||||
self.item.ID, self.item.name, hex(id(self))
|
||||
)
|
||||
if self.item is not None:
|
||||
return f"Booster(ID={self.item.ID}, name={self.item.name}) at {hex(id(self))}"
|
||||
return f"Booster(ID={self.itemID}) at {hex(id(self))}"
|
||||
|
||||
@@ -96,7 +96,7 @@ class Character:
|
||||
if cls.__itemNameMap is None:
|
||||
map = {}
|
||||
for skill in cls.getSkillList():
|
||||
map[skill.name] = skill
|
||||
map[skill.typeName] = skill
|
||||
|
||||
cls.__itemNameMap = map
|
||||
|
||||
|
||||
@@ -25,122 +25,143 @@ from sqlalchemy.orm import reconstructor
|
||||
import eos.db
|
||||
|
||||
|
||||
def _t(x):
|
||||
return x
|
||||
|
||||
|
||||
def _c(x):
|
||||
return '[' + x + ']'
|
||||
|
||||
|
||||
# Order is significant here - UI uses order as-is for built-in patterns
|
||||
BUILTINS = OrderedDict([
|
||||
(-1, ('Uniform', 25, 25, 25, 25)),
|
||||
(-2, ('[Generic]EM', 1, 0, 0, 0)),
|
||||
(-3, ('[Generic]Thermal', 0, 1, 0, 0)),
|
||||
(-4, ('[Generic]Kinetic', 0, 0, 1, 0)),
|
||||
(-5, ('[Generic]Explosive', 0, 0, 0, 1)),
|
||||
(-6, ('[Frequency Crystals]|[T2] Aurora', 5, 3, 0, 0)),
|
||||
(-7, ('[Frequency Crystals]|[T2] Scorch', 9, 2, 0, 0)),
|
||||
(-8, ('[Frequency Crystals]Radio', 5, 0, 0, 0)),
|
||||
(-9, ('[Frequency Crystals]Microwave', 4, 2, 0, 0)),
|
||||
(-10, ('[Frequency Crystals]Infrared', 5, 2, 0, 0)),
|
||||
(-11, ('[Frequency Crystals]Standard', 5, 3, 0, 0)),
|
||||
(-12, ('[Frequency Crystals]Ultraviolet', 6, 3, 0, 0)),
|
||||
(-13, ('[Frequency Crystals]Xray', 6, 4, 0, 0)),
|
||||
(-14, ('[Frequency Crystals]Gamma', 7, 4, 0, 0)),
|
||||
(-15, ('[Frequency Crystals]Multifrequency', 7, 5, 0, 0)),
|
||||
(-16, ('[Frequency Crystals]|[T2] Gleam', 7, 7, 0, 0)),
|
||||
(-17, ('[Frequency Crystals]|[T2] Conflagration', 7.7, 7.7, 0, 0)),
|
||||
(-1, (_t('Uniform'), 25, 25, 25, 25)),
|
||||
(-2, (_c(_t('Generic')) + _t('EM'), 1, 0, 0, 0)),
|
||||
(-3, (_c(_t('Generic')) + _t('Thermal'), 0, 1, 0, 0)),
|
||||
(-4, (_c(_t('Generic')) + _t('Kinetic'), 0, 0, 1, 0)),
|
||||
(-5, (_c(_t('Generic')) + _t('Explosive'), 0, 0, 0, 1)),
|
||||
(-6, (_c(_t('Frequency Crystals')) + '|' + _t('[T2] Aurora'), 5, 3, 0, 0)),
|
||||
(-7, (_c(_t('Frequency Crystals')) + '|' + _t('[T2] Scorch'), 9, 2, 0, 0)),
|
||||
(-8, (_c(_t('Frequency Crystals')) + _t('Radio'), 5, 0, 0, 0)),
|
||||
(-9, (_c(_t('Frequency Crystals')) + _t('Microwave'), 4, 2, 0, 0)),
|
||||
(-10, (_c(_t('Frequency Crystals')) + _t('Infrared'), 5, 2, 0, 0)),
|
||||
(-11, (_c(_t('Frequency Crystals')) + _t('Standard'), 5, 3, 0, 0)),
|
||||
(-12, (_c(_t('Frequency Crystals')) + _t('Ultraviolet'), 6, 3, 0, 0)),
|
||||
(-13, (_c(_t('Frequency Crystals')) + _t('Xray'), 6, 4, 0, 0)),
|
||||
(-14, (_c(_t('Frequency Crystals')) + _t('Gamma'), 7, 4, 0, 0)),
|
||||
(-15, (_c(_t('Frequency Crystals')) + _t('Multifrequency'), 7, 5, 0, 0)),
|
||||
(-16, (_c(_t('Frequency Crystals')) + '|' + _t('[T2] Gleam'), 7, 7, 0, 0)),
|
||||
(-17, (_c(_t('Frequency Crystals')) + '|' + _t('[T2] Conflagration'), 7.7, 7.7, 0, 0)),
|
||||
# Different sizes of plasma do different damage ratios, the values here
|
||||
# are average of ratios across sizes
|
||||
(-18, ('[Exotic Plasma]|[T2] Mystic', 0, 66319, 0, 33681)),
|
||||
(-19, ('[Exotic Plasma]Meson', 0, 60519, 0, 39481)),
|
||||
(-20, ('[Exotic Plasma]Baryon', 0, 59737, 0, 40263)),
|
||||
(-21, ('[Exotic Plasma]Tetryon', 0, 69208, 0, 30792)),
|
||||
(-22, ('[Exotic Plasma]|[T2] Occult', 0, 55863, 0, 44137)),
|
||||
(-23, ('[Hybrid Charges]|[T2] Spike', 0, 4, 4, 0)),
|
||||
(-24, ('[Hybrid Charges]|[T2] Null', 0, 6, 5, 0)),
|
||||
(-25, ('[Hybrid Charges]Iron', 0, 2, 3, 0)),
|
||||
(-26, ('[Hybrid Charges]Tungsten', 0, 2, 4, 0)),
|
||||
(-27, ('[Hybrid Charges]Iridium', 0, 3, 4, 0)),
|
||||
(-28, ('[Hybrid Charges]Lead', 0, 3, 5, 0)),
|
||||
(-29, ('[Hybrid Charges]Thorium', 0, 4, 5, 0)),
|
||||
(-30, ('[Hybrid Charges]Uranium', 0, 4, 6, 0)),
|
||||
(-31, ('[Hybrid Charges]Plutonium', 0, 5, 6, 0)),
|
||||
(-32, ('[Hybrid Charges]Antimatter', 0, 5, 7, 0)),
|
||||
(-33, ('[Hybrid Charges]|[T2] Javelin', 0, 8, 6, 0)),
|
||||
(-34, ('[Hybrid Charges]|[T2] Void', 0, 7.7, 7.7, 0)),
|
||||
(-35, ('[Projectile Ammo]|[T2] Tremor', 0, 0, 3, 5)),
|
||||
(-36, ('[Projectile Ammo]|[T2] Barrage', 0, 0, 5, 6)),
|
||||
(-37, ('[Projectile Ammo]Carbonized Lead', 0, 0, 4, 1)),
|
||||
(-38, ('[Projectile Ammo]Nuclear', 0, 0, 1, 4)),
|
||||
(-39, ('[Projectile Ammo]Proton', 3, 0, 2, 0)),
|
||||
(-40, ('[Projectile Ammo]Depleted Uranium', 0, 3, 2, 3)),
|
||||
(-41, ('[Projectile Ammo]Titanium Sabot', 0, 0, 6, 2)),
|
||||
(-42, ('[Projectile Ammo]EMP', 9, 0, 1, 2)),
|
||||
(-43, ('[Projectile Ammo]Phased Plasma', 0, 10, 2, 0)),
|
||||
(-44, ('[Projectile Ammo]Fusion', 0, 0, 2, 10)),
|
||||
(-45, ('[Projectile Ammo]|[T2] Quake', 0, 0, 5, 9)),
|
||||
(-46, ('[Projectile Ammo]|[T2] Hail', 0, 0, 3.3, 12.1)),
|
||||
(-47, ('[Missiles]Mjolnir', 1, 0, 0, 0)),
|
||||
(-48, ('[Missiles]Inferno', 0, 1, 0, 0)),
|
||||
(-49, ('[Missiles]Scourge', 0, 0, 1, 0)),
|
||||
(-50, ('[Missiles]Nova', 0, 0, 0, 1)),
|
||||
(-51, ('[Bombs]Electron Bomb', 6400, 0, 0, 0)),
|
||||
(-52, ('[Bombs]Scorch Bomb', 0, 6400, 0, 0)),
|
||||
(-53, ('[Bombs]Concussion Bomb', 0, 0, 6400, 0)),
|
||||
(-54, ('[Bombs]Shrapnel Bomb', 0, 0, 0, 6400)),
|
||||
(-18, (_c(_t('Exotic Plasma')) + '|' + _t('[T2] Mystic'), 0, 66319, 0, 33681)),
|
||||
(-19, (_c(_t('Exotic Plasma')) + _t('Meson'), 0, 60519, 0, 39481)),
|
||||
(-20, (_c(_t('Exotic Plasma')) + _t('Baryon'), 0, 59737, 0, 40263)),
|
||||
(-21, (_c(_t('Exotic Plasma')) + _t('Tetryon'), 0, 69208, 0, 30792)),
|
||||
(-22, (_c(_t('Exotic Plasma')) + '|' + _t('[T2] Occult'), 0, 55863, 0, 44137)),
|
||||
(-23, (_c(_t('Hybrid Charges')) + '|' + _t('[T2] Spike'), 0, 4, 4, 0)),
|
||||
(-24, (_c(_t('Hybrid Charges')) + '|' + _t('[T2] Null'), 0, 6, 5, 0)),
|
||||
(-25, (_c(_t('Hybrid Charges')) + _t('Iron'), 0, 2, 3, 0)),
|
||||
(-26, (_c(_t('Hybrid Charges')) + _t('Tungsten'), 0, 2, 4, 0)),
|
||||
(-27, (_c(_t('Hybrid Charges')) + _t('Iridium'), 0, 3, 4, 0)),
|
||||
(-28, (_c(_t('Hybrid Charges')) + _t('Lead'), 0, 3, 5, 0)),
|
||||
(-29, (_c(_t('Hybrid Charges')) + _t('Thorium'), 0, 4, 5, 0)),
|
||||
(-30, (_c(_t('Hybrid Charges')) + _t('Uranium'), 0, 4, 6, 0)),
|
||||
(-31, (_c(_t('Hybrid Charges')) + _t('Plutonium'), 0, 5, 6, 0)),
|
||||
(-32, (_c(_t('Hybrid Charges')) + _t('Antimatter'), 0, 5, 7, 0)),
|
||||
(-33, (_c(_t('Hybrid Charges')) + '|' + _t('[T2] Javelin'), 0, 8, 6, 0)),
|
||||
(-34, (_c(_t('Hybrid Charges')) + '|' + _t('[T2] Void'), 0, 7.7, 7.7, 0)),
|
||||
(-35, (_c(_t('Projectile Ammo')) + '|' + _t('[T2] Tremor'), 0, 0, 3, 5)),
|
||||
(-36, (_c(_t('Projectile Ammo')) + '|' + _t('[T2] Barrage'), 0, 0, 5, 6)),
|
||||
(-37, (_c(_t('Projectile Ammo')) + _t('Carbonized Lead'), 0, 0, 4, 1)),
|
||||
(-38, (_c(_t('Projectile Ammo')) + _t('Nuclear'), 0, 0, 1, 4)),
|
||||
(-39, (_c(_t('Projectile Ammo')) + _t('Proton'), 3, 0, 2, 0)),
|
||||
(-40, (_c(_t('Projectile Ammo')) + _t('Depleted Uranium'), 0, 3, 2, 3)),
|
||||
(-41, (_c(_t('Projectile Ammo')) + _t('Titanium Sabot'), 0, 0, 6, 2)),
|
||||
(-42, (_c(_t('Projectile Ammo')) + _t('EMP'), 9, 0, 1, 2)),
|
||||
(-43, (_c(_t('Projectile Ammo')) + _t('Phased Plasma'), 0, 10, 2, 0)),
|
||||
(-44, (_c(_t('Projectile Ammo')) + _t('Fusion'), 0, 0, 2, 10)),
|
||||
(-45, (_c(_t('Projectile Ammo')) + '|' + _t('[T2] Quake'), 0, 0, 5, 9)),
|
||||
(-46, (_c(_t('Projectile Ammo')) + '|' + _t('[T2] Hail'), 0, 0, 3.3, 12.1)),
|
||||
(-47, (_c(_t('Missiles')) + _t('Mjolnir'), 1, 0, 0, 0)),
|
||||
(-48, (_c(_t('Missiles')) + _t('Inferno'), 0, 1, 0, 0)),
|
||||
(-49, (_c(_t('Missiles')) + _t('Scourge'), 0, 0, 1, 0)),
|
||||
(-50, (_c(_t('Missiles')) + _t('Nova'), 0, 0, 0, 1)),
|
||||
(-51, (_c(_t('Bombs')) + _t('Electron Bomb'), 6400, 0, 0, 0)),
|
||||
(-52, (_c(_t('Bombs')) + _t('Scorch Bomb'), 0, 6400, 0, 0)),
|
||||
(-53, (_c(_t('Bombs')) + _t('Concussion Bomb'), 0, 0, 6400, 0)),
|
||||
(-54, (_c(_t('Bombs')) + _t('Shrapnel Bomb'), 0, 0, 0, 6400)),
|
||||
# Source: ticket #2067 and #2265
|
||||
(-55, (_c(_t('NPC')) + _c(_t('Abyssal')) + _t('All'), 126, 427, 218, 230)),
|
||||
(-109, (_c(_t('NPC')) + _c(_t('Abyssal')) + _t('Angel'), 450, 72, 80, 398)),
|
||||
(-107, (_c(_t('NPC')) + _c(_t('Abyssal')) + _t('Concord'), 53, 559, 94, 295)),
|
||||
(-56, (_c(_t('NPC')) + _c(_t('Abyssal')) + _t('Drifter'), 250, 250, 250, 250)),
|
||||
(-57, (_c(_t('NPC')) + _c(_t('Abyssal')) + _t('Drones'), 250, 250, 250, 250)),
|
||||
(-58, (_c(_t('NPC')) + _c(_t('Abyssal')) + _t('Overmind'), 0, 410, 590, 0)),
|
||||
(-108, (_c(_t('NPC')) + _c(_t('Abyssal')) + _t('Sansha'), 569, 431, 0, 0)),
|
||||
(-59, (_c(_t('NPC')) + _c(_t('Abyssal')) + _t('Seeker'), 402, 402, 98, 98)),
|
||||
(-60, (_c(_t('NPC')) + _c(_t('Abyssal')) + _t('Sleeper'), 313, 313, 187, 187)),
|
||||
(-61, (_c(_t('NPC')) + _c(_t('Abyssal')) + _t('Triglavian'), 0, 615, 0, 385)),
|
||||
(-62, (_c(_t('NPC')) + _c(_t('Asteroid')) + _t('Angel Cartel'), 1838, 562, 2215, 3838)),
|
||||
(-63, (_c(_t('NPC')) + _c(_t('Asteroid')) + _t('Blood Raiders'), 5067, 4214, 0, 0)),
|
||||
(-64, (_c(_t('NPC')) + _c(_t('Asteroid')) + _t('Guristas'), 0, 1828, 7413, 0)),
|
||||
(-65, (_c(_t('NPC')) + _c(_t('Asteroid')) + _t('Rogue Drone'), 394, 666, 1090, 1687)),
|
||||
(-66, (_c(_t('NPC')) + _c(_t('Asteroid')) + _t('Sanshas Nation'), 5586, 4112, 0, 0)),
|
||||
(-67, (_c(_t('NPC')) + _c(_t('Asteroid')) + _t('Serpentis'), 0, 5373, 4813, 0)),
|
||||
(-68, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Cruor (Blood Raiders)'), 90, 90, 0, 0)),
|
||||
(-69, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Dramiel (Angel)'), 55, 0, 20, 96)),
|
||||
(-70, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Daredevil (Serpentis)'), 0, 110, 154, 0)),
|
||||
(-71, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Succubus (Sanshas Nation)'), 135, 30, 0, 0)),
|
||||
(-72, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Worm (Guristas)'), 0, 0, 228, 0)),
|
||||
(-73, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Enyo'), 0, 147, 147, 0)),
|
||||
(-74, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Hawk'), 0, 0, 247, 0)),
|
||||
(-75, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Jaguar'), 36, 0, 50, 182)),
|
||||
(-76, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Vengeance'), 232, 0, 0, 0)),
|
||||
(-77, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Ashimmu (Blood Raiders)'), 260, 100, 0, 0)),
|
||||
(-78, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Talos'), 0, 413, 413, 0)),
|
||||
(-79, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Sentinel'), 0, 75, 0, 90)),
|
||||
(-80, (_c(_t('NPC')) + _c(_t('Deadspace')) + _t('Angel Cartel'), 369, 533, 1395, 3302)),
|
||||
(-81, (_c(_t('NPC')) + _c(_t('Deadspace')) + _t('Blood Raiders'), 6040, 5052, 10, 15)),
|
||||
(-82, (_c(_t('NPC')) + _c(_t('Deadspace')) + _t('Guristas'), 0, 1531, 9680, 0)),
|
||||
(-83, (_c(_t('NPC')) + _c(_t('Deadspace')) + _t('Rogue Drone'), 276, 1071, 1069, 871)),
|
||||
(-84, (_c(_t('NPC')) + _c(_t('Deadspace')) + _t('Sanshas Nation'), 3009, 2237, 0, 0)),
|
||||
(-85, (_c(_t('NPC')) + _c(_t('Deadspace')) + _t('Serpentis'), 0, 3110, 1929, 0)),
|
||||
# Source: ticket #2067
|
||||
(-55, ('[NPC][Abyssal]All', 130, 396, 258, 216)),
|
||||
(-56, ('[NPC][Abyssal]Drifter', 250, 250, 250, 250)),
|
||||
(-57, ('[NPC][Abyssal]Drones', 250, 250, 250, 250)),
|
||||
(-58, ('[NPC][Abyssal]Overmind', 0, 408, 592, 0)),
|
||||
(-59, ('[NPC][Abyssal]Seeker', 406, 406, 94, 94)),
|
||||
(-60, ('[NPC][Abyssal]Sleeper', 313, 313, 187, 187)),
|
||||
(-61, ('[NPC][Abyssal]Triglavian', 0, 610, 0, 390)),
|
||||
(-62, ('[NPC][Asteroid]Angel Cartel', 1838, 562, 2215, 3838)),
|
||||
(-63, ('[NPC][Asteroid]Blood Raiders', 5067, 4214, 0, 0)),
|
||||
(-64, ('[NPC][Asteroid]Guristas', 0, 1828, 7413, 0)),
|
||||
(-65, ('[NPC][Asteroid]Rogue Drone', 394, 666, 1090, 1687)),
|
||||
(-66, ('[NPC][Asteroid]Sanshas Nation', 5586, 4112, 0, 0)),
|
||||
(-67, ('[NPC][Asteroid]Serpentis', 0, 5373, 4813, 0)),
|
||||
(-68, ('[NPC][Burner]Cruor (Blood Raiders)', 90, 90, 0, 0)),
|
||||
(-69, ('[NPC][Burner]Dramiel (Angel)', 55, 0, 20, 96)),
|
||||
(-70, ('[NPC][Burner]Daredevil (Serpentis)', 0, 110, 154, 0)),
|
||||
(-71, ('[NPC][Burner]Succubus (Sanshas Nation)', 135, 30, 0, 0)),
|
||||
(-72, ('[NPC][Burner]Worm (Guristas)', 0, 0, 228, 0)),
|
||||
(-73, ('[NPC][Burner]Enyo', 0, 147, 147, 0)),
|
||||
(-74, ('[NPC][Burner]Hawk', 0, 0, 247, 0)),
|
||||
(-75, ('[NPC][Burner]Jaguar', 36, 0, 50, 182)),
|
||||
(-76, ('[NPC][Burner]Vengeance', 232, 0, 0, 0)),
|
||||
(-77, ('[NPC][Burner]Ashimmu (Blood Raiders)', 260, 100, 0, 0)),
|
||||
(-78, ('[NPC][Burner]Talos', 0, 413, 413, 0)),
|
||||
(-79, ('[NPC][Burner]Sentinel', 0, 75, 0, 90)),
|
||||
(-80, ('[NPC][Deadspace]Angel Cartel', 369, 533, 1395, 3302)),
|
||||
(-81, ('[NPC][Deadspace]Blood Raiders', 6040, 5052, 10, 15)),
|
||||
(-82, ('[NPC][Deadspace]Guristas', 0, 1531, 9680, 0)),
|
||||
(-83, ('[NPC][Deadspace]Rogue Drone', 276, 1071, 1069, 871)),
|
||||
(-84, ('[NPC][Deadspace]Sanshas Nation', 3009, 2237, 0, 0)),
|
||||
(-85, ('[NPC][Deadspace]Serpentis', 0, 3110, 1929, 0)),
|
||||
# Source: ticket #2067
|
||||
(-86, ('[NPC][Invasion][Invading Precursor Entities]Dread', 0, 417, 0, 583)),
|
||||
(-87, ('[NPC][Invasion][Invading Precursor Entities]Normal Subcaps', 0, 610, 0, 390)),
|
||||
(-88, ('[NPC][Invasion][Invading Precursor Entities]Subcaps w/missiles 0% spool up', 367, 155, 367, 112)),
|
||||
(-89, ('[NPC][Invasion][Invading Precursor Entities]Subcaps w/missiles 50% spool up', 291, 243, 291, 175)),
|
||||
(-90, ('[NPC][Invasion][Invading Precursor Entities]Subcaps w/missiles 100% spool up', 241, 301, 241, 217)),
|
||||
(-91, ('[NPC][Invasion][Retaliating Amarr Entities]Dread/Subcaps', 583, 417, 0, 0)),
|
||||
(-92, ('[NPC][Invasion][Retaliating Caldari Entities]Dread', 1000, 0, 0, 0)),
|
||||
(-93, ('[NPC][Invasion][Retaliating Caldari Entities]Subcaps', 511, 21, 29, 440)),
|
||||
(-94, ('[NPC][Invasion][Retaliating Gallente Entities]Dread/Subcaps', 0, 417, 583, 0)),
|
||||
(-95, ('[NPC][Invasion][Retaliating Minmatar Entities]Dread', 0, 0, 583, 417)),
|
||||
(-96, ('[NPC][Invasion][Retaliating Minmatar Entities]Subcaps', 302, 136, 328, 234)),
|
||||
(-97, ('[NPC][Mission]Amarr Empire', 4464, 3546, 97, 0)),
|
||||
(-98, ('[NPC][Mission]Caldari State', 0, 2139, 4867, 0)),
|
||||
(-99, ('[NPC][Mission]CONCORD', 336, 134, 212, 412)),
|
||||
(-100, ('[NPC][Mission]Gallente Federation', 9, 3712, 2758, 0)),
|
||||
(-101, ('[NPC][Mission]Khanid', 612, 483, 43, 6)),
|
||||
(-102, ('[NPC][Mission]Minmatar Republic', 1024, 388, 1655, 4285)),
|
||||
(-103, ('[NPC][Mission]Mordus Legion', 25, 262, 625, 0)),
|
||||
(-104, ('[NPC][Mission]Thukker', 0, 52, 10, 79)),
|
||||
(-105, ('[NPC]Sansha Incursion', 1682, 1347, 3678, 3678)),
|
||||
(-106, ('[NPC]Sleepers', 1472, 1472, 1384, 1384))])
|
||||
(-86, (_c(_t('NPC')) + _c(_t('Invasion')) + _c(_t('Triglavian Entities')) + _t('Dread'), 0, 417, 0, 583)),
|
||||
(-87, (_c(_t('NPC')) + _c(_t('Invasion')) + _c(_t('Triglavian Entities')) + _t('Normal Subcaps'), 0, 610, 0, 390)),
|
||||
# To avoid errors on msgfmt, we have to mark that '0%' is meaning literally 0% with no-python-format.
|
||||
# See also: https://github.com/vslavik/poedit/issues/645
|
||||
(-88, (_c(_t('NPC')) + _c(_t('Invasion')) + _c(_t('Triglavian Entities')) +
|
||||
# xgettext:no-python-format
|
||||
_t('Subcaps w/missiles 0% spool up'), 367, 155, 367, 112)),
|
||||
(-89, (_c(_t('NPC')) + _c(_t('Invasion')) + _c(_t('Triglavian Entities')) +
|
||||
# xgettext:no-python-format
|
||||
_t('Subcaps w/missiles 50% spool up'), 291, 243, 291, 175)),
|
||||
(-90, (_c(_t('NPC')) + _c(_t('Invasion')) + _c(_t('Triglavian Entities')) +
|
||||
# xgettext:no-python-format
|
||||
_t('Subcaps w/missiles 100% spool up'), 241, 301, 241, 217)),
|
||||
(-91, (_c(_t('NPC')) + _c(_t('Invasion')) + _c(_t('Amarr EDENCOM Entities')) + _t('Dread/Subcaps'), 583, 417, 0, 0)),
|
||||
(-92, (_c(_t('NPC')) + _c(_t('Invasion')) + _c(_t('Caldari EDENCOM Entities')) + _t('Dread'), 1000, 0, 0, 0)),
|
||||
(-93, (_c(_t('NPC')) + _c(_t('Invasion')) + _c(_t('Caldari EDENCOM Entities')) + _t('Subcaps'), 511, 21, 29, 440)),
|
||||
(-94, (_c(_t('NPC')) + _c(_t('Invasion')) + _c(_t('Gallente EDENCOM Entities')) + _t('Dread/Subcaps'), 0, 417, 583, 0)),
|
||||
(-95, (_c(_t('NPC')) + _c(_t('Invasion')) + _c(_t('Minmatar EDENCOM Entities')) + _t('Dread'), 0, 0, 583, 417)),
|
||||
(-96, (_c(_t('NPC')) + _c(_t('Invasion')) + _c(_t('Minmatar EDENCOM Entities')) + _t('Subcaps'), 302, 136, 328, 234)),
|
||||
(-110, (_c(_t('NPC')) + _c(_t('Invasion')) + _t('Drifter Entities'), 250, 250, 250, 250)),
|
||||
(-112, (_c(_t('NPC')) + _c(_t('Invasion')) + _t('Sleeper Entities'), 265, 265, 235, 235)),
|
||||
(-111, (_c(_t('NPC')) + _c(_t('Invasion')) + _t('Rogue Drone Entities'), 250, 250, 250, 250)),
|
||||
(-97, (_c(_t('NPC')) + _c(_t('Mission')) + _t('Amarr Empire'), 4464, 3546, 97, 0)),
|
||||
(-98, (_c(_t('NPC')) + _c(_t('Mission')) + _t('Caldari State'), 0, 2139, 4867, 0)),
|
||||
(-99, (_c(_t('NPC')) + _c(_t('Mission')) + _t('CONCORD'), 336, 134, 212, 412)),
|
||||
(-100, (_c(_t('NPC')) + _c(_t('Mission')) + _t('Gallente Federation'), 9, 3712, 2758, 0)),
|
||||
(-101, (_c(_t('NPC')) + _c(_t('Mission')) + _t('Khanid'), 612, 483, 43, 6)),
|
||||
(-102, (_c(_t('NPC')) + _c(_t('Mission')) + _t('Minmatar Republic'), 1024, 388, 1655, 4285)),
|
||||
(-103, (_c(_t('NPC')) + _c(_t('Mission')) + _t('Mordus Legion'), 25, 262, 625, 0)),
|
||||
(-104, (_c(_t('NPC')) + _c(_t('Mission')) + _t('Thukker'), 0, 52, 10, 79)),
|
||||
(-105, (_c(_t('NPC')) + _t('Sansha Incursion'), 1682, 1347, 3678, 3678)),
|
||||
(-106, (_c(_t('NPC')) + _t('Sleepers'), 1472, 1472, 1384, 1384))])
|
||||
|
||||
|
||||
class DamagePattern:
|
||||
|
||||
DAMAGE_TYPES = ('em', 'thermal', 'kinetic', 'explosive')
|
||||
_builtins = None
|
||||
|
||||
@@ -201,7 +222,8 @@ class DamagePattern:
|
||||
"armorRepair": "armor",
|
||||
"armorRepairPreSpool": "armor",
|
||||
"armorRepairFullSpool": "armor",
|
||||
"hullRepair": "hull"}
|
||||
"hullRepair": "hull"
|
||||
}
|
||||
ereps = {}
|
||||
for field in tankInfo:
|
||||
if field in typeMap:
|
||||
@@ -225,10 +247,10 @@ class DamagePattern:
|
||||
return amount / (specificDivider or 1)
|
||||
|
||||
importMap = {
|
||||
"em" : "em",
|
||||
"em": "em",
|
||||
"therm": "thermal",
|
||||
"kin" : "kinetic",
|
||||
"exp" : "explosive"
|
||||
"kin": "kinetic",
|
||||
"exp": "explosive"
|
||||
}
|
||||
|
||||
@classmethod
|
||||
|
||||
@@ -25,6 +25,8 @@ from sqlalchemy.orm import reconstructor, validates
|
||||
import eos.db
|
||||
from eos.effectHandlerHelpers import HandledCharge, HandledItem
|
||||
from eos.modifiedAttributeDict import ChargeAttrShortcut, ItemAttrShortcut, ModifiedAttributeDict
|
||||
from eos.saveddata.mutatedMixin import MutatedMixin, MutaError
|
||||
from eos.saveddata.mutator import MutatorDrone
|
||||
from eos.utils.cycles import CycleInfo
|
||||
from eos.utils.default import DEFAULT
|
||||
from eos.utils.stats import DmgTypes, RRTypes
|
||||
@@ -33,12 +35,13 @@ from eos.utils.stats import DmgTypes, RRTypes
|
||||
pyfalog = Logger(__name__)
|
||||
|
||||
|
||||
class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut, MutatedMixin):
|
||||
MINING_ATTRIBUTES = ("miningAmount",)
|
||||
|
||||
def __init__(self, item):
|
||||
def __init__(self, item, baseItem=None, mutaplasmid=None):
|
||||
"""Initialize a drone from the program"""
|
||||
self.__item = item
|
||||
self._item = item
|
||||
self._mutaInit(baseItem=baseItem, mutaplasmid=mutaplasmid)
|
||||
|
||||
if self.isInvalid:
|
||||
raise ValueError("Passed item is not a Drone")
|
||||
@@ -53,14 +56,19 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
@reconstructor
|
||||
def init(self):
|
||||
"""Initialize a drone from the database and validate"""
|
||||
self.__item = None
|
||||
self._item = None
|
||||
|
||||
if self.itemID:
|
||||
self.__item = eos.db.getItem(self.itemID)
|
||||
if self.__item is None:
|
||||
self._item = eos.db.getItem(self.itemID)
|
||||
if self._item is None:
|
||||
pyfalog.error("Item (id: {0}) does not exist", self.itemID)
|
||||
return
|
||||
|
||||
try:
|
||||
self._mutaReconstruct()
|
||||
except MutaError:
|
||||
return
|
||||
|
||||
if self.isInvalid:
|
||||
pyfalog.error("Item (id: {0}) is not a Drone", self.itemID)
|
||||
return
|
||||
@@ -74,10 +82,13 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
self.__baseRRAmount = None
|
||||
self.__miningyield = None
|
||||
self.__itemModifiedAttributes = ModifiedAttributeDict()
|
||||
self.__itemModifiedAttributes.original = self.__item.attributes
|
||||
self.__itemModifiedAttributes.overrides = self.__item.overrides
|
||||
|
||||
self.__itemModifiedAttributes.original = self._item.attributes
|
||||
self.__itemModifiedAttributes.overrides = self._item.overrides
|
||||
self.__chargeModifiedAttributes = ModifiedAttributeDict()
|
||||
|
||||
self._mutaLoadMutators(mutatorClass=MutatorDrone)
|
||||
self.__itemModifiedAttributes.mutators = self.mutators
|
||||
|
||||
# pheonix todo: check the attribute itself, not the modified. this will always return 0 now.
|
||||
chargeID = self.getModifiedItemAttr("entityMissileTypeID", None)
|
||||
if chargeID is not None:
|
||||
@@ -96,11 +107,17 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
|
||||
@property
|
||||
def isInvalid(self):
|
||||
return self.__item is None or self.__item.category.name != "Drone"
|
||||
if self._item is None:
|
||||
return True
|
||||
if self._item.category.name != "Drone":
|
||||
return True
|
||||
if self._mutaIsInvalid:
|
||||
return True
|
||||
return False
|
||||
|
||||
@property
|
||||
def item(self):
|
||||
return self.__item
|
||||
return self._item
|
||||
|
||||
@property
|
||||
def charge(self):
|
||||
@@ -111,7 +128,7 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
if self.hasAmmo:
|
||||
cycleTime = self.getModifiedItemAttr("missileLaunchDuration", 0)
|
||||
else:
|
||||
for attr in ("speed", "duration"):
|
||||
for attr in ("speed", "duration", "durationHighisGood"):
|
||||
cycleTime = self.getModifiedItemAttr(attr, None)
|
||||
if cycleTime is not None:
|
||||
break
|
||||
@@ -337,10 +354,11 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
effect.handler(fit, self, ("droneCharge",), projectionRange, effect=effect)
|
||||
|
||||
def __deepcopy__(self, memo):
|
||||
copy = Drone(self.item)
|
||||
copy = Drone(self.item, self.baseItem, self.mutaplasmid)
|
||||
copy.amount = self.amount
|
||||
copy.amountActive = self.amountActive
|
||||
copy.projectionRange = self.projectionRange
|
||||
self._mutaApplyMutators(mutatorClass=MutatorDrone, targetInstance=copy)
|
||||
return copy
|
||||
|
||||
def rebase(self, item):
|
||||
@@ -348,10 +366,11 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
amountActive = self.amountActive
|
||||
projectionRange = self.projectionRange
|
||||
|
||||
Drone.__init__(self, item)
|
||||
Drone.__init__(self, item, self.baseItem, self.mutaplasmid)
|
||||
self.amount = amount
|
||||
self.amountActive = amountActive
|
||||
self.projectionRange = projectionRange
|
||||
self._mutaApplyMutators(mutatorClass=MutatorDrone)
|
||||
|
||||
def fits(self, fit):
|
||||
fitDroneGroupLimits = set()
|
||||
|
||||
@@ -42,10 +42,13 @@ from eos.saveddata.targetProfile import TargetProfile
|
||||
from eos.utils.float import floatUnerr
|
||||
from eos.utils.stats import DmgTypes, RRTypes
|
||||
|
||||
|
||||
pyfalog = Logger(__name__)
|
||||
|
||||
|
||||
def _t(x):
|
||||
return x
|
||||
|
||||
|
||||
class FitLite:
|
||||
|
||||
def __init__(self, id=None, name=None, shipID=None, shipName=None, shipNameShort=None):
|
||||
@@ -152,7 +155,7 @@ class Fit:
|
||||
self.factorReload = False
|
||||
self.boostsFits = set()
|
||||
self.gangBoosts = None
|
||||
self.ecmProjectedStr = 1
|
||||
self.__ecmProjectedList = []
|
||||
self.commandBonuses = {}
|
||||
|
||||
def clearFactorReloadDependentData(self):
|
||||
@@ -395,20 +398,24 @@ class Fit:
|
||||
@property
|
||||
def scanType(self):
|
||||
maxStr = -1
|
||||
type = None
|
||||
for scanType in ("Magnetometric", "Ladar", "Radar", "Gravimetric"):
|
||||
type_ = None
|
||||
for scanType in (_t("Magnetometric"), _t("Ladar"), _t("Radar"), _t("Gravimetric")):
|
||||
currStr = self.ship.getModifiedItemAttr("scan%sStrength" % scanType)
|
||||
if currStr > maxStr:
|
||||
maxStr = currStr
|
||||
type = scanType
|
||||
type_ = scanType
|
||||
elif currStr == maxStr:
|
||||
type = "Multispectral"
|
||||
type_ = _t("Multispectral")
|
||||
|
||||
return type
|
||||
return type_
|
||||
|
||||
@property
|
||||
def jamChance(self):
|
||||
return (1 - self.ecmProjectedStr) * 100
|
||||
sensors = self.scanStrength
|
||||
retainLockChance = 1
|
||||
for jamStr in self.__ecmProjectedList:
|
||||
retainLockChance *= 1 - min(1, jamStr / sensors)
|
||||
return (1 - retainLockChance) * 100
|
||||
|
||||
@property
|
||||
def maxSpeed(self):
|
||||
@@ -443,9 +450,9 @@ class Fit:
|
||||
@validates("ID", "ownerID", "shipID")
|
||||
def validator(self, key, val):
|
||||
map = {
|
||||
"ID" : lambda _val: isinstance(_val, int),
|
||||
"ID": lambda _val: isinstance(_val, int),
|
||||
"ownerID": lambda _val: isinstance(_val, int) or _val is None,
|
||||
"shipID" : lambda _val: isinstance(_val, int) or _val is None
|
||||
"shipID": lambda _val: isinstance(_val, int) or _val is None
|
||||
}
|
||||
|
||||
if not map[key](val):
|
||||
@@ -496,7 +503,7 @@ class Fit:
|
||||
self.__capUsed = None
|
||||
self.__capRecharge = None
|
||||
self.__savedCapSimData.clear()
|
||||
self.ecmProjectedStr = 1
|
||||
self.__ecmProjectedList = []
|
||||
# self.commandBonuses = {}
|
||||
|
||||
del self.__calculatedTargets[:]
|
||||
@@ -559,6 +566,9 @@ class Fit:
|
||||
if warfareBuffID not in self.commandBonuses or abs(self.commandBonuses[warfareBuffID][1]) < abs(value):
|
||||
self.commandBonuses[warfareBuffID] = (runTime, value, module, effect)
|
||||
|
||||
def addProjectedEcm(self, strength):
|
||||
self.__ecmProjectedList.append(strength)
|
||||
|
||||
def __runCommandBoosts(self, runTime="normal"):
|
||||
pyfalog.debug("Applying gang boosts for {0}", repr(self))
|
||||
for warfareBuffID in list(self.commandBonuses.keys()):
|
||||
@@ -578,15 +588,15 @@ class Fit:
|
||||
|
||||
if warfareBuffID == 11: # Shield Burst: Active Shielding: Repair Duration/Capacitor
|
||||
self.modules.filteredItemBoost(
|
||||
lambda mod: mod.item.requiresSkill("Shield Operation") or
|
||||
mod.item.requiresSkill("Shield Emission Systems") or
|
||||
mod.item.requiresSkill("Capital Shield Emission Systems"),
|
||||
"capacitorNeed", value)
|
||||
lambda mod: mod.item.requiresSkill("Shield Operation") or
|
||||
mod.item.requiresSkill("Shield Emission Systems") or
|
||||
mod.item.requiresSkill("Capital Shield Emission Systems"),
|
||||
"capacitorNeed", value)
|
||||
self.modules.filteredItemBoost(
|
||||
lambda mod: mod.item.requiresSkill("Shield Operation") or
|
||||
mod.item.requiresSkill("Shield Emission Systems") or
|
||||
mod.item.requiresSkill("Capital Shield Emission Systems"),
|
||||
"duration", value)
|
||||
lambda mod: mod.item.requiresSkill("Shield Operation") or
|
||||
mod.item.requiresSkill("Shield Emission Systems") or
|
||||
mod.item.requiresSkill("Capital Shield Emission Systems"),
|
||||
"duration", value)
|
||||
|
||||
if warfareBuffID == 12: # Shield Burst: Shield Extension: Shield HP
|
||||
self.ship.boostItemAttr("shieldCapacity", value, stackingPenalties=True)
|
||||
@@ -597,15 +607,15 @@ class Fit:
|
||||
|
||||
if warfareBuffID == 14: # Armor Burst: Rapid Repair: Repair Duration/Capacitor
|
||||
self.modules.filteredItemBoost(
|
||||
lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems") or
|
||||
mod.item.requiresSkill("Repair Systems") or
|
||||
mod.item.requiresSkill("Capital Remote Armor Repair Systems"),
|
||||
"capacitorNeed", value)
|
||||
lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems") or
|
||||
mod.item.requiresSkill("Repair Systems") or
|
||||
mod.item.requiresSkill("Capital Remote Armor Repair Systems"),
|
||||
"capacitorNeed", value)
|
||||
self.modules.filteredItemBoost(
|
||||
lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems") or
|
||||
mod.item.requiresSkill("Repair Systems") or
|
||||
mod.item.requiresSkill("Capital Remote Armor Repair Systems"),
|
||||
"duration", value)
|
||||
lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems") or
|
||||
mod.item.requiresSkill("Repair Systems") or
|
||||
mod.item.requiresSkill("Capital Remote Armor Repair Systems"),
|
||||
"duration", value)
|
||||
|
||||
if warfareBuffID == 15: # Armor Burst: Armor Reinforcement: Armor HP
|
||||
self.ship.boostItemAttr("armorHP", value, stackingPenalties=True)
|
||||
@@ -679,8 +689,8 @@ class Fit:
|
||||
"duration", value, stackingPenalties=True)
|
||||
|
||||
if warfareBuffID == 25: # Mining Burst: Mining Equipment Preservation: Crystal Volatility
|
||||
self.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Mining"),
|
||||
"crystalVolatilityChance", value, stackingPenalties=True)
|
||||
self.modules.filteredChargeBoost(lambda mod: mod.item.requiresSkill("Mining"),
|
||||
"crystalVolatilityChance", value, stackingPenalties=True)
|
||||
|
||||
if warfareBuffID == 26: # Information Burst: Sensor Optimization: Targeting Range
|
||||
self.ship.boostItemAttr("maxTargetRange", value, stackingPenalties=True)
|
||||
@@ -1006,14 +1016,14 @@ class Fit:
|
||||
for _ in range(projectionInfo.amount):
|
||||
targetFit.register(item, origin=self)
|
||||
item.calculateModifiedAttributes(
|
||||
targetFit, runTime, forceProjected=True,
|
||||
forcedProjRange=0)
|
||||
targetFit, runTime, forceProjected=True,
|
||||
forcedProjRange=0)
|
||||
for mod in self.modules:
|
||||
for _ in range(projectionInfo.amount):
|
||||
targetFit.register(mod, origin=self)
|
||||
mod.calculateModifiedAttributes(
|
||||
targetFit, runTime, forceProjected=True,
|
||||
forcedProjRange=projectionInfo.projectionRange)
|
||||
targetFit, runTime, forceProjected=True,
|
||||
forcedProjRange=projectionInfo.projectionRange)
|
||||
|
||||
def fill(self):
|
||||
"""
|
||||
@@ -1029,7 +1039,8 @@ class Fit:
|
||||
|
||||
# Look for any dummies of that type to remove
|
||||
posToRemove = {}
|
||||
for slotType in (FittingSlot.LOW.value, FittingSlot.MED.value, FittingSlot.HIGH.value, FittingSlot.RIG.value, FittingSlot.SUBSYSTEM.value, FittingSlot.SERVICE.value):
|
||||
for slotType in (
|
||||
FittingSlot.LOW.value, FittingSlot.MED.value, FittingSlot.HIGH.value, FittingSlot.RIG.value, FittingSlot.SUBSYSTEM.value, FittingSlot.SERVICE.value):
|
||||
amount = self.getSlotsFree(slotType, True)
|
||||
if amount > 0:
|
||||
for _ in range(int(amount)):
|
||||
@@ -1106,22 +1117,23 @@ class Fit:
|
||||
|
||||
for mod in chain(self.modules, self.fighters):
|
||||
if mod.slot is type and (not getattr(mod, "isEmpty", False) or countDummies):
|
||||
if type in (FittingSlot.F_HEAVY, FittingSlot.F_SUPPORT, FittingSlot.F_LIGHT, FittingSlot.FS_HEAVY, FittingSlot.FS_LIGHT, FittingSlot.FS_SUPPORT) and not mod.active:
|
||||
if type in (FittingSlot.F_HEAVY, FittingSlot.F_SUPPORT, FittingSlot.F_LIGHT, FittingSlot.FS_HEAVY, FittingSlot.FS_LIGHT,
|
||||
FittingSlot.FS_SUPPORT) and not mod.active:
|
||||
continue
|
||||
amount += 1
|
||||
|
||||
return amount
|
||||
|
||||
slots = {
|
||||
FittingSlot.LOW : "lowSlots",
|
||||
FittingSlot.MED : "medSlots",
|
||||
FittingSlot.HIGH : "hiSlots",
|
||||
FittingSlot.RIG : "rigSlots",
|
||||
FittingSlot.LOW: "lowSlots",
|
||||
FittingSlot.MED: "medSlots",
|
||||
FittingSlot.HIGH: "hiSlots",
|
||||
FittingSlot.RIG: "rigSlots",
|
||||
FittingSlot.SUBSYSTEM: "maxSubSystems",
|
||||
FittingSlot.SERVICE : "serviceSlots",
|
||||
FittingSlot.F_LIGHT : "fighterLightSlots",
|
||||
FittingSlot.SERVICE: "serviceSlots",
|
||||
FittingSlot.F_LIGHT: "fighterLightSlots",
|
||||
FittingSlot.F_SUPPORT: "fighterSupportSlots",
|
||||
FittingSlot.F_HEAVY : "fighterHeavySlots",
|
||||
FittingSlot.F_HEAVY: "fighterHeavySlots",
|
||||
FittingSlot.FS_LIGHT: "fighterStandupLightSlots",
|
||||
FittingSlot.FS_SUPPORT: "fighterStandupSupportSlots",
|
||||
FittingSlot.FS_HEAVY: "fighterStandupHeavySlots",
|
||||
@@ -1403,8 +1415,8 @@ class Fit:
|
||||
"""Return how much cap regen do we gain from having this module"""
|
||||
currentRegen = self.calculateCapRecharge()
|
||||
nomodRegen = self.calculateCapRecharge(
|
||||
capacity=self.ship.getModifiedItemAttrExtended("capacitorCapacity", ignoreAfflictors=[mod]),
|
||||
rechargeRate=self.ship.getModifiedItemAttrExtended("rechargeRate", ignoreAfflictors=[mod]) / 1000.0)
|
||||
capacity=self.ship.getModifiedItemAttrExtended("capacitorCapacity", ignoreAfflictors=[mod]),
|
||||
rechargeRate=self.ship.getModifiedItemAttrExtended("rechargeRate", ignoreAfflictors=[mod]) / 1000.0)
|
||||
return currentRegen - nomodRegen
|
||||
|
||||
def getRemoteReps(self, spoolOptions=None):
|
||||
@@ -1448,7 +1460,8 @@ class Fit:
|
||||
"armorRepair": self.extraAttributes["armorRepair"],
|
||||
"armorRepairPreSpool": self.extraAttributes["armorRepairPreSpool"],
|
||||
"armorRepairFullSpool": self.extraAttributes["armorRepairFullSpool"],
|
||||
"hullRepair": self.extraAttributes["hullRepair"]}
|
||||
"hullRepair": self.extraAttributes["hullRepair"]
|
||||
}
|
||||
return reps
|
||||
|
||||
@property
|
||||
@@ -1488,7 +1501,8 @@ class Fit:
|
||||
"armorRepair": self.extraAttributes["armorRepair"],
|
||||
"armorRepairPreSpool": self.extraAttributes["armorRepairPreSpool"],
|
||||
"armorRepairFullSpool": self.extraAttributes["armorRepairFullSpool"],
|
||||
"hullRepair": self.extraAttributes["hullRepair"]}
|
||||
"hullRepair": self.extraAttributes["hullRepair"]
|
||||
}
|
||||
if not self.capStable or self.factorReload:
|
||||
# Map a local repairer type to the attribute it uses
|
||||
groupAttrMap = {
|
||||
@@ -1496,14 +1510,16 @@ class Fit:
|
||||
"Ancillary Shield Booster": "shieldBonus",
|
||||
"Armor Repair Unit": "armorDamageAmount",
|
||||
"Ancillary Armor Repairer": "armorDamageAmount",
|
||||
"Hull Repair Unit": "structureDamageAmount"}
|
||||
"Hull Repair Unit": "structureDamageAmount"
|
||||
}
|
||||
# Map local repairer type to tank type
|
||||
groupStoreMap = {
|
||||
"Shield Booster": "shieldRepair",
|
||||
"Ancillary Shield Booster": "shieldRepair",
|
||||
"Armor Repair Unit": "armorRepair",
|
||||
"Ancillary Armor Repairer": "armorRepair",
|
||||
"Hull Repair Unit": "hullRepair"}
|
||||
"Hull Repair Unit": "hullRepair"
|
||||
}
|
||||
repairers = []
|
||||
localAdjustment = {"shieldRepair": 0, "armorRepair": 0, "hullRepair": 0}
|
||||
capUsed = self.capUsed
|
||||
@@ -1555,7 +1571,7 @@ class Fit:
|
||||
|
||||
# Sort repairers by efficiency. We want to use the most efficient repairers first
|
||||
repairers.sort(key=lambda _mod: _mod.getModifiedItemAttr(
|
||||
groupAttrMap[_mod.item.group.name]) * (_mod.getModifiedItemAttr(
|
||||
groupAttrMap[_mod.item.group.name]) * (_mod.getModifiedItemAttr(
|
||||
"chargedArmorDamageMultiplier") or 1) / _mod.getModifiedItemAttr("capacitorNeed"), reverse=True)
|
||||
|
||||
# Loop through every module until we're above peak recharge
|
||||
@@ -1680,7 +1696,6 @@ class Fit:
|
||||
secstatus = FitSystemSecurity.NULLSEC
|
||||
return secstatus
|
||||
|
||||
|
||||
def activeModulesIter(self):
|
||||
for mod in self.modules:
|
||||
if mod.state >= FittingModuleState.ACTIVE:
|
||||
|
||||
@@ -23,7 +23,6 @@ from eos.modifiedAttributeDict import ModifiedAttributeDict, ItemAttrShortcut
|
||||
|
||||
class Mode(ItemAttrShortcut, HandledItem):
|
||||
|
||||
|
||||
def __init__(self, item, owner=None):
|
||||
if item.group.name != "Ship Modifiers":
|
||||
raise ValueError(
|
||||
@@ -34,7 +33,6 @@ class Mode(ItemAttrShortcut, HandledItem):
|
||||
self.__itemModifiedAttributes.original = self.item.attributes
|
||||
self.__itemModifiedAttributes.overrides = self.item.overrides
|
||||
|
||||
|
||||
@property
|
||||
def item(self):
|
||||
return self.__item
|
||||
|
||||
@@ -27,7 +27,8 @@ from eos.const import FittingHardpoint, FittingModuleState, FittingSlot
|
||||
from eos.effectHandlerHelpers import HandledCharge, HandledItem
|
||||
from eos.modifiedAttributeDict import ChargeAttrShortcut, ItemAttrShortcut, ModifiedAttributeDict
|
||||
from eos.saveddata.citadel import Citadel
|
||||
from eos.saveddata.mutator import Mutator
|
||||
from eos.saveddata.mutatedMixin import MutatedMixin, MutaError
|
||||
from eos.saveddata.mutator import MutatorModule
|
||||
from eos.utils.cycles import CycleInfo, CycleSequence
|
||||
from eos.utils.default import DEFAULT
|
||||
from eos.utils.float import floatUnerr
|
||||
@@ -61,7 +62,7 @@ ProjectedSystem = {
|
||||
}
|
||||
|
||||
|
||||
class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut, MutatedMixin):
|
||||
"""An instance of this class represents a module together with its charge and modified attributes"""
|
||||
MINING_ATTRIBUTES = ("miningAmount",)
|
||||
SYSTEM_GROUPS = (
|
||||
@@ -72,21 +73,9 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
"""Initialize a module from the program"""
|
||||
|
||||
self.itemID = item.ID if item is not None else None
|
||||
self.baseItemID = baseItem.ID if baseItem is not None else None
|
||||
self.mutaplasmidID = mutaplasmid.ID if mutaplasmid is not None else None
|
||||
|
||||
if baseItem is not None:
|
||||
# we're working with a mutated module, need to get abyssal module loaded with the base attributes
|
||||
# Note: there may be a better way of doing this, such as a metho on this classe to convert(mutaplamid). This
|
||||
# will require a bit more research though, considering there has never been a need to "swap" out the item of a Module
|
||||
# before, and there may be assumptions taken with regards to the item never changing (pre-calculated / cached results, for example)
|
||||
self.__item = eos.db.getItemWithBaseItemAttribute(self.itemID, self.baseItemID)
|
||||
self.__baseItem = baseItem
|
||||
self.__mutaplasmid = mutaplasmid
|
||||
else:
|
||||
self.__item = item
|
||||
self.__baseItem = baseItem
|
||||
self.__mutaplasmid = mutaplasmid
|
||||
self._item = item
|
||||
self._mutaInit(baseItem=baseItem, mutaplasmid=mutaplasmid)
|
||||
|
||||
if item is not None and self.isInvalid:
|
||||
raise ValueError("Passed item is not a Module")
|
||||
@@ -101,27 +90,22 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
@reconstructor
|
||||
def init(self):
|
||||
"""Initialize a module from the database and validate"""
|
||||
self.__item = None
|
||||
self.__baseItem = None
|
||||
self._item = None
|
||||
self.__charge = None
|
||||
self.__mutaplasmid = None
|
||||
|
||||
# we need this early if module is invalid and returns early
|
||||
self.__slot = self.dummySlot
|
||||
|
||||
if self.itemID:
|
||||
self.__item = eos.db.getItem(self.itemID)
|
||||
if self.__item is None:
|
||||
self._item = eos.db.getItem(self.itemID)
|
||||
if self._item is None:
|
||||
pyfalog.error("Item (id: {0}) does not exist", self.itemID)
|
||||
return
|
||||
|
||||
if self.baseItemID:
|
||||
self.__item = eos.db.getItemWithBaseItemAttribute(self.itemID, self.baseItemID)
|
||||
self.__baseItem = eos.db.getItem(self.baseItemID)
|
||||
self.__mutaplasmid = eos.db.getMutaplasmid(self.mutaplasmidID)
|
||||
if self.__baseItem is None:
|
||||
pyfalog.error("Base Item (id: {0}) does not exist", self.itemID)
|
||||
return
|
||||
try:
|
||||
self._mutaReconstruct()
|
||||
except MutaError:
|
||||
return
|
||||
|
||||
if self.isInvalid:
|
||||
pyfalog.error("Item (id: {0}) is not a Module", self.itemID)
|
||||
@@ -149,21 +133,13 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
self.__chargeModifiedAttributes = ModifiedAttributeDict(parent=self)
|
||||
self.__slot = self.dummySlot # defaults to None
|
||||
|
||||
if self.__item:
|
||||
self.__itemModifiedAttributes.original = self.__item.attributes
|
||||
self.__itemModifiedAttributes.overrides = self.__item.overrides
|
||||
self.__hardpoint = self.__calculateHardpoint(self.__item)
|
||||
self.__slot = self.calculateSlot(self.__item)
|
||||
|
||||
# Instantiate / remove mutators if this is a mutated module
|
||||
if self.__baseItem:
|
||||
for x in self.mutaplasmid.attributes:
|
||||
attr = self.item.attributes[x.name]
|
||||
id = attr.ID
|
||||
if id not in self.mutators: # create the mutator
|
||||
Mutator(self, attr, attr.value)
|
||||
# @todo: remove attributes that are no longer part of the mutaplasmid.
|
||||
if self._item:
|
||||
self.__itemModifiedAttributes.original = self._item.attributes
|
||||
self.__itemModifiedAttributes.overrides = self._item.overrides
|
||||
self.__hardpoint = self.__calculateHardpoint(self._item)
|
||||
self.__slot = self.calculateSlot(self._item)
|
||||
|
||||
self._mutaLoadMutators(mutatorClass=MutatorModule)
|
||||
self.__itemModifiedAttributes.mutators = self.mutators
|
||||
|
||||
if self.__charge:
|
||||
@@ -198,23 +174,22 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
# todo: validate baseItem as well if it's set.
|
||||
if self.isEmpty:
|
||||
return False
|
||||
if self.__item is None:
|
||||
if self._item is None:
|
||||
return True
|
||||
if (
|
||||
self.__item.category.name not in ("Module", "Subsystem", "Structure Module")
|
||||
and self.__item.group.name not in self.SYSTEM_GROUPS
|
||||
self._item.category.name not in ("Module", "Subsystem", "Structure Module")
|
||||
and self._item.group.name not in self.SYSTEM_GROUPS
|
||||
):
|
||||
return True
|
||||
if self.item.isAbyssal and not self.isMutated:
|
||||
if (
|
||||
self._item.category.name == "Structure Module"
|
||||
and self._item.group.name == "Quantum Cores"
|
||||
):
|
||||
return True
|
||||
if self.isMutated and not self.__mutaplasmid:
|
||||
if self._mutaIsInvalid:
|
||||
return True
|
||||
return False
|
||||
|
||||
@property
|
||||
def isMutated(self):
|
||||
return self.baseItemID and self.mutaplasmidID
|
||||
|
||||
@property
|
||||
def numCharges(self):
|
||||
return self.getNumCharges(self.charge)
|
||||
@@ -414,15 +389,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
|
||||
@property
|
||||
def item(self):
|
||||
return self.__item if self.__item != 0 else None
|
||||
|
||||
@property
|
||||
def baseItem(self):
|
||||
return self.__baseItem
|
||||
|
||||
@property
|
||||
def mutaplasmid(self):
|
||||
return self.__mutaplasmid
|
||||
return self._item if self._item != 0 else None
|
||||
|
||||
@property
|
||||
def charge(self):
|
||||
@@ -534,7 +501,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
return DmgTypes(0, 0, 0, 0)
|
||||
return volleyParams[min(volleyParams)]
|
||||
|
||||
def getDps(self, spoolOptions=None, targetProfile=None, ignoreState=False):
|
||||
def getDps(self, spoolOptions=None, targetProfile=None, ignoreState=False, getSpreadDPS=False):
|
||||
dmgDuringCycle = DmgTypes(0, 0, 0, 0)
|
||||
cycleParams = self.getCycleParameters()
|
||||
if cycleParams is None:
|
||||
@@ -551,7 +518,12 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
thermal=dmgDuringCycle.thermal * dpsFactor,
|
||||
kinetic=dmgDuringCycle.kinetic * dpsFactor,
|
||||
explosive=dmgDuringCycle.explosive * dpsFactor)
|
||||
return dps
|
||||
if not getSpreadDPS:
|
||||
return dps
|
||||
return {'em':dmgDuringCycle.em * dpsFactor,
|
||||
'therm': dmgDuringCycle.thermal * dpsFactor,
|
||||
'kin': dmgDuringCycle.kinetic * dpsFactor,
|
||||
'exp': dmgDuringCycle.explosive * dpsFactor}
|
||||
|
||||
def isRemoteRepping(self, ignoreState=False):
|
||||
repParams = self.getRepAmountParameters(ignoreState=ignoreState)
|
||||
@@ -1016,6 +988,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
speed = max(
|
||||
self.getModifiedItemAttr("speed", 0), # Most weapons
|
||||
self.getModifiedItemAttr("duration", 0), # Most average modules
|
||||
self.getModifiedItemAttr("durationHighisGood", 0), # Most average modules
|
||||
self.getModifiedItemAttr("durationSensorDampeningBurstProjector", 0),
|
||||
self.getModifiedItemAttr("durationTargetIlluminationBurstProjector", 0),
|
||||
self.getModifiedItemAttr("durationECMJammerBurstProjector", 0),
|
||||
@@ -1087,9 +1060,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
copy.spoolType = self.spoolType
|
||||
copy.spoolAmount = self.spoolAmount
|
||||
copy.projectionRange = self.projectionRange
|
||||
|
||||
for x in self.mutators.values():
|
||||
Mutator(copy, x.attribute, x.value)
|
||||
self._mutaApplyMutators(mutatorClass=MutatorModule, targetInstance=copy)
|
||||
|
||||
return copy
|
||||
|
||||
@@ -1107,14 +1078,11 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
self.spoolType = spoolType
|
||||
self.spoolAmount = spoolAmount
|
||||
self.projectionRange = projectionRange
|
||||
for x in self.mutators.values():
|
||||
Mutator(self, x.attribute, x.value)
|
||||
self._mutaApplyMutators(mutatorClass=MutatorModule)
|
||||
|
||||
def __repr__(self):
|
||||
if self.item:
|
||||
return "Module(ID={}, name={}) at {}".format(
|
||||
self.item.ID, self.item.name, hex(id(self))
|
||||
)
|
||||
return "Module(ID={}, name={}) at {}".format(self.item.ID, self.item.name, hex(id(self)))
|
||||
else:
|
||||
return "EmptyModule() at {}".format(hex(id(self)))
|
||||
|
||||
|
||||
105
eos/saveddata/mutatedMixin.py
Normal file
105
eos/saveddata/mutatedMixin.py
Normal file
@@ -0,0 +1,105 @@
|
||||
# ===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
#
|
||||
# eos is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# eos 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
# ===============================================================================
|
||||
|
||||
|
||||
import eos.db
|
||||
|
||||
from logbook import Logger
|
||||
|
||||
|
||||
pyfalog = Logger(__name__)
|
||||
|
||||
|
||||
class MutaError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class MutatedMixin:
|
||||
|
||||
@property
|
||||
def isMutated(self):
|
||||
return bool(self.baseItemID and self.mutaplasmidID)
|
||||
|
||||
@property
|
||||
def baseItem(self):
|
||||
return self.__baseItem
|
||||
|
||||
@property
|
||||
def mutaplasmid(self):
|
||||
return self.__mutaplasmid
|
||||
|
||||
@property
|
||||
def fullName(self):
|
||||
if self.isMutated:
|
||||
mutaShortName = self.mutaplasmid.shortName
|
||||
mutaFullName = self.mutaplasmid.item.customName
|
||||
# Short name can be unavailable for non-english language
|
||||
if mutaShortName != mutaFullName:
|
||||
return f'{self.mutaplasmid.shortName} {self.baseItem.customName}'
|
||||
return self.item.customName
|
||||
|
||||
def _mutaInit(self, baseItem, mutaplasmid):
|
||||
self.baseItemID = baseItem.ID if baseItem is not None else None
|
||||
self.mutaplasmidID = mutaplasmid.ID if mutaplasmid is not None else None
|
||||
if baseItem is not None:
|
||||
# we're working with a mutated module, need to get abyssal module loaded with the base attributes
|
||||
# Note: there may be a better way of doing this, such as a metho on this classe to convert(mutaplamid). This
|
||||
# will require a bit more research though, considering there has never been a need to "swap" out the item of a Module
|
||||
# before, and there may be assumptions taken with regards to the item never changing (pre-calculated / cached results, for example)
|
||||
self._item = eos.db.getItemWithBaseItemAttribute(self._item.ID, self.baseItemID)
|
||||
self.__baseItem = baseItem
|
||||
self.__mutaplasmid = mutaplasmid
|
||||
else:
|
||||
self.__baseItem = None
|
||||
self.__mutaplasmid = None
|
||||
|
||||
def _mutaReconstruct(self):
|
||||
self.__baseItem = None
|
||||
self.__mutaplasmid = None
|
||||
if self.baseItemID:
|
||||
self._item = eos.db.getItemWithBaseItemAttribute(self.itemID, self.baseItemID)
|
||||
self.__baseItem = eos.db.getItem(self.baseItemID)
|
||||
self.__mutaplasmid = eos.db.getMutaplasmid(self.mutaplasmidID)
|
||||
if self.__baseItem is None:
|
||||
pyfalog.error("Base Item (id: {0}) does not exist", self.itemID)
|
||||
raise MutaError
|
||||
|
||||
def _mutaLoadMutators(self, mutatorClass):
|
||||
# Instantiate / remove mutators if this is a mutated module
|
||||
if self.__baseItem:
|
||||
for x in self.mutaplasmid.attributes:
|
||||
attr = self.item.attributes[x.name]
|
||||
id = attr.ID
|
||||
if id not in self.mutators: # create the mutator
|
||||
mutatorClass(self, attr, attr.value)
|
||||
# @todo: remove attributes that are no longer part of the mutaplasmid.
|
||||
|
||||
@property
|
||||
def _mutaIsInvalid(self):
|
||||
if self.item.isAbyssal and not self.isMutated:
|
||||
return True
|
||||
if self.isMutated and not self.__mutaplasmid:
|
||||
return True
|
||||
return False
|
||||
|
||||
def _mutaApplyMutators(self, mutatorClass, targetInstance=None):
|
||||
if targetInstance is None:
|
||||
targetInstance = self
|
||||
for x in self.mutators.values():
|
||||
mutatorClass(targetInstance, x.attribute, x.value)
|
||||
@@ -27,10 +27,10 @@ from eos.eqBase import EqBase
|
||||
pyfalog = Logger(__name__)
|
||||
|
||||
|
||||
class Mutator(EqBase):
|
||||
""" Mutators are the object that represent an attribute override on the module level, in conjunction with
|
||||
mutaplasmids. Each mutated module, when created, is instantiated with a list of these objects, dictated by the
|
||||
mutaplasmid that is used on the base module.
|
||||
class MutatorBase(EqBase):
|
||||
""" Mutators are the object that represent an attribute override on the eos item level, in conjunction with
|
||||
mutaplasmids. Each mutated item, when created, is instantiated with a list of these objects, dictated by the
|
||||
mutaplasmid that is used on the base item.
|
||||
|
||||
A note on the different attributes on this object:
|
||||
* attribute: points to the definition of the attribute from dgmattribs.
|
||||
@@ -40,13 +40,13 @@ class Mutator(EqBase):
|
||||
This could probably be cleaned up with smarter relationships, but whatever
|
||||
"""
|
||||
|
||||
def __init__(self, module, attr, value):
|
||||
# this needs to be above module assignment, as assigning the module will add it to the list and it via
|
||||
def __init__(self, item, attr, value):
|
||||
# this needs to be above item assignment, as assigning the item will add it to the list and it via
|
||||
# relationship and needs this set 4correctly
|
||||
self.attrID = attr.ID
|
||||
|
||||
self.module = module
|
||||
self.moduleID = module.ID
|
||||
self.item = item
|
||||
self.itemID = item.ID
|
||||
|
||||
self.__attr = attr
|
||||
self.build()
|
||||
@@ -67,20 +67,20 @@ class Mutator(EqBase):
|
||||
|
||||
def build(self):
|
||||
# try...except here to catch orphaned mutators. Pretty rare, only happens so far if hacking the database
|
||||
# But put it here to remove the module link if it happens, until a better solution can be developed
|
||||
# But put it here to remove the eos item link if it happens, until a better solution can be developed
|
||||
try:
|
||||
# dynamic attribute links to the Mutaplasmids attribute definition for this mutated definition
|
||||
self.dynamicAttribute = next(a for a in self.module.mutaplasmid.attributes if a.attributeID == self.attrID)
|
||||
self.dynamicAttribute = next(a for a in self.item.mutaplasmid.attributes if a.attributeID == self.attrID)
|
||||
# base attribute links to the base ite's attribute for this mutated definition (contains original, base value)
|
||||
self.baseAttribute = self.module.item.attributes[self.dynamicAttribute.name]
|
||||
self.baseAttribute = self.item.baseItem.attributes[self.dynamicAttribute.name]
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
self.module = None
|
||||
self.item = None
|
||||
|
||||
@validates("value")
|
||||
def validator(self, key, val):
|
||||
""" Validates values as properly falling within the range of the modules' Mutaplasmid """
|
||||
""" Validates values as properly falling within the range of the items' Mutaplasmid """
|
||||
if self.baseValue == 0:
|
||||
return 0
|
||||
mod = val / self.baseValue
|
||||
@@ -89,12 +89,9 @@ class Mutator(EqBase):
|
||||
# sweet, all good
|
||||
returnVal = val
|
||||
else:
|
||||
# need to fudge the numbers a bit. Go with the value closest to base
|
||||
if val >= 0:
|
||||
returnVal = min(self.maxValue, max(self.minValue, val))
|
||||
else:
|
||||
returnVal = max(self.maxValue, min(self.minValue, val))
|
||||
|
||||
actualMin = min(self.minValue, self.maxValue)
|
||||
actualMax = max(self.minValue, self.maxValue)
|
||||
returnVal = min(actualMax, max(actualMin, val))
|
||||
return returnVal
|
||||
|
||||
@property
|
||||
@@ -102,7 +99,7 @@ class Mutator(EqBase):
|
||||
# @todo: need to test what happens:
|
||||
# 1) if an attribute is removed from the EVE database
|
||||
# 2) if a mutaplasmid does not have the attribute anymore
|
||||
# 3) if a mutaplasmid does not exist (in eve or on the module's item)
|
||||
# 3) if a mutaplasmid does not exist (in eve or on the pyfa item's item)
|
||||
# Can remove invalid ones in a SQLAlchemy collection class... eventually
|
||||
return self.__attr is None
|
||||
|
||||
@@ -142,3 +139,11 @@ class Mutator(EqBase):
|
||||
@property
|
||||
def attribute(self):
|
||||
return self.__attr
|
||||
|
||||
|
||||
class MutatorModule(MutatorBase):
|
||||
pass
|
||||
|
||||
|
||||
class MutatorDrone(MutatorBase):
|
||||
pass
|
||||
|
||||
@@ -26,164 +26,213 @@ from sqlalchemy.orm import reconstructor
|
||||
|
||||
import eos.db
|
||||
|
||||
|
||||
pyfalog = Logger(__name__)
|
||||
|
||||
|
||||
def _t(x):
|
||||
return x
|
||||
|
||||
|
||||
def _c(x):
|
||||
return '[' + x + ']'
|
||||
|
||||
|
||||
BUILTINS = OrderedDict([
|
||||
# 0 is taken by ideal target profile, composed manually in one of TargetProfile methods
|
||||
(-1, ('Uniform (25%)', 0.25, 0.25, 0.25, 0.25)),
|
||||
(-2, ('Uniform (50%)', 0.50, 0.50, 0.50, 0.50)),
|
||||
(-3, ('Uniform (75%)', 0.75, 0.75, 0.75, 0.75)),
|
||||
(-4, ('Uniform (90%)', 0.90, 0.90, 0.90, 0.90)),
|
||||
(-5, ('[T1 Resist]Shield', 0.0, 0.20, 0.40, 0.50)),
|
||||
(-6, ('[T1 Resist]Armor', 0.50, 0.45, 0.25, 0.10)),
|
||||
(-7, ('[T1 Resist]Hull', 0.33, 0.33, 0.33, 0.33)),
|
||||
(-8, ('[T1 Resist]Shield (+T2 DCU)', 0.125, 0.30, 0.475, 0.562)),
|
||||
(-9, ('[T1 Resist]Armor (+T2 DCU)', 0.575, 0.532, 0.363, 0.235)),
|
||||
(-10, ('[T1 Resist]Hull (+T2 DCU)', 0.598, 0.598, 0.598, 0.598)),
|
||||
(-11, ('[T2 Resist]Amarr (Shield)', 0.0, 0.20, 0.70, 0.875)),
|
||||
(-12, ('[T2 Resist]Amarr (Armor)', 0.50, 0.35, 0.625, 0.80)),
|
||||
(-13, ('[T2 Resist]Caldari (Shield)', 0.20, 0.84, 0.76, 0.60)),
|
||||
(-14, ('[T2 Resist]Caldari (Armor)', 0.50, 0.8625, 0.625, 0.10)),
|
||||
(-15, ('[T2 Resist]Gallente (Shield)', 0.0, 0.60, 0.85, 0.50)),
|
||||
(-16, ('[T2 Resist]Gallente (Armor)', 0.50, 0.675, 0.8375, 0.10)),
|
||||
(-17, ('[T2 Resist]Minmatar (Shield)', 0.75, 0.60, 0.40, 0.50)),
|
||||
(-18, ('[T2 Resist]Minmatar (Armor)', 0.90, 0.675, 0.25, 0.10)),
|
||||
(-19, ('[NPC][Asteroid]Angel Cartel', 0.54, 0.42, 0.37, 0.32)),
|
||||
(-20, ('[NPC][Asteroid]Blood Raiders', 0.34, 0.39, 0.45, 0.52)),
|
||||
(-21, ('[NPC][Asteroid]Guristas', 0.55, 0.35, 0.3, 0.48)),
|
||||
(-22, ('[NPC][Asteroid]Rogue Drones', 0.35, 0.38, 0.44, 0.49)),
|
||||
(-23, ('[NPC][Asteroid]Sanshas Nation', 0.35, 0.4, 0.47, 0.53)),
|
||||
(-24, ('[NPC][Asteroid]Serpentis', 0.49, 0.38, 0.29, 0.51)),
|
||||
(-25, ('[NPC][Deadspace]Angel Cartel', 0.59, 0.48, 0.4, 0.32)),
|
||||
(-26, ('[NPC][Deadspace]Blood Raiders', 0.31, 0.39, 0.47, 0.56)),
|
||||
(-27, ('[NPC][Deadspace]Guristas', 0.57, 0.39, 0.31, 0.5)),
|
||||
(-28, ('[NPC][Deadspace]Rogue Drones', 0.42, 0.42, 0.47, 0.49)),
|
||||
(-29, ('[NPC][Deadspace]Sanshas Nation', 0.31, 0.39, 0.47, 0.56)),
|
||||
(-30, ('[NPC][Deadspace]Serpentis', 0.49, 0.38, 0.29, 0.56)),
|
||||
(-31, ('[NPC][Mission]Amarr Empire', 0.34, 0.38, 0.42, 0.46)),
|
||||
(-32, ('[NPC][Mission]Caldari State', 0.51, 0.38, 0.3, 0.51)),
|
||||
(-33, ('[NPC][Mission]CONCORD', 0.47, 0.46, 0.47, 0.47)),
|
||||
(-34, ('[NPC][Mission]Gallente Federation', 0.51, 0.38, 0.31, 0.52)),
|
||||
(-35, ('[NPC][Mission]Khanid', 0.51, 0.42, 0.36, 0.4)),
|
||||
(-36, ('[NPC][Mission]Minmatar Republic', 0.51, 0.46, 0.41, 0.35)),
|
||||
(-37, ('[NPC][Mission]Mordus Legion', 0.32, 0.48, 0.4, 0.62)),
|
||||
(-38, ('[NPC][Other]Sleeper', 0.61, 0.61, 0.61, 0.61)),
|
||||
(-39, ('[NPC][Other]Sansha Incursion', 0.65, 0.63, 0.64, 0.65)),
|
||||
(-40, ('[NPC][Burner]Cruor (Blood Raiders)', 0.8, 0.73, 0.69, 0.67)),
|
||||
(-41, ('[NPC][Burner]Dramiel (Angel)', 0.35, 0.48, 0.61, 0.68)),
|
||||
(-42, ('[NPC][Burner]Daredevil (Serpentis)', 0.69, 0.59, 0.59, 0.43)),
|
||||
(-43, ('[NPC][Burner]Succubus (Sanshas Nation)', 0.35, 0.48, 0.61, 0.68)),
|
||||
(-44, ('[NPC][Burner]Worm (Guristas)', 0.48, 0.58, 0.69, 0.74)),
|
||||
(-45, ('[NPC][Burner]Enyo', 0.58, 0.72, 0.86, 0.24)),
|
||||
(-46, ('[NPC][Burner]Hawk', 0.3, 0.86, 0.79, 0.65)),
|
||||
(-47, ('[NPC][Burner]Jaguar', 0.78, 0.65, 0.48, 0.56)),
|
||||
(-48, ('[NPC][Burner]Vengeance', 0.66, 0.56, 0.75, 0.86)),
|
||||
(-49, ('[NPC][Burner]Ashimmu (Blood Raiders)', 0.8, 0.76, 0.68, 0.7)),
|
||||
(-50, ('[NPC][Burner]Talos', 0.68, 0.59, 0.59, 0.43)),
|
||||
(-51, ('[NPC][Burner]Sentinel', 0.58, 0.45, 0.52, 0.66)),
|
||||
(-1, (_t('Uniform (25%)'), 0.25, 0.25, 0.25, 0.25)),
|
||||
(-2, (_t('Uniform (50%)'), 0.50, 0.50, 0.50, 0.50)),
|
||||
(-3, (_t('Uniform (75%)'), 0.75, 0.75, 0.75, 0.75)),
|
||||
(-4, (_t('Uniform (90%)'), 0.90, 0.90, 0.90, 0.90)),
|
||||
(-5, (_c(_t('T1 Resist')) + _t('Shield'), 0.0, 0.20, 0.40, 0.50)),
|
||||
(-6, (_c(_t('T1 Resist')) + _t('Armor'), 0.50, 0.45, 0.25, 0.10)),
|
||||
(-7, (_c(_t('T1 Resist')) + _t('Hull'), 0.33, 0.33, 0.33, 0.33)),
|
||||
(-8, (_c(_t('T1 Resist')) + _t('Shield (+T2 DCU)'), 0.125, 0.30, 0.475, 0.562)),
|
||||
(-9, (_c(_t('T1 Resist')) + _t('Armor (+T2 DCU)'), 0.575, 0.532, 0.363, 0.235)),
|
||||
(-10, (_c(_t('T1 Resist')) + _t('Hull (+T2 DCU)'), 0.598, 0.598, 0.598, 0.598)),
|
||||
(-11, (_c(_t('T2 Resist')) + _t('Amarr (Shield)'), 0.0, 0.20, 0.70, 0.875)),
|
||||
(-12, (_c(_t('T2 Resist')) + _t('Amarr (Armor)'), 0.50, 0.35, 0.625, 0.80)),
|
||||
(-13, (_c(_t('T2 Resist')) + _t('Caldari (Shield)'), 0.20, 0.84, 0.76, 0.60)),
|
||||
(-14, (_c(_t('T2 Resist')) + _t('Caldari (Armor)'), 0.50, 0.8625, 0.625, 0.10)),
|
||||
(-15, (_c(_t('T2 Resist')) + _t('Gallente (Shield)'), 0.0, 0.60, 0.85, 0.50)),
|
||||
(-16, (_c(_t('T2 Resist')) + _t('Gallente (Armor)'), 0.50, 0.675, 0.8375, 0.10)),
|
||||
(-17, (_c(_t('T2 Resist')) + _t('Minmatar (Shield)'), 0.75, 0.60, 0.40, 0.50)),
|
||||
(-18, (_c(_t('T2 Resist')) + _t('Minmatar (Armor)'), 0.90, 0.675, 0.25, 0.10)),
|
||||
(-19, (_c(_t('NPC')) + _c(_t('Asteroid')) + _t('Angel Cartel'), 0.54, 0.42, 0.37, 0.32)),
|
||||
(-20, (_c(_t('NPC')) + _c(_t('Asteroid')) + _t('Blood Raiders'), 0.34, 0.39, 0.45, 0.52)),
|
||||
(-21, (_c(_t('NPC')) + _c(_t('Asteroid')) + _t('Guristas'), 0.55, 0.35, 0.3, 0.48)),
|
||||
(-22, (_c(_t('NPC')) + _c(_t('Asteroid')) + _t('Rogue Drones'), 0.35, 0.38, 0.44, 0.49)),
|
||||
(-23, (_c(_t('NPC')) + _c(_t('Asteroid')) + _t('Sanshas Nation'), 0.35, 0.4, 0.47, 0.53)),
|
||||
(-24, (_c(_t('NPC')) + _c(_t('Asteroid')) + _t('Serpentis'), 0.49, 0.38, 0.29, 0.51)),
|
||||
(-25, (_c(_t('NPC')) + _c(_t('Deadspace')) + _t('Angel Cartel'), 0.59, 0.48, 0.4, 0.32)),
|
||||
(-26, (_c(_t('NPC')) + _c(_t('Deadspace')) + _t('Blood Raiders'), 0.31, 0.39, 0.47, 0.56)),
|
||||
(-27, (_c(_t('NPC')) + _c(_t('Deadspace')) + _t('Guristas'), 0.57, 0.39, 0.31, 0.5)),
|
||||
(-28, (_c(_t('NPC')) + _c(_t('Deadspace')) + _t('Rogue Drones'), 0.42, 0.42, 0.47, 0.49)),
|
||||
(-29, (_c(_t('NPC')) + _c(_t('Deadspace')) + _t('Sanshas Nation'), 0.31, 0.39, 0.47, 0.56)),
|
||||
(-30, (_c(_t('NPC')) + _c(_t('Deadspace')) + _t('Serpentis'), 0.49, 0.38, 0.29, 0.56)),
|
||||
(-31, (_c(_t('NPC')) + _c(_t('Mission')) + _t('Amarr Empire'), 0.34, 0.38, 0.42, 0.46)),
|
||||
(-32, (_c(_t('NPC')) + _c(_t('Mission')) + _t('Caldari State'), 0.51, 0.38, 0.3, 0.51)),
|
||||
(-33, (_c(_t('NPC')) + _c(_t('Mission')) + _t('CONCORD'), 0.47, 0.46, 0.47, 0.47)),
|
||||
(-34, (_c(_t('NPC')) + _c(_t('Mission')) + _t('Gallente Federation'), 0.51, 0.38, 0.31, 0.52)),
|
||||
(-35, (_c(_t('NPC')) + _c(_t('Mission')) + _t('Khanid'), 0.51, 0.42, 0.36, 0.4)),
|
||||
(-36, (_c(_t('NPC')) + _c(_t('Mission')) + _t('Minmatar Republic'), 0.51, 0.46, 0.41, 0.35)),
|
||||
(-37, (_c(_t('NPC')) + _c(_t('Mission')) + _t('Mordus Legion'), 0.32, 0.48, 0.4, 0.62)),
|
||||
(-38, (_c(_t('NPC')) + _c(_t('Other')) + _t('Sleeper'), 0.61, 0.61, 0.61, 0.61)),
|
||||
(-39, (_c(_t('NPC')) + _c(_t('Other')) + _t('Sansha Incursion'), 0.65, 0.63, 0.64, 0.65)),
|
||||
(-40, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Cruor (Blood Raiders)'), 0.8, 0.73, 0.69, 0.67)),
|
||||
(-41, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Dramiel (Angel)'), 0.35, 0.48, 0.61, 0.68)),
|
||||
(-42, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Daredevil (Serpentis)'), 0.69, 0.59, 0.59, 0.43)),
|
||||
(-43, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Succubus (Sanshas Nation)'), 0.35, 0.48, 0.61, 0.68)),
|
||||
(-44, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Worm (Guristas)'), 0.48, 0.58, 0.69, 0.74)),
|
||||
(-45, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Enyo'), 0.58, 0.72, 0.86, 0.24)),
|
||||
(-46, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Hawk'), 0.3, 0.86, 0.79, 0.65)),
|
||||
(-47, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Jaguar'), 0.78, 0.65, 0.48, 0.56)),
|
||||
(-48, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Vengeance'), 0.66, 0.56, 0.75, 0.86)),
|
||||
(-49, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Ashimmu (Blood Raiders)'), 0.8, 0.76, 0.68, 0.7)),
|
||||
(-50, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Talos'), 0.68, 0.59, 0.59, 0.43)),
|
||||
(-51, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Sentinel'), 0.58, 0.45, 0.52, 0.66)),
|
||||
# Source: ticket #2067
|
||||
(-52, ('[NPC][Invasion]Invading Precursor Entities', 0.422, 0.367, 0.453, 0.411)),
|
||||
(-53, ('[NPC][Invasion]Retaliating Amarr Entities', 0.360, 0.310, 0.441, 0.602)),
|
||||
(-54, ('[NPC][Invasion]Retaliating Caldari Entities', 0.303, 0.610, 0.487, 0.401)),
|
||||
(-55, ('[NPC][Invasion]Retaliating Gallente Entities', 0.383, 0.414, 0.578, 0.513)),
|
||||
(-56, ('[NPC][Invasion]Retaliating Minmatar Entities', 0.620, 0.422, 0.355, 0.399)),
|
||||
(-57, ('[NPC][Abyssal][Dark Matter All Tiers]Drones', 0.439, 0.522, 0.529, 0.435)),
|
||||
(-58, ('[NPC][Abyssal][Dark Matter All Tiers]Overmind', 0.626, 0.576, 0.612, 0.624)),
|
||||
(-59, ('[NPC][Abyssal][Dark Matter All Tiers]Seeker', 0.082, 0.082, 0.082, 0.082)),
|
||||
(-60, ('[NPC][Abyssal][Dark Matter All Tiers]Triglavian', 0.477, 0.401, 0.449, 0.37)),
|
||||
(-61, ('[NPC][Abyssal][Dark Matter All Tiers]Drifter', 0.403, 0.403, 0.403, 0.403)),
|
||||
(-62, ('[NPC][Abyssal][Dark Matter All Tiers]Sleeper', 0.435, 0.435, 0.435, 0.435)),
|
||||
(-63, ('[NPC][Abyssal][Dark Matter All Tiers]All', 0.507, 0.477, 0.502, 0.493)),
|
||||
(-64, ('[NPC][Abyssal][Electrical T1/T2]Drones', 0.323, 0.522, 0.529, 0.435)),
|
||||
(-65, ('[NPC][Abyssal][Electrical T1/T2]Overmind', 0.521, 0.576, 0.612, 0.624)),
|
||||
(-66, ('[NPC][Abyssal][Electrical T1/T2]Seeker', 0, 0.082, 0.082, 0.082)),
|
||||
(-67, ('[NPC][Abyssal][Electrical T1/T2]Triglavian', 0.333, 0.401, 0.449, 0.37)),
|
||||
(-68, ('[NPC][Abyssal][Electrical T1/T2]Drifter', 0.267, 0.403, 0.403, 0.403)),
|
||||
(-69, ('[NPC][Abyssal][Electrical T1/T2]Sleeper', 0.329, 0.435, 0.435, 0.435)),
|
||||
(-70, ('[NPC][Abyssal][Electrical T1/T2]All', 0.385, 0.477, 0.502, 0.493)),
|
||||
(-71, ('[NPC][Abyssal][Electrical T3 (Some T5 Rooms)]Drones', 0.255, 0.522, 0.529, 0.435)),
|
||||
(-72, ('[NPC][Abyssal][Electrical T3 (Some T5 Rooms)]Overmind', 0.457, 0.576, 0.612, 0.624)),
|
||||
(-73, ('[NPC][Abyssal][Electrical T3 (Some T5 Rooms)]Seeker', 0, 0.082, 0.082, 0.082)),
|
||||
(-74, ('[NPC][Abyssal][Electrical T3 (Some T5 Rooms)]Triglavian', 0.241, 0.401, 0.449, 0.37)),
|
||||
(-75, ('[NPC][Abyssal][Electrical T3 (Some T5 Rooms)]Drifter', 0.184, 0.403, 0.403, 0.403)),
|
||||
(-76, ('[NPC][Abyssal][Electrical T3 (Some T5 Rooms)]Sleeper', 0.268, 0.435, 0.435, 0.435)),
|
||||
(-77, ('[NPC][Abyssal][Electrical T3 (Some T5 Rooms)]All', 0.313, 0.477, 0.502, 0.493)),
|
||||
(-78, ('[NPC][Abyssal][Electrical T4/T5]Drones', 0.193, 0.522, 0.529, 0.435)),
|
||||
(-79, ('[NPC][Abyssal][Electrical T4/T5]Overmind', 0.398, 0.576, 0.612, 0.624)),
|
||||
(-80, ('[NPC][Abyssal][Electrical T4/T5]Seeker', 0, 0.082, 0.082, 0.082)),
|
||||
(-81, ('[NPC][Abyssal][Electrical T4/T5]Triglavian', 0.183, 0.401, 0.449, 0.37)),
|
||||
(-82, ('[NPC][Abyssal][Electrical T4/T5]Drifter', 0.107, 0.403, 0.403, 0.403)),
|
||||
(-83, ('[NPC][Abyssal][Electrical T4/T5]Sleeper', 0.215, 0.435, 0.435, 0.435)),
|
||||
(-84, ('[NPC][Abyssal][Electrical T4/T5]All', 0.25, 0.477, 0.502, 0.493)),
|
||||
(-85, ('[NPC][Abyssal][Firestorm T1/T2]Drones', 0.461, 0.425, 0.541, 0.443)),
|
||||
(-86, ('[NPC][Abyssal][Firestorm T1/T2]Overmind', 0.65, 0.469, 0.625, 0.633)),
|
||||
(-87, ('[NPC][Abyssal][Firestorm T1/T2]Seeker', 0.084, 0, 0.084, 0.084)),
|
||||
(-88, ('[NPC][Abyssal][Firestorm T1/T2]Triglavian', 0.534, 0.266, 0.484, 0.366)),
|
||||
(-89, ('[NPC][Abyssal][Firestorm T1/T2]Drifter', 0.422, 0.282, 0.422, 0.422)),
|
||||
(-90, ('[NPC][Abyssal][Firestorm T1/T2]Sleeper', 0.512, 0.402, 0.512, 0.512)),
|
||||
(-91, ('[NPC][Abyssal][Firestorm T1/T2]All', 0.541, 0.365, 0.524, 0.504)),
|
||||
(-92, ('[NPC][Abyssal][Firestorm T3 (Some T5 Rooms)]Drones', 0.461, 0.36, 0.541, 0.443)),
|
||||
(-93, ('[NPC][Abyssal][Firestorm T3 (Some T5 Rooms)]Overmind', 0.65, 0.391, 0.625, 0.633)),
|
||||
(-94, ('[NPC][Abyssal][Firestorm T3 (Some T5 Rooms)]Seeker', 0.084, 0, 0.084, 0.084)),
|
||||
(-95, ('[NPC][Abyssal][Firestorm T3 (Some T5 Rooms)]Triglavian', 0.534, 0.161, 0.484, 0.366)),
|
||||
(-96, ('[NPC][Abyssal][Firestorm T3 (Some T5 Rooms)]Drifter', 0.422, 0.196, 0.422, 0.422)),
|
||||
(-97, ('[NPC][Abyssal][Firestorm T3 (Some T5 Rooms)]Sleeper', 0.512, 0.337, 0.512, 0.512)),
|
||||
(-98, ('[NPC][Abyssal][Firestorm T3 (Some T5 Rooms)]All', 0.541, 0.284, 0.524, 0.504)),
|
||||
(-99, ('[NPC][Abyssal][Firestorm T4/T5]Drones', 0.461, 0.305, 0.541, 0.443)),
|
||||
(-100, ('[NPC][Abyssal][Firestorm T4/T5]Overmind', 0.65, 0.323, 0.625, 0.633)),
|
||||
(-101, ('[NPC][Abyssal][Firestorm T4/T5]Seeker', 0.084, 0, 0.084, 0.084)),
|
||||
(-102, ('[NPC][Abyssal][Firestorm T4/T5]Triglavian', 0.534, 0.082, 0.484, 0.366)),
|
||||
(-103, ('[NPC][Abyssal][Firestorm T4/T5]Drifter', 0.422, 0.114, 0.422, 0.422)),
|
||||
(-104, ('[NPC][Abyssal][Firestorm T4/T5]Sleeper', 0.512, 0.276, 0.512, 0.512)),
|
||||
(-105, ('[NPC][Abyssal][Firestorm T4/T5]All', 0.541, 0.214, 0.524, 0.504)),
|
||||
(-106, ('[NPC][Abyssal][Exotic T1/T2]Drones', 0.439, 0.522, 0.417, 0.435)),
|
||||
(-107, ('[NPC][Abyssal][Exotic T1/T2]Overmind', 0.626, 0.576, 0.496, 0.624)),
|
||||
(-108, ('[NPC][Abyssal][Exotic T1/T2]Seeker', 0.082, 0.082, 0, 0.082)),
|
||||
(-109, ('[NPC][Abyssal][Exotic T1/T2]Triglavian', 0.477, 0.401, 0.284, 0.37)),
|
||||
(-110, ('[NPC][Abyssal][Exotic T1/T2]Drifter', 0.403, 0.403, 0.267, 0.403)),
|
||||
(-111, ('[NPC][Abyssal][Exotic T1/T2]Sleeper', 0.435, 0.435, 0.329, 0.435)),
|
||||
(-112, ('[NPC][Abyssal][Exotic T1/T2]All', 0.507, 0.477, 0.373, 0.493)),
|
||||
(-113, ('[NPC][Abyssal][Exotic T3 (Some T5 Rooms)]Drones', 0.439, 0.522, 0.351, 0.435)),
|
||||
(-114, ('[NPC][Abyssal][Exotic T3 (Some T5 Rooms)]Overmind', 0.626, 0.576, 0.419, 0.624)),
|
||||
(-115, ('[NPC][Abyssal][Exotic T3 (Some T5 Rooms)]Seeker', 0.082, 0.082, 0, 0.082)),
|
||||
(-116, ('[NPC][Abyssal][Exotic T3 (Some T5 Rooms)]Triglavian', 0.477, 0.401, 0.176, 0.37)),
|
||||
(-117, ('[NPC][Abyssal][Exotic T3 (Some T5 Rooms)]Drifter', 0.403, 0.403, 0.184, 0.403)),
|
||||
(-118, ('[NPC][Abyssal][Exotic T3 (Some T5 Rooms)]Sleeper', 0.435, 0.435, 0.268, 0.435)),
|
||||
(-119, ('[NPC][Abyssal][Exotic T3 (Some T5 Rooms)]All', 0.507, 0.477, 0.293, 0.493)),
|
||||
(-120, ('[NPC][Abyssal][Exotic T4/T5]Drones', 0.439, 0.522, 0.293, 0.435)),
|
||||
(-121, ('[NPC][Abyssal][Exotic T4/T5]Overmind', 0.626, 0.576, 0.344, 0.624)),
|
||||
(-122, ('[NPC][Abyssal][Exotic T4/T5]Seeker', 0.082, 0.082, 0, 0.082)),
|
||||
(-123, ('[NPC][Abyssal][Exotic T4/T5]Triglavian', 0.477, 0.401, 0.107, 0.37)),
|
||||
(-124, ('[NPC][Abyssal][Exotic T4/T5]Drifter', 0.403, 0.403, 0.107, 0.403)),
|
||||
(-125, ('[NPC][Abyssal][Exotic T4/T5]Sleeper', 0.435, 0.435, 0.215, 0.435)),
|
||||
(-126, ('[NPC][Abyssal][Exotic T4/T5]All', 0.507, 0.477, 0.223, 0.493)),
|
||||
(-127, ('[NPC][Abyssal][Gamma T1/T2]Drones', 0.449, 0.54, 0.549, 0.336)),
|
||||
(-128, ('[NPC][Abyssal][Gamma T1/T2]Overmind', 0.6, 0.557, 0.601, 0.504)),
|
||||
(-129, ('[NPC][Abyssal][Gamma T1/T2]Seeker', 0.085, 0.085, 0.085, 0)),
|
||||
(-130, ('[NPC][Abyssal][Gamma T1/T2]Triglavian', 0.463, 0.392, 0.447, 0.193)),
|
||||
(-131, ('[NPC][Abyssal][Gamma T1/T2]Drifter', 0.428, 0.428, 0.428, 0.287)),
|
||||
(-132, ('[NPC][Abyssal][Gamma T1/T2]Sleeper', 0.435, 0.435, 0.435, 0.329)),
|
||||
(-133, ('[NPC][Abyssal][Gamma T1/T2]All', 0.493, 0.472, 0.5, 0.362)),
|
||||
(-134, ('[NPC][Abyssal][Gamma T3 (Some T5 Rooms)]Drones', 0.449, 0.54, 0.549, 0.264)),
|
||||
(-135, ('[NPC][Abyssal][Gamma T3 (Some T5 Rooms)]Overmind', 0.6, 0.557, 0.601, 0.428)),
|
||||
(-136, ('[NPC][Abyssal][Gamma T3 (Some T5 Rooms)]Seeker', 0.085, 0.085, 0.085, 0)),
|
||||
(-137, ('[NPC][Abyssal][Gamma T3 (Some T5 Rooms)]Triglavian', 0.463, 0.392, 0.447, 0.071)),
|
||||
(-138, ('[NPC][Abyssal][Gamma T3 (Some T5 Rooms)]Drifter', 0.428, 0.428, 0.428, 0.2)),
|
||||
(-139, ('[NPC][Abyssal][Gamma T3 (Some T5 Rooms)]Sleeper', 0.435, 0.435, 0.435, 0.268)),
|
||||
(-140, ('[NPC][Abyssal][Gamma T3 (Some T5 Rooms)]All', 0.493, 0.472, 0.5, 0.28)),
|
||||
(-141, ('[NPC][Abyssal][Gamma T4/T5]Drones', 0.449, 0.54, 0.549, 0.197)),
|
||||
(-142, ('[NPC][Abyssal][Gamma T4/T5]Overmind', 0.6, 0.557, 0.601, 0.356)),
|
||||
(-143, ('[NPC][Abyssal][Gamma T4/T5]Seeker', 0.085, 0.085, 0.085, 0)),
|
||||
(-144, ('[NPC][Abyssal][Gamma T4/T5]Triglavian', 0.463, 0.392, 0.447, 0.029)),
|
||||
(-145, ('[NPC][Abyssal][Gamma T4/T5]Drifter', 0.428, 0.428, 0.428, 0.117)),
|
||||
(-146, ('[NPC][Abyssal][Gamma T4/T5]Sleeper', 0.435, 0.435, 0.435, 0.215)),
|
||||
(-147, ('[NPC][Abyssal][Gamma T4/T5]All', 0.493, 0.472, 0.5, 0.21))])
|
||||
(-52, (_c(_t('NPC')) + _c(_t('Invasion')) + _t('Triglavian Entities'), 0.422, 0.367, 0.453, 0.411)),
|
||||
(-53, (_c(_t('NPC')) + _c(_t('Invasion')) + _t('Amarr EDENCOM Entities'), 0.360, 0.310, 0.441, 0.602)),
|
||||
(-54, (_c(_t('NPC')) + _c(_t('Invasion')) + _t('Caldari EDENCOM Entities'), 0.303, 0.610, 0.487, 0.401)),
|
||||
(-55, (_c(_t('NPC')) + _c(_t('Invasion')) + _t('Gallente EDENCOM Entities'), 0.383, 0.414, 0.578, 0.513)),
|
||||
(-56, (_c(_t('NPC')) + _c(_t('Invasion')) + _t('Minmatar EDENCOM Entities'), 0.620, 0.422, 0.355, 0.399)),
|
||||
(-57, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Dark Matter All Tiers')) + _t('Drones'), 0.439, 0.522, 0.529, 0.435)),
|
||||
(-58, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Dark Matter All Tiers')) + _t('Overmind'), 0.643, 0.593, 0.624, 0.639)),
|
||||
(-59, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Dark Matter All Tiers')) + _t('Seeker'), 0.082, 0.082, 0.082, 0.082)),
|
||||
(-60, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Dark Matter All Tiers')) + _t('Triglavian'), 0.494, 0.41, 0.464, 0.376)),
|
||||
(-61, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Dark Matter All Tiers')) + _t('Drifter'), 0.415, 0.415, 0.415, 0.415)),
|
||||
(-62, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Dark Matter All Tiers')) + _t('Sleeper'), 0.435, 0.435, 0.435, 0.435)),
|
||||
(-63, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Dark Matter All Tiers')) + _t('All'), 0.508, 0.474, 0.495, 0.488)),
|
||||
(-64, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T0/T1/T2')) + _t('Drones'), 0.323, 0.522, 0.529, 0.435)),
|
||||
(-65, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T0/T1/T2')) + _t('Overmind'), 0.542, 0.593, 0.624, 0.639)),
|
||||
(-66, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T0/T1/T2')) + _t('Seeker'), 0, 0.082, 0.082, 0.082)),
|
||||
(-67, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T0/T1/T2')) + _t('Triglavian'), 0.356, 0.41, 0.464, 0.376)),
|
||||
(-68, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T0/T1/T2')) + _t('Drifter'), 0.277, 0.415, 0.415, 0.415)),
|
||||
(-69, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T0/T1/T2')) + _t('Sleeper'), 0.329, 0.435, 0.435, 0.435)),
|
||||
(-70, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T0/T1/T2')) + _t('All'), 0.381, 0.474, 0.495, 0.488)),
|
||||
(-71, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T3 (Some T5 Rooms)')) + _t('Drones'), 0.255, 0.522, 0.529, 0.435)),
|
||||
(-72, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T3 (Some T5 Rooms)')) + _t('Overmind'), 0.48, 0.593, 0.624, 0.639)),
|
||||
(-73, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T3 (Some T5 Rooms)')) + _t('Seeker'), 0, 0.082, 0.082, 0.0822)),
|
||||
(-74, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T3 (Some T5 Rooms)')) + _t('Triglavian'), 0.268, 0.41, 0.464, 0.376)),
|
||||
(-75, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T3 (Some T5 Rooms)')) + _t('Drifter'), 0.191, 0.415, 0.415, 0.415)),
|
||||
(-76, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T3 (Some T5 Rooms)')) + _t('Sleeper'), 0.268, 0.435, 0.435, 0.435)),
|
||||
(-77, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T3 (Some T5 Rooms)')) + _t('All'), 0.308, 0.474, 0.495, 0.488)),
|
||||
(-78, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T4/T5/T6')) + _t('Drones'), 0.193, 0.522, 0.529, 0.435)),
|
||||
(-79, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T4/T5/T6')) + _t('Overmind'), 0.423, 0.593, 0.624, 0.639)),
|
||||
(-80, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T4/T5/T6')) + _t('Seeker'), 0, 0.082, 0.082, 0.082)),
|
||||
(-81, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T4/T5/T6')) + _t('Triglavian'), 0.206, 0.41, 0.464, 0.376)),
|
||||
(-82, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T4/T5/T6')) + _t('Drifter'), 0.111, 0.415, 0.415, 0.415)),
|
||||
(-83, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T4/T5/T6')) + _t('Sleeper'), 0.215, 0.435, 0.435, 0.435)),
|
||||
(-84, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T4/T5/T6')) + _t('All'), 0.247, 0.474, 0.495, 0.488)),
|
||||
(-85, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T0/T1/T2')) + _t('Drones'), 0.461, 0.425, 0.541, 0.443)),
|
||||
(-86, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T0/T1/T2')) + _t('Overmind'), 0.666, 0.489, 0.634, 0.646)),
|
||||
(-87, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T0/T1/T2')) + _t('Seeker'), 0.084, 0, 0.084, 0.084)),
|
||||
(-88, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T0/T1/T2')) + _t('Triglavian'), 0.537, 0.269, 0.489, 0.371)),
|
||||
(-89, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T0/T1/T2')) + _t('Drifter'), 0.43, 0.289, 0.43, 0.43)),
|
||||
(-90, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T0/T1/T2')) + _t('Sleeper'), 0.512, 0.402, 0.512, 0.512)),
|
||||
(-91, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T0/T1/T2')) + _t('All'), 0.537, 0.352, 0.512, 0.495)),
|
||||
(-92, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T3 (Some T5 Rooms)')) + _t('Drones'), 0.461, 0.36, 0.541, 0.443)),
|
||||
(-93, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T3 (Some T5 Rooms)')) + _t('Overmind'), 0.666, 0.413, 0.634, 0.646)),
|
||||
(-94, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T3 (Some T5 Rooms)')) + _t('Seeker'), 0.084, 0, 0.084, 0.084)),
|
||||
(-95, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T3 (Some T5 Rooms)')) + _t('Triglavian'), 0.537, 0.166, 0.489, 0.371)),
|
||||
(-96, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T3 (Some T5 Rooms)')) + _t('Drifter'), 0.43, 0.201, 0.43, 0.43)),
|
||||
(-97, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T3 (Some T5 Rooms)')) + _t('Sleeper'), 0.512, 0.337, 0.512, 0.512)),
|
||||
(-98, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T3 (Some T5 Rooms)')) + _t('All'), 0.537, 0.269, 0.512, 0.495)),
|
||||
(-99, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T4/T5/T6')) + _t('Drones'), 0.461, 0.305, 0.541, 0.443)),
|
||||
(-100, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T4/T5/T6')) + _t('Overmind'), 0.666, 0.345, 0.634, 0.646)),
|
||||
(-101, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T4/T5/T6')) + _t('Seeker'), 0.084, 0, 0.084, 0.084)),
|
||||
(-102, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T4/T5/T6')) + _t('Triglavian'), 0.537, 0.085, 0.489, 0.371)),
|
||||
(-103, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T4/T5/T6')) + _t('Drifter'), 0.43, 0.117, 0.43, 0.43)),
|
||||
(-104, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T4/T5/T6')) + _t('Sleeper'), 0.512, 0.276, 0.512, 0.512)),
|
||||
(-105, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T4/T5/T6')) + _t('All'), 0.537, 0.201, 0.512, 0.495)),
|
||||
(-106, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T0/T1/T2')) + _t('Drones'), 0.439, 0.522, 0.417, 0.435)),
|
||||
(-107, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T0/T1/T2')) + _t('Overmind'), 0.643, 0.593, 0.511, 0.639)),
|
||||
(-108, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T0/T1/T2')) + _t('Seeker'), 0.082, 0.082, 0, 0.082)),
|
||||
(-109, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T0/T1/T2')) + _t('Triglavian'), 0.494, 0.41, 0.304, 0.376)),
|
||||
(-110, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T0/T1/T2')) + _t('Drifter'), 0.415, 0.415, 0.277, 0.415)),
|
||||
(-111, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T0/T1/T2')) + _t('Sleeper'), 0.435, 0.435, 0.329, 0.435)),
|
||||
(-112, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T0/T1/T2')) + _t('All'), 0.508, 0.474, 0.359, 0.488)),
|
||||
(-113, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T3 (Some T5 Rooms)')) + _t('Drones'), 0.439, 0.522, 0.351, 0.435)),
|
||||
(-114, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T3 (Some T5 Rooms)')) + _t('Overmind'), 0.643, 0.593, 0.435, 0.639)),
|
||||
(-115, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T3 (Some T5 Rooms)')) + _t('Seeker'), 0.082, 0.082, 0, 0.082)),
|
||||
(-116, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T3 (Some T5 Rooms)')) + _t('Triglavian'), 0.494, 0.41, 0.198, 0.376)),
|
||||
(-117, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T3 (Some T5 Rooms)')) + _t('Drifter'), 0.415, 0.415, 0.191, 0.415)),
|
||||
(-118, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T3 (Some T5 Rooms)')) + _t('Sleeper'), 0.435, 0.435, 0.268, 0.435)),
|
||||
(-119, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T3 (Some T5 Rooms)')) + _t('All'), 0.508, 0.474, 0.276, 0.488)),
|
||||
(-120, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T4/T5/T6')) + _t('Drones'), 0.439, 0.522, 0.293, 0.435)),
|
||||
(-121, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T4/T5/T6')) + _t('Overmind'), 0.643, 0.593, 0.362, 0.639)),
|
||||
(-122, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T4/T5/T6')) + _t('Seeker'), 0.082, 0.082, 0, 0.082)),
|
||||
(-123, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T4/T5/T6')) + _t('Triglavian'), 0.494, 0.41, 0.122, 0.376)),
|
||||
(-124, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T4/T5/T6')) + _t('Drifter'), 0.415, 0.415, 0.111, 0.415)),
|
||||
(-125, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T4/T5/T6')) + _t('Sleeper'), 0.435, 0.435, 0.215, 0.435)),
|
||||
(-126, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T4/T5/T6')) + _t('All'), 0.508, 0.474, 0.208, 0.488)),
|
||||
(-127, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T0/T1/T2')) + _t('Drones'), 0.449, 0.54, 0.549, 0.336)),
|
||||
(-128, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T0/T1/T2')) + _t('Overmind'), 0.619, 0.574, 0.612, 0.522)),
|
||||
(-129, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T0/T1/T2')) + _t('Seeker'), 0.085, 0.085, 0.085, 0)),
|
||||
(-130, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T0/T1/T2')) + _t('Triglavian'), 0.477, 0.4, 0.461, 0.202)),
|
||||
(-131, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T0/T1/T2')) + _t('Drifter'), 0.437, 0.437, 0.437, 0.295)),
|
||||
(-132, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T0/T1/T2')) + _t('Sleeper'), 0.435, 0.435, 0.435, 0.329)),
|
||||
(-133, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T0/T1/T2')) + _t('All'), 0.493, 0.468, 0.492, 0.35)),
|
||||
(-134, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T3 (Some T5 Rooms)')) + _t('Drones'), 0.449, 0.54, 0.549, 0.264)),
|
||||
(-135, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T3 (Some T5 Rooms)')) + _t('Overmind'), 0.619, 0.574, 0.612, 0.449)),
|
||||
(-136, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T3 (Some T5 Rooms)')) + _t('Seeker'), 0.085, 0.085, 0.085, 0)),
|
||||
(-137, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T3 (Some T5 Rooms)')) + _t('Triglavian'), 0.477, 0.4, 0.461, 0.081)),
|
||||
(-138, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T3 (Some T5 Rooms)')) + _t('Drifter'), 0.437, 0.437, 0.437, 0.206)),
|
||||
(-139, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T3 (Some T5 Rooms)')) + _t('Sleeper'), 0.435, 0.435, 0.435, 0.268)),
|
||||
(-140, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T3 (Some T5 Rooms)')) + _t('All'), 0.493, 0.468, 0.492, 0.264)),
|
||||
(-141, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T4/T5/T6')) + _t('Drones'), 0.449, 0.54, 0.549, 0.197)),
|
||||
(-142, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T4/T5/T6')) + _t('Overmind'), 0.619, 0.574, 0.612, 0.379)),
|
||||
(-143, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T4/T5/T6')) + _t('Seeker'), 0.085, 0.085, 0.085, 0)),
|
||||
(-144, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T4/T5/T6')) + _t('Triglavian'), 0.477, 0.4, 0.461, 0.034)),
|
||||
(-145, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T4/T5/T6')) + _t('Drifter'), 0.437, 0.437, 0.437, 0.121)),
|
||||
(-146, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T4/T5/T6')) + _t('Sleeper'), 0.435, 0.435, 0.435, 0.215)),
|
||||
(-147, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T4/T5/T6')) + _t('All'), 0.493, 0.468, 0.492, 0.196)),
|
||||
# Source: ticket #2265
|
||||
(-148, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Dark Matter All Tiers')) + _t('Concord'), 0.324, 0.318, 0.369, 0.372)),
|
||||
(-149, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Dark Matter All Tiers')) + _t('Sansha'), 0.137, 0.331, 0.332, 0.322)),
|
||||
(-150, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Dark Matter All Tiers')) + _t('Angel'), 0.582, 0.508, 0.457, 0.416)),
|
||||
(-151, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T0/T1/T2')) + _t('Concord'), 0.121, 0.318, 0.369, 0.372)),
|
||||
(-152, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T0/T1/T2')) + _t('Sansha'), 0.034, 0.331, 0.332, 0.322)),
|
||||
(-153, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T0/T1/T2')) + _t('Angel'), 0.456, 0.508, 0.457, 0.416)),
|
||||
(-154, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T3 (Some T5 Rooms)')) + _t('Concord'), 0.025, 0.318, 0.369, 0.372)),
|
||||
(-155, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T3 (Some T5 Rooms)')) + _t('Sansha'), 0.018, 0.331, 0.332, 0.322)),
|
||||
(-156, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T3 (Some T5 Rooms)')) + _t('Angel'), 0.373, 0.508, 0.457, 0.416)),
|
||||
(-157, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T4/T5/T6')) + _t('Concord'), 0.008, 0.318, 0.369, 0.372)),
|
||||
(-158, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T4/T5/T6')) + _t('Sansha'), 0.009, 0.331, 0.332, 0.322)),
|
||||
(-159, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T4/T5/T6')) + _t('Angel'), 0.3, 0.508, 0.457, 0.416)),
|
||||
(-160, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T0/T1/T2')) + _t('Concord'), 0.324, 0.107, 0.369, 0.372)),
|
||||
(-161, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T0/T1/T2')) + _t('Sansha'), 0.148, 0.181, 0.329, 0.328)),
|
||||
(-162, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T0/T1/T2')) + _t('Angel'), 0.587, 0.342, 0.439, 0.39)),
|
||||
(-163, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T3 (Some T5 Rooms)')) + _t('Concord'), 0.324, 0.016, 0.369, 0.372)),
|
||||
(-164, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T3 (Some T5 Rooms)')) + _t('Sansha'), 0.148, 0.14, 0.329, 0.328)),
|
||||
(-165, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T3 (Some T5 Rooms)')) + _t('Angel'), 0.587, 0.241, 0.439, 0.39)),
|
||||
(-166, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T4/T5/T6')) + _t('Concord'), 0.324, 0.004, 0.369, 0.372)),
|
||||
(-167, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T4/T5/T6')) + _t('Sansha'), 0.148, 0.106, 0.329, 0.328)),
|
||||
(-168, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T4/T5/T6')) + _t('Angel'), 0.587, 0.172, 0.439, 0.39)),
|
||||
(-169, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T0/T1/T2')) + _t('Concord'), 0.324, 0.318, 0.18, 0.372)),
|
||||
(-170, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T0/T1/T2')) + _t('Sansha'), 0.137, 0.331, 0.166, 0.322)),
|
||||
(-171, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T0/T1/T2')) + _t('Angel'), 0.582, 0.508, 0.295, 0.416)),
|
||||
(-172, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T3 (Some T5 Rooms)')) + _t('Concord'), 0.324, 0.318, 0.089, 0.372)),
|
||||
(-173, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T3 (Some T5 Rooms)')) + _t('Sansha'), 0.137, 0.331, 0.108, 0.322)),
|
||||
(-174, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T3 (Some T5 Rooms)')) + _t('Angel'), 0.582, 0.508, 0.203, 0.416)),
|
||||
(-175, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T4/T5/T6')) + _t('Concord'), 0.324, 0.318, 0.068, 0.372)),
|
||||
(-176, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T4/T5/T6')) + _t('Sansha'), 0.137, 0.331, 0.073, 0.322)),
|
||||
(-177, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T4/T5/T6')) + _t('Angel'), 0.582, 0.508, 0.14, 0.416)),
|
||||
(-178, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T0/T1/T2')) + _t('Concord'), 0.324, 0.318, 0.369, 0.203)),
|
||||
(-179, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T0/T1/T2')) + _t('Sansha'), 0.137, 0.355, 0.352, 0.16)),
|
||||
(-180, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T0/T1/T2')) + _t('Angel'), 0.59, 0.528, 0.477, 0.286)),
|
||||
(-181, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T3 (Some T5 Rooms)')) + _t('Concord'), 0.324, 0.318, 0.369, 0.112)),
|
||||
(-182, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T3 (Some T5 Rooms)')) + _t('Sansha'), 0.137, 0.355, 0.352, 0.05)),
|
||||
(-183, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T3 (Some T5 Rooms)')) + _t('Angel'), 0.59, 0.528, 0.477, 0.197)),
|
||||
(-184, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T4/T5/T6')) + _t('Concord'), 0.324, 0.318, 0.369, 0.086)),
|
||||
(-185, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T4/T5/T6')) + _t('Sansha'), 0.137, 0.355, 0.352, 0)),
|
||||
(-186, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T4/T5/T6')) + _t('Angel'), 0.59, 0.528, 0.477, 0.126)),
|
||||
(-187, (_c(_t('NPC')) + _c(_t('Invasion')) + _t('Drifter Entities'), 0.128, 0.375, 0.383, 0.383)),
|
||||
(-188, (_c(_t('NPC')) + _c(_t('Invasion')) + _t('Rogue Drone Entities'), 0.104, 0.147, 0.147, 0.102)),
|
||||
(-189, (_c(_t('NPC')) + _c(_t('Invasion')) + _t('Sleeper Entities'), 0.563, 0.563, 0.563, 0.563))])
|
||||
|
||||
|
||||
class TargetProfile:
|
||||
|
||||
# also determined import/export order - VERY IMPORTANT
|
||||
DAMAGE_TYPES = ('em', 'thermal', 'kinetic', 'explosive')
|
||||
_idealTarget = None
|
||||
@@ -234,14 +283,14 @@ class TargetProfile:
|
||||
def getIdeal(cls):
|
||||
if cls._idealTarget is None:
|
||||
cls._idealTarget = cls(
|
||||
emAmount=0,
|
||||
thermalAmount=0,
|
||||
kineticAmount=0,
|
||||
explosiveAmount=0,
|
||||
maxVelocity=0,
|
||||
signatureRadius=None,
|
||||
radius=0)
|
||||
cls._idealTarget.rawName = 'Ideal Target'
|
||||
emAmount=0,
|
||||
thermalAmount=0,
|
||||
kineticAmount=0,
|
||||
explosiveAmount=0,
|
||||
maxVelocity=0,
|
||||
signatureRadius=None,
|
||||
radius=0)
|
||||
cls._idealTarget.rawName = _t('Ideal Target')
|
||||
cls._idealTarget.ID = 0
|
||||
cls._idealTarget.builtin = True
|
||||
return cls._idealTarget
|
||||
@@ -399,7 +448,7 @@ class TargetProfile:
|
||||
|
||||
def __deepcopy__(self, memo):
|
||||
p = TargetProfile(
|
||||
self.emAmount, self.thermalAmount, self.kineticAmount, self.explosiveAmount,
|
||||
self._maxVelocity, self._signatureRadius, self._radius)
|
||||
self.emAmount, self.thermalAmount, self.kineticAmount, self.explosiveAmount,
|
||||
self._maxVelocity, self._signatureRadius, self._radius)
|
||||
p.rawName = "%s copy" % self.rawName
|
||||
return p
|
||||
|
||||
@@ -22,6 +22,10 @@ from eos.utils.float import floatUnerr
|
||||
from utils.repr import makeReprStr
|
||||
|
||||
|
||||
def _t(x):
|
||||
return x
|
||||
|
||||
|
||||
class DmgTypes:
|
||||
"""Container for damage data stats."""
|
||||
|
||||
@@ -116,7 +120,7 @@ class DmgTypes:
|
||||
|
||||
@staticmethod
|
||||
def names(short=None, postProcessor=None):
|
||||
value = ['em', 'th', 'kin', 'exp'] if short else ['em', 'thermal', 'kinetic', 'explosive']
|
||||
value = [_t('em'), _t('th'), _t('kin'), _t('exp')] if short else [_t('em'), _t('thermal'), _t('kinetic'), _t('explosive')]
|
||||
|
||||
if postProcessor:
|
||||
value = [postProcessor(x) for x in value]
|
||||
|
||||
@@ -18,31 +18,34 @@
|
||||
# =============================================================================
|
||||
|
||||
|
||||
from graphs.data.base import FitGraph, XDef, YDef, Input, InputCheckbox
|
||||
import wx
|
||||
|
||||
from graphs.data.base import FitGraph, Input, InputCheckbox, XDef, YDef
|
||||
from .getter import CapAmount2CapAmountGetter, CapAmount2CapRegenGetter, Time2CapAmountGetter, Time2CapRegenGetter
|
||||
|
||||
_t = wx.GetTranslation
|
||||
|
||||
|
||||
class FitCapacitorGraph(FitGraph):
|
||||
|
||||
# UI stuff
|
||||
internalName = 'capacitorGraph'
|
||||
name = 'Capacitor'
|
||||
name = _t('Capacitor')
|
||||
xDefs = [
|
||||
XDef(handle='time', unit='s', label='Time', mainInput=('time', 's')),
|
||||
XDef(handle='capAmount', unit='GJ', label='Cap amount', mainInput=('capAmount', '%')),
|
||||
XDef(handle='capAmount', unit='%', label='Cap amount', mainInput=('capAmount', '%'))]
|
||||
XDef(handle='time', unit='s', label=_t('Time'), mainInput=('time', 's')),
|
||||
XDef(handle='capAmount', unit='GJ', label=_t('Cap amount'), mainInput=('capAmount', '%')),
|
||||
XDef(handle='capAmount', unit='%', label=_t('Cap amount'), mainInput=('capAmount', '%'))]
|
||||
yDefs = [
|
||||
YDef(handle='capAmount', unit='GJ', label='Cap amount'),
|
||||
YDef(handle='capRegen', unit='GJ/s', label='Cap regen')]
|
||||
YDef(handle='capAmount', unit='GJ', label=_t('Cap amount')),
|
||||
YDef(handle='capRegen', unit='GJ/s', label=_t('Cap regen'))]
|
||||
inputs = [
|
||||
Input(handle='time', unit='s', label='Time', iconID=1392, defaultValue=120, defaultRange=(0, 300), conditions=[
|
||||
Input(handle='time', unit='s', label=_t('Time'), iconID=1392, defaultValue=120, defaultRange=(0, 300), conditions=[
|
||||
(('time', 's'), None)]),
|
||||
Input(handle='capAmount', unit='%', label='Cap amount', iconID=1668, defaultValue=25, defaultRange=(0, 100), conditions=[
|
||||
Input(handle='capAmount', unit='%', label=_t('Cap amount'), iconID=1668, defaultValue=25, defaultRange=(0, 100), conditions=[
|
||||
(('capAmount', 'GJ'), None),
|
||||
(('capAmount', '%'), None)]),
|
||||
Input(handle='capAmountT0', unit='%', label='Starting cap amount', iconID=1668, defaultValue=100, defaultRange=(0, 100), conditions=[
|
||||
Input(handle='capAmountT0', unit='%', label=_t('Starting cap amount'), iconID=1668, defaultValue=100, defaultRange=(0, 100), conditions=[
|
||||
(('time', 's'), None)])]
|
||||
checkboxes = [InputCheckbox(handle='useCapsim', label='Use capacitor simulator', defaultValue=True, conditions=[
|
||||
checkboxes = [InputCheckbox(handle='useCapsim', label=_t('Use capacitor simulator'), defaultValue=True, conditions=[
|
||||
(('time', 's'), ('capAmount', 'GJ'))])]
|
||||
srcExtraCols = ('CapAmount', 'CapTime')
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ class ProjectedDataCache(FitDataCache):
|
||||
if 'doomsdayAOEWeb' in mod.item.effects:
|
||||
webMods.append(ModProjData(
|
||||
mod.getModifiedItemAttr('speedFactor'),
|
||||
max(0, (mod.maxRange or 0) + mod.getModifiedItemAttr('doomsdayAOERange') - src.getRadius()),
|
||||
max(0, (mod.maxRange or 0) + mod.getModifiedItemAttr('doomsdayAOERange')),
|
||||
mod.falloff or 0,
|
||||
'default',
|
||||
getResistanceAttrID(modifyingItem=mod, effect=mod.item.effects['doomsdayAOEWeb'])))
|
||||
@@ -65,7 +65,7 @@ class ProjectedDataCache(FitDataCache):
|
||||
if 'doomsdayAOEPaint' in mod.item.effects:
|
||||
tpMods.append(ModProjData(
|
||||
mod.getModifiedItemAttr('signatureRadiusBonus'),
|
||||
max(0, (mod.maxRange or 0) + mod.getModifiedItemAttr('doomsdayAOERange') - src.getRadius()),
|
||||
max(0, (mod.maxRange or 0) + mod.getModifiedItemAttr('doomsdayAOERange')),
|
||||
mod.falloff or 0,
|
||||
'default',
|
||||
getResistanceAttrID(modifyingItem=mod, effect=mod.item.effects['doomsdayAOEPaint'])))
|
||||
|
||||
@@ -18,15 +18,17 @@
|
||||
# =============================================================================
|
||||
|
||||
|
||||
from graphs.data.base import FitGraph, XDef, YDef, Input, VectorDef
|
||||
import wx
|
||||
|
||||
from graphs.data.base import FitGraph, Input, VectorDef, XDef, YDef
|
||||
from service.const import GraphCacheCleanupReason
|
||||
from service.settings import GraphSettings
|
||||
from .cache import ProjectedDataCache, TimeCache
|
||||
from .getter import (
|
||||
Distance2DpsGetter, Distance2VolleyGetter, Distance2InflictedDamageGetter,
|
||||
Time2DpsGetter, Time2VolleyGetter, Time2InflictedDamageGetter,
|
||||
TgtSpeed2DpsGetter, TgtSpeed2VolleyGetter, TgtSpeed2InflictedDamageGetter,
|
||||
TgtSigRadius2DpsGetter, TgtSigRadius2VolleyGetter, TgtSigRadius2InflictedDamageGetter)
|
||||
from .getter import (Distance2DpsGetter, Distance2InflictedDamageGetter, Distance2VolleyGetter, TgtSigRadius2DpsGetter, TgtSigRadius2InflictedDamageGetter,
|
||||
TgtSigRadius2VolleyGetter, TgtSpeed2DpsGetter, TgtSpeed2InflictedDamageGetter, TgtSpeed2VolleyGetter, Time2DpsGetter,
|
||||
Time2InflictedDamageGetter, Time2VolleyGetter)
|
||||
|
||||
_t = wx.GetTranslation
|
||||
|
||||
|
||||
class FitDamageStatsGraph(FitGraph):
|
||||
@@ -51,23 +53,26 @@ class FitDamageStatsGraph(FitGraph):
|
||||
|
||||
# UI stuff
|
||||
internalName = 'dmgStatsGraph'
|
||||
name = 'Damage Stats'
|
||||
name = _t('Damage Stats')
|
||||
xDefs = [
|
||||
XDef(handle='distance', unit='km', label='Distance', mainInput=('distance', 'km')),
|
||||
XDef(handle='time', unit='s', label='Time', mainInput=('time', 's')),
|
||||
XDef(handle='tgtSpeed', unit='m/s', label='Target speed', mainInput=('tgtSpeed', '%')),
|
||||
XDef(handle='tgtSpeed', unit='%', label='Target speed', mainInput=('tgtSpeed', '%')),
|
||||
XDef(handle='tgtSigRad', unit='m', label='Target signature radius', mainInput=('tgtSigRad', '%')),
|
||||
XDef(handle='tgtSigRad', unit='%', label='Target signature radius', mainInput=('tgtSigRad', '%'))]
|
||||
XDef(handle='distance', unit='km', label=_t('Distance'), mainInput=('distance', 'km')),
|
||||
XDef(handle='time', unit='s', label=_t('Time'), mainInput=('time', 's')),
|
||||
XDef(handle='tgtSpeed', unit='m/s', label=_t('Target speed'), mainInput=('tgtSpeed', '%')),
|
||||
XDef(handle='tgtSpeed', unit='%', label=_t('Target speed'), mainInput=('tgtSpeed', '%')),
|
||||
XDef(handle='tgtSigRad', unit='m', label=_t('Target signature radius'), mainInput=('tgtSigRad', '%')),
|
||||
XDef(handle='tgtSigRad', unit='%', label=_t('Target signature radius'), mainInput=('tgtSigRad', '%'))]
|
||||
inputs = [
|
||||
Input(handle='distance', unit='km', label='Distance', iconID=1391, defaultValue=None, defaultRange=(0, 100), mainTooltip='Distance between the attacker and the target, as seen in overview (surface-to-surface)', secondaryTooltip='Distance between the attacker and the target, as seen in overview (surface-to-surface)\nWhen set, places the target that far away from the attacker\nWhen not set, attacker\'s weapons always hit the target'),
|
||||
Input(handle='time', unit='s', label='Time', iconID=1392, defaultValue=None, defaultRange=(0, 80), secondaryTooltip='When set, uses attacker\'s exact damage stats at a given time\nWhen not set, uses attacker\'s damage stats as shown in stats panel of main window'),
|
||||
Input(handle='tgtSpeed', unit='%', label='Target speed', iconID=1389, defaultValue=100, defaultRange=(0, 100)),
|
||||
Input(handle='tgtSigRad', unit='%', label='Target signature', iconID=1390, defaultValue=100, defaultRange=(100, 200), conditions=[
|
||||
Input(handle='distance', unit='km', label=_t('Distance'), iconID=1391, defaultValue=None, defaultRange=(0, 100),
|
||||
mainTooltip=_t('Distance between the attacker and the target, as seen in overview (surface-to-surface)'),
|
||||
secondaryTooltip=_t('Distance between the attacker and the target, as seen in overview (surface-to-surface)\nWhen set, places the target that far away from the attacker\nWhen not set, attacker\'s weapons always hit the target')),
|
||||
Input(handle='time', unit='s', label=_t('Time'), iconID=1392, defaultValue=None, defaultRange=(0, 80),
|
||||
secondaryTooltip=_t('When set, uses attacker\'s exact damage stats at a given time\nWhen not set, uses attacker\'s damage stats as shown in stats panel of main window')),
|
||||
Input(handle='tgtSpeed', unit='%', label=_t('Target speed'), iconID=1389, defaultValue=100, defaultRange=(0, 100)),
|
||||
Input(handle='tgtSigRad', unit='%', label=_t('Target signature'), iconID=1390, defaultValue=100, defaultRange=(100, 200), conditions=[
|
||||
(('tgtSigRad', 'm'), None),
|
||||
(('tgtSigRad', '%'), None)])]
|
||||
srcVectorDef = VectorDef(lengthHandle='atkSpeed', lengthUnit='%', angleHandle='atkAngle', angleUnit='degrees', label='Attacker')
|
||||
tgtVectorDef = VectorDef(lengthHandle='tgtSpeed', lengthUnit='%', angleHandle='tgtAngle', angleUnit='degrees', label='Target')
|
||||
srcVectorDef = VectorDef(lengthHandle='atkSpeed', lengthUnit='%', angleHandle='atkAngle', angleUnit='degrees', label=_t('Attacker'))
|
||||
tgtVectorDef = VectorDef(lengthHandle='tgtSpeed', lengthUnit='%', angleHandle='tgtAngle', angleUnit='degrees', label=_t('Target'))
|
||||
hasTargets = True
|
||||
srcExtraCols = ('Dps', 'Volley', 'Speed', 'Radius')
|
||||
|
||||
@@ -75,9 +80,9 @@ class FitDamageStatsGraph(FitGraph):
|
||||
def yDefs(self):
|
||||
ignoreResists = GraphSettings.getInstance().get('ignoreResists')
|
||||
return [
|
||||
YDef(handle='dps', unit=None, label='DPS' if ignoreResists else 'Effective DPS'),
|
||||
YDef(handle='volley', unit=None, label='Volley' if ignoreResists else 'Effective volley'),
|
||||
YDef(handle='damage', unit=None, label='Damage inflicted' if ignoreResists else 'Effective damage inflicted')]
|
||||
YDef(handle='dps', unit=None, label=_t('DPS') if ignoreResists else _t('Effective DPS')),
|
||||
YDef(handle='volley', unit=None, label=_t('Volley') if ignoreResists else _t('Effective volley')),
|
||||
YDef(handle='damage', unit=None, label=_t('Damage inflicted') if ignoreResists else _t('Effective damage inflicted'))]
|
||||
|
||||
@property
|
||||
def tgtExtraCols(self):
|
||||
|
||||
@@ -46,7 +46,7 @@ class Distance2NeutingStrGetter(SmoothPointGetter):
|
||||
if 'doomsdayAOENeut' in mod.item.effects:
|
||||
neuts.append((
|
||||
mod.getModifiedItemAttr('energyNeutralizerAmount') / self.__getDuration(mod) * resonance,
|
||||
max(0, (mod.maxRange or 0) + mod.getModifiedItemAttr('doomsdayAOERange') - src.getRadius()),
|
||||
max(0, (mod.maxRange or 0) + mod.getModifiedItemAttr('doomsdayAOERange')),
|
||||
mod.falloff or 0, False, False))
|
||||
for drone in src.item.activeDronesIter():
|
||||
if 'entityEnergyNeutralizerFalloff' in drone.item.effects:
|
||||
@@ -93,7 +93,7 @@ class Distance2WebbingStrGetter(SmoothPointGetter):
|
||||
if 'doomsdayAOEWeb' in mod.item.effects:
|
||||
webs.append((
|
||||
mod.getModifiedItemAttr('speedFactor') * resonance,
|
||||
max(0, (mod.maxRange or 0) + mod.getModifiedItemAttr('doomsdayAOERange') - src.getRadius()),
|
||||
max(0, (mod.maxRange or 0) + mod.getModifiedItemAttr('doomsdayAOERange')),
|
||||
mod.falloff or 0, 'default', False, False))
|
||||
for drone in src.item.activeDronesIter():
|
||||
if 'remoteWebifierEntity' in drone.item.effects:
|
||||
@@ -142,7 +142,7 @@ class Distance2EcmStrMaxGetter(SmoothPointGetter):
|
||||
if 'doomsdayAOEECM' in mod.item.effects:
|
||||
ecms.append((
|
||||
max(mod.getModifiedItemAttr(a) for a in self.ECM_ATTRS_GENERAL) * resonance,
|
||||
max(0, (mod.maxRange or 0) + mod.getModifiedItemAttr('doomsdayAOERange') - src.getRadius()),
|
||||
max(0, (mod.maxRange or 0) + mod.getModifiedItemAttr('doomsdayAOERange')),
|
||||
mod.falloff or 0, False, False))
|
||||
for drone in src.item.activeDronesIter():
|
||||
if 'entityECMFalloff' in drone.item.effects:
|
||||
@@ -185,7 +185,7 @@ class Distance2DampStrLockRangeGetter(SmoothPointGetter):
|
||||
if 'doomsdayAOEDamp' in mod.item.effects:
|
||||
damps.append((
|
||||
mod.getModifiedItemAttr('maxTargetRangeBonus') * resonance,
|
||||
max(0, (mod.maxRange or 0) + mod.getModifiedItemAttr('doomsdayAOERange') - src.getRadius()),
|
||||
max(0, (mod.maxRange or 0) + mod.getModifiedItemAttr('doomsdayAOERange')),
|
||||
mod.falloff or 0, 'default', False, False))
|
||||
for drone in src.item.activeDronesIter():
|
||||
if 'remoteSensorDampEntity' in drone.item.effects:
|
||||
@@ -226,7 +226,7 @@ class Distance2TdStrOptimalGetter(SmoothPointGetter):
|
||||
if 'doomsdayAOETrack' in mod.item.effects:
|
||||
tds.append((
|
||||
mod.getModifiedItemAttr('maxRangeBonus') * resonance,
|
||||
max(0, (mod.maxRange or 0) + mod.getModifiedItemAttr('doomsdayAOERange') - src.getRadius()),
|
||||
max(0, (mod.maxRange or 0) + mod.getModifiedItemAttr('doomsdayAOERange')),
|
||||
mod.falloff or 0, 'default', False, False))
|
||||
for drone in src.item.activeDronesIter():
|
||||
if 'npcEntityWeaponDisruptor' in drone.item.effects:
|
||||
@@ -269,7 +269,7 @@ class Distance2GdStrRangeGetter(SmoothPointGetter):
|
||||
gds.append((
|
||||
mod.getModifiedItemAttr('missileVelocityBonus') * resonance,
|
||||
mod.getModifiedItemAttr('explosionDelayBonus') * resonance,
|
||||
max(0, (mod.maxRange or 0) + mod.getModifiedItemAttr('doomsdayAOERange') - src.getRadius()),
|
||||
max(0, (mod.maxRange or 0) + mod.getModifiedItemAttr('doomsdayAOERange')),
|
||||
mod.falloff or 0, 'default', False, False))
|
||||
return {'gds': gds}
|
||||
|
||||
@@ -310,7 +310,7 @@ class Distance2TpStrGetter(SmoothPointGetter):
|
||||
if 'doomsdayAOEPaint' in mod.item.effects:
|
||||
tps.append((
|
||||
mod.getModifiedItemAttr('signatureRadiusBonus') * resonance,
|
||||
max(0, (mod.maxRange or 0) + mod.getModifiedItemAttr('doomsdayAOERange') - src.getRadius()),
|
||||
max(0, (mod.maxRange or 0) + mod.getModifiedItemAttr('doomsdayAOERange')),
|
||||
mod.falloff or 0, 'default', False, False))
|
||||
for drone in src.item.activeDronesIter():
|
||||
if 'remoteTargetPaintEntity' in drone.item.effects:
|
||||
|
||||
@@ -18,30 +18,31 @@
|
||||
# =============================================================================
|
||||
|
||||
|
||||
import wx
|
||||
|
||||
from graphs.data.base import FitGraph, Input, XDef, YDef
|
||||
from .getter import (
|
||||
Distance2NeutingStrGetter, Distance2WebbingStrGetter, Distance2EcmStrMaxGetter,
|
||||
Distance2DampStrLockRangeGetter, Distance2TdStrOptimalGetter, Distance2GdStrRangeGetter,
|
||||
Distance2TpStrGetter)
|
||||
from .getter import (Distance2DampStrLockRangeGetter, Distance2EcmStrMaxGetter, Distance2GdStrRangeGetter, Distance2NeutingStrGetter, Distance2TdStrOptimalGetter,
|
||||
Distance2TpStrGetter, Distance2WebbingStrGetter)
|
||||
|
||||
_t = wx.GetTranslation
|
||||
|
||||
|
||||
class FitEwarStatsGraph(FitGraph):
|
||||
|
||||
# UI stuff
|
||||
internalName = 'ewarStatsGraph'
|
||||
name = 'Electronic Warfare Stats'
|
||||
xDefs = [XDef(handle='distance', unit='km', label='Distance', mainInput=('distance', 'km'))]
|
||||
name = _t('Electronic Warfare Stats')
|
||||
xDefs = [XDef(handle='distance', unit='km', label=_t('Distance'), mainInput=('distance', 'km'))]
|
||||
yDefs = [
|
||||
YDef(handle='neutStr', unit=None, label='Cap neutralized per second', selectorLabel='Neuts: cap per second'),
|
||||
YDef(handle='webStr', unit='%', label='Speed reduction', selectorLabel='Webs: speed reduction'),
|
||||
YDef(handle='ecmStrMax', unit=None, label='Combined ECM strength', selectorLabel='ECM: combined strength'),
|
||||
YDef(handle='dampStrLockRange', unit='%', label='Lock range reduction', selectorLabel='Damps: lock range reduction'),
|
||||
YDef(handle='tdStrOptimal', unit='%', label='Turret optimal range reduction', selectorLabel='TDs: turret optimal range reduction'),
|
||||
YDef(handle='gdStrRange', unit='%', label='Missile flight range reduction', selectorLabel='GDs: missile flight range reduction'),
|
||||
YDef(handle='tpStr', unit='%', label='Signature radius increase', selectorLabel='TPs: signature radius increase')]
|
||||
YDef(handle='neutStr', unit=None, label=_t('Cap neutralized per second'), selectorLabel=_t('Neuts: cap per second')),
|
||||
YDef(handle='webStr', unit='%', label=_t('Speed reduction'), selectorLabel=_t('Webs: speed reduction')),
|
||||
YDef(handle='ecmStrMax', unit=None, label=_t('Combined ECM strength'), selectorLabel=_t('ECM: combined strength')),
|
||||
YDef(handle='dampStrLockRange', unit='%', label=_t('Lock range reduction'), selectorLabel=_t('Damps: lock range reduction')),
|
||||
YDef(handle='tdStrOptimal', unit='%', label=_t('Turret optimal range reduction'), selectorLabel=_t('TDs: turret optimal range reduction')),
|
||||
YDef(handle='gdStrRange', unit='%', label=_t('Missile flight range reduction'), selectorLabel=_t('GDs: missile flight range reduction')),
|
||||
YDef(handle='tpStr', unit='%', label=_t('Signature radius increase'), selectorLabel=_t('TPs: signature radius increase'))]
|
||||
inputs = [
|
||||
Input(handle='distance', unit='km', label='Distance', iconID=1391, defaultValue=None, defaultRange=(0, 100)),
|
||||
Input(handle='resist', unit='%', label='Target resistance', iconID=1393, defaultValue=0, defaultRange=(0, 100))]
|
||||
Input(handle='distance', unit='km', label=_t('Distance'), iconID=1391, defaultValue=None, defaultRange=(0, 100)),
|
||||
Input(handle='resist', unit='%', label=_t('Target resistance'), iconID=1393, defaultValue=0, defaultRange=(0, 100))]
|
||||
|
||||
# Calculation stuff
|
||||
_normalizers = {
|
||||
|
||||
@@ -20,18 +20,21 @@
|
||||
|
||||
import math
|
||||
|
||||
from graphs.data.base import FitGraph, XDef, YDef, Input
|
||||
import wx
|
||||
|
||||
from graphs.data.base import FitGraph, Input, XDef, YDef
|
||||
from .getter import TgtSigRadius2LockTimeGetter
|
||||
|
||||
_t = wx.GetTranslation
|
||||
|
||||
|
||||
class FitLockTimeGraph(FitGraph):
|
||||
|
||||
# UI stuff
|
||||
internalName = 'lockTimeGraph'
|
||||
name = 'Lock Time'
|
||||
xDefs = [XDef(handle='tgtSigRad', unit='m', label='Target signature radius', mainInput=('tgtSigRad', 'm'))]
|
||||
yDefs = [YDef(handle='time', unit='s', label='Lock time')]
|
||||
inputs = [Input(handle='tgtSigRad', unit='m', label='Target signature', iconID=1390, defaultValue=None, defaultRange=(25, 500))]
|
||||
name = _t('Lock Time')
|
||||
xDefs = [XDef(handle='tgtSigRad', unit='m', label=_t('Target signature radius'), mainInput=('tgtSigRad', 'm'))]
|
||||
yDefs = [YDef(handle='time', unit='s', label=_t('Lock time'))]
|
||||
inputs = [Input(handle='tgtSigRad', unit='m', label=_t('Target signature'), iconID=1390, defaultValue=None, defaultRange=(25, 500))]
|
||||
srcExtraCols = ('ScanResolution',)
|
||||
|
||||
# Calculation stuff
|
||||
|
||||
@@ -18,27 +18,32 @@
|
||||
# =============================================================================
|
||||
|
||||
|
||||
from graphs.data.base import FitGraph, XDef, YDef, Input
|
||||
from .getter import Time2SpeedGetter, Time2DistanceGetter, Time2MomentumGetter, Time2BumpSpeedGetter, Time2BumpDistanceGetter
|
||||
import wx
|
||||
|
||||
from graphs.data.base import FitGraph, Input, XDef, YDef
|
||||
from .getter import Time2BumpDistanceGetter, Time2BumpSpeedGetter, Time2DistanceGetter, Time2MomentumGetter, Time2SpeedGetter
|
||||
|
||||
_t = wx.GetTranslation
|
||||
|
||||
|
||||
class FitMobilityGraph(FitGraph):
|
||||
|
||||
# UI stuff
|
||||
internalName = 'mobilityGraph'
|
||||
name = 'Mobility'
|
||||
xDefs = [XDef(handle='time', unit='s', label='Time', mainInput=('time', 's'))]
|
||||
name = _t('Mobility')
|
||||
xDefs = [XDef(handle='time', unit='s', label=_t('Time'), mainInput=('time', 's'))]
|
||||
yDefs = [
|
||||
YDef(handle='speed', unit='m/s', label='Speed'),
|
||||
YDef(handle='distance', unit='km', label='Distance'),
|
||||
YDef(handle='momentum', unit='Gkg⋅m/s', label='Momentum'),
|
||||
YDef(handle='bumpSpeed', unit='m/s', label='Target speed', selectorLabel='Bump speed'),
|
||||
YDef(handle='bumpDistance', unit='km', label='Target distance traveled', selectorLabel='Bump distance')]
|
||||
YDef(handle='speed', unit='m/s', label=_t('Speed')),
|
||||
YDef(handle='distance', unit='km', label=_t('Distance')),
|
||||
YDef(handle='momentum', unit='Gkg⋅m/s', label=_t('Momentum')),
|
||||
YDef(handle='bumpSpeed', unit='m/s', label=_t('Target speed'), selectorLabel=_t('Bump speed')),
|
||||
YDef(handle='bumpDistance', unit='km', label=_t('Target distance traveled'), selectorLabel=_t('Bump distance'))]
|
||||
inputs = [
|
||||
Input(handle='time', unit='s', label='Time', iconID=1392, defaultValue=10, defaultRange=(0, 30)),
|
||||
Input(handle='time', unit='s', label=_t('Time'), iconID=1392, defaultValue=10, defaultRange=(0, 30)),
|
||||
# Default values in target fields correspond to a random carrier/fax
|
||||
Input(handle='tgtMass', unit='Mkg', label='Target mass', iconID=76, defaultValue=1300, defaultRange=(100, 2500), conditions=[(None, ('bumpSpeed', 'm/s')), (None, ('bumpDistance', 'km'))], secondaryTooltip='Defined in millions of kilograms'),
|
||||
Input(handle='tgtInertia', unit=None, label='Target inertia factor', iconID=1401, defaultValue=0.015, defaultRange=(0.03, 0.1), conditions=[(None, ('bumpDistance', 'km'))], secondaryTooltip='Inertia Modifier attribute value of the target ship')]
|
||||
Input(handle='tgtMass', unit='Mkg', label=_t('Target mass'), iconID=76, defaultValue=1300, defaultRange=(100, 2500),
|
||||
conditions=[(None, ('bumpSpeed', 'm/s')), (None, ('bumpDistance', 'km'))], secondaryTooltip=_t('Defined in millions of kilograms')),
|
||||
Input(handle='tgtInertia', unit=None, label=_t('Target inertia factor'), iconID=1401, defaultValue=0.015, defaultRange=(0.03, 0.1),
|
||||
conditions=[(None, ('bumpDistance', 'km'))], secondaryTooltip=_t('Inertia Modifier attribute value of the target ship'))]
|
||||
srcExtraCols = ('Speed', 'Agility')
|
||||
|
||||
# Calculation stuff
|
||||
|
||||
@@ -18,10 +18,14 @@
|
||||
# =============================================================================
|
||||
|
||||
|
||||
from graphs.data.base import FitGraph, XDef, YDef, Input, InputCheckbox
|
||||
import wx
|
||||
|
||||
from graphs.data.base import FitGraph, Input, InputCheckbox, XDef, YDef
|
||||
from service.const import GraphCacheCleanupReason
|
||||
from .cache import TimeCache
|
||||
from .getter import Distance2RpsGetter, Distance2RepAmountGetter, Time2RpsGetter, Time2RepAmountGetter
|
||||
from .getter import Distance2RepAmountGetter, Distance2RpsGetter, Time2RepAmountGetter, Time2RpsGetter
|
||||
|
||||
_t = wx.GetTranslation
|
||||
|
||||
|
||||
class FitRemoteRepsGraph(FitGraph):
|
||||
@@ -41,18 +45,21 @@ class FitRemoteRepsGraph(FitGraph):
|
||||
|
||||
# UI stuff
|
||||
internalName = 'remoteRepsGraph'
|
||||
name = 'Remote Repairs'
|
||||
name = _t('Remote Repairs')
|
||||
xDefs = [
|
||||
XDef(handle='distance', unit='km', label='Distance', mainInput=('distance', 'km')),
|
||||
XDef(handle='time', unit='s', label='Time', mainInput=('time', 's'))]
|
||||
XDef(handle='distance', unit='km', label=_t('Distance'), mainInput=('distance', 'km')),
|
||||
XDef(handle='time', unit='s', label=_t('Time'), mainInput=('time', 's'))]
|
||||
yDefs = [
|
||||
YDef(handle='rps', unit='HP/s', label='Repair speed'),
|
||||
YDef(handle='total', unit='HP', label='Total repaired')]
|
||||
YDef(handle='rps', unit='HP/s', label=_t('Repair speed')),
|
||||
YDef(handle='total', unit='HP', label=_t('Total repaired'))]
|
||||
inputs = [
|
||||
Input(handle='time', unit='s', label='Time', iconID=1392, defaultValue=None, defaultRange=(0, 80), secondaryTooltip='When set, uses repairing ship\'s exact RR stats at a given time\nWhen not set, uses repairing ship\'s RR stats as shown in stats panel of main window'),
|
||||
Input(handle='distance', unit='km', label='Distance', iconID=1391, defaultValue=None, defaultRange=(0, 100), mainTooltip='Distance between the repairing ship and the target, as seen in overview (surface-to-surface)', secondaryTooltip='Distance between the repairing ship and the target, as seen in overview (surface-to-surface)')]
|
||||
Input(handle='time', unit='s', label=_t('Time'), iconID=1392, defaultValue=None, defaultRange=(0, 80),
|
||||
secondaryTooltip=_t('When set, uses repairing ship\'s exact RR stats at a given time\nWhen not set, uses repairing ship\'s RR stats as shown in stats panel of main window')),
|
||||
Input(handle='distance', unit='km', label=_t('Distance'), iconID=1391, defaultValue=None, defaultRange=(0, 100),
|
||||
mainTooltip=_t('Distance between the repairing ship and the target, as seen in overview (surface-to-surface)'),
|
||||
secondaryTooltip=_t('Distance between the repairing ship and the target, as seen in overview (surface-to-surface)'))]
|
||||
srcExtraCols = ('ShieldRR', 'ArmorRR', 'HullRR')
|
||||
checkboxes = [InputCheckbox(handle='ancReload', label='Reload ancillary RRs', defaultValue=True)]
|
||||
checkboxes = [InputCheckbox(handle='ancReload', label=_t('Reload ancillary RRs'), defaultValue=True)]
|
||||
|
||||
# Calculation stuff
|
||||
_normalizers = {('distance', 'km'): lambda v, src, tgt: None if v is None else v * 1000}
|
||||
|
||||
@@ -18,11 +18,13 @@
|
||||
# =============================================================================
|
||||
|
||||
|
||||
import wx
|
||||
|
||||
import gui.mainFrame
|
||||
from graphs.data.base import FitGraph, XDef, YDef, Input
|
||||
from .getter import (
|
||||
Time2ShieldAmountGetter, Time2ShieldRegenGetter,
|
||||
ShieldAmount2ShieldAmountGetter, ShieldAmount2ShieldRegenGetter)
|
||||
from graphs.data.base import FitGraph, Input, XDef, YDef
|
||||
from .getter import (ShieldAmount2ShieldAmountGetter, ShieldAmount2ShieldRegenGetter, Time2ShieldAmountGetter, Time2ShieldRegenGetter)
|
||||
|
||||
_t = wx.GetTranslation
|
||||
|
||||
|
||||
class FitShieldRegenGraph(FitGraph):
|
||||
@@ -33,15 +35,15 @@ class FitShieldRegenGraph(FitGraph):
|
||||
|
||||
# UI stuff
|
||||
internalName = 'shieldRegenGraph'
|
||||
name = 'Shield Regeneration'
|
||||
name = _t('Shield Regeneration')
|
||||
inputs = [
|
||||
Input(handle='time', unit='s', label='Time', iconID=1392, defaultValue=120, defaultRange=(0, 300), conditions=[
|
||||
Input(handle='time', unit='s', label=_t('Time'), iconID=1392, defaultValue=120, defaultRange=(0, 300), conditions=[
|
||||
(('time', 's'), None)]),
|
||||
Input(handle='shieldAmount', unit='%', label='Shield amount', iconID=1384, defaultValue=25, defaultRange=(0, 100), conditions=[
|
||||
Input(handle='shieldAmount', unit='%', label=_t('Shield amount'), iconID=1384, defaultValue=25, defaultRange=(0, 100), conditions=[
|
||||
(('shieldAmount', 'EHP'), None),
|
||||
(('shieldAmount', 'HP'), None),
|
||||
(('shieldAmount', '%'), None)]),
|
||||
Input(handle='shieldAmountT0', unit='%', label='Starting shield amount', iconID=1384, defaultValue=0, defaultRange=(0, 100), conditions=[
|
||||
Input(handle='shieldAmountT0', unit='%', label=_t('Starting shield amount'), iconID=1384, defaultValue=0, defaultRange=(0, 100), conditions=[
|
||||
(('time', 's'), None)])]
|
||||
srcExtraCols = ('ShieldAmount', 'ShieldTime')
|
||||
usesHpEffectivity = True
|
||||
@@ -49,15 +51,15 @@ class FitShieldRegenGraph(FitGraph):
|
||||
@property
|
||||
def xDefs(self):
|
||||
return [
|
||||
XDef(handle='time', unit='s', label='Time', mainInput=('time', 's')),
|
||||
XDef(handle='shieldAmount', unit='EHP' if self.isEffective else 'HP', label='Shield amount', mainInput=('shieldAmount', '%')),
|
||||
XDef(handle='shieldAmount', unit='%', label='Shield amount', mainInput=('shieldAmount', '%'))]
|
||||
XDef(handle='time', unit='s', label=_t('Time'), mainInput=('time', 's')),
|
||||
XDef(handle='shieldAmount', unit='EHP' if self.isEffective else 'HP', label=_t('Shield amount'), mainInput=('shieldAmount', '%')),
|
||||
XDef(handle='shieldAmount', unit='%', label=_t('Shield amount'), mainInput=('shieldAmount', '%'))]
|
||||
|
||||
@property
|
||||
def yDefs(self):
|
||||
return [
|
||||
YDef(handle='shieldAmount', unit='EHP' if self.isEffective else 'HP', label='Shield amount'),
|
||||
YDef(handle='shieldRegen', unit='EHP/s' if self.isEffective else 'HP/s', label='Shield regen')]
|
||||
YDef(handle='shieldAmount', unit='EHP' if self.isEffective else 'HP', label=_t('Shield amount')),
|
||||
YDef(handle='shieldRegen', unit='EHP/s' if self.isEffective else 'HP/s', label=_t('Shield regen'))]
|
||||
|
||||
# Calculation stuff
|
||||
_normalizers = {
|
||||
|
||||
@@ -55,7 +55,7 @@ def calculate_time_in_warp(max_warp_speed, max_subwarp_speed, warp_dist):
|
||||
k_accel = max_warp_speed
|
||||
k_decel = min(max_warp_speed / 3, 2)
|
||||
|
||||
warp_dropout_speed = max_subwarp_speed / 2
|
||||
warp_dropout_speed = min(max_subwarp_speed / 2, 100)
|
||||
max_ms_warp_speed = max_warp_speed * AU_METERS
|
||||
|
||||
accel_dist = AU_METERS
|
||||
|
||||
@@ -18,11 +18,15 @@
|
||||
# =============================================================================
|
||||
|
||||
|
||||
import wx
|
||||
|
||||
from graphs.data.base import FitGraph, Input, XDef, YDef
|
||||
from service.const import GraphCacheCleanupReason
|
||||
from .cache import SubwarpSpeedCache
|
||||
from .getter import AU_METERS, Distance2TimeGetter
|
||||
|
||||
_t = wx.GetTranslation
|
||||
|
||||
|
||||
class FitWarpTimeGraph(FitGraph):
|
||||
|
||||
@@ -38,20 +42,21 @@ class FitWarpTimeGraph(FitGraph):
|
||||
|
||||
# UI stuff
|
||||
internalName = 'warpTimeGraph'
|
||||
name = 'Warp Time'
|
||||
name = _t('Warp Time')
|
||||
xDefs = [
|
||||
XDef(handle='distance', unit='AU', label='Distance', mainInput=('distance', 'AU')),
|
||||
XDef(handle='distance', unit='km', label='Distance', mainInput=('distance', 'km'))]
|
||||
yDefs = [YDef(handle='time', unit='s', label='Warp time')]
|
||||
XDef(handle='distance', unit='AU', label=_t('Distance'), mainInput=('distance', 'AU')),
|
||||
XDef(handle='distance', unit='km', label=_t('Distance'), mainInput=('distance', 'km'))]
|
||||
yDefs = [YDef(handle='time', unit='s', label=_t('Warp time'))]
|
||||
inputs = [
|
||||
Input(handle='distance', unit='AU', label='Distance', iconID=1391, defaultValue=20, defaultRange=(0, 50)),
|
||||
Input(handle='distance', unit='km', label='Distance', iconID=1391, defaultValue=1000, defaultRange=(150, 5000))]
|
||||
Input(handle='distance', unit='AU', label=_t('Distance'), iconID=1391, defaultValue=20, defaultRange=(0, 50)),
|
||||
Input(handle='distance', unit='km', label=_t('Distance'), iconID=1391, defaultValue=1000, defaultRange=(150, 5000))]
|
||||
srcExtraCols = ('WarpSpeed', 'WarpDistance')
|
||||
|
||||
# Calculation stuff
|
||||
_normalizers = {
|
||||
('distance', 'AU'): lambda v, src, tgt: v * AU_METERS,
|
||||
('distance', 'km'): lambda v, src, tgt: v * 1000}
|
||||
('distance', 'km'): lambda v, src, tgt: v * 1000
|
||||
}
|
||||
_limiters = {'distance': lambda src, tgt: (0, src.item.maxWarpDistance * AU_METERS)}
|
||||
_getters = {('distance', 'time'): Distance2TimeGetter}
|
||||
_denormalizers = {
|
||||
|
||||
@@ -31,10 +31,10 @@ from service.fit import Fit
|
||||
from .lists import SourceWrapperList, TargetWrapperList
|
||||
from .vector import VectorPicker
|
||||
|
||||
|
||||
InputData = namedtuple('InputData', ('handle', 'unit', 'value'))
|
||||
InputBox = namedtuple('InputBox', ('handle', 'unit', 'textBox', 'icon', 'label'))
|
||||
CheckBox = namedtuple('CheckBox', ('handle', 'checkBox'))
|
||||
_t = wx.GetTranslation
|
||||
|
||||
|
||||
class GraphControlPanel(wx.Panel):
|
||||
@@ -53,7 +53,7 @@ class GraphControlPanel(wx.Panel):
|
||||
|
||||
commonOptsSizer = wx.BoxSizer(wx.VERTICAL)
|
||||
ySubSelectionSizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||
yText = wx.StaticText(self, wx.ID_ANY, 'Axis Y:')
|
||||
yText = wx.StaticText(self, wx.ID_ANY, _t('Axis Y:'))
|
||||
ySubSelectionSizer.Add(yText, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 5)
|
||||
self.ySubSelection = wx.Choice(self, wx.ID_ANY)
|
||||
self.ySubSelection.Bind(wx.EVT_CHOICE, self.OnYTypeUpdate)
|
||||
@@ -61,18 +61,18 @@ class GraphControlPanel(wx.Panel):
|
||||
commonOptsSizer.Add(ySubSelectionSizer, 0, wx.EXPAND | wx.ALL, 0)
|
||||
|
||||
xSubSelectionSizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||
xText = wx.StaticText(self, wx.ID_ANY, 'Axis X:')
|
||||
xText = wx.StaticText(self, wx.ID_ANY, _t('Axis X:'))
|
||||
xSubSelectionSizer.Add(xText, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 5)
|
||||
self.xSubSelection = wx.Choice(self, wx.ID_ANY)
|
||||
self.xSubSelection.Bind(wx.EVT_CHOICE, self.OnXTypeUpdate)
|
||||
xSubSelectionSizer.Add(self.xSubSelection, 1, wx.EXPAND | wx.ALL, 0)
|
||||
commonOptsSizer.Add(xSubSelectionSizer, 0, wx.EXPAND | wx.TOP, 5)
|
||||
|
||||
self.showLegendCb = wx.CheckBox(self, wx.ID_ANY, 'Show legend', wx.DefaultPosition, wx.DefaultSize, 0)
|
||||
self.showLegendCb = wx.CheckBox(self, wx.ID_ANY, _t('Show legend'), wx.DefaultPosition, wx.DefaultSize, 0)
|
||||
self.showLegendCb.SetValue(True)
|
||||
self.showLegendCb.Bind(wx.EVT_CHECKBOX, self.OnShowLegendChange)
|
||||
commonOptsSizer.Add(self.showLegendCb, 0, wx.EXPAND | wx.TOP, 5)
|
||||
self.showY0Cb = wx.CheckBox(self, wx.ID_ANY, 'Always show Y = 0', wx.DefaultPosition, wx.DefaultSize, 0)
|
||||
self.showY0Cb = wx.CheckBox(self, wx.ID_ANY, _t('Always show Y = 0'), wx.DefaultPosition, wx.DefaultSize, 0)
|
||||
self.showY0Cb.SetValue(True)
|
||||
self.showY0Cb.Bind(wx.EVT_CHECKBOX, self.OnShowY0Change)
|
||||
commonOptsSizer.Add(self.showY0Cb, 0, wx.EXPAND | wx.TOP, 5)
|
||||
|
||||
@@ -34,8 +34,8 @@ from service.settings import GraphSettings
|
||||
from . import canvasPanel
|
||||
from .ctrlPanel import GraphControlPanel
|
||||
|
||||
|
||||
pyfalog = Logger(__name__)
|
||||
_t = wx.GetTranslation
|
||||
|
||||
|
||||
REDRAW_DELAY = 500
|
||||
@@ -48,7 +48,7 @@ class GraphFrame(AuxiliaryFrame):
|
||||
pyfalog.warning('Matplotlib is not enabled. Skipping initialization.')
|
||||
return
|
||||
|
||||
super().__init__(parent, title='Graphs', size=(520, 390), resizeable=True)
|
||||
super().__init__(parent, title=_t('Graphs'), size=(520, 390), resizeable=True)
|
||||
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
|
||||
self.includeHidden = includeHidden
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ from service.const import GraphCacheCleanupReason
|
||||
from service.fit import Fit
|
||||
from .stylePickers import ColorPickerPopup, LightnessPickerPopup, LineStylePickerPopup
|
||||
|
||||
_t = wx.GetTranslation
|
||||
|
||||
class BaseWrapperList(gui.display.Display):
|
||||
|
||||
@@ -302,14 +303,14 @@ class SourceWrapperList(BaseWrapperList):
|
||||
selection = self.getSelectedWrappers()
|
||||
mainItem = self.getWrapper(clickedPos)
|
||||
|
||||
itemContext = None if mainItem is None else 'Fit'
|
||||
itemContext = None if mainItem is None else _t('Fit')
|
||||
menu = ContextMenu.getMenu(self, mainItem, selection, ('graphFitList', itemContext), ('graphFitListMisc', itemContext))
|
||||
if menu:
|
||||
self.PopupMenu(menu)
|
||||
|
||||
@property
|
||||
def defaultTTText(self):
|
||||
return 'Drag a fit into this list to graph it'
|
||||
return _t('Drag a fit into this list to graph it')
|
||||
|
||||
|
||||
class TargetWrapperList(BaseWrapperList):
|
||||
@@ -355,7 +356,7 @@ class TargetWrapperList(BaseWrapperList):
|
||||
selection = self.getSelectedWrappers()
|
||||
mainItem = self.getWrapper(clickedPos)
|
||||
|
||||
itemContext = None if mainItem is None else 'Target'
|
||||
itemContext = None if mainItem is None else _t('Target')
|
||||
menu = ContextMenu.getMenu(self, mainItem, selection, ('graphTgtList', itemContext), ('graphTgtListMisc', itemContext))
|
||||
if menu:
|
||||
self.PopupMenu(menu)
|
||||
@@ -366,7 +367,7 @@ class TargetWrapperList(BaseWrapperList):
|
||||
|
||||
@property
|
||||
def defaultTTText(self):
|
||||
return 'Drag a fit into this list to have your fits graphed against it'
|
||||
return _t('Drag a fit into this list to have your fits graphed against it')
|
||||
|
||||
# Context menu handlers
|
||||
def addProfile(self, profile):
|
||||
|
||||
@@ -25,9 +25,9 @@ import wx
|
||||
|
||||
from service.const import GraphColor, GraphLightness, GraphLineStyle
|
||||
|
||||
|
||||
ColorData = namedtuple('ColorData', ('hsl', 'name', 'iconName'))
|
||||
LightnessData = namedtuple('LightnessData', ('name', 'iconName', 'func'))
|
||||
_t = wx.GetTranslation
|
||||
|
||||
|
||||
class LineStyleData:
|
||||
@@ -49,14 +49,14 @@ class LineStyleData:
|
||||
|
||||
# In HSL format
|
||||
BASE_COLORS = OrderedDict([
|
||||
(GraphColor.red, ColorData((0 / 360.0, 1.0, 0.5), 'Red', 'color_red')),
|
||||
(GraphColor.green, ColorData((120 / 360.0, 1.0, 0.5), 'Green', 'color_green')),
|
||||
(GraphColor.blue, ColorData((240 / 360.0, 1.0, 0.5), 'Blue', 'color_blue')),
|
||||
(GraphColor.orange, ColorData((40 / 360.0, 1.0, 0.5), 'Orange', 'color_orange')),
|
||||
(GraphColor.magenta, ColorData((300 / 360.0, 1.0, 0.5), 'Magenta', 'color_magenta')),
|
||||
(GraphColor.cyan, ColorData((180 / 360.0, 1.0, 0.5), 'Cyan', 'color_cyan')),
|
||||
(GraphColor.purple, ColorData((275 / 360.0, 1.0, 0.5), 'Purple', 'color_purple')),
|
||||
(GraphColor.yellow, ColorData((56 / 360.0, 1.0, 0.5), 'Yellow', 'color_yellow'))])
|
||||
(GraphColor.red, ColorData((0 / 360.0, 1.0, 0.5), _t('Red'), 'color_red')),
|
||||
(GraphColor.green, ColorData((120 / 360.0, 1.0, 0.5), _t('Green'), 'color_green')),
|
||||
(GraphColor.blue, ColorData((240 / 360.0, 1.0, 0.5), _t('Blue'), 'color_blue')),
|
||||
(GraphColor.orange, ColorData((40 / 360.0, 1.0, 0.5), _t('Orange'), 'color_orange')),
|
||||
(GraphColor.magenta, ColorData((300 / 360.0, 1.0, 0.5), _t('Magenta'), 'color_magenta')),
|
||||
(GraphColor.cyan, ColorData((180 / 360.0, 1.0, 0.5), _t('Cyan'), 'color_cyan')),
|
||||
(GraphColor.purple, ColorData((275 / 360.0, 1.0, 0.5), _t('Purple'), 'color_purple')),
|
||||
(GraphColor.yellow, ColorData((56 / 360.0, 1.0, 0.5), _t('Yellow'), 'color_yellow'))])
|
||||
|
||||
|
||||
def hsl_to_hsv(hsl):
|
||||
@@ -77,13 +77,13 @@ def brighten(hsl):
|
||||
|
||||
|
||||
LIGHTNESSES = OrderedDict([
|
||||
(GraphLightness.normal, LightnessData('Normal', 'lightness_normal', lambda hsl: hsl)),
|
||||
(GraphLightness.dark, LightnessData('Dark', 'lightness_dark', darken)),
|
||||
(GraphLightness.bright, LightnessData('Bright', 'lightness_bright', brighten))])
|
||||
(GraphLightness.normal, LightnessData(_t('Normal'), 'lightness_normal', lambda hsl: hsl)),
|
||||
(GraphLightness.dark, LightnessData(_t('Dark'), 'lightness_dark', darken)),
|
||||
(GraphLightness.bright, LightnessData(_t('Bright'), 'lightness_bright', brighten))])
|
||||
|
||||
|
||||
STYLES = OrderedDict([
|
||||
(GraphLineStyle.solid, LineStyleData('Solid', 'style_solid', 'solid')),
|
||||
(GraphLineStyle.dashed, LineStyleData('Dashed', 'style_dashed', (0, (5, 1)))),
|
||||
(GraphLineStyle.dotted, LineStyleData('Dotted', 'style_dotted', (0, (1, 1)))),
|
||||
(GraphLineStyle.dashdotted, LineStyleData('Dash-dotted', 'style_dashdot', (0, (3, 1, 1, 1))))])
|
||||
(GraphLineStyle.solid, LineStyleData(_t('Solid'), 'style_solid', 'solid')),
|
||||
(GraphLineStyle.dashed, LineStyleData(_t('Dashed'), 'style_dashed', (0, (5, 1)))),
|
||||
(GraphLineStyle.dotted, LineStyleData(_t('Dotted'), 'style_dotted', (0, (1, 1)))),
|
||||
(GraphLineStyle.dashdotted, LineStyleData(_t('Dash-dotted'), 'style_dashdot', (0, (3, 1, 1, 1))))])
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
# =============================================================================
|
||||
|
||||
import config
|
||||
import wx
|
||||
_t = wx.GetTranslation
|
||||
|
||||
try:
|
||||
versionString = "{0}".format(config.getVersion())
|
||||
@@ -26,10 +28,10 @@ except NameError:
|
||||
versionString = "0.0"
|
||||
|
||||
licenses = (
|
||||
"pyfa is released under GNU GPLv3 - see included LICENSE file",
|
||||
"All EVE-Online related materials are property of CCP hf.",
|
||||
"Silk Icons Set by famfamfam.com - Creative Commons Attribution 2.5 License",
|
||||
"Fat Cow Icons by fatcow.com - Creative Commons Attribution 3.0 License"
|
||||
_t("pyfa is released under GNU GPLv3 - see included LICENSE file"),
|
||||
_t("All EVE-Online related materials are property of CCP hf."),
|
||||
_t("Silk Icons Set by famfamfam.com - Creative Commons Attribution 2.5 License"),
|
||||
_t("Fat Cow Icons by fatcow.com - Creative Commons Attribution 3.0 License")
|
||||
)
|
||||
developers = (
|
||||
"blitzmann \tSable Blitzmann (maintainer)",
|
||||
@@ -44,7 +46,7 @@ credits = (
|
||||
"Corollax (Aamrr) \tVarious EOS / pyfa improvements",
|
||||
"Dreae (Dreae)\tPyCrest")
|
||||
description = (
|
||||
"Pyfa (the Python Fitting Assistant) is an open-source standalone application able to "
|
||||
_t("Pyfa (the Python Fitting Assistant) is an open-source standalone application able to "
|
||||
"create and simulate fittings for EVE-Online SciFi MMORPG with a very high degree of "
|
||||
"accuracy. Pyfa can run on all platforms where Python and wxWidgets are supported."
|
||||
"accuracy. Pyfa can run on all platforms where Python and wxWidgets are supported.")
|
||||
)
|
||||
|
||||
@@ -33,6 +33,7 @@ from gui.builtinAdditionPanes.projectedView import ProjectedView
|
||||
from gui.chrome_tabs import ChromeNotebook
|
||||
from gui.toggle_panel import TogglePanel
|
||||
|
||||
_t = wx.GetTranslation
|
||||
|
||||
class AdditionsPane(TogglePanel):
|
||||
|
||||
@@ -41,7 +42,7 @@ class AdditionsPane(TogglePanel):
|
||||
TogglePanel.__init__(self, parent, force_layout=1)
|
||||
self.mainFrame = mainFrame
|
||||
|
||||
self.SetLabel("Additions")
|
||||
self.SetLabel(_t("Additions"))
|
||||
pane = self.GetContentPanel()
|
||||
|
||||
baseSizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||
@@ -62,28 +63,28 @@ class AdditionsPane(TogglePanel):
|
||||
notesImg = BitmapLoader.getImage("skill_small", "gui")
|
||||
|
||||
self.drone = DroneView(self.notebook)
|
||||
self.notebook.AddPage(self.drone, "Drones", image=droneImg, closeable=False)
|
||||
self.notebook.AddPage(self.drone, _t("Drones"), image=droneImg, closeable=False)
|
||||
|
||||
self.fighter = FighterView(self.notebook)
|
||||
self.notebook.AddPage(self.fighter, "Fighters", image=fighterImg, closeable=False)
|
||||
self.notebook.AddPage(self.fighter, _t("Fighters"), image=fighterImg, closeable=False)
|
||||
|
||||
self.cargo = CargoView(self.notebook)
|
||||
self.notebook.AddPage(self.cargo, "Cargo", image=cargoImg, closeable=False)
|
||||
self.notebook.AddPage(self.cargo, _t("Cargo"), image=cargoImg, closeable=False)
|
||||
|
||||
self.implant = ImplantView(self.notebook)
|
||||
self.notebook.AddPage(self.implant, "Implants", image=implantImg, closeable=False)
|
||||
self.notebook.AddPage(self.implant, _t("Implants"), image=implantImg, closeable=False)
|
||||
|
||||
self.booster = BoosterView(self.notebook)
|
||||
self.notebook.AddPage(self.booster, "Boosters", image=boosterImg, closeable=False)
|
||||
self.notebook.AddPage(self.booster, _t("Boosters"), image=boosterImg, closeable=False)
|
||||
|
||||
self.projectedPage = ProjectedView(self.notebook)
|
||||
self.notebook.AddPage(self.projectedPage, "Projected", image=projectedImg, closeable=False)
|
||||
self.notebook.AddPage(self.projectedPage, _t("Projected"), image=projectedImg, closeable=False)
|
||||
|
||||
self.gangPage = CommandView(self.notebook)
|
||||
self.notebook.AddPage(self.gangPage, "Command", image=gangImg, closeable=False)
|
||||
self.notebook.AddPage(self.gangPage, _t("Command"), image=gangImg, closeable=False)
|
||||
|
||||
self.notes = NotesView(self.notebook)
|
||||
self.notebook.AddPage(self.notes, "Notes", image=notesImg, closeable=False)
|
||||
self.notebook.AddPage(self.notes, _t("Notes"), image=notesImg, closeable=False)
|
||||
|
||||
self.mainFrame.Bind(GE.FIT_CHANGED, self.OnFitChanged)
|
||||
self.mainFrame.Bind(GE.FIT_NOTES_CHANGED, self.OnNotesChanged)
|
||||
|
||||
77
gui/app.py
Normal file
77
gui/app.py
Normal file
@@ -0,0 +1,77 @@
|
||||
import wx
|
||||
import config
|
||||
import os
|
||||
import sys
|
||||
from logbook import Logger
|
||||
pyfalog = Logger(__name__)
|
||||
from service.settings import LocaleSettings
|
||||
|
||||
|
||||
class PyfaApp(wx.App):
|
||||
def OnInit(self):
|
||||
"""
|
||||
Do application initialization work, e.g. define application globals.
|
||||
"""
|
||||
|
||||
# Name for my application.
|
||||
self.appName = "pyfa"
|
||||
|
||||
#------------
|
||||
|
||||
# # Simplified init method.
|
||||
# self.DoConfig()
|
||||
# self.Init() # InspectionMixin
|
||||
# # work around for Python stealing "_".
|
||||
# sys.displayhook = _displayHook
|
||||
#
|
||||
# #------------
|
||||
|
||||
|
||||
# Return locale folder.
|
||||
localeDir = os.path.join(config.pyfaPath, "locale")
|
||||
|
||||
# Set language stuff and update to last used language.
|
||||
self.locale = None
|
||||
wx.Locale.AddCatalogLookupPathPrefix(localeDir)
|
||||
# Set language stuff and update to last used language.
|
||||
self.UpdateLanguage(config.language)
|
||||
|
||||
return True
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
def UpdateLanguage(self, lang=None):
|
||||
"""
|
||||
Update the language to the requested one.
|
||||
|
||||
Make *sure* any existing locale is deleted before the new
|
||||
one is created. The old C++ object needs to be deleted
|
||||
before the new one is created, and if we just assign a new
|
||||
instance to the old Python variable, the old C++ locale will
|
||||
not be destroyed soon enough, likely causing a crash.
|
||||
|
||||
:param string `lang`: one of the supported language codes.
|
||||
"""
|
||||
|
||||
# Language domain.
|
||||
langDomain = config.CATALOG
|
||||
|
||||
# If an unsupported language is requested default to English.
|
||||
|
||||
if self.locale:
|
||||
assert sys.getrefcount(self.locale) <= 2
|
||||
del self.locale
|
||||
|
||||
# Create a locale object for this language.
|
||||
langInfo = wx.Locale.FindLanguageInfo(lang)
|
||||
if langInfo is not None:
|
||||
pyfalog.debug("Setting language to: " + lang)
|
||||
self.locale = wx.Locale(langInfo.Language)
|
||||
if self.locale.IsOk():
|
||||
success = self.locale.AddCatalog(langDomain)
|
||||
if not success:
|
||||
print("Langauage catalog not successfully loaded")
|
||||
|
||||
else:
|
||||
pyfalog.debug("Cannot find langauge: " + lang)
|
||||
self.locale = wx.Locale(wx.Locale.FindLanguageInfo(LocaleSettings.defaults['locale']).Language)
|
||||
@@ -29,7 +29,7 @@ from gui.contextMenu import ContextMenu
|
||||
from gui.utils.staticHelpers import DragDropHelper
|
||||
from service.fit import Fit
|
||||
from service.market import Market
|
||||
|
||||
_t = wx.GetTranslation
|
||||
|
||||
class BoosterViewDrop(wx.DropTarget):
|
||||
def __init__(self, dropFn, *args, **kwargs):
|
||||
@@ -212,7 +212,7 @@ class BoosterView(d.Display):
|
||||
else:
|
||||
if booster in self.original:
|
||||
mainBooster = booster
|
||||
itemContext = None if mainBooster is None else "Booster"
|
||||
itemContext = None if mainBooster is None else _t("Booster")
|
||||
menu = ContextMenu.getMenu(self, mainBooster, selection, ("boosterItem", itemContext), ("boosterItemMisc", itemContext))
|
||||
if menu:
|
||||
self.PopupMenu(menu)
|
||||
|
||||
@@ -70,7 +70,7 @@ class CargoView(d.Display):
|
||||
|
||||
def addItem(self, event):
|
||||
item = Market.getInstance().getItem(event.itemID, eager='group')
|
||||
if item is None or not item.isCharge:
|
||||
if item is None or not (item.isCharge or item.isCommodity):
|
||||
event.Skip()
|
||||
return
|
||||
|
||||
@@ -227,7 +227,7 @@ class CargoView(d.Display):
|
||||
else:
|
||||
if cargo in self.original:
|
||||
mainCargo = cargo
|
||||
itemContext = None if mainCargo is None else Market.getInstance().getCategoryByItem(mainCargo.item).name
|
||||
itemContext = None if mainCargo is None else Market.getInstance().getCategoryByItem(mainCargo.item).displayName
|
||||
menu = ContextMenu.getMenu(self, mainCargo, selection, ("cargoItem", itemContext), ("cargoItemMisc", itemContext))
|
||||
if menu:
|
||||
self.PopupMenu(menu)
|
||||
|
||||
@@ -30,6 +30,7 @@ from gui.contextMenu import ContextMenu
|
||||
from gui.utils.staticHelpers import DragDropHelper
|
||||
from service.fit import Fit
|
||||
|
||||
_t = wx.GetTranslation
|
||||
|
||||
class DummyItem:
|
||||
|
||||
@@ -159,7 +160,7 @@ class CommandView(d.Display):
|
||||
self.fits.sort(key=self.fitSort)
|
||||
stuff.extend(self.fits)
|
||||
if not stuff:
|
||||
stuff = [DummyEntry("Drag a fit to this area")]
|
||||
stuff = [DummyEntry(_t("Drag a fit to this area"))]
|
||||
self.update(stuff)
|
||||
|
||||
def click(self, event):
|
||||
@@ -197,7 +198,7 @@ class CommandView(d.Display):
|
||||
pass
|
||||
contexts = []
|
||||
if mainCommandFit is not None:
|
||||
contexts.append(('commandFit', 'Command Fit'))
|
||||
contexts.append(('commandFit', _t('Command Fit')))
|
||||
contexts.append(('commandView',))
|
||||
menu = ContextMenu.getMenu(self, mainCommandFit, selection, *contexts)
|
||||
if menu:
|
||||
|
||||
@@ -193,11 +193,8 @@ class DroneView(Display):
|
||||
|
||||
@staticmethod
|
||||
def droneKey(drone):
|
||||
sMkt = Market.getInstance()
|
||||
|
||||
groupName = sMkt.getMarketGroupByItem(drone.item).name
|
||||
|
||||
return (DRONE_ORDER.index(groupName), drone.item.name)
|
||||
groupName = Market.getInstance().getMarketGroupByItem(drone.item).marketGroupName
|
||||
return (DRONE_ORDER.index(groupName), drone.isMutated, drone.fullName)
|
||||
|
||||
def fitChanged(self, event):
|
||||
event.Skip()
|
||||
@@ -324,7 +321,7 @@ class DroneView(Display):
|
||||
if drone in self.original:
|
||||
mainDrone = drone
|
||||
selection = self.getSelectedDrones()
|
||||
itemContext = None if mainDrone is None else Market.getInstance().getCategoryByItem(mainDrone.item).name
|
||||
itemContext = None if mainDrone is None else Market.getInstance().getCategoryByItem(mainDrone.item).displayName
|
||||
menu = ContextMenu.getMenu(self, mainDrone, selection, ("droneItem", itemContext), ("droneItemMisc", itemContext))
|
||||
if menu:
|
||||
self.PopupMenu(menu)
|
||||
|
||||
@@ -35,6 +35,7 @@ from service.market import Market
|
||||
|
||||
|
||||
FIGHTER_ORDER = ('Light Fighter', 'Heavy Fighter', 'Support Fighter')
|
||||
_t = wx.GetTranslation
|
||||
|
||||
|
||||
class FighterViewDrop(wx.DropTarget):
|
||||
@@ -58,7 +59,7 @@ class FighterView(wx.Panel):
|
||||
def __init__(self, parent):
|
||||
wx.Panel.__init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, style=wx.TAB_TRAVERSAL)
|
||||
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
|
||||
self.labels = ["Light", "Heavy", "Support"]
|
||||
self.labels = [("Light", _t("Light")), ("Heavy", _t("Heavy")), ("Support", _t("Support"))]
|
||||
|
||||
mainSizer = wx.BoxSizer(wx.VERTICAL)
|
||||
|
||||
@@ -68,18 +69,18 @@ class FighterView(wx.Panel):
|
||||
textSizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||
textSizer.AddStretchSpacer()
|
||||
|
||||
for x in self.labels:
|
||||
lbl = wx.StaticText(self, wx.ID_ANY, x.capitalize())
|
||||
for attr, label in self.labels:
|
||||
lbl = wx.StaticText(self, wx.ID_ANY, label)
|
||||
textSizer.Add(lbl, 0, wx.ALIGN_CENTER | wx.LEFT, 5)
|
||||
|
||||
lbl = wx.StaticText(self, wx.ID_ANY, "0")
|
||||
setattr(self, "label%sUsed" % (x.capitalize()), lbl)
|
||||
setattr(self, "label%sUsed" % attr, lbl)
|
||||
textSizer.Add(lbl, 0, wx.ALIGN_CENTER | wx.LEFT, 5)
|
||||
|
||||
textSizer.Add(wx.StaticText(self, wx.ID_ANY, "/"), 0, wx.ALIGN_CENTER)
|
||||
|
||||
lbl = wx.StaticText(self, wx.ID_ANY, "0")
|
||||
setattr(self, "label%sTotal" % (x.capitalize()), lbl)
|
||||
setattr(self, "label%sTotal" % attr, lbl)
|
||||
textSizer.Add(lbl, 0, wx.ALIGN_CENTER)
|
||||
textSizer.AddStretchSpacer()
|
||||
|
||||
@@ -100,7 +101,7 @@ class FighterView(wx.Panel):
|
||||
fit = sFit.getFit(activeFitID)
|
||||
|
||||
if fit:
|
||||
for x in self.labels:
|
||||
for x, _ in self.labels:
|
||||
if fit.isStructure:
|
||||
slot = getattr(FittingSlot, "FS_{}".format(x.upper()))
|
||||
else:
|
||||
@@ -382,7 +383,7 @@ class FighterDisplay(d.Display):
|
||||
else:
|
||||
if fighter in self.original:
|
||||
mainFighter = fighter
|
||||
itemContext = None if mainFighter is None else Market.getInstance().getCategoryByItem(mainFighter.item).name
|
||||
itemContext = None if mainFighter is None else Market.getInstance().getCategoryByItem(mainFighter.item).displayName
|
||||
menu = ContextMenu.getMenu(self, mainFighter, selection, ("fighterItem", itemContext), ("fighterItemMisc", itemContext))
|
||||
if menu:
|
||||
self.PopupMenu(menu)
|
||||
|
||||
@@ -32,6 +32,8 @@ from gui.utils.staticHelpers import DragDropHelper
|
||||
from service.fit import Fit
|
||||
from service.market import Market
|
||||
|
||||
_t = wx.GetTranslation
|
||||
|
||||
|
||||
class ImplantViewDrop(wx.DropTarget):
|
||||
def __init__(self, dropFn, *args, **kwargs):
|
||||
@@ -62,8 +64,8 @@ class ImplantView(wx.Panel):
|
||||
|
||||
radioSizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||
radioSizer.AddStretchSpacer()
|
||||
self.rbFit = wx.RadioButton(self, id=wx.ID_ANY, label="Use Fit-specific Implants", style=wx.RB_GROUP)
|
||||
self.rbChar = wx.RadioButton(self, id=wx.ID_ANY, label="Use Character Implants")
|
||||
self.rbFit = wx.RadioButton(self, id=wx.ID_ANY, label=_t("Use Fit-specific Implants"), style=wx.RB_GROUP)
|
||||
self.rbChar = wx.RadioButton(self, id=wx.ID_ANY, label=_t("Use Character Implants"))
|
||||
radioSizer.Add(self.rbFit, 0, wx.ALL, 5)
|
||||
radioSizer.Add(self.rbChar, 0, wx.ALL, 5)
|
||||
radioSizer.AddStretchSpacer()
|
||||
@@ -298,7 +300,7 @@ class ImplantDisplay(d.Display):
|
||||
fit = Fit.getInstance().getFit(fitID)
|
||||
sourceContext1 = "implantItem" if fit.implantSource == ImplantLocation.FIT else "implantItemChar"
|
||||
sourceContext2 = "implantItemMisc" if fit.implantSource == ImplantLocation.FIT else "implantItemMiscChar"
|
||||
itemContext = None if mainImplant is None else Market.getInstance().getCategoryByItem(mainImplant.item).name
|
||||
itemContext = None if mainImplant is None else Market.getInstance().getCategoryByItem(mainImplant.item).displayName
|
||||
menu = ContextMenu.getMenu(self, mainImplant, selection,
|
||||
(sourceContext1, itemContext),
|
||||
(sourceContext2, itemContext)
|
||||
|
||||
@@ -26,7 +26,12 @@ class NotesView(wx.Panel):
|
||||
|
||||
def OnKeyDown(self, event):
|
||||
if event.RawControlDown() and event.GetKeyCode() == wx.WXK_BACK:
|
||||
HandleCtrlBackspace(self.editNotes)
|
||||
try:
|
||||
HandleCtrlBackspace(self.editNotes)
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
event.Skip()
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ from service.market import Market
|
||||
|
||||
|
||||
pyfalog = Logger(__name__)
|
||||
|
||||
_t = wx.GetTranslation
|
||||
|
||||
class DummyItem:
|
||||
def __init__(self, txt):
|
||||
@@ -221,7 +221,7 @@ class ProjectedView(d.Display):
|
||||
stuff.extend(self.drones)
|
||||
stuff.extend(self.fighters)
|
||||
if not stuff:
|
||||
stuff = [DummyEntry('Drag an item or fit, or use right-click menu for wormhole effects')]
|
||||
stuff = [DummyEntry(_t('Drag an item or fit, or use right-click menu for wormhole effects'))]
|
||||
self.update(stuff)
|
||||
|
||||
def get(self, row):
|
||||
@@ -301,27 +301,27 @@ class ProjectedView(d.Display):
|
||||
|
||||
if isinstance(mainItem, EosModule):
|
||||
modSrcContext = 'projectedModule'
|
||||
modItemContext = 'Projected Item'
|
||||
modItemContext = _t('Projected Item')
|
||||
modFullContext = (modSrcContext, modItemContext)
|
||||
contexts.append(modFullContext)
|
||||
if mainItem.charge is not None:
|
||||
chargeSrcContext = 'projectedCharge'
|
||||
chargeItemContext = sMkt.getCategoryByItem(mainItem.charge).name
|
||||
chargeItemContext = sMkt.getCategoryByItem(mainItem.charge).displayName
|
||||
chargeFullContext = (chargeSrcContext, chargeItemContext)
|
||||
contexts.append(chargeFullContext)
|
||||
elif isinstance(mainItem, EosDrone):
|
||||
srcContext = 'projectedDrone'
|
||||
itemContext = 'Projected Item'
|
||||
itemContext = _t('Projected Item')
|
||||
droneFullContext = (srcContext, itemContext)
|
||||
contexts.append(droneFullContext)
|
||||
elif isinstance(mainItem, EosFighter):
|
||||
srcContext = 'projectedFighter'
|
||||
itemContext = 'Projected Item'
|
||||
itemContext = _t('Projected Item')
|
||||
fighterFullContext = (srcContext, itemContext)
|
||||
contexts.append(fighterFullContext)
|
||||
else:
|
||||
fitSrcContext = 'projectedFit'
|
||||
fitItemContext = 'Projected Item'
|
||||
fitItemContext = _t('Projected Item')
|
||||
fitFullContext = (fitSrcContext, fitItemContext)
|
||||
contexts.append(fitFullContext)
|
||||
contexts.append(('projected',))
|
||||
|
||||
@@ -26,7 +26,7 @@ from gui.builtinContextMenus import itemAmountChange
|
||||
from gui.builtinContextMenus import itemProjectionRange
|
||||
from gui.builtinContextMenus import droneSplitStack
|
||||
from gui.builtinContextMenus import itemVariationChange
|
||||
from gui.builtinContextMenus import moduleMutations
|
||||
from gui.builtinContextMenus import itemMutations
|
||||
from gui.builtinContextMenus import moduleFill
|
||||
from gui.builtinContextMenus import moduleMutatedExport
|
||||
from gui.builtinContextMenus import skillAffectors
|
||||
|
||||
@@ -1,44 +1,46 @@
|
||||
import wx
|
||||
|
||||
import gui.mainFrame
|
||||
from gui.contextMenu import ContextMenuUnconditional
|
||||
from gui.utils.clipboard import toClipboard
|
||||
from service.fit import Fit
|
||||
from service.port.eft import exportDrones, exportFighters, exportCargo, exportImplants, exportBoosters
|
||||
from service.port.eft import exportBoosters, exportCargo, exportDrones, exportFighters, exportImplants
|
||||
|
||||
|
||||
viewSpecMap = {
|
||||
'droneItemMisc': ('Drones', lambda cw: cw.drones, exportDrones),
|
||||
'fighterItemMisc': ('Fighters', lambda cw: cw.fighters, exportFighters),
|
||||
'cargoItemMisc': ('Cargo Items', lambda cw: cw.cargo, exportCargo),
|
||||
'implantItemMisc': ('Implants', lambda cw: cw.implants, exportImplants),
|
||||
'implantItemMiscChar': ('Implants', lambda cw: cw.implants, exportImplants),
|
||||
'boosterItemMisc': ('Boosters', lambda cw: cw.boosters, exportBoosters)}
|
||||
_t = wx.GetTranslation
|
||||
|
||||
|
||||
class AdditionsExportAll(ContextMenuUnconditional):
|
||||
|
||||
visibilitySetting = 'additionsCopyPaste'
|
||||
|
||||
def __init__(self):
|
||||
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
|
||||
self.viewSpecMap = {
|
||||
'droneItemMisc': (_t('Drones'), lambda cw: cw.drones, exportDrones),
|
||||
'fighterItemMisc': (_t('Fighters'), lambda cw: cw.fighters, exportFighters),
|
||||
'cargoItemMisc': (_t('Cargo Items'), lambda cw: cw.cargo, exportCargo),
|
||||
'implantItemMisc': (_t('Implants'), lambda cw: cw.implants, exportImplants),
|
||||
'implantItemMiscChar': (_t('Implants'), lambda cw: cw.implants, exportImplants),
|
||||
'boosterItemMisc': (_t('Boosters'), lambda cw: cw.boosters, exportBoosters)
|
||||
}
|
||||
|
||||
def display(self, callingWindow, srcContext):
|
||||
if srcContext not in viewSpecMap:
|
||||
if srcContext not in self.viewSpecMap:
|
||||
return False
|
||||
fit = Fit.getInstance().getFit(self.mainFrame.getActiveFit())
|
||||
if fit is None:
|
||||
return False
|
||||
if not viewSpecMap[srcContext][1](callingWindow):
|
||||
if not self.viewSpecMap[srcContext][1](callingWindow):
|
||||
return False
|
||||
|
||||
self.srcContext = srcContext
|
||||
return True
|
||||
|
||||
def getText(self, callingWindow, itmContext):
|
||||
return 'Copy All {}'.format(viewSpecMap[self.srcContext][0])
|
||||
return _t('Copy All {}').format(self.viewSpecMap[self.srcContext][0])
|
||||
|
||||
def activate(self, callingWindow, fullContext, i):
|
||||
items = viewSpecMap[self.srcContext][1](callingWindow)
|
||||
export = viewSpecMap[self.srcContext][2](items)
|
||||
items = self.viewSpecMap[self.srcContext][1](callingWindow)
|
||||
export = self.viewSpecMap[self.srcContext][2](items)
|
||||
if export:
|
||||
toClipboard(export)
|
||||
|
||||
|
||||
@@ -1,28 +1,30 @@
|
||||
import wx
|
||||
|
||||
import gui.mainFrame
|
||||
from gui.contextMenu import ContextMenuSelection
|
||||
from gui.utils.clipboard import toClipboard
|
||||
from service.fit import Fit
|
||||
from service.port.eft import exportDrones, exportFighters, exportCargo, exportImplants, exportBoosters
|
||||
from service.port.eft import exportBoosters, exportCargo, exportDrones, exportFighters, exportImplants
|
||||
|
||||
|
||||
viewSpecMap = {
|
||||
'droneItemMisc': ('Drones', exportDrones),
|
||||
'fighterItemMisc': ('Fighters', exportFighters),
|
||||
'cargoItemMisc': ('Cargo Items', exportCargo),
|
||||
'implantItemMisc': ('Implants', exportImplants),
|
||||
'implantItemMiscChar': ('Implants', exportImplants),
|
||||
'boosterItemMisc': ('Boosters', exportBoosters)}
|
||||
_t = wx.GetTranslation
|
||||
|
||||
|
||||
class AdditionsExportAll(ContextMenuSelection):
|
||||
|
||||
visibilitySetting = 'additionsCopyPaste'
|
||||
|
||||
def __init__(self):
|
||||
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
|
||||
self.viewSpecMap = {
|
||||
'droneItemMisc': (_t('Drones'), exportDrones),
|
||||
'fighterItemMisc': (_t('Fighters'), exportFighters),
|
||||
'cargoItemMisc': (_t('Cargo Items'), exportCargo),
|
||||
'implantItemMisc': (_t('Implants'), exportImplants),
|
||||
'implantItemMiscChar': (_t('Implants'), exportImplants),
|
||||
'boosterItemMisc': (_t('Boosters'), exportBoosters)
|
||||
}
|
||||
|
||||
def display(self, callingWindow, srcContext, selection):
|
||||
if srcContext not in viewSpecMap:
|
||||
if srcContext not in self.viewSpecMap:
|
||||
return False
|
||||
if not selection:
|
||||
return False
|
||||
@@ -34,10 +36,10 @@ class AdditionsExportAll(ContextMenuSelection):
|
||||
return True
|
||||
|
||||
def getText(self, callingWindow, itmContext, selection):
|
||||
return 'Copy Selected {}'.format(viewSpecMap[self.srcContext][0])
|
||||
return _t('Copy Selected {}').format(self.viewSpecMap[self.srcContext][0])
|
||||
|
||||
def activate(self, callingWindow, fullContext, selection, i):
|
||||
export = viewSpecMap[self.srcContext][1](selection)
|
||||
export = self.viewSpecMap[self.srcContext][1](selection)
|
||||
if export:
|
||||
toClipboard(export)
|
||||
|
||||
|
||||
@@ -1,29 +1,31 @@
|
||||
import wx
|
||||
|
||||
import gui.mainFrame
|
||||
from gui import fitCommands as cmd
|
||||
from gui.contextMenu import ContextMenuUnconditional
|
||||
from gui.utils.clipboard import fromClipboard
|
||||
from service.fit import Fit
|
||||
from service.port.eft import parseAdditions
|
||||
from service.port.eft import parseAdditions, importGetMutationData, lineIter
|
||||
|
||||
|
||||
viewSpecMap = {
|
||||
'droneItemMisc': ('Drones', lambda i: i.isDrone, cmd.GuiImportLocalDronesCommand),
|
||||
'fighterItemMisc': ('Fighters', lambda i: i.isFighter, cmd.GuiImportLocalFightersCommand),
|
||||
'cargoItemMisc': ('Cargo Items', lambda i: not i.isAbyssal, cmd.GuiImportCargosCommand),
|
||||
'implantItemMisc': ('Implants', lambda i: i.isImplant, cmd.GuiImportImplantsCommand),
|
||||
'implantItemMiscChar': ('Implants', lambda i: i.isImplant, cmd.GuiImportImplantsCommand),
|
||||
'boosterItemMisc': ('Boosters', lambda i: i.isBooster, cmd.GuiImportBoostersCommand)}
|
||||
_t = wx.GetTranslation
|
||||
|
||||
|
||||
class AdditionsImport(ContextMenuUnconditional):
|
||||
|
||||
visibilitySetting = 'additionsCopyPaste'
|
||||
|
||||
def __init__(self):
|
||||
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
|
||||
self.viewSpecMap = {
|
||||
'droneItemMisc': (_t('Drones'), lambda i: i.isDrone, cmd.GuiImportLocalDronesCommand),
|
||||
'fighterItemMisc': (_t('Fighters'), lambda i: i.isFighter, cmd.GuiImportLocalFightersCommand),
|
||||
'cargoItemMisc': (_t('Cargo Items'), lambda i: not i.isAbyssal, cmd.GuiImportCargosCommand),
|
||||
'implantItemMisc': (_t('Implants'), lambda i: i.isImplant, cmd.GuiImportImplantsCommand),
|
||||
'implantItemMiscChar': (_t('Implants'), lambda i: i.isImplant, cmd.GuiImportImplantsCommand),
|
||||
'boosterItemMisc': (_t('Boosters'), lambda i: i.isBooster, cmd.GuiImportBoostersCommand)
|
||||
}
|
||||
|
||||
def display(self, callingWindow, srcContext):
|
||||
if srcContext not in viewSpecMap:
|
||||
if srcContext not in self.viewSpecMap:
|
||||
return False
|
||||
fit = Fit.getInstance().getFit(self.mainFrame.getActiveFit())
|
||||
if fit is None:
|
||||
@@ -35,16 +37,19 @@ class AdditionsImport(ContextMenuUnconditional):
|
||||
return True
|
||||
|
||||
def getText(self, callingWindow, itmContext):
|
||||
return 'Paste {}'.format(viewSpecMap[self.srcContext][0])
|
||||
return _t('Paste {}').format(self.viewSpecMap[self.srcContext][0])
|
||||
|
||||
def activate(self, callingWindow, fullContext, i):
|
||||
text = fromClipboard()
|
||||
items = parseAdditions(text)
|
||||
filterFunc = viewSpecMap[self.srcContext][1]
|
||||
items = [(i.ID, a) for i, a in items if filterFunc(i)]
|
||||
lines = list(lineIter(text))
|
||||
mutaData = importGetMutationData(lines)
|
||||
text = '\n'.join(lines)
|
||||
items = parseAdditions(text, mutaData=mutaData)
|
||||
filterFunc = self.viewSpecMap[self.srcContext][1]
|
||||
items = [(i.ID, a, m) for i, a, m in items if filterFunc(i)]
|
||||
if not items:
|
||||
return
|
||||
command = viewSpecMap[self.srcContext][2]
|
||||
command = self.viewSpecMap[self.srcContext][2]
|
||||
self.mainFrame.command.Submit(command(self.mainFrame.getActiveFit(), items))
|
||||
|
||||
|
||||
|
||||
@@ -6,9 +6,10 @@ import gui.mainFrame
|
||||
from gui.contextMenu import ContextMenuSingle
|
||||
from service.fit import Fit
|
||||
|
||||
_t = wx.GetTranslation
|
||||
|
||||
|
||||
class AmmoToDmgPattern(ContextMenuSingle):
|
||||
|
||||
visibilitySetting = 'ammoPattern'
|
||||
|
||||
def __init__(self):
|
||||
@@ -28,7 +29,7 @@ class AmmoToDmgPattern(ContextMenuSingle):
|
||||
return False
|
||||
|
||||
def getText(self, callingWindow, itmContext, mainItem):
|
||||
return "Set {} as Damage Pattern".format(itmContext if itmContext is not None else "Item")
|
||||
return _t("Set {} as Damage Pattern").format(itmContext if itmContext is not None else _t("Item"))
|
||||
|
||||
def activate(self, callingWindow, fullContext, mainItem, i):
|
||||
fitID = self.mainFrame.getActiveFit()
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# noinspection PyPackageRequirements
|
||||
|
||||
import wx
|
||||
|
||||
import gui.mainFrame
|
||||
@@ -6,6 +7,8 @@ from gui import fitCommands as cmd
|
||||
from gui.contextMenu import ContextMenuSingle
|
||||
from service.fit import Fit
|
||||
|
||||
_t = wx.GetTranslation
|
||||
|
||||
|
||||
class BoosterSideEffects(ContextMenuSingle):
|
||||
|
||||
@@ -28,7 +31,7 @@ class BoosterSideEffects(ContextMenuSingle):
|
||||
return False
|
||||
|
||||
def getText(self, callingWindow, itmContext, mainItem):
|
||||
return "Side Effects"
|
||||
return _t("Side Effects")
|
||||
|
||||
def addEffect(self, menu, ability):
|
||||
label = ability.name
|
||||
@@ -67,7 +70,7 @@ class BoosterSideEffects(ContextMenuSingle):
|
||||
if booster in fit.boosters:
|
||||
index = fit.boosters.index(booster)
|
||||
self.mainFrame.command.Submit(cmd.GuiToggleBoosterSideEffectStateCommand(
|
||||
fitID=fitID, position=index, effectID=effect.effectID))
|
||||
fitID=fitID, position=index, effectID=effect.effectID))
|
||||
|
||||
|
||||
BoosterSideEffects.register()
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
import wx
|
||||
|
||||
import gui.fitCommands as cmd
|
||||
import gui.mainFrame
|
||||
from gui.contextMenu import ContextMenuSingle
|
||||
from service.fit import Fit
|
||||
|
||||
_t = wx.GetTranslation
|
||||
|
||||
|
||||
class AddToCargo(ContextMenuSingle):
|
||||
|
||||
@@ -26,7 +30,7 @@ class AddToCargo(ContextMenuSingle):
|
||||
return True
|
||||
|
||||
def getText(self, callingWindow, itmContext, mainItem):
|
||||
return "Add {} to Cargo".format(itmContext)
|
||||
return _t("Add {} to Cargo").format(itmContext)
|
||||
|
||||
def activate(self, callingWindow, fullContext, mainItem, i):
|
||||
fitID = self.mainFrame.getActiveFit()
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
import wx
|
||||
|
||||
import gui.fitCommands as cmd
|
||||
import gui.mainFrame
|
||||
from gui.contextMenu import ContextMenuSingle
|
||||
|
||||
_t = wx.GetTranslation
|
||||
|
||||
|
||||
class AddToCargoAmmo(ContextMenuSingle):
|
||||
|
||||
@@ -21,7 +25,7 @@ class AddToCargoAmmo(ContextMenuSingle):
|
||||
return True
|
||||
|
||||
def getText(self, callingWindow, itmContext, mainItem):
|
||||
return "Add {0} to Cargo (x1000)".format(itmContext)
|
||||
return _t("Add {0} to Cargo (x1000)").format(itmContext)
|
||||
|
||||
def activate(self, callingWindow, fullContext, mainItem, i):
|
||||
fitID = self.mainFrame.getActiveFit()
|
||||
|
||||
@@ -7,9 +7,10 @@ from gui.contextMenu import ContextMenuUnconditional
|
||||
from service.fit import Fit
|
||||
from service.market import Market
|
||||
|
||||
_t = wx.GetTranslation
|
||||
|
||||
|
||||
class AddCommandFit(ContextMenuUnconditional):
|
||||
|
||||
# Get list of items that define a command fit
|
||||
sMkt = Market.getInstance()
|
||||
grp = sMkt.getGroup(1770) # Command burst group
|
||||
@@ -47,7 +48,7 @@ class AddCommandFit(ContextMenuUnconditional):
|
||||
return True
|
||||
|
||||
def getText(self, callingWindow, itmContext):
|
||||
return "Command Fits"
|
||||
return _t("Command Fits")
|
||||
|
||||
def addFit(self, menu, fit, includeShip=False):
|
||||
label = fit.name if not includeShip else "({}) {}".format(fit.ship.item.name, fit.name)
|
||||
|
||||
@@ -11,6 +11,8 @@ from gui.utils.sorter import smartSort
|
||||
from service.damagePattern import DamagePattern as DmgPatternSvc
|
||||
from service.fit import Fit
|
||||
|
||||
_t = wx.GetTranslation
|
||||
|
||||
|
||||
class ChangeDamagePattern(ContextMenuUnconditional):
|
||||
|
||||
@@ -35,16 +37,18 @@ class ChangeDamagePattern(ContextMenuUnconditional):
|
||||
# Order here is important: patterns with duplicate names from the latter will overwrite
|
||||
# patterns from the former
|
||||
self.patterns = sorted(
|
||||
chain(builtinPatterns, userPatterns),
|
||||
key=lambda p: p.fullName not in ["Uniform", "Selected Ammo"])
|
||||
chain(builtinPatterns, userPatterns),
|
||||
key=lambda p: p.fullName not in ["Uniform", "Selected Ammo"])
|
||||
|
||||
self.patternEventMap = {}
|
||||
self.items = (OrderedDict(), OrderedDict())
|
||||
for pattern in self.patterns:
|
||||
container = self.items
|
||||
for categoryName in pattern.hierarchy:
|
||||
categoryName = _t(categoryName) if pattern.builtin else categoryName
|
||||
container = container[1].setdefault(categoryName, (OrderedDict(), OrderedDict()))
|
||||
container[0][pattern.shortName] = pattern
|
||||
shortName = _t(pattern.shortName) if pattern.builtin else pattern.shortName
|
||||
container[0][shortName] = pattern
|
||||
|
||||
return list(self.items[0].keys()) + list(self.items[1].keys())
|
||||
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
import wx
|
||||
|
||||
import gui.fitCommands as cmd
|
||||
import gui.mainFrame
|
||||
from gui.contextMenu import ContextMenuSingle
|
||||
from gui.fitCommands.helpers import droneStackLimit
|
||||
from service.fit import Fit
|
||||
|
||||
_t = wx.GetTranslation
|
||||
|
||||
|
||||
class DroneAddStack(ContextMenuSingle):
|
||||
|
||||
@@ -33,14 +37,14 @@ class DroneAddStack(ContextMenuSingle):
|
||||
return True
|
||||
|
||||
def getText(self, callingWindow, itmContext, mainItem):
|
||||
return 'Add {} to Drone Bay{}'.format(
|
||||
itmContext, '' if self.amount == 1 else ' (x{})'.format(self.amount))
|
||||
return _t('Add {} to Drone Bay{}').format(
|
||||
itmContext, '' if self.amount == 1 else ' (x{})'.format(self.amount))
|
||||
|
||||
def activate(self, callingWindow, fullContext, mainItem, i):
|
||||
command = cmd.GuiAddLocalDroneCommand(
|
||||
fitID=self.mainFrame.getActiveFit(),
|
||||
itemID=int(mainItem.ID),
|
||||
amount=self.amount)
|
||||
fitID=self.mainFrame.getActiveFit(),
|
||||
itemID=int(mainItem.ID),
|
||||
amount=self.amount)
|
||||
if self.mainFrame.command.Submit(command):
|
||||
self.mainFrame.additionsPane.select('Drones', focus=False)
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@ import gui.mainFrame
|
||||
from gui.contextMenu import ContextMenuSingle
|
||||
from service.fit import Fit
|
||||
|
||||
_t = wx.GetTranslation
|
||||
|
||||
|
||||
class DroneSplitStack(ContextMenuSingle):
|
||||
|
||||
@@ -24,7 +26,7 @@ class DroneSplitStack(ContextMenuSingle):
|
||||
return mainItem.amount > 1
|
||||
|
||||
def getText(self, callingWindow, itmContext, mainItem):
|
||||
return "Split {} Stack".format(itmContext)
|
||||
return _t("Split {} Stack").format(itmContext)
|
||||
|
||||
def activate(self, callingWindow, fullContext, mainItem, i):
|
||||
with DroneStackSplit(self.mainFrame, mainItem.amount) as dlg:
|
||||
@@ -41,7 +43,7 @@ class DroneSplitStack(ContextMenuSingle):
|
||||
if mainItem in fit.drones:
|
||||
position = fit.drones.index(mainItem)
|
||||
self.mainFrame.command.Submit(cmd.GuiSplitLocalDroneStackCommand(
|
||||
fitID=fitID, position=position, amount=int(cleanInput)))
|
||||
fitID=fitID, position=position, amount=int(cleanInput)))
|
||||
|
||||
|
||||
DroneSplitStack.register()
|
||||
|
||||
@@ -10,6 +10,8 @@ import gui.mainFrame
|
||||
from gui.contextMenu import ContextMenuUnconditional
|
||||
from service.market import Market
|
||||
|
||||
_t = wx.GetTranslation
|
||||
|
||||
|
||||
class Group:
|
||||
|
||||
@@ -32,9 +34,7 @@ class Entry:
|
||||
self.shortName = shortName
|
||||
|
||||
|
||||
|
||||
class AddEnvironmentEffect(ContextMenuUnconditional):
|
||||
|
||||
# CCP doesn't currently provide a mapping between the general Environment, and the specific environment effect
|
||||
# (which can be random when going into Abyssal space). This is how we currently define it:
|
||||
# environment type: specific type name prefix
|
||||
@@ -53,7 +53,7 @@ class AddEnvironmentEffect(ContextMenuUnconditional):
|
||||
return srcContext == "projected"
|
||||
|
||||
def getText(self, callingWindow, itmContext):
|
||||
return "Add Environmental Effect"
|
||||
return _t("Add Environmental Effect")
|
||||
|
||||
def _addGroup(self, parentMenu, name):
|
||||
id = ContextMenuUnconditional.nextID()
|
||||
@@ -102,16 +102,30 @@ class AddEnvironmentEffect(ContextMenuUnconditional):
|
||||
|
||||
def getData(self):
|
||||
data = Group()
|
||||
data.groups['Metaliminal Storm'] = self.getEffectBeacons(
|
||||
'Electrical', 'Exotic', 'Gamma', 'Plasma',
|
||||
extra_garbage=('Metaliminal', 'Storm', 'Matter', 'Ray', 'Firestorm'))
|
||||
data.groups['Wormhole'] = self.getEffectBeacons(
|
||||
'Black Hole', 'Cataclysmic Variable', 'Magnetar',
|
||||
'Pulsar', 'Red Giant', 'Wolf Rayet')
|
||||
data.groups['Abyssal Weather'] = self.getAbyssalWeather()
|
||||
data.groups['Sansha Incursion'] = self.getEffectBeacons('Sansha Incursion')
|
||||
data.groups['Triglavian Invasion'] = self.getEffectBeacons('Triglavian Invasion')
|
||||
data.groups['Triglavian Invasion'].groups['Destructible Beacons'] = self.getDestructibleBeacons()
|
||||
data.groups[_t('Metaliminal Storm')] = self.getEffectBeacons(
|
||||
_t('ContextMenu|ProjectedEffectManipulation|Electrical'),
|
||||
_t('ContextMenu|ProjectedEffectManipulation|Exotic'),
|
||||
_t('ContextMenu|ProjectedEffectManipulation|Gamma'),
|
||||
_t('ContextMenu|ProjectedEffectManipulation|Plasma'),
|
||||
extra_garbage=(
|
||||
_t('ContextMenu|ProjectedEffectManipulation|Metaliminal'),
|
||||
_t('ContextMenu|ProjectedEffectManipulation|Storm'),
|
||||
_t('ContextMenu|ProjectedEffectManipulation|Matter'),
|
||||
_t('ContextMenu|ProjectedEffectManipulation|Ray'),
|
||||
_t('ContextMenu|ProjectedEffectManipulation|Firestorm')))
|
||||
data.groups[_t('Wormhole')] = self.getEffectBeacons(
|
||||
_t('ContextMenu|ProjectedEffectManipulation|Black Hole'),
|
||||
_t('ContextMenu|ProjectedEffectManipulation|Cataclysmic Variable'),
|
||||
_t('ContextMenu|ProjectedEffectManipulation|Magnetar'),
|
||||
_t('ContextMenu|ProjectedEffectManipulation|Pulsar'),
|
||||
_t('ContextMenu|ProjectedEffectManipulation|Red Giant'),
|
||||
_t('ContextMenu|ProjectedEffectManipulation|Wolf Rayet'))
|
||||
data.groups[_t('Abyssal Weather')] = self.getAbyssalWeather()
|
||||
data.groups[_t('Sansha Incursion')] = self.getEffectBeacons(
|
||||
_t('ContextMenu|ProjectedEffectManipulation|Sansha Incursion'))
|
||||
data.groups[_t('Triglavian Invasion')] = self.getEffectBeacons(
|
||||
_t('ContextMenu|ProjectedEffectManipulation|Triglavian Invasion'))
|
||||
data.groups[_t('Triglavian Invasion')].groups[_t('Destructible Beacons')] = self.getDestructibleBeacons()
|
||||
return data
|
||||
|
||||
def getEffectBeacons(self, *groups, extra_garbage=()):
|
||||
@@ -125,7 +139,9 @@ class AddEnvironmentEffect(ContextMenuUnconditional):
|
||||
data = Group()
|
||||
|
||||
# Stuff we don't want to see in names
|
||||
garbages = ["System Effects", "Effects"]
|
||||
garbages = [
|
||||
_t('ContextMenu|ProjectedEffectManipulation|System Effects'),
|
||||
_t('ContextMenu|ProjectedEffectManipulation|Effects')]
|
||||
garbages.extend(extra_garbage)
|
||||
|
||||
# Get group with all the system-wide beacons
|
||||
@@ -169,8 +185,8 @@ class AddEnvironmentEffect(ContextMenuUnconditional):
|
||||
|
||||
environments = {x.ID: x for x in sMkt.getGroup("Abyssal Environment").items}
|
||||
items = chain(
|
||||
sMkt.getGroup("MassiveEnvironments").items,
|
||||
sMkt.getGroup("Non-Interactable Object").items)
|
||||
sMkt.getGroup("MassiveEnvironments").items,
|
||||
sMkt.getGroup("Non-Interactable Object").items)
|
||||
for beacon in items:
|
||||
if not beacon.isType('projected'):
|
||||
continue
|
||||
@@ -186,21 +202,24 @@ class AddEnvironmentEffect(ContextMenuUnconditional):
|
||||
# Localized abyssal hazards
|
||||
items = sMkt.getGroup("Abyssal Hazards").items
|
||||
if items:
|
||||
subdata = data.groups.setdefault('Localized', Group())
|
||||
subdata = data.groups.setdefault(_t('Localized'), Group())
|
||||
for beacon in sMkt.getGroup("Abyssal Hazards").items:
|
||||
if not beacon.isType('projected'):
|
||||
continue
|
||||
# Localized effects, currently, have a name like "(size) (type) Cloud"
|
||||
# Until this inevitably changes, do a simple split
|
||||
name_parts = beacon.name.split(" ")
|
||||
groups = (_t('Bioluminescence'), _t('Tachyon'), _t('Filament'))
|
||||
for group in groups:
|
||||
if re.search(group, beacon.customName):
|
||||
key = group
|
||||
break
|
||||
else:
|
||||
continue
|
||||
|
||||
key = name_parts[1].strip()
|
||||
subsubdata = subdata.groups.setdefault(key, Group())
|
||||
subsubdata.items.append(Entry(beacon.ID, beacon.name, beacon.name))
|
||||
subsubdata.items.append(Entry(beacon.ID, beacon.customName, beacon.customName))
|
||||
subdata.sort()
|
||||
|
||||
# PVP weather
|
||||
data.items.append(Entry(49766, 'PvP Weather', 'PvP Weather'))
|
||||
data.items.append(Entry(49766, _t('PvP Weather'), _t('PvP Weather')))
|
||||
|
||||
return data
|
||||
|
||||
@@ -214,4 +233,5 @@ class AddEnvironmentEffect(ContextMenuUnconditional):
|
||||
data.sort()
|
||||
return data
|
||||
|
||||
|
||||
AddEnvironmentEffect.register()
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# noinspection PyPackageRequirements
|
||||
|
||||
import wx
|
||||
|
||||
import gui.globalEvents as GE
|
||||
@@ -6,6 +7,8 @@ import gui.mainFrame
|
||||
from gui.contextMenu import ContextMenuUnconditional
|
||||
from service.fit import Fit
|
||||
|
||||
_t = wx.GetTranslation
|
||||
|
||||
|
||||
class FactorReload(ContextMenuUnconditional):
|
||||
|
||||
@@ -20,7 +23,7 @@ class FactorReload(ContextMenuUnconditional):
|
||||
return self.mainFrame.getActiveFit() is not None
|
||||
|
||||
def getText(self, callingWindow, itmContext):
|
||||
return "Factor in Reload Time"
|
||||
return _t("Factor in Reload Time")
|
||||
|
||||
def activate(self, callingWindow, fullContext, i):
|
||||
fitIDs = Fit.getInstance().toggleFactorReload()
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
# noinspection PyPackageRequirements
|
||||
|
||||
import wx
|
||||
|
||||
import gui.mainFrame
|
||||
from gui import fitCommands as cmd
|
||||
from gui.fitCommands.helpers import getSimilarFighters
|
||||
from gui.contextMenu import ContextMenuCombined
|
||||
from gui.fitCommands.helpers import getSimilarFighters
|
||||
from service.fit import Fit
|
||||
|
||||
_t = wx.GetTranslation
|
||||
|
||||
|
||||
class FighterAbilities(ContextMenuCombined):
|
||||
|
||||
@@ -27,7 +30,7 @@ class FighterAbilities(ContextMenuCombined):
|
||||
return True
|
||||
|
||||
def getText(self, callingWindow, itmContext, mainItem, selection):
|
||||
return "Abilities"
|
||||
return _t("Abilities")
|
||||
|
||||
def addAbility(self, menu, ability):
|
||||
label = ability.name
|
||||
@@ -78,10 +81,10 @@ class FighterAbilities(ContextMenuCombined):
|
||||
if fighter in container:
|
||||
positions.append(container.index(fighter))
|
||||
self.mainFrame.command.Submit(command(
|
||||
fitID=fitID,
|
||||
mainPosition=mainPosition,
|
||||
positions=positions,
|
||||
effectID=ability.effectID))
|
||||
fitID=fitID,
|
||||
mainPosition=mainPosition,
|
||||
positions=positions,
|
||||
effectID=ability.effectID))
|
||||
|
||||
|
||||
FighterAbilities.register()
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
# noinspection PyPackageRequirements
|
||||
|
||||
import wx
|
||||
|
||||
import gui.mainFrame
|
||||
from gui.contextMenu import ContextMenuUnconditional
|
||||
|
||||
_t = wx.GetTranslation
|
||||
|
||||
|
||||
class AddBrowsedFits(ContextMenuUnconditional):
|
||||
|
||||
@@ -16,7 +19,7 @@ class AddBrowsedFits(ContextMenuUnconditional):
|
||||
return True
|
||||
|
||||
def getText(self, callingWindow, itmContext):
|
||||
return 'Add Fit...'
|
||||
return _t('Add Fit...')
|
||||
|
||||
def activate(self, callingWindow, fullContext, i):
|
||||
from gui.fitBrowserLite import FitBrowserLiteDialog
|
||||
@@ -24,7 +27,8 @@ class AddBrowsedFits(ContextMenuUnconditional):
|
||||
'projected': 'Add Projected Fits',
|
||||
'commandView': 'Add Command Fits',
|
||||
'graphFitList': 'Add Fits to Graph',
|
||||
'graphTgtList': 'Add Targets to Graph'}
|
||||
'graphTgtList': 'Add Targets to Graph'
|
||||
}
|
||||
excludedFitIDs = callingWindow.getExistingFitIDs()
|
||||
with FitBrowserLiteDialog(self.mainFrame, title=titles[fullContext[0]], excludedFitIDs=excludedFitIDs) as dlg:
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# noinspection PyPackageRequirements
|
||||
|
||||
import wx
|
||||
|
||||
import gui.mainFrame
|
||||
@@ -6,6 +7,8 @@ from gui.builtinViews.emptyView import BlankPage
|
||||
from gui.contextMenu import ContextMenuUnconditional
|
||||
from service.fit import Fit
|
||||
|
||||
_t = wx.GetTranslation
|
||||
|
||||
|
||||
class AddCurrentlyOpenFit(ContextMenuUnconditional):
|
||||
|
||||
@@ -23,7 +26,7 @@ class AddCurrentlyOpenFit(ContextMenuUnconditional):
|
||||
return True
|
||||
|
||||
def getText(self, callingWindow, itmContext):
|
||||
return 'Add Currently Open Fit'
|
||||
return _t('Add Currently Open Fit')
|
||||
|
||||
def getSubMenu(self, callingWindow, context, rootMenu, i, pitem):
|
||||
self.fitLookup = {}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# noinspection PyPackageRequirements
|
||||
|
||||
import wx
|
||||
|
||||
import gui.mainFrame
|
||||
@@ -6,6 +7,8 @@ from graphs.wrapper import BaseWrapper
|
||||
from gui.builtinShipBrowser.events import FitSelected
|
||||
from gui.contextMenu import ContextMenuSingle
|
||||
|
||||
_t = wx.GetTranslation
|
||||
|
||||
|
||||
class OpenFitInNewTab(ContextMenuSingle):
|
||||
|
||||
@@ -31,7 +34,7 @@ class OpenFitInNewTab(ContextMenuSingle):
|
||||
return True
|
||||
|
||||
def getText(self, callingWindow, itmContext, mainItem):
|
||||
return "Open Fit in New Tab"
|
||||
return _t("Open Fit in New Tab")
|
||||
|
||||
def activate(self, callingWindow, fullContext, mainItem, i):
|
||||
if isinstance(mainItem, BaseWrapper):
|
||||
|
||||
@@ -8,18 +8,18 @@ from eos.const import FitSystemSecurity
|
||||
from gui.contextMenu import ContextMenuUnconditional
|
||||
from service.fit import Fit
|
||||
|
||||
|
||||
optionMap = OrderedDict((
|
||||
('High Security', FitSystemSecurity.HISEC),
|
||||
('Low Security', FitSystemSecurity.LOWSEC),
|
||||
('Null Security', FitSystemSecurity.NULLSEC),
|
||||
('W-Space', FitSystemSecurity.WSPACE)))
|
||||
_t = wx.GetTranslation
|
||||
|
||||
|
||||
class FitSystemSecurityMenu(ContextMenuUnconditional):
|
||||
|
||||
def __init__(self):
|
||||
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
|
||||
self.optionMap = OrderedDict((
|
||||
(_t('High Security'), FitSystemSecurity.HISEC),
|
||||
(_t('Low Security'), FitSystemSecurity.LOWSEC),
|
||||
(_t('Null Security'), FitSystemSecurity.NULLSEC),
|
||||
(_t('W-Space'), FitSystemSecurity.WSPACE)))
|
||||
|
||||
def display(self, callingWindow, srcContext):
|
||||
if srcContext != "fittingShip":
|
||||
@@ -34,7 +34,7 @@ class FitSystemSecurityMenu(ContextMenuUnconditional):
|
||||
return True
|
||||
|
||||
def getText(self, callingWindow, itmContext):
|
||||
return "Citadel System Security"
|
||||
return _t("Citadel System Security")
|
||||
|
||||
def addOption(self, menu, optionLabel):
|
||||
id = ContextMenuUnconditional.nextID()
|
||||
@@ -49,7 +49,7 @@ class FitSystemSecurityMenu(ContextMenuUnconditional):
|
||||
msw = True if "wxMSW" in wx.PlatformInfo else False
|
||||
self.optionIds = {}
|
||||
sub = wx.Menu()
|
||||
for optionLabel, optionValue in optionMap.items():
|
||||
for optionLabel, optionValue in self.optionMap.items():
|
||||
menuItem = self.addOption(rootMenu if msw else sub, optionLabel)
|
||||
sub.Append(menuItem)
|
||||
menuItem.Check(fit.getSystemSecurity() == optionValue)
|
||||
@@ -58,10 +58,10 @@ class FitSystemSecurityMenu(ContextMenuUnconditional):
|
||||
|
||||
def handleMode(self, event):
|
||||
optionLabel = self.optionIds[event.Id]
|
||||
optionValue = optionMap[optionLabel]
|
||||
optionValue = self.optionMap[optionLabel]
|
||||
self.mainFrame.command.Submit(cmd.GuiChangeFitSystemSecurityCommand(
|
||||
fitID=self.mainFrame.getActiveFit(),
|
||||
secStatus=optionValue))
|
||||
fitID=self.mainFrame.getActiveFit(),
|
||||
secStatus=optionValue))
|
||||
|
||||
|
||||
FitSystemSecurityMenu.register()
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# noinspection PyPackageRequirements
|
||||
|
||||
import wx
|
||||
|
||||
import gui.globalEvents as GE
|
||||
@@ -6,6 +7,8 @@ import gui.mainFrame
|
||||
from gui.contextMenu import ContextMenuUnconditional
|
||||
from service.settings import GraphSettings
|
||||
|
||||
_t = wx.GetTranslation
|
||||
|
||||
|
||||
class GraphDmgApplyProjectedMenu(ContextMenuUnconditional):
|
||||
|
||||
@@ -17,7 +20,7 @@ class GraphDmgApplyProjectedMenu(ContextMenuUnconditional):
|
||||
return srcContext == 'dmgStatsGraph'
|
||||
|
||||
def getText(self, callingWindow, itmContext):
|
||||
return 'Apply Projected Items'
|
||||
return _t('Apply Projected Items')
|
||||
|
||||
def activate(self, callingWindow, fullContext, i):
|
||||
self.settings.set('applyProjected', not self.settings.get('applyProjected'))
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from collections import OrderedDict
|
||||
|
||||
# noinspection PyPackageRequirements
|
||||
import wx
|
||||
|
||||
import gui.globalEvents as GE
|
||||
@@ -9,6 +8,10 @@ from gui.contextMenu import ContextMenuUnconditional
|
||||
from service.const import GraphDpsDroneMode
|
||||
from service.settings import GraphSettings
|
||||
|
||||
# noinspection PyPackageRequirements
|
||||
|
||||
_t = wx.GetTranslation
|
||||
|
||||
|
||||
class GraphDmgDroneModeMenu(ContextMenuUnconditional):
|
||||
|
||||
@@ -20,7 +23,7 @@ class GraphDmgDroneModeMenu(ContextMenuUnconditional):
|
||||
return srcContext == 'dmgStatsGraph'
|
||||
|
||||
def getText(self, callingWindow, itmContext):
|
||||
return 'Drone Mode'
|
||||
return _t('Drone Mode')
|
||||
|
||||
def handleModeSwitch(self, event):
|
||||
option = self.idOptionMap[event.Id]
|
||||
@@ -37,9 +40,9 @@ class GraphDmgDroneModeMenu(ContextMenuUnconditional):
|
||||
bindmenu = m
|
||||
self.idOptionMap = {}
|
||||
optionMap = OrderedDict([
|
||||
(GraphDpsDroneMode.auto, 'Auto'),
|
||||
(GraphDpsDroneMode.followTarget, 'Stick to Target'),
|
||||
(GraphDpsDroneMode.followAttacker, 'Stick to Attacker')])
|
||||
(GraphDpsDroneMode.auto, _t('Auto')),
|
||||
(GraphDpsDroneMode.followTarget, _t('Stick to Target')),
|
||||
(GraphDpsDroneMode.followAttacker, _t('Stick to Attacker'))])
|
||||
for option, label in optionMap.items():
|
||||
menuId = ContextMenuUnconditional.nextID()
|
||||
item = wx.MenuItem(m, menuId, label, kind=wx.ITEM_CHECK)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# noinspection PyPackageRequirements
|
||||
|
||||
import wx
|
||||
|
||||
import gui.globalEvents as GE
|
||||
@@ -6,6 +7,8 @@ import gui.mainFrame
|
||||
from gui.contextMenu import ContextMenuUnconditional
|
||||
from service.settings import GraphSettings
|
||||
|
||||
_t = wx.GetTranslation
|
||||
|
||||
|
||||
class GraphDmgIgnoreResistsMenu(ContextMenuUnconditional):
|
||||
|
||||
@@ -17,7 +20,7 @@ class GraphDmgIgnoreResistsMenu(ContextMenuUnconditional):
|
||||
return srcContext == 'dmgStatsGraph'
|
||||
|
||||
def getText(self, callingWindow, itmContext):
|
||||
return 'Ignore Target Resists'
|
||||
return _t('Ignore Target Resists')
|
||||
|
||||
def activate(self, callingWindow, fullContext, i):
|
||||
self.settings.set('ignoreResists', not self.settings.get('ignoreResists'))
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# noinspection PyPackageRequirements
|
||||
|
||||
import wx
|
||||
|
||||
import gui.globalEvents as GE
|
||||
@@ -6,6 +7,8 @@ import gui.mainFrame
|
||||
from gui.contextMenu import ContextMenuUnconditional
|
||||
from service.settings import GraphSettings
|
||||
|
||||
_t = wx.GetTranslation
|
||||
|
||||
|
||||
class GraphIgnoreDcrMenu(ContextMenuUnconditional):
|
||||
|
||||
@@ -17,7 +20,7 @@ class GraphIgnoreDcrMenu(ContextMenuUnconditional):
|
||||
return srcContext in ('dmgStatsGraph', 'remoteRepsGraph', 'ewarStatsGraph')
|
||||
|
||||
def getText(self, callingWindow, itmContext):
|
||||
return 'Ignore Drone Control Range'
|
||||
return _t('Ignore Drone Control Range')
|
||||
|
||||
def activate(self, callingWindow, fullContext, i):
|
||||
self.settings.set('ignoreDCR', not self.settings.get('ignoreDCR'))
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# noinspection PyPackageRequirements
|
||||
|
||||
import wx
|
||||
|
||||
import gui.mainFrame
|
||||
@@ -7,6 +8,8 @@ from gui.contextMenu import ContextMenuSingle
|
||||
from service.ammo import Ammo
|
||||
from service.market import Market
|
||||
|
||||
_t = wx.GetTranslation
|
||||
|
||||
|
||||
class GraphFitAmmoPicker(ContextMenuSingle):
|
||||
|
||||
@@ -23,7 +26,7 @@ class GraphFitAmmoPicker(ContextMenuSingle):
|
||||
return True
|
||||
|
||||
def getText(self, callingWindow, itmContext, mainItem):
|
||||
return 'Plot with Different Ammo...'
|
||||
return _t('Plot with Different Ammo...')
|
||||
|
||||
def activate(self, callingWindow, fullContext, mainItem, i):
|
||||
AmmoPickerFrame.openOne(callingWindow, mainItem.item, forceReopen=True)
|
||||
@@ -73,7 +76,6 @@ class AmmoPickerFrame(AuxiliaryDialog):
|
||||
|
||||
|
||||
class AmmoPickerContents(wx.ScrolledCanvas):
|
||||
|
||||
indent = 15
|
||||
|
||||
def __init__(self, parent, fit):
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# noinspection PyPackageRequirements
|
||||
|
||||
import wx
|
||||
|
||||
import gui.globalEvents as GE
|
||||
@@ -6,6 +7,8 @@ import gui.mainFrame
|
||||
from gui.contextMenu import ContextMenuUnconditional
|
||||
from service.settings import GraphSettings
|
||||
|
||||
_t = wx.GetTranslation
|
||||
|
||||
|
||||
class GraphIgnoreLockRangeMenu(ContextMenuUnconditional):
|
||||
|
||||
@@ -17,7 +20,7 @@ class GraphIgnoreLockRangeMenu(ContextMenuUnconditional):
|
||||
return srcContext in ('dmgStatsGraph', 'remoteRepsGraph', 'ewarStatsGraph')
|
||||
|
||||
def getText(self, callingWindow, itmContext):
|
||||
return 'Ignore Lock Range'
|
||||
return _t('Ignore Lock Range')
|
||||
|
||||
def activate(self, callingWindow, fullContext, i):
|
||||
self.settings.set('ignoreLockRange', not self.settings.get('ignoreLockRange'))
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
# noinspection PyPackageRequirements
|
||||
|
||||
import wx
|
||||
|
||||
from gui.contextMenu import ContextMenuUnconditional
|
||||
from service.market import Market
|
||||
from service.implantSet import ImplantSets as UserImplantSets
|
||||
from service.precalcImplantSet import PrecalcedImplantSets
|
||||
|
||||
_t = wx.GetTranslation
|
||||
|
||||
|
||||
class ImplantSetApply(ContextMenuUnconditional):
|
||||
|
||||
@@ -20,7 +22,7 @@ class ImplantSetApply(ContextMenuUnconditional):
|
||||
return srcContext in ("implantItemMisc", "implantEditor")
|
||||
|
||||
def getText(self, callingWindow, context):
|
||||
return "Apply Implant Set"
|
||||
return _t("Apply Implant Set")
|
||||
|
||||
def _addSeparator(self, m, text):
|
||||
id_ = ContextMenuUnconditional.nextID()
|
||||
|
||||
@@ -4,6 +4,8 @@ import gui.mainFrame
|
||||
from gui.contextMenu import ContextMenuUnconditional
|
||||
from service.fit import Fit
|
||||
|
||||
_t = wx.GetTranslation
|
||||
|
||||
|
||||
class ImplantSetSave(ContextMenuUnconditional):
|
||||
|
||||
@@ -22,7 +24,7 @@ class ImplantSetSave(ContextMenuUnconditional):
|
||||
return True
|
||||
|
||||
def getText(self, callingWindow, context):
|
||||
return 'Save as New Implant Set'
|
||||
return _t('Save as New Implant Set')
|
||||
|
||||
def activate(self, callingWindow, fullContext, i):
|
||||
with NameDialog(self.mainFrame, '') as dlg:
|
||||
@@ -40,13 +42,13 @@ ImplantSetSave.register()
|
||||
class NameDialog(wx.Dialog):
|
||||
|
||||
def __init__(self, parent, value):
|
||||
super().__init__(parent, title='New Implant Set', style=wx.DEFAULT_DIALOG_STYLE)
|
||||
super().__init__(parent, title=_t('New Implant Set'), style=wx.DEFAULT_DIALOG_STYLE)
|
||||
self.SetMinSize((346, 156))
|
||||
|
||||
bSizer1 = wx.BoxSizer(wx.VERTICAL)
|
||||
|
||||
bSizer2 = wx.BoxSizer(wx.VERTICAL)
|
||||
text = wx.StaticText(self, wx.ID_ANY, 'Enter a name for your new Implant Set:')
|
||||
text = wx.StaticText(self, wx.ID_ANY, _t('Enter a name for your new Implant Set:'))
|
||||
bSizer2.Add(text, 0)
|
||||
|
||||
bSizer1.Add(bSizer2, 0, wx.ALL, 10)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import re
|
||||
|
||||
# noinspection PyPackageRequirements
|
||||
import wx
|
||||
|
||||
import gui.fitCommands as cmd
|
||||
@@ -9,16 +8,20 @@ from eos.saveddata.cargo import Cargo as es_Cargo
|
||||
from eos.saveddata.drone import Drone
|
||||
from eos.saveddata.fighter import Fighter as es_Fighter
|
||||
from eos.saveddata.fit import Fit as es_Fit
|
||||
from gui.contextMenu import ContextMenuSingle
|
||||
from gui.contextMenu import ContextMenuCombined
|
||||
from service.fit import Fit
|
||||
|
||||
# noinspection PyPackageRequirements
|
||||
|
||||
class ChangeItemAmount(ContextMenuSingle):
|
||||
_t = wx.GetTranslation
|
||||
|
||||
|
||||
class ChangeItemAmount(ContextMenuCombined):
|
||||
|
||||
def __init__(self):
|
||||
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
|
||||
|
||||
def display(self, callingWindow, srcContext, mainItem):
|
||||
def display(self, callingWindow, srcContext, mainItem, selection):
|
||||
if srcContext not in ("droneItem", "projectedDrone", "cargoItem", "projectedFit", "fighterItem", "projectedFighter"):
|
||||
return False
|
||||
|
||||
@@ -27,10 +30,12 @@ class ChangeItemAmount(ContextMenuSingle):
|
||||
|
||||
return True
|
||||
|
||||
def getText(self, callingWindow, itmContext, mainItem):
|
||||
return "Change {0} Quantity".format(itmContext)
|
||||
def getText(self, callingWindow, itmContext, mainItem, selection):
|
||||
if isinstance(mainItem, es_Cargo):
|
||||
return _t("Change Selection Quantity")
|
||||
return _t("Change {0} Quantity").format(itmContext)
|
||||
|
||||
def activate(self, callingWindow, fullContext, mainItem, i):
|
||||
def activate(self, callingWindow, fullContext, mainItem, selection, i):
|
||||
fitID = self.mainFrame.getActiveFit()
|
||||
srcContext = fullContext[0]
|
||||
if isinstance(mainItem, es_Fit):
|
||||
@@ -53,31 +58,35 @@ class ChangeItemAmount(ContextMenuSingle):
|
||||
cleanInput = int(float(re.sub(r'[^0-9.]', '', dlg.input.GetLineText(0).strip())))
|
||||
|
||||
if isinstance(mainItem, es_Cargo):
|
||||
self.mainFrame.command.Submit(cmd.GuiChangeCargoAmountCommand(
|
||||
fitID=fitID, itemID=mainItem.itemID, amount=cleanInput))
|
||||
itemIDs = []
|
||||
for cargo in selection:
|
||||
if cargo in fit.cargo:
|
||||
itemIDs.append(cargo.itemID)
|
||||
self.mainFrame.command.Submit(cmd.GuiChangeCargosAmountCommand(
|
||||
fitID=fitID, itemIDs=itemIDs, amount=cleanInput))
|
||||
elif isinstance(mainItem, Drone):
|
||||
if srcContext == "projectedDrone":
|
||||
self.mainFrame.command.Submit(cmd.GuiChangeProjectedDroneAmountCommand(
|
||||
fitID=fitID, itemID=mainItem.itemID, amount=cleanInput))
|
||||
fitID=fitID, itemID=mainItem.itemID, amount=cleanInput))
|
||||
else:
|
||||
if mainItem in fit.drones:
|
||||
position = fit.drones.index(mainItem)
|
||||
self.mainFrame.command.Submit(cmd.GuiChangeLocalDroneAmountCommand(
|
||||
fitID=fitID, position=position, amount=cleanInput))
|
||||
fitID=fitID, position=position, amount=cleanInput))
|
||||
elif isinstance(mainItem, es_Fit):
|
||||
self.mainFrame.command.Submit(cmd.GuiChangeProjectedFitAmountCommand(
|
||||
fitID=fitID, projectedFitID=mainItem.ID, amount=cleanInput))
|
||||
fitID=fitID, projectedFitID=mainItem.ID, amount=cleanInput))
|
||||
elif isinstance(mainItem, es_Fighter):
|
||||
if srcContext == "projectedFighter":
|
||||
if mainItem in fit.projectedFighters:
|
||||
position = fit.projectedFighters.index(mainItem)
|
||||
self.mainFrame.command.Submit(cmd.GuiChangeProjectedFighterAmountCommand(
|
||||
fitID=fitID, position=position, amount=cleanInput))
|
||||
fitID=fitID, position=position, amount=cleanInput))
|
||||
else:
|
||||
if mainItem in fit.fighters:
|
||||
position = fit.fighters.index(mainItem)
|
||||
self.mainFrame.command.Submit(cmd.GuiChangeLocalFighterAmountCommand(
|
||||
fitID=fitID, position=position, amount=cleanInput))
|
||||
fitID=fitID, position=position, amount=cleanInput))
|
||||
|
||||
|
||||
ChangeItemAmount.register()
|
||||
@@ -86,13 +95,13 @@ ChangeItemAmount.register()
|
||||
class AmountChanger(wx.Dialog):
|
||||
|
||||
def __init__(self, parent, value, limits=None):
|
||||
super().__init__(parent, title="Change Amount", style=wx.DEFAULT_DIALOG_STYLE)
|
||||
super().__init__(parent, title=_t("Change Amount"), style=wx.DEFAULT_DIALOG_STYLE)
|
||||
self.SetMinSize((346, 156))
|
||||
|
||||
bSizer1 = wx.BoxSizer(wx.VERTICAL)
|
||||
|
||||
bSizer2 = wx.BoxSizer(wx.VERTICAL)
|
||||
text = wx.StaticText(self, wx.ID_ANY, "New Amount:" if limits is None else "New Amount ({}-{})".format(*limits))
|
||||
text = wx.StaticText(self, wx.ID_ANY, _t("New Amount:") if limits is None else _t("New Amount ({}-{})").format(*limits))
|
||||
bSizer2.Add(text, 0)
|
||||
|
||||
bSizer1.Add(bSizer2, 0, wx.ALL, 10)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user