Compare commits

...

367 Commits

Author SHA1 Message Date
DarkPhoenix
23916165bb Bump version 2021-06-11 23:27:11 +03:00
DarkPhoenix
3cca6a6c95 Update effects 2021-06-11 23:26:09 +03:00
DarkPhoenix
a52172a3c6 Update static data to 1910538 2021-06-11 21:26:46 +03:00
Anton Vorobyov
8a2bfb48ce Merge pull request #2339 from pyfa-org/crowdin_master
New Crowdin updates
2021-06-11 21:08:04 +03:00
DarkPhoenix
b42254cb61 Avoid crashes on ctrl-backspace in notes view 2021-06-11 21:04:59 +03:00
DarkPhoenix
91fbcd4eb4 Fix bastion rof bonus 2021-06-11 20:58:17 +03:00
DarkPhoenix
bdc52da05d Remove travis configuration 2021-06-11 20:34:01 +03:00
DarkPhoenix
2bbe17722b Refresh deployment tokens 2021-06-09 13:57:03 +03:00
DarkPhoenix
3ef07b9153 Upload artifacts on tags to github 2021-06-08 22:47:00 +03:00
DarkPhoenix
5af904ca18 Split build process into multiple stages 2021-06-08 21:07:11 +03:00
DarkPhoenix
d3cdc67472 Update path to macos build 2021-06-08 21:01:38 +03:00
DarkPhoenix
0991124d5f Store package as an appveyor artifact 2021-06-08 20:55:10 +03:00
DarkPhoenix
83ea548c4d Try python 3.7
This is the version we used on Travis
2021-06-08 20:43:09 +03:00
DarkPhoenix
4752eee09d Fix venv path 2021-06-08 20:36:47 +03:00
DarkPhoenix
53d2d1fabe Activate python 3.8 2021-06-08 20:34:29 +03:00
DarkPhoenix
f600868eb2 Move sleep to init 2021-06-08 20:29:03 +03:00
DarkPhoenix
f6a489fa22 Add sleep to give some time to debug 2021-06-08 20:24:26 +03:00
DarkPhoenix
2962a89919 Enable macOS debugging 2021-06-08 20:19:50 +03:00
DarkPhoenix
c3d53f56a9 Preinstall pathlib on macOS 2021-06-08 19:46:43 +03:00
DarkPhoenix
3257abbeff Remove linking of gettext for macOS
Apprently, it's already linked on appveyor images
2021-06-08 19:36:48 +03:00
DarkPhoenix
5858d96deb Set python version to 3.8 for mac before building 2021-06-08 19:36:18 +03:00
DarkPhoenix
94d1eae464 Move macOS build scripts to appveyor configuration 2021-06-08 19:29:34 +03:00
DarkPhoenix
b7e2b782c9 Move all windows-specific code under windows section 2021-06-08 19:02:37 +03:00
DarkPhoenix
05e5958d36 Make PYTHON variable image-specific to test if it works 2021-06-08 18:54:07 +03:00
Anton Vorobyov
e9364fe65a New translations lang.pot (Russian) 2021-05-27 14:31:12 +03:00
Anton Vorobyov
b3b71896ae New translations lang.pot (Russian) 2021-05-26 14:22:49 +03:00
Anton Vorobyov
00d20f53d0 New translations lang.pot (Russian) 2021-05-19 21:03:26 +03:00
DarkPhoenix
88e4f7a77e Set SQLAlchemy version to last known working 2021-05-19 03:40:09 +03:00
DarkPhoenix
5763954f51 Fix bastion falloff bonus 2021-05-19 03:29:25 +03:00
DarkPhoenix
4fbfbcc84e Bump version 2021-05-19 03:12:20 +03:00
DarkPhoenix
1f2c20e95b Update icons 2021-05-19 03:11:13 +03:00
DarkPhoenix
d7aa744bc1 Do not activate WCS and nullifiers by default 2021-05-19 02:55:20 +03:00
DarkPhoenix
1117c786ff Add new nullifier/WCS effects 2021-05-19 02:52:29 +03:00
DarkPhoenix
6a715f6678 Update effects for metaliminal storms 2021-05-19 02:27:39 +03:00
DarkPhoenix
5e93235b02 Add jargon entries for SRS and wubble 2021-05-19 01:35:32 +03:00
DarkPhoenix
271b915ce6 Fix sig suppressor effect #2 2021-05-19 01:30:58 +03:00
DarkPhoenix
52667da64a Fix sig suppressor effect 2021-05-19 01:29:20 +03:00
DarkPhoenix
82f0fea1bf Run effectUsedBy script 2021-05-19 01:28:48 +03:00
DarkPhoenix
751823177b Update static data to 1903677 2021-05-19 01:19:49 +03:00
DarkPhoenix
ac7e8a1efa Fix msgformat 2021-05-19 00:40:29 +03:00
Anton Vorobyov
066a12e912 Merge pull request #2337 from pyfa-org/crowdin_master
New Crowdin updates
2021-05-19 00:23:35 +03:00
Anton Vorobyov
ea64657fba New translations lang.pot (Chinese Simplified) 2021-05-18 20:34:57 +03:00
Anton Vorobyov
17b94001e0 New translations lang.pot (Turkish) 2021-05-18 20:34:56 +03:00
Anton Vorobyov
cc481f9f29 New translations lang.pot (Russian) 2021-05-18 20:34:55 +03:00
Anton Vorobyov
f73bb14990 New translations lang.pot (Korean) 2021-05-18 20:34:53 +03:00
Anton Vorobyov
a5ed992cd2 New translations lang.pot (Japanese) 2021-05-18 20:34:52 +03:00
Anton Vorobyov
f7e792411a New translations lang.pot (Italian) 2021-05-18 20:34:51 +03:00
Anton Vorobyov
fc71d7b706 New translations lang.pot (Spanish) 2021-05-18 20:34:50 +03:00
Anton Vorobyov
162055d5ce New translations lang.pot (French) 2021-05-18 20:34:48 +03:00
DarkPhoenix
5cc87a439f Merge branch 'i18n' 2021-05-12 22:39:41 +03:00
Anton Vorobyov
d2d3a42adf Merge pull request #2331 from pyfa-org/crowdin_l10n
New Crowdin updates
2021-05-12 22:38:37 +03:00
Ryan Holmes
e43cb74906 New translations lang.pot (Korean) 2021-04-07 20:23:31 -04:00
DarkPhoenix
ace00d495a Add stacking penalty for bastion missile range bonus 2021-03-27 19:40:34 +03:00
DarkPhoenix
729b39e351 Define backref for boosters manually 2021-03-27 19:37:11 +03:00
DarkPhoenix
5ae1e64a76 Revert "Remove backref to owner since it seems to be unused, but it crashed attempts to remove items which have been removed from static data"
This reverts commit 8ee900a90e.
2021-03-27 18:51:15 +03:00
DarkPhoenix
88a9ce03ba Merge branch 'i18n' 2021-03-26 17:18:22 +03:00
Anton Vorobyov
cbd3d8cc1b Merge pull request #2319 from pyfa-org/crowdin_l10n
New Crowdin updates
2021-03-26 17:17:06 +03:00
Anton Vorobyov
65a126b4c5 Merge pull request #2312 from sajuukthanatoskhar/EFS_Information_Export_add_on
Adding more information to EFS Export
2021-03-25 15:47:56 +03:00
DarkPhoenix
241c744d40 Fixed stacking penalization of heat rof bonus 2021-03-25 15:37:09 +03:00
DarkPhoenix
8ee900a90e Remove backref to owner since it seems to be unused, but it crashed attempts to remove items which have been removed from static data 2021-03-25 15:13:18 +03:00
DarkPhoenix
1c415fbe06 Mark objects dirty so that they get removed, instead of setting their item ID to 0 2021-03-25 15:06:28 +03:00
DarkPhoenix
304aebbccf Update static data to 1889623 2021-03-25 14:31:41 +03:00
DarkPhoenix
18d9f6a542 Fix repr for boosters with no item 2021-03-25 13:52:40 +03:00
DarkPhoenix
cdc6e046b0 Fix #2308 2021-03-25 13:15:48 +03:00
DarkPhoenix
59bb9670b6 Multiple fixes related to sig suppressor 2021-03-25 12:49:50 +03:00
DarkPhoenix
9321a78a61 Update effects 2021-03-25 12:35:40 +03:00
DarkPhoenix
53191714f2 Exclude TSB from list of projectable mods for EFS purposes 2021-03-24 17:47:54 +03:00
DarkPhoenix
b17347156c Update static data to 1888542 2021-03-24 17:40:26 +03:00
DarkPhoenix
66ace06194 Run effect used by script 2021-03-23 18:44:06 +03:00
DarkPhoenix
e8697c6131 Update static data to 1888542 2021-03-23 18:38:26 +03:00
Ryan Holmes
7a6e87330d New translations lang.pot (Russian) 2021-03-02 10:09:27 -05:00
Ryan Holmes
2acf92160e New translations lang.pot (Russian) 2021-03-02 09:11:19 -05:00
DarkPhoenix
6e49f6fd7a Bump version 2021-02-23 21:34:06 +03:00
DarkPhoenix
6e56230a0e Update staticdata to 1878176 2021-02-23 21:28:30 +03:00
DarkPhoenix
01282d103a Add extraction filaments as well 2021-02-20 21:24:11 +03:00
DarkPhoenix
a0317d5b3c Bump version 2021-02-20 20:23:04 +03:00
DarkPhoenix
a697c1890a Adjust effects 2021-02-20 20:22:44 +03:00
DarkPhoenix
aaf719437f Update static data to 1877575 2021-02-20 20:09:24 +03:00
DarkPhoenix
3d6e703b7c Trigger travis builds only on tags 2021-02-19 21:17:34 +03:00
DarkPhoenix
ce26b22752 Add filament market group 2021-02-19 20:44:57 +03:00
DarkPhoenix
6b30b2859e Allow adding items to cargo via double-click 2021-02-19 20:39:10 +03:00
DarkPhoenix
961258618a Make filaments searchable 2021-02-19 20:36:11 +03:00
DarkPhoenix
f07684875f Use proper attribute for missiles 2021-02-19 10:37:52 +03:00
DarkPhoenix
538954f4a6 Fix vargur damage bonus 2021-02-19 02:16:57 +03:00
DarkPhoenix
30e73ed795 Fix bastion stacking penalties on RoF 2021-02-18 23:38:24 +03:00
DarkPhoenix
d216eb3e55 Bump version 2021-02-18 22:15:00 +03:00
DarkPhoenix
c25fa0f632 Update bastion effect 2021-02-18 22:11:51 +03:00
DarkPhoenix
8a115be0bd Update effect uses 2021-02-18 21:03:53 +03:00
DarkPhoenix
b897ee5146 Update static data to 1876339 2021-02-18 20:41:40 +03:00
Ryan Holmes
7b3bda5816 New translations lang.pot (Korean) 2021-01-27 11:06:59 -05:00
Ryan Holmes
f62e16288d New translations lang.pot (Korean) 2021-01-27 09:54:33 -05:00
Ryan Holmes
9aad8860a9 New translations lang.pot (Korean) 2021-01-26 23:57:54 -05:00
Ryan Holmes
f8dd1f27a9 New translations lang.pot (Korean) 2021-01-26 22:46:04 -05:00
DarkPhoenix
09bc2da863 Limit subwarp speed to 100 for warp considerations 2021-01-26 00:33:43 +03:00
Ryan Holmes
f531c144af New translations lang.pot (Chinese Simplified) 2021-01-23 21:52:34 -05:00
Gareth Williams
dfd08fa8e2 MOD: EFS Export Version Number to 0.05
ADD: OptimalSignatureRadius is now exported with each *turret*
2021-01-23 17:55:00 +01:00
Gareth Williams
e430848be9 ADD: Added the ability for EFS exports to contain the following information: shieldrecharge rate, inertia, energy|neutraliser Resistance 2021-01-09 22:34:29 +01:00
Anton Vorobyov
2d645b8f91 Merge pull request #2301 from pyfa-org/i18n
I18n
2020-12-08 20:00:30 +03:00
DarkPhoenix
e33cb80608 Bump version 2020-12-08 19:56:43 +03:00
Anton Vorobyov
fcc8c3eeb9 Merge pull request #2300 from pyfa-org/crowdin_l10n
New Crowdin updates
2020-12-08 19:51:37 +03:00
DarkPhoenix
c29d567255 Change default jargon definitions for missile types, they now include launchers as well 2020-12-08 19:46:13 +03:00
DarkPhoenix
e85b618cbc Add set of hacks to rename caustic to tachyon 2020-12-08 19:40:48 +03:00
DarkPhoenix
008b6a887d Rename Caustic to Tachyon 2020-12-08 19:30:21 +03:00
DarkPhoenix
05ab2d47c7 Fix error handler in a situation when gamedata metadata is not available 2020-12-08 19:16:05 +03:00
DarkPhoenix
75b611c94a Fix salvaging spec effect 2020-12-08 18:01:57 +03:00
Ryan Holmes
356d594637 New translations lang.pot (French) 2020-12-08 09:14:01 -05:00
Ryan Holmes
03f4bc1d75 New translations lang.pot (French) 2020-12-08 08:13:23 -05:00
DarkPhoenix
226c5d7fad Update static data to 1860847 2020-12-08 15:09:51 +03:00
DarkPhoenix
0c3998b640 Add new effects 2020-12-05 16:39:58 +03:00
DarkPhoenix
942f9a35ee Update static data to 1859379 2020-12-05 14:27:19 +03:00
DarkPhoenix
031a3c2d3e Fix IDs of new damage patterns 2020-11-27 18:03:18 +03:00
DarkPhoenix
ed7df2f1a7 Bump version 2020-11-26 15:57:15 +03:00
DarkPhoenix
fb2ad2cc10 Update static data to 1853874 2020-11-26 15:56:40 +03:00
DarkPhoenix
34bce4e083 Bump version 2020-11-24 14:56:39 +03:00
DarkPhoenix
fc45b43295 Update static data to 1852074 2020-11-24 14:53:32 +03:00
DarkPhoenix
4160b08388 Fix mining preservation charge 2020-11-24 13:08:25 +03:00
DarkPhoenix
95c25b274c Add logging to help with no localization debugging 2020-11-24 13:01:52 +03:00
DarkPhoenix
690e5caf52 Bump version 2020-11-19 15:33:11 +03:00
DarkPhoenix
95ada5d61d Fix misc column for ewar drones 2020-11-19 14:54:44 +03:00
DarkPhoenix
976820a7c0 Merge branch 'master' into singularity 2020-11-19 14:21:08 +03:00
DarkPhoenix
8ab14bcfcc Attempt to fix unavailable graphs 2020-11-19 14:20:41 +03:00
DarkPhoenix
6e8798eb08 Adjust effects 2020-11-19 14:01:03 +03:00
DarkPhoenix
15af830dca Update staticdata to 1848209 2020-11-19 13:36:14 +03:00
Anton Vorobyov
ce728243b0 Merge pull request #2287 from porowns/master
Fix typo in ECM targetting view
2020-11-19 12:50:19 +03:00
DarkPhoenix
2696b480fa Fix mistype 2020-11-17 19:20:25 +03:00
Kaleb
ca7a3cae9c Fix typo in ECM targetting view 2020-11-13 13:11:50 -05:00
DarkPhoenix
10613c9070 Consider a market group as non-final when it has sub-market groups 2020-11-11 22:37:49 +03:00
DarkPhoenix
a692b1fe74 Bump version 2020-11-11 00:30:49 +03:00
DarkPhoenix
0592d2c3f4 Update staticdata to 1842315 2020-11-11 00:24:19 +03:00
DarkPhoenix
301a3473cc Update static data to 1837348 2020-11-04 01:35:44 +03:00
DarkPhoenix
4887852de4 Update po template after merge 2020-10-28 15:29:11 +03:00
DarkPhoenix
6b3bf1f7a8 Merge branch 'master' of github.com:pyfa-org/Pyfa into master 2020-10-28 15:28:49 +03:00
DarkPhoenix
a4d163fc89 Update po template 2020-10-28 15:28:33 +03:00
Anton Vorobyov
e88e3996a8 Merge pull request #2282 from Neugeniko/master
Added new target and damage profiles for invasion drifters, rogue drones and sleepers.
2020-10-28 15:27:25 +03:00
Neugeniko
a36dd20890 Add new invasion target profiles for drifters, rogue drones and sleepers. 2020-10-28 20:41:02 +11:00
Neugeniko
c9f37457ab Add new invasion damage profiles for drifters, rogue drones and sleepers. 2020-10-28 20:39:35 +11:00
DarkPhoenix
4709cd78f3 Update contribution readme 2020-10-28 00:03:24 +03:00
DarkPhoenix
5ac5b3f5e4 Bump version 2020-10-27 23:05:40 +03:00
DarkPhoenix
da78c24d9b Do not persist messages across generation sessions 2020-10-27 22:56:02 +03:00
DarkPhoenix
566c87fa59 Avoid crash when .mo files are not generated 2020-10-27 22:42:03 +03:00
DarkPhoenix
e6d7a140cf Add message for case when mo files are not generated 2020-10-27 22:39:21 +03:00
DarkPhoenix
89e496f3af Move language setting to top 2020-10-27 22:17:06 +03:00
DarkPhoenix
d650284ae1 Update english translations 2020-10-27 21:42:18 +03:00
DarkPhoenix
b41d7d2603 Merge branch 'i18n' into master 2020-10-27 21:36:24 +03:00
Anton Vorobyov
33c20bfc3b Merge pull request #2239 from pyfa-org/crowdin_l10n
New Crowdin updates
2020-10-27 21:34:47 +03:00
DarkPhoenix
6f0778ad94 Update po template 2020-10-27 21:27:20 +03:00
DarkPhoenix
7ce39a0dac Update staticdata to 1832008 2020-10-27 15:55:38 +03:00
DarkPhoenix
7de7a17bae Update effect list 2020-10-27 13:25:47 +03:00
DarkPhoenix
50b8c3fc61 Avoid subtraction of attacker radius for ships with AoE bursts twice 2020-10-27 00:37:24 +03:00
DarkPhoenix
dab5d1f211 Fix item diff script 2020-10-25 00:11:56 +03:00
DarkPhoenix
5141a30e22 Update static data to 1830766 2020-10-23 21:27:18 +03:00
DarkPhoenix
1172e5011e Merge branch 'i18n' into singularity 2020-10-23 19:53:36 +03:00
DarkPhoenix
ea2141b719 Update effects 2020-10-22 17:58:10 +03:00
DarkPhoenix
9f7fdfc800 Update static data to 1828662 2020-10-22 13:53:57 +03:00
DarkPhoenix
de63b11a80 Rename invasion profiles 2020-10-22 12:38:55 +03:00
DarkPhoenix
514d11e6f2 Bump pyfa version 2020-10-13 18:38:29 +03:00
DarkPhoenix
9d759054ca Add migrations/conversions 2020-10-13 18:33:21 +03:00
DarkPhoenix
c162d96cc0 Rename triglavian profiles 2020-10-13 18:27:05 +03:00
DarkPhoenix
3c22397377 Update staticdata 2020-10-13 17:58:41 +03:00
DarkPhoenix
20e605c30f Make quantum cores invalid modules for pyfa fits 2020-09-24 16:51:40 +03:00
DarkPhoenix
9601887855 Add ability to import modules from ESI directly into pyfa 2020-09-23 17:24:40 +03:00
blitzmann
a80b7c098a Use natural sort for dictionaries when dumping staticdata 2020-09-20 12:57:23 -04:00
Ryan Holmes
1580a8ddc9 New translations lang.pot (Chinese Simplified) 2020-09-17 11:09:10 -04:00
Ryan Holmes
c08216252e New translations lang.pot (Chinese Simplified) 2020-08-04 11:03:34 -04:00
blitzmann
02219846a7 Merge branch 'i18n' into crowdin_l10n 2020-08-02 22:57:24 -04:00
blitzmann
ff0af7cce7 Add check to see if crowdin API key is available 2020-08-02 22:25:15 -04:00
blitzmann
0e8316192b data updates 2020-08-02 20:20:25 -04:00
blitzmann
c0f8099f49 Merge branch 'master' into i18n
# Conflicts:
#	staticdata/fsd_binary/typedogma.json
#	staticdata/fsd_lite/evetypes.json
#	staticdata/phobos/metadata.0.json
#	staticdata/phobos/traits.json
2020-08-02 18:54:31 -04:00
Ryan Holmes
32a03dedaa I18n - Fixes for translations during build (#2251) 2020-08-02 18:52:55 -04:00
Ryan Holmes
5ae43fc648 New translations lang.pot (Spanish) 2020-08-02 13:10:03 -04:00
Ryan Holmes
d1f26dd4db New translations lang.pot (Turkish) 2020-08-02 13:10:01 -04:00
Ryan Holmes
c595e4426e New translations lang.pot (Chinese Simplified) 2020-08-02 13:09:59 -04:00
Ryan Holmes
abe7fa4ac1 New translations lang.pot (Russian) 2020-08-02 13:09:57 -04:00
Ryan Holmes
fd5d6ffca5 New translations lang.pot (Korean) 2020-08-02 13:09:55 -04:00
Ryan Holmes
abaa7f395d New translations lang.pot (Japanese) 2020-08-02 13:09:53 -04:00
Ryan Holmes
8e3893d6c6 New translations lang.pot (Italian) 2020-08-02 13:09:52 -04:00
Ryan Holmes
5de808456e New translations lang.pot (French) 2020-08-02 13:09:50 -04:00
Ryan Holmes
362d081338 Merge pull request #2240 from zhaoweny/i18n
I18n: more string annotations (mostly tooltips)
2020-08-02 13:07:11 -04:00
zhaoweny
7bc4e5b34c i18n: update lang.pot for plural strings 2020-07-27 15:31:37 +08:00
zhaoweny
9450f4a915 i18n: improve wording for locale/README.md 2020-07-27 15:21:42 +08:00
zhaoweny
1a9ebf0772 i18n: add detail for excluding a folder (virtualenv) when generating new lang.pot
Because in-tree virtualenv folder is developer-defined, we can't really predict and provide specific commands for excluding virtualenv.
2020-07-27 14:51:26 +08:00
zhaoweny
1c7036e612 i18n: update locale/README.md to reflect current usage of xgettext 2020-07-27 09:59:59 +08:00
zhaoweny
87cb9713f9 i18n: update lang.pot 2020-07-26 18:20:05 +08:00
zhaoweny
d3f0d9d41a i18n: use named placeholder to allow Russian translation to rearrange word order 2020-07-26 18:20:05 +08:00
zhaoweny
b0d088ab31 i18n: update lang.pot for more Tooltip annotation 2020-07-26 18:20:05 +08:00
zhaoweny
47bda45516 i18n: more Tooltip annotation 2020-07-26 18:20:05 +08:00
zhaoweny
95d18dc3ab i18n: update lang.pot for annotating SensorStr scanType 2020-07-26 18:20:05 +08:00
zhaoweny
be5f8ce37d i18n: annotate for SensorStr scanType 2020-07-26 18:20:05 +08:00
blitzmann
107856ab0e Add hyperlink to README for translations 2020-07-25 20:14:11 -04:00
Ryan Holmes
c1f9b1d0d7 Fix version dump when tag ahas a + in it 2020-07-25 17:53:42 -04:00
Ryan Holmes
469c255bbf Show progress of translations 2020-07-25 17:39:28 -04:00
Ryan Holmes
bec9eb2224 Add translation progress dump to travis and remove the data dump to console 2020-07-25 16:54:15 -04:00
Ryan Holmes
7dc362fef9 fix api key environment variable name 2020-07-25 16:42:29 -04:00
Ryan Holmes
80781c7eff debugging why build is failing 2020-07-25 16:33:14 -04:00
Ryan Holmes
fca78a72e4 Create translation progress dump script and add to appveryor build (travis soon) 2020-07-25 16:27:42 -04:00
Ryan Holmes
7438fb72bc revert compile_lang, don't have access to config here... will need to fix 2020-07-25 12:40:12 -04:00
Ryan Holmes
b6f24ec4c2 New translations lang.pot (Spanish) 2020-07-24 22:58:23 -04:00
Ryan Holmes
db2bd22ddc New Crowdin updates (#2238)
* New translations lang.pot (Turkish)

* New translations lang.pot (Turkish)

* New translations lang.pot (Turkish)

* New translations lang.pot (Italian)

* New translations lang.pot (Italian)

* New translations lang.pot (Chinese Simplified)
2020-07-24 22:23:02 -04:00
blitzmann
bbcedbf2cb Better description for language flag 2020-07-24 22:22:11 -04:00
blitzmann
937adb68d7 Show user-friendly name for the eos lang dropdown as well 2020-07-24 22:14:54 -04:00
blitzmann
1fe83ddcdf Finish up the dynamic translations 2020-07-24 21:59:38 -04:00
Ryan Holmes
ac1e6fe5b7 Starting to generate list of languages dynamically 2020-07-24 20:42:47 -04:00
Ryan Holmes
cb99151f69 New Crowdin updates (#2236)
* New translations lang.pot (Russian)

* New translations lang.pot (Russian)

* New translations lang.pot (Russian)

* New translations lang.pot (Italian)

* New translations lang.pot (Russian)

* New translations lang.pot (Russian)

* New translations lang.pot (Russian)

* New translations lang.pot (Japanese)

* New translations lang.pot (Korean)

* New translations lang.pot (Italian)

* New translations lang.pot (Russian)

* New translations lang.pot (Italian)

* New translations lang.pot (Japanese)

* New translations lang.pot (Japanese)

* New translations lang.pot (Russian)

* New translations lang.pot (Italian)

* New translations lang.pot (Russian)

* New translations lang.pot (Italian)

* New translations lang.pot (Korean)

* New translations lang.pot (Korean)

* New translations lang.pot (Italian)

* New translations lang.pot (Italian)

* New translations lang.pot (Russian)

* New translations lang.pot (Russian)

* New translations lang.pot (Russian)

* New translations lang.pot (Russian)

* New translations lang.pot (Russian)

* New translations lang.pot (French)

* New translations lang.pot (Italian)

* New translations lang.pot (Japanese)

* New translations lang.pot (Korean)

* New translations lang.pot (Russian)

* New translations lang.pot (Chinese Simplified)

* New translations lang.pot (Russian)

* New translations lang.pot (Russian)
2020-07-22 23:48:47 -04:00
blitzmann
0b850808cb Update README to remove reference to 'only support EVE languages' 2020-07-22 23:43:24 -04:00
blitzmann
ffb14a2393 Add ability to set eos language separate from pyfa language 2020-07-22 23:41:38 -04:00
blitzmann
f1feb8cebe Fix typo 2020-07-22 00:23:55 -04:00
blitzmann
507cc09a2f update data 2020-07-19 21:33:35 -04:00
blitzmann
6990a71d14 Merge remote-tracking branch 'origin/master' into i18n
# Conflicts:
#	staticdata/fsd_binary/marketgroups.json
#	staticdata/fsd_binary/typedogma.json
#	staticdata/fsd_lite/evegroups.json
#	staticdata/fsd_lite/evetypes.json
#	staticdata/phobos/metadata.0.json
2020-07-19 21:33:14 -04:00
blitzmann
2239428b71 Merge branch 'i18n' of https://github.com/pyfa-org/Pyfa into i18n 2020-07-19 21:03:03 -04:00
blitzmann
ce755e393c Merge branch 'i18n' of https://github.com/zhaoweny/Pyfa into i18n 2020-07-19 20:52:16 -04:00
blitzmann
d07e46099b Update localization README 2020-07-19 20:52:07 -04:00
Ryan Holmes
d11e9c52c0 Merge pull request #2235 from pyfa-org/crowdin_l10n
New Crowdin updates
2020-07-19 20:48:23 -04:00
Ryan Holmes
57aaed4140 New translations lang.pot (Chinese Simplified) 2020-07-19 14:18:22 -04:00
Ryan Holmes
af76103957 New translations lang.pot (Chinese Simplified) 2020-07-19 14:04:35 -04:00
Ryan Holmes
fdaf682dbd New translations lang.pot (Russian) 2020-07-19 14:04:33 -04:00
Ryan Holmes
26e1ab47f2 New translations lang.pot (Korean) 2020-07-19 14:04:31 -04:00
Ryan Holmes
f1ffd369d0 New translations lang.pot (Japanese) 2020-07-19 14:04:29 -04:00
Ryan Holmes
9ac8969d43 New translations lang.pot (Italian) 2020-07-19 14:04:27 -04:00
Ryan Holmes
7bc4a1d334 New translations lang.pot (French) 2020-07-19 14:04:26 -04:00
Ryan Holmes
bb9866e175 Merge pull request #2232 from zhaoweny/i18n
i18n: string annotation for graph panels
2020-07-19 14:03:06 -04:00
zhaoweny
d81e25fc50 i18n/zh_CN: update translation for graph pannels 2020-07-17 12:48:40 +08:00
zhaoweny
6b11fd0a91 i18n: string annotation for graph panels 2020-07-17 12:44:47 +08:00
Ryan Holmes
8a5b2b3e48 Merge pull request #2227 from pyfa-org/crowdin_l10n
New Crowdin updates
2020-07-12 21:16:07 -04:00
Ryan Holmes
99d1655c20 New translations lang.pot (Chinese Simplified) 2020-07-12 21:11:16 -04:00
Ryan Holmes
91c30832b3 New translations lang.pot (Russian) 2020-07-12 21:11:15 -04:00
Ryan Holmes
390f198310 New translations lang.pot (Korean) 2020-07-12 21:11:13 -04:00
Ryan Holmes
316265e19d New translations lang.pot (Japanese) 2020-07-12 21:11:11 -04:00
Ryan Holmes
8754326446 New translations lang.pot (Italian) 2020-07-12 21:11:09 -04:00
Ryan Holmes
443769badd New translations lang.pot (French) 2020-07-12 21:11:08 -04:00
Ryan Holmes
0cee45e33d Update Crowdin configuration file 2020-07-11 18:37:23 -04:00
Ryan Holmes
9d02845875 Update Crowdin configuration file 2020-07-11 18:33:57 -04:00
blitzmann
5f97ba6931 Merge branch 'i18n' of https://github.com/pyfa-org/Pyfa into i18n 2020-07-11 18:25:43 -04:00
blitzmann
ca7358d2fc Include .pot file in epo 2020-07-11 18:25:30 -04:00
Ryan Holmes
dcdd50a91b Update Crowdin configuration file 2020-07-11 18:01:10 -04:00
Ryan Holmes
9895339c13 Merge pull request #2222 from zhaoweny/i18n
i18n: more annotation, more translation
2020-07-11 12:27:45 -04:00
blitzmann
04f9c1c9f8 Move the pyfa app initialization back to where it was 2020-07-11 12:27:09 -04:00
zhaoweny
e536aa5f1c i18n: special comments to mark strings containing '%' mean literally '%', not part of escape sequence
see also:
* https://github.com/vslavik/poedit/issues/645
* https://www.gnu.org/software/gettext/manual/html_node/PO-Files.html
* https://www.gnu.org/software/gettext/manual/html_node/c_002dformat-Flag.html
2020-07-11 21:12:57 +08:00
zhaoweny
b82030090c i18n/zh_CN: update translation for damagePattern and targetProfiles 2020-07-11 16:09:45 +08:00
zhaoweny
9868b219d7 i18n: deferred translation and category annotation for targetProfile and damagePattern
* use deferred translation annotation, to annotate strings in eos.db and translate on the GUI side

  As @blitzmann said in #2222, we should not include wx as a dependency for eos module.

* category annotation _c for taking '[]' out of string literals
2020-07-11 16:09:02 +08:00
Zhao Wen Yuan
f9b3defd4b Merge pull request #1 from pyfa-org/zhaoweny-i18n
Update to translations for damage profiles
2020-07-11 14:54:22 +08:00
blitzmann
7451ce147e Create a dummy translation annotation for damage patterns, and do translations on the GUI side 2020-07-10 23:36:52 -04:00
zhaoweny
2203767fde i18n/zh_CN: update Chinese translation for damage pattern and target profile 2020-07-09 10:17:57 +08:00
zhaoweny
067f60bfcd i18n: separate strings for simpler translation 2020-07-08 17:51:55 +08:00
zhaoweny
d4c9423c77 i18n: annotate targetProfile.py, damagePattern.py
Also init PyfaApp earlier for targetProfile.py and damagePattern.py localization
2020-07-08 14:42:05 +08:00
zhaoweny
ffbae4826d i18n/zh_CN: tweaks for Chinese translation 2020-07-07 17:13:47 +08:00
zhaoweny
da2ec4d759 i18n/zh_CN: update translation for service slot 2020-07-07 16:37:13 +08:00
zhaoweny
5a45863432 i18n: add translation mapping for service slot 2020-07-07 16:37:13 +08:00
zhaoweny
605addd0d6 i18n/zh_CN: update translation for pyfa_gauge.py 2020-07-07 16:37:13 +08:00
zhaoweny
5f45709118 i18n: annotate pyfa_gauge.py 2020-07-07 16:37:12 +08:00
blitzmann
76674435c9 Remove default for language 2020-07-05 15:22:08 -04:00
blitzmann
dcdf69d658 Merge branch 'master' into i18n 2020-07-05 14:10:04 -04:00
blitzmann
47e428d57e Fix publicity and group checking 2020-07-05 14:00:46 -04:00
blitzmann
95af9660b6 Move mainframe import below app init, which will allow us to set up locale correctly before anything else loads 2020-07-05 14:00:18 -04:00
blitzmann
6e7b8cca24 Fix missing damage type icons for missle selector 2020-07-05 13:42:23 -04:00
Ryan Holmes
af62a7273f Merge pull request #2220 from zhaoweny/i18n
i18n: return compiled_data in _readData
2020-07-02 09:00:33 -04:00
zhaoweny
6cdb4a7dc1 i18n: return compiled_data in _readData 2020-07-02 16:13:39 +08:00
blitzmann
469f0a9be7 Skills were attempting to match English names with translated names 2020-07-01 20:49:06 -04:00
blitzmann
832ad5bc6b Merge commit '5d95877d2c856bc7336d2032ecb2a4d5c24c75c6' into i18n2 2020-07-01 20:47:50 -04:00
Joshua Pierce
bc77f24471 Translating Typo To English 2020-07-01 20:45:40 -04:00
zhaoweny
5d95877d2c i18n: use rsplit on typeName to avoid explict for-loop 2020-07-01 21:45:21 +08:00
zhaoweny
3642ff8cee i18n: update zh_CN translation 2020-07-01 11:48:55 +08:00
zhaoweny
8cc770467e i18n: fix crash on right clicking a Tactical Destroyer fit 2020-07-01 11:48:37 +08:00
zhaoweny
85e779469f i18n: more annotation 2020-07-01 11:48:06 +08:00
blitzmann
29f6ac0d99 Initialize other langauges, update README to provide more information, simplify the langauge codes 2020-06-30 23:33:34 -04:00
Ryan Holmes
4d49512a7e Merge pull request #2217 from zhaoweny/i18n
i18n: sort zh_CN translation, more zh_CN translation
2020-06-30 09:32:45 -04:00
zhaoweny
dae13f934e i18n/zh_CN: update translation 2020-06-30 17:21:02 +08:00
zhaoweny
bf99132f2f i18n: more string annotation 2020-06-30 17:19:40 +08:00
zhaoweny
25a694bd69 i18n: annotate copySelectDialog.py 2020-06-30 16:37:36 +08:00
zhaoweny
038b7ce931 i18n: fix 'Level Not learned' issue in #2202 (comment) 2020-06-30 15:15:15 +08:00
zhaoweny
8625dea833 i18n: update locale/README.md to include sort detail; sort zh_CN lang.po 2020-06-30 11:50:19 +08:00
Ryan Holmes
6f3049f39b Merge pull request #2208 from pyfa-org/i18n_db
i18n Localization - Database
2020-06-29 22:32:29 -04:00
blitzmann
52b74d9950 Some export fixes 2020-06-29 22:15:26 -04:00
blitzmann
dc60c3d68b Update the dump script with latest phobos changes (including custom write in case phobos doesn't merge it in) 2020-06-29 22:06:03 -04:00
blitzmann
6612724beb Fix market group generation to be language agnostic 2020-06-29 21:26:58 -04:00
blitzmann
c242a18a34 Ensure that languages that are set are actually supported 2020-06-29 21:10:10 -04:00
blitzmann
732634fefa Updated the string manipulation texts to be prefixed, allowing for better context management if needed for things like "Effects", "System Effects". Added en translations to handle them on the English side. Updated the zh translations using merge:
`msgmerge --update locale/zh_CN/LC_MESSAGES/lang.p o locale/lang.pot`
2020-06-29 20:57:17 -04:00
blitzmann
10a4f62b78 Merge branch 'i18n_db' of https://github.com/pyfa-org/Pyfa into i18n_db 2020-06-29 20:13:18 -04:00
blitzmann
c39ae080fb Update db-update to be language agnostic (further testing required) 2020-06-29 20:03:33 -04:00
Ryan Holmes
e5e8a570db Merge pull request #2213 from zhaoweny/i18n_db
i18n_db: sort and (slightly) update zh_CN translation
2020-06-29 11:01:16 -04:00
zhaoweny
eaea671f4e i18n_db: remove git-lfs from Travis CI config 2020-06-29 15:38:10 +08:00
zhaoweny
1145a27e04 i18n_db: update shipBrowser to use displayName 2020-06-29 15:31:50 +08:00
zhaoweny
b18205a184 i18n_db: sort and (slightly) update zh_CN translation 2020-06-29 10:51:43 +08:00
blitzmann
9703ce70d9 Merge branch 'i18n' into i18n_db 2020-06-28 17:57:20 -04:00
blitzmann
47dd6f7bba Add annotations to the rack separators in the fitting view 2020-06-28 17:56:57 -04:00
blitzmann
3db9c637e0 Force EFT export to English variant 2020-06-28 17:41:28 -04:00
blitzmann
77d233ca1c Fix environmental variables for localizations 2020-06-28 13:38:33 -04:00
blitzmann
b225093b1f Fix exception when opening WH projection menu (still have other issues that need to be worked out tho) 2020-06-28 11:57:39 -04:00
blitzmann
4a6a3fc6ea Keep name on group, create displayName property to point to translated version 2020-06-28 00:54:51 -04:00
blitzmann
2fd4168ab7 Fix two group name issues 2020-06-28 00:40:59 -04:00
Ryan Holmes
22498e5605 Merge pull request #2211 from zhaoweny/i18n_db
i18n_db: fix ValueError exception when name should be groupName
2020-06-28 00:18:01 -04:00
zhaoweny
f515536d1a i18n_db: fix ValueError exception when name should be groupName 2020-06-28 11:42:27 +08:00
blitzmann
5c7e3fe782 Remove LSF, convert staticdata files to split files 2020-06-27 22:27:28 -04:00
blitzmann
546a3b6e01 Fix turrent ammo type grouping (using English names for grouping). Also made missile damage type grouping translation-aware 2020-06-27 21:06:16 -04:00
blitzmann
1d0c890c23 Fix the preferences not loading / saving correctly (needed to be done after paths were set) 2020-06-27 21:05:00 -04:00
blitzmann
427b1189f7 travis fix? 2020-06-25 22:37:31 -04:00
blitzmann
19da89a467 Fixes to some translations 2020-06-25 22:23:12 -04:00
blitzmann
be4f6241a9 more tweaks 2020-06-25 22:06:57 -04:00
blitzmann
03e29e02b1 update unit to include all the translations 2020-06-25 22:04:04 -04:00
blitzmann
853b65d6aa Some clean up and commenting out unused columns [I think] 2020-06-25 22:01:27 -04:00
blitzmann
45dae7a031 Remove index on items.description(lol) 2020-06-25 21:51:24 -04:00
blitzmann
4130852e76 Remove old todo 2020-06-25 21:47:26 -04:00
blitzmann
3d238a1cc1 Reset forced language to English 2020-06-25 21:36:09 -04:00
blitzmann
977ae98ea6 more conversions on the traits 2020-06-25 21:35:26 -04:00
blitzmann
dac35597ea Update traits 2020-06-25 21:32:43 -04:00
blitzmann
0a1489719b Rename the descriptions so as not to confuse the synonym 2020-06-25 21:18:25 -04:00
blitzmann
4ff63e5fc4 Create deferred descriptions for each of the item description languages, and then one synonym to rule them all 2020-06-25 21:09:32 -04:00
blitzmann
c3389fb19b Add all languages to market groups 2020-06-25 21:08:37 -04:00
blitzmann
42706f35c6 Update various instances where Category name wasn't displaying the translated version (in context menus) 2020-06-25 20:32:49 -04:00
blitzmann
c7ec87b979 Fix a couple of bugs by referencing raw names, and include all translations for types table 2020-06-25 19:23:28 -04:00
blitzmann
66140f092b More tweaks to dynamically generate the columns, and a fix for attribute display names 2020-06-25 00:40:29 -04:00
blitzmann
8be4b0dd91 Introduce way to dynamically map the languages, helps reduce the typing and also should "just work" if there's any new languages added 2020-06-25 00:09:36 -04:00
blitzmann
a2f65e9d46 categoryName > name (this was caused by having name not be the literal data rather than the synonym) 2020-06-24 23:59:58 -04:00
blitzmann
c040ff26c0 Update schema and db_update to support translations.
(language setting from preferences is borked for some reason)
2020-06-24 23:33:24 -04:00
blitzmann
92ecd8c844 Add the other files 2020-06-24 23:28:08 -04:00
blitzmann
60c8a66bea Add the other directories 2020-06-24 23:28:00 -04:00
blitzmann
b1ff13e370 Add fsd_binary 2020-06-24 23:27:16 -04:00
blitzmann
50b0df7d6d Track fsd_binary 2020-06-24 23:26:50 -04:00
blitzmann
281e30f78a Remove static data 2020-06-24 23:23:37 -04:00
blitzmann
821378e2c3 Add LFS, because... translations are heafty 2020-06-24 23:01:23 -04:00
blitzmann
d4106a7229 fix mac spec file to include locales 2020-06-24 13:28:58 -04:00
blitzmann
079256a99f some tweaks to get the languages to compile 2020-06-24 13:01:36 -04:00
blitzmann
bcd7e6d56d Add language compilation to build process (maybe?) 2020-06-24 12:51:19 -04:00
blitzmann
e56db0d129 add script to automatically generate all languages 2020-06-24 12:47:11 -04:00
blitzmann
6035d26dd0 add msgfmt.py to scripts/ to have a way to produce localizations 2020-06-24 12:11:24 -04:00
Ryan Holmes
61127dc4d3 Merge pull request #2204 from zhaoweny/i18n
i18n: annotate Preferences, update zh_CN translations
2020-06-24 09:48:47 -04:00
zhaoweny
f4f0dc775c i18n/zh_CN: update translation for context menus 2020-06-23 16:45:30 +08:00
zhaoweny
d33976a2ad i18n: more annotation for context menus, stats view tooltips 2020-06-23 15:55:28 +08:00
zhaoweny
1c4de8b259 i18n: annotate gui/builtinContextMenus 2020-06-23 15:55:16 +08:00
zhaoweny
1079371ecf i18n/zh_CN: update translation for unified wildcard annotations 2020-06-23 01:36:00 +08:00
zhaoweny
85c3158e98 i18n: unify FileDialog wildcard string annotations 2020-06-23 01:16:42 +08:00
zhaoweny
2d97f0952e i18n/zh_CN: translation for item stat views 2020-06-22 20:04:21 +08:00
zhaoweny
396640e5b1 i18n: annotate item stat views 2020-06-22 20:03:53 +08:00
zhaoweny
aa8a03b18b i18n/zh_CN: update translation 2020-06-22 17:56:35 +08:00
zhaoweny
889e901cbd i18n: improve string literal annotations
1. annotate more strings for statsViews, itemStats
2. fix raw title and description for preferences
3. fix crash on opening AttributeEditor, characterEditor
2020-06-22 17:55:58 +08:00
zhaoweny
07696ce0ed i18n: fix typos in locale/README.md 2020-06-22 10:16:48 +08:00
zhaoweny
ffdbab87e9 i18n/zh_CN: lots of new strings for Preferences, more translations 2020-06-21 17:23:46 +08:00
zhaoweny
4eda1a1d66 i18n: minor tweaks for easier translation
1. tweaks for characterEditor.py and patternEditor.py according to PR discussion.
2. fix for "Recent Fits" label not translated
2020-06-21 17:11:58 +08:00
zhaoweny
29ec297acb i18n: annotate string literals in gui/builtinPreferenceViews 2020-06-21 16:06:43 +08:00
zhaoweny
7cd7d475db i18n: minor tweaks for locale/README.md 2020-06-21 15:35:41 +08:00
blitzmann
02aa4eb2b4 Add UI to change language 2020-06-20 15:46:30 -04:00
blitzmann
7cf9326311 Add language to eos config
This should be accessible now when table mapping occurs, so we should be able to use it to determine which column to pull from for translation values.
2020-06-20 15:31:10 -04:00
blitzmann
2214269cca Bring language selection to the forefront before wx app initialization 2020-06-20 15:20:56 -04:00
blitzmann
9b73f1c221 Final conversion of _t() 2020-06-20 15:13:33 -04:00
blitzmann
339367f730 More _t() conversion 2020-06-20 15:09:42 -04:00
blitzmann
68f7e6c709 Start converting _() to _t() 2020-06-20 15:07:14 -04:00
Ryan Holmes
eb657e804c Merge pull request #2203 from zhaoweny/i18n
I18n: more zh_CN translations and a better locale/README.md
2020-06-20 15:01:13 -04:00
blitzmann
413bc5d46c Minor tweaks per PR review 2020-06-20 14:59:49 -04:00
zhaoweny
e4e49cef54 i18n: extend locale/README.md and add translation workflow detail 2020-06-20 21:43:47 +08:00
zhaoweny
49cf03759b i18n: fix unresolved reference Inspection errors 2020-06-20 17:57:01 +08:00
zhaoweny
a05e7dbad1 i18n/zh_CN: add more UI translation 2020-06-20 17:42:52 +08:00
zhaoweny
d28665f172 i18n/zh_CN: add lots of UI translation 2020-06-20 16:03:42 +08:00
Ryan Holmes
1848acc1ba Merge pull request #2201 from pyfa-org/i18n_zhaoweny
I18n - zhaoweny
2020-06-19 23:22:40 -04:00
blitzmann
d9e5349edd Move supported languages to the LocaleSettings class, and use the command parameter as an override 2020-06-19 22:44:09 -04:00
blitzmann
d939b0e565 rename pyfa.po to lang.po 2020-06-19 22:27:35 -04:00
blitzmann
c290e9e23a Add various references 2020-06-19 22:25:23 -04:00
zhaoweny
ce0d8b1247 i18n/zh_CN: add more translation for builtinStatsViews
(cherry picked from commit 97c1c597c8c75450350123ed471f082e5ad8dabd)
2020-06-19 22:20:37 -04:00
zhaoweny
834e4a3d6e i18n: implement LocaleSettings, use wx.GetTranslation instead of gettext
(cherry picked from commit 3648a5c8c7b230a4b695a29ebfaad3877e7b644f)
2020-06-19 22:19:20 -04:00
zhaoweny
3d9b4c11d4 i18n/zh_CN: reformat code and ignore _
1. update `Pyfa_Inspections.xml` to ignore `_`

i18n module `gettext` will do a `gettext.install(...)` to put `_` function into `builtin` module. Currently PyCharm does not recognize this as a function and report as unresolved reference.

2. reformat code to remove padding for vertical dicts

3. update `Pyfa_CodeStyle.xml` to not pad vertical dicts

(cherry picked from commit e5a570a0078f05fe34c473841af6b7746e06bfca)
2020-06-19 22:17:49 -04:00
zhaoweny
2d3a661442 i18n/zh_CN: update zh_CN translation for lots of StatsViews
(cherry picked from commit bdac2f825fba27000c87f20de8e09e61ae1376d2)
2020-06-19 22:17:21 -04:00
zhaoweny
343f4a5196 i18n/zh_CN: basic gettext i18n setup and demo for zh_CN translation
(cherry picked from commit 8fe58a95f7d9c08d792b8e17605700607662f7c9)
2020-06-19 22:15:44 -04:00
blitzmann
31fd480fb0 Fix some missing references 2020-06-19 21:54:30 -04:00
blitzmann
8e83adf7db Merge tag 'v2.22.1' into i18n
# Conflicts:
#	gui/esiFittings.py
2020-06-19 21:51:45 -04:00
blitzmann
7fa638f62b More localization 2020-06-19 11:35:37 -04:00
blitzmann
2490d3de92 More localization 2020-06-07 13:44:15 -04:00
blitzmann
c3ceebcec7 remove old test string 2020-05-16 15:10:01 -04:00
blitzmann
5177768962 Start working through the files, adding translation strings 2020-05-16 14:42:29 -04:00
blitzmann
fdd06ed3d6 Add some boilerplate code to add support for localization 2020-05-15 21:55:48 -04:00
543 changed files with 3967822 additions and 3098441 deletions

View File

@@ -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
View File

@@ -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
View File

@@ -67,7 +67,6 @@ coverage.xml
# Translations
*.mo
*.pot
# Django stuff:
*.log
@@ -123,3 +122,4 @@ gitversion
*.swp
*.fsdbinary
/locale/progress.json

View File

@@ -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

View File

@@ -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).

View File

@@ -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" />

View File

@@ -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>

View File

@@ -41,6 +41,7 @@ cipher = None
clientHash = None
experimentalFeatures = None
version = None
language = None
ESI_CACHE = 'esi_cache'
@@ -52,6 +53,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 +109,7 @@ def defPaths(customSavePath=None):
global clientHash
global version
global experimentalFeatures
global language
pyfalog.debug("Configuring Pyfa")
@@ -185,9 +189,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
View File

@@ -0,0 +1,3 @@
files:
- source: /locale/*.pot
translation: /locale/%locale_with_underscore%/LC_MESSAGES/lang.po

View File

@@ -28,6 +28,8 @@ import sqlite3
import sys
# 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 +41,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 +87,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 +136,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 +172,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 +274,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 +349,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 +537,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:

View File

@@ -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', '.'),

View File

@@ -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'):

View File

@@ -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")

View File

@@ -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
})

View File

@@ -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
})

View File

@@ -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")

View File

@@ -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
)

View File

@@ -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))
}
)

View File

@@ -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:

View File

@@ -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)),
}
)

View File

@@ -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={

View 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))

View File

@@ -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",

View File

@@ -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,

View File

@@ -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):

File diff suppressed because it is too large Load Diff

View File

@@ -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))
)

View File

@@ -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))}"

View File

@@ -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

View File

@@ -25,125 +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, ('[NPC][Abyssal]All', 126, 427, 218, 230)),
(-109, ('[NPC][Abyssal]Angel', 450, 72, 80, 398)),
(-107, ('[NPC][Abyssal]Concord', 53, 559, 94, 295)),
(-56, ('[NPC][Abyssal]Drifter', 250, 250, 250, 250)),
(-57, ('[NPC][Abyssal]Drones', 250, 250, 250, 250)),
(-58, ('[NPC][Abyssal]Overmind', 0, 410, 590, 0)),
(-108, ('[NPC][Abyssal]Sansha', 569, 431, 0, 0)),
(-59, ('[NPC][Abyssal]Seeker', 402, 402, 98, 98)),
(-60, ('[NPC][Abyssal]Sleeper', 313, 313, 187, 187)),
(-61, ('[NPC][Abyssal]Triglavian', 0, 615, 0, 385)),
(-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)),
(-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
(-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
@@ -204,7 +222,8 @@ class DamagePattern:
"armorRepair": "armor",
"armorRepairPreSpool": "armor",
"armorRepairFullSpool": "armor",
"hullRepair": "hull"}
"hullRepair": "hull"
}
ereps = {}
for field in tankInfo:
if field in typeMap:
@@ -228,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

View File

@@ -111,7 +111,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

View File

@@ -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):
@@ -395,16 +398,16 @@ 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):
@@ -443,9 +446,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):
@@ -578,15 +581,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 +600,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 +682,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 +1009,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 +1032,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 +1110,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 +1408,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 +1453,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 +1494,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 +1503,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 +1564,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 +1689,6 @@ class Fit:
secstatus = FitSystemSecurity.NULLSEC
return secstatus
def activeModulesIter(self):
for mod in self.modules:
if mod.state >= FittingModuleState.ACTIVE:

View File

@@ -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

View File

@@ -205,6 +205,11 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
and self.__item.group.name not in self.SYSTEM_GROUPS
):
return True
if (
self.__item.category.name == "Structure Module"
and self.__item.group.name == "Quantum Cores"
):
return True
if self.item.isAbyssal and not self.isMutated:
return True
if self.isMutated and not self.__mutaplasmid:
@@ -534,7 +539,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 +556,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 +1026,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),

View File

@@ -26,204 +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.643, 0.593, 0.624, 0.639)),
(-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.494, 0.41, 0.464, 0.376)),
(-61, ('[NPC][Abyssal][Dark Matter All Tiers]Drifter', 0.415, 0.415, 0.415, 0.415)),
(-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.508, 0.474, 0.495, 0.488)),
(-64, ('[NPC][Abyssal][Electrical T0/T1/T2]Drones', 0.323, 0.522, 0.529, 0.435)),
(-65, ('[NPC][Abyssal][Electrical T0/T1/T2]Overmind', 0.542, 0.593, 0.624, 0.639)),
(-66, ('[NPC][Abyssal][Electrical T0/T1/T2]Seeker', 0, 0.082, 0.082, 0.082)),
(-67, ('[NPC][Abyssal][Electrical T0/T1/T2]Triglavian', 0.356, 0.41, 0.464, 0.376)),
(-68, ('[NPC][Abyssal][Electrical T0/T1/T2]Drifter', 0.277, 0.415, 0.415, 0.415)),
(-69, ('[NPC][Abyssal][Electrical T0/T1/T2]Sleeper', 0.329, 0.435, 0.435, 0.435)),
(-70, ('[NPC][Abyssal][Electrical T0/T1/T2]All', 0.381, 0.474, 0.495, 0.488)),
(-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.48, 0.593, 0.624, 0.639)),
(-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.268, 0.41, 0.464, 0.376)),
(-75, ('[NPC][Abyssal][Electrical T3 (Some T5 Rooms)]Drifter', 0.191, 0.415, 0.415, 0.415)),
(-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.308, 0.474, 0.495, 0.488)),
(-78, ('[NPC][Abyssal][Electrical T4/T5/T6]Drones', 0.193, 0.522, 0.529, 0.435)),
(-79, ('[NPC][Abyssal][Electrical T4/T5/T6]Overmind', 0.423, 0.593, 0.624, 0.639)),
(-80, ('[NPC][Abyssal][Electrical T4/T5/T6]Seeker', 0, 0.082, 0.082, 0.082)),
(-81, ('[NPC][Abyssal][Electrical T4/T5/T6]Triglavian', 0.206, 0.41, 0.464, 0.376)),
(-82, ('[NPC][Abyssal][Electrical T4/T5/T6]Drifter', 0.111, 0.415, 0.415, 0.415)),
(-83, ('[NPC][Abyssal][Electrical T4/T5/T6]Sleeper', 0.215, 0.435, 0.435, 0.435)),
(-84, ('[NPC][Abyssal][Electrical T4/T5/T6]All', 0.247, 0.474, 0.495, 0.488)),
(-85, ('[NPC][Abyssal][Firestorm T0/T1/T2]Drones', 0.461, 0.425, 0.541, 0.443)),
(-86, ('[NPC][Abyssal][Firestorm T0/T1/T2]Overmind', 0.666, 0.489, 0.634, 0.646)),
(-87, ('[NPC][Abyssal][Firestorm T0/T1/T2]Seeker', 0.084, 0, 0.084, 0.084)),
(-88, ('[NPC][Abyssal][Firestorm T0/T1/T2]Triglavian', 0.537, 0.269, 0.489, 0.371)),
(-89, ('[NPC][Abyssal][Firestorm T0/T1/T2]Drifter', 0.43, 0.289, 0.43, 0.43)),
(-90, ('[NPC][Abyssal][Firestorm T0/T1/T2]Sleeper', 0.512, 0.402, 0.512, 0.512)),
(-91, ('[NPC][Abyssal][Firestorm T0/T1/T2]All', 0.537, 0.352, 0.512, 0.495)),
(-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.666, 0.413, 0.634, 0.646)),
(-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.537, 0.166, 0.489, 0.371)),
(-96, ('[NPC][Abyssal][Firestorm T3 (Some T5 Rooms)]Drifter', 0.43, 0.201, 0.43, 0.43)),
(-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.537, 0.269, 0.512, 0.495)),
(-99, ('[NPC][Abyssal][Firestorm T4/T5/T6]Drones', 0.461, 0.305, 0.541, 0.443)),
(-100, ('[NPC][Abyssal][Firestorm T4/T5/T6]Overmind', 0.666, 0.345, 0.634, 0.646)),
(-101, ('[NPC][Abyssal][Firestorm T4/T5/T6]Seeker', 0.084, 0, 0.084, 0.084)),
(-102, ('[NPC][Abyssal][Firestorm T4/T5/T6]Triglavian', 0.537, 0.085, 0.489, 0.371)),
(-103, ('[NPC][Abyssal][Firestorm T4/T5/T6]Drifter', 0.43, 0.117, 0.43, 0.43)),
(-104, ('[NPC][Abyssal][Firestorm T4/T5/T6]Sleeper', 0.512, 0.276, 0.512, 0.512)),
(-105, ('[NPC][Abyssal][Firestorm T4/T5/T6]All', 0.537, 0.201, 0.512, 0.495)),
(-106, ('[NPC][Abyssal][Exotic T0/T1/T2]Drones', 0.439, 0.522, 0.417, 0.435)),
(-107, ('[NPC][Abyssal][Exotic T0/T1/T2]Overmind', 0.643, 0.593, 0.511, 0.639)),
(-108, ('[NPC][Abyssal][Exotic T0/T1/T2]Seeker', 0.082, 0.082, 0, 0.082)),
(-109, ('[NPC][Abyssal][Exotic T0/T1/T2]Triglavian', 0.494, 0.41, 0.304, 0.376)),
(-110, ('[NPC][Abyssal][Exotic T0/T1/T2]Drifter', 0.415, 0.415, 0.277, 0.415)),
(-111, ('[NPC][Abyssal][Exotic T0/T1/T2]Sleeper', 0.435, 0.435, 0.329, 0.435)),
(-112, ('[NPC][Abyssal][Exotic T0/T1/T2]All', 0.508, 0.474, 0.359, 0.488)),
(-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.643, 0.593, 0.435, 0.639)),
(-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.494, 0.41, 0.198, 0.376)),
(-117, ('[NPC][Abyssal][Exotic T3 (Some T5 Rooms)]Drifter', 0.415, 0.415, 0.191, 0.415)),
(-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.508, 0.474, 0.276, 0.488)),
(-120, ('[NPC][Abyssal][Exotic T4/T5/T6]Drones', 0.439, 0.522, 0.293, 0.435)),
(-121, ('[NPC][Abyssal][Exotic T4/T5/T6]Overmind', 0.643, 0.593, 0.362, 0.639)),
(-122, ('[NPC][Abyssal][Exotic T4/T5/T6]Seeker', 0.082, 0.082, 0, 0.082)),
(-123, ('[NPC][Abyssal][Exotic T4/T5/T6]Triglavian', 0.494, 0.41, 0.122, 0.376)),
(-124, ('[NPC][Abyssal][Exotic T4/T5/T6]Drifter', 0.415, 0.415, 0.111, 0.415)),
(-125, ('[NPC][Abyssal][Exotic T4/T5/T6]Sleeper', 0.435, 0.435, 0.215, 0.435)),
(-126, ('[NPC][Abyssal][Exotic T4/T5/T6]All', 0.508, 0.474, 0.208, 0.488)),
(-127, ('[NPC][Abyssal][Gamma T0/T1/T2]Drones', 0.449, 0.54, 0.549, 0.336)),
(-128, ('[NPC][Abyssal][Gamma T0/T1/T2]Overmind', 0.619, 0.574, 0.612, 0.522)),
(-129, ('[NPC][Abyssal][Gamma T0/T1/T2]Seeker', 0.085, 0.085, 0.085, 0)),
(-130, ('[NPC][Abyssal][Gamma T0/T1/T2]Triglavian', 0.477, 0.4, 0.461, 0.202)),
(-131, ('[NPC][Abyssal][Gamma T0/T1/T2]Drifter', 0.437, 0.437, 0.437, 0.295)),
(-132, ('[NPC][Abyssal][Gamma T0/T1/T2]Sleeper', 0.435, 0.435, 0.435, 0.329)),
(-133, ('[NPC][Abyssal][Gamma T0/T1/T2]All', 0.493, 0.468, 0.492, 0.35)),
(-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.619, 0.574, 0.612, 0.449)),
(-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.477, 0.4, 0.461, 0.081)),
(-138, ('[NPC][Abyssal][Gamma T3 (Some T5 Rooms)]Drifter', 0.437, 0.437, 0.437, 0.206)),
(-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.468, 0.492, 0.264)),
(-141, ('[NPC][Abyssal][Gamma T4/T5/T6]Drones', 0.449, 0.54, 0.549, 0.197)),
(-142, ('[NPC][Abyssal][Gamma T4/T5/T6]Overmind', 0.619, 0.574, 0.612, 0.379)),
(-143, ('[NPC][Abyssal][Gamma T4/T5/T6]Seeker', 0.085, 0.085, 0.085, 0)),
(-144, ('[NPC][Abyssal][Gamma T4/T5/T6]Triglavian', 0.477, 0.4, 0.461, 0.034)),
(-145, ('[NPC][Abyssal][Gamma T4/T5/T6]Drifter', 0.437, 0.437, 0.437, 0.121)),
(-146, ('[NPC][Abyssal][Gamma T4/T5/T6]Sleeper', 0.435, 0.435, 0.435, 0.215)),
(-147, ('[NPC][Abyssal][Gamma T4/T5/T6]All', 0.493, 0.468, 0.492, 0.196)),
(-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, ('[NPC][Abyssal][Dark Matter All Tiers]Concord', 0.324, 0.318, 0.369, 0.372)),
(-149, ('[NPC][Abyssal][Dark Matter All Tiers]Sansha', 0.137, 0.331, 0.332, 0.322)),
(-150, ('[NPC][Abyssal][Dark Matter All Tiers]Angel', 0.582, 0.508, 0.457, 0.416)),
(-151, ('[NPC][Abyssal][Electrical T0/T1/T2]Concord', 0.121, 0.318, 0.369, 0.372)),
(-152, ('[NPC][Abyssal][Electrical T0/T1/T2]Sansha', 0.034, 0.331, 0.332, 0.322)),
(-153, ('[NPC][Abyssal][Electrical T0/T1/T2]Angel', 0.456, 0.508, 0.457, 0.416)),
(-154, ('[NPC][Abyssal][Electrical T3 (Some T5 Rooms)]Concord', 0.025, 0.318, 0.369, 0.372)),
(-155, ('[NPC][Abyssal][Electrical T3 (Some T5 Rooms)]Sansha', 0.018, 0.331, 0.332, 0.322)),
(-156, ('[NPC][Abyssal][Electrical T3 (Some T5 Rooms)]Angel', 0.373, 0.508, 0.457, 0.416)),
(-157, ('[NPC][Abyssal][Electrical T4/T5/T6]Concord', 0.008, 0.318, 0.369, 0.372)),
(-158, ('[NPC][Abyssal][Electrical T4/T5/T6]Sansha', 0.009, 0.331, 0.332, 0.322)),
(-159, ('[NPC][Abyssal][Electrical T4/T5/T6]Angel', 0.3, 0.508, 0.457, 0.416)),
(-160, ('[NPC][Abyssal][Firestorm T0/T1/T2]Concord', 0.324, 0.107, 0.369, 0.372)),
(-161, ('[NPC][Abyssal][Firestorm T0/T1/T2]Sansha', 0.148, 0.181, 0.329, 0.328)),
(-162, ('[NPC][Abyssal][Firestorm T0/T1/T2]Angel', 0.587, 0.342, 0.439, 0.39)),
(-163, ('[NPC][Abyssal][Firestorm T3 (Some T5 Rooms)]Concord', 0.324, 0.016, 0.369, 0.372)),
(-164, ('[NPC][Abyssal][Firestorm T3 (Some T5 Rooms)]Sansha', 0.148, 0.14, 0.329, 0.328)),
(-165, ('[NPC][Abyssal][Firestorm T3 (Some T5 Rooms)]Angel', 0.587, 0.241, 0.439, 0.39)),
(-166, ('[NPC][Abyssal][Firestorm T4/T5/T6]Concord', 0.324, 0.004, 0.369, 0.372)),
(-167, ('[NPC][Abyssal][Firestorm T4/T5/T6]Sansha', 0.148, 0.106, 0.329, 0.328)),
(-168, ('[NPC][Abyssal][Firestorm T4/T5/T6]Angel', 0.587, 0.172, 0.439, 0.39)),
(-169, ('[NPC][Abyssal][Exotic T0/T1/T2]Concord', 0.324, 0.318, 0.18, 0.372)),
(-170, ('[NPC][Abyssal][Exotic T0/T1/T2]Sansha', 0.137, 0.331, 0.166, 0.322)),
(-171, ('[NPC][Abyssal][Exotic T0/T1/T2]Angel', 0.582, 0.508, 0.295, 0.416)),
(-172, ('[NPC][Abyssal][Exotic T3 (Some T5 Rooms)]Concord', 0.324, 0.318, 0.089, 0.372)),
(-173, ('[NPC][Abyssal][Exotic T3 (Some T5 Rooms)]Sansha', 0.137, 0.331, 0.108, 0.322)),
(-174, ('[NPC][Abyssal][Exotic T3 (Some T5 Rooms)]Angel', 0.582, 0.508, 0.203, 0.416)),
(-175, ('[NPC][Abyssal][Exotic T4/T5/T6]Concord', 0.324, 0.318, 0.068, 0.372)),
(-176, ('[NPC][Abyssal][Exotic T4/T5/T6]Sansha', 0.137, 0.331, 0.073, 0.322)),
(-177, ('[NPC][Abyssal][Exotic T4/T5/T6]Angel', 0.582, 0.508, 0.14, 0.416)),
(-178, ('[NPC][Abyssal][Gamma T0/T1/T2]Concord', 0.324, 0.318, 0.369, 0.203)),
(-179, ('[NPC][Abyssal][Gamma T0/T1/T2]Sansha', 0.137, 0.355, 0.352, 0.16)),
(-180, ('[NPC][Abyssal][Gamma T0/T1/T2]Angel', 0.59, 0.528, 0.477, 0.286)),
(-181, ('[NPC][Abyssal][Gamma T3 (Some T5 Rooms)]Concord', 0.324, 0.318, 0.369, 0.112)),
(-182, ('[NPC][Abyssal][Gamma T3 (Some T5 Rooms)]Sansha', 0.137, 0.355, 0.352, 0.05)),
(-183, ('[NPC][Abyssal][Gamma T3 (Some T5 Rooms)]Angel', 0.59, 0.528, 0.477, 0.197)),
(-184, ('[NPC][Abyssal][Gamma T4/T5/T6]Concord', 0.324, 0.318, 0.369, 0.086)),
(-185, ('[NPC][Abyssal][Gamma T4/T5/T6]Sansha', 0.137, 0.355, 0.352, 0)),
(-186, ('[NPC][Abyssal][Gamma T4/T5/T6]Angel', 0.59, 0.528, 0.477, 0.126))])
(-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
@@ -274,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
@@ -439,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

View File

@@ -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]

View File

@@ -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')

View File

@@ -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'])))

View File

@@ -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):

View File

@@ -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:

View File

@@ -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 = {

View File

@@ -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

View File

@@ -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

View File

@@ -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}

View File

@@ -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 = {

View File

@@ -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

View File

@@ -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 = {

View File

@@ -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)

View File

@@ -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

View File

@@ -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):

View File

@@ -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))))])

View File

@@ -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.")
)

View File

@@ -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
View 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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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:

View File

@@ -195,7 +195,7 @@ class DroneView(Display):
def droneKey(drone):
sMkt = Market.getInstance()
groupName = sMkt.getMarketGroupByItem(drone.item).name
groupName = sMkt.getMarketGroupByItem(drone.item).marketGroupName
return (DRONE_ORDER.index(groupName), drone.item.name)
@@ -324,7 +324,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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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()

View File

@@ -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',))

View File

@@ -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)

View File

@@ -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)

View File

@@ -1,3 +1,5 @@
import wx
import gui.mainFrame
from gui import fitCommands as cmd
from gui.contextMenu import ContextMenuUnconditional
@@ -5,25 +7,25 @@ from gui.utils.clipboard import fromClipboard
from service.fit import Fit
from service.port.eft import parseAdditions
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,16 @@ 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]
filterFunc = self.viewSpecMap[self.srcContext][1]
items = [(i.ID, a) for i, a 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))

View File

@@ -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()

View File

@@ -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()

View File

@@ -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()

View File

@@ -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()

View File

@@ -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)

View File

@@ -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())

View File

@@ -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)

View File

@@ -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()

View File

@@ -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()

View File

@@ -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()

View File

@@ -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()

View File

@@ -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:

View File

@@ -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 = {}

View File

@@ -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):

View File

@@ -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()

View File

@@ -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'))

View File

@@ -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)

View File

@@ -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'))

View File

@@ -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'))

View File

@@ -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):

View File

@@ -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'))

View File

@@ -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()

View File

@@ -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)

View File

@@ -1,6 +1,5 @@
import re
# noinspection PyPackageRequirements
import wx
import gui.fitCommands as cmd
@@ -12,6 +11,10 @@ from eos.saveddata.fit import Fit as es_Fit
from gui.contextMenu import ContextMenuSingle
from service.fit import Fit
# noinspection PyPackageRequirements
_t = wx.GetTranslation
class ChangeItemAmount(ContextMenuSingle):
@@ -28,7 +31,7 @@ class ChangeItemAmount(ContextMenuSingle):
return True
def getText(self, callingWindow, itmContext, mainItem):
return "Change {0} Quantity".format(itmContext)
return _t("Change {0} Quantity").format(itmContext)
def activate(self, callingWindow, fullContext, mainItem, i):
fitID = self.mainFrame.getActiveFit()
@@ -54,30 +57,30 @@ class ChangeItemAmount(ContextMenuSingle):
if isinstance(mainItem, es_Cargo):
self.mainFrame.command.Submit(cmd.GuiChangeCargoAmountCommand(
fitID=fitID, itemID=mainItem.itemID, amount=cleanInput))
fitID=fitID, itemID=mainItem.itemID, 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 +89,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)

View File

@@ -1,10 +1,13 @@
import wx
import gui.fitCommands as cmd
import gui.mainFrame
from gui.contextMenu import ContextMenuSingle
_t = wx.GetTranslation
class FillWithItem(ContextMenuSingle):
visibilitySetting = 'moduleFill'
def __init__(self):
@@ -26,12 +29,12 @@ class FillWithItem(ContextMenuSingle):
return True
def getText(self, callingWindow, itmContext, mainItem):
return "Fill With Module"
return _t("Fill With Module")
def activate(self, callingWindow, fullContext, mainItem, i):
self.mainFrame.command.Submit(cmd.GuiFillWithNewLocalModulesCommand(
fitID=self.mainFrame.getActiveFit(),
itemID=int(mainItem.ID)))
fitID=self.mainFrame.getActiveFit(),
itemID=int(mainItem.ID)))
FillWithItem.register()

View File

@@ -1,7 +1,11 @@
import wx
import gui.mainFrame
from gui.contextMenu import ContextMenuSingle
from service.market import Market
_t = wx.GetTranslation
class JumpToMarketItem(ContextMenuSingle):
def __init__(self):
@@ -37,7 +41,7 @@ class JumpToMarketItem(ContextMenuSingle):
return doit
def getText(self, callingWindow, itmContext, mainItem):
return "{0} Market Group".format(itmContext if itmContext is not None else "Item")
return _t("{0} Market Group").format(itmContext if itmContext is not None else _t("Item"))
def activate(self, callingWindow, fullContext, mainItem, i):
srcContext = fullContext[0]

View File

@@ -1,11 +1,14 @@
import wx
import gui.fitCommands as cmd
import gui.mainFrame
from gui.contextMenu import ContextMenuSingle
from service.fit import Fit
_t = wx.GetTranslation
class ProjectItem(ContextMenuSingle):
visibilitySetting = 'project'
def __init__(self):
@@ -28,7 +31,7 @@ class ProjectItem(ContextMenuSingle):
return mainItem.isType("projected")
def getText(self, callingWindow, itmContext, mainItem):
return "Project {0} onto Fit".format(itmContext)
return _t("Project {0} onto Fit").format(itmContext)
def activate(self, callingWindow, fullContext, mainItem, i):
fitID = self.mainFrame.getActiveFit()

View File

@@ -1,6 +1,5 @@
import re
# noinspection PyPackageRequirements
import wx
import gui.fitCommands as cmd
@@ -12,6 +11,10 @@ from gui.contextMenu import ContextMenuCombined
from gui.fitCommands.helpers import getSimilarFighters, getSimilarModPositions
from service.fit import Fit
# noinspection PyPackageRequirements
_t = wx.GetTranslation
class ChangeItemProjectionRange(ContextMenuCombined):
@@ -28,7 +31,7 @@ class ChangeItemProjectionRange(ContextMenuCombined):
return True
def getText(self, callingWindow, itmContext, mainItem, selection):
return 'Change {} Range'.format(itmContext)
return _t('Change {} Range').format(itmContext)
def activate(self, callingWindow, fullContext, mainItem, selection, i):
fitID = self.mainFrame.getActiveFit()
@@ -63,7 +66,7 @@ class ChangeItemProjectionRange(ContextMenuCombined):
fit = Fit.getInstance().getFit(fitID)
items = getSimilarFighters(fit.projectedFighters, mainItem)
self.mainFrame.command.Submit(cmd.GuiChangeProjectedItemsProjectionRangeCommand(
fitID=fitID, items=items, projectionRange=newRange))
fitID=fitID, items=items, projectionRange=newRange))
ChangeItemProjectionRange.register()

View File

@@ -12,6 +12,8 @@ from gui.contextMenu import ContextMenuCombined
from gui.fitCommands.helpers import getSimilarFighters, getSimilarModPositions
from service.fit import Fit
_t = wx.GetTranslation
class RemoveItem(ContextMenuCombined):
@@ -20,13 +22,13 @@ class RemoveItem(ContextMenuCombined):
def display(self, callingWindow, srcContext, mainItem, selection):
if srcContext not in (
"fittingModule", "droneItem",
"implantItem", "boosterItem",
"projectedModule", "cargoItem",
"projectedFit", "projectedDrone",
"fighterItem", "projectedFighter",
"commandFit", "graphFitList",
"graphTgtList"
"fittingModule", "droneItem",
"implantItem", "boosterItem",
"projectedModule", "cargoItem",
"projectedFit", "projectedDrone",
"fighterItem", "projectedFighter",
"commandFit", "graphFitList",
"graphTgtList"
):
return False
@@ -37,9 +39,9 @@ class RemoveItem(ContextMenuCombined):
return True
def getText(self, callingWindow, itmContext, mainItem, selection):
return 'Remove {}{}'.format(
itmContext if itmContext is not None else 'Item',
' Stack' if self.srcContext in ('droneItem', 'projectedDrone', 'cargoItem', 'projectedFit') else '')
return _t('Remove {item}{stack}').format(
item=itmContext if itmContext is not None else _t('Item'),
stack=_t(' Stack') if self.srcContext in ('droneItem', 'projectedDrone', 'cargoItem', 'projectedFit') else '')
def activate(self, callingWindow, fullContext, mainItem, selection, i):
handlerMap = {
@@ -55,7 +57,8 @@ class RemoveItem(ContextMenuCombined):
'projectedFighter': self.__handleProjectedItem,
'commandFit': self.__handleCommandFit,
'graphFitList': self.__handleGraphItem,
'graphTgtList': self.__handleGraphItem}
'graphTgtList': self.__handleGraphItem
}
srcContext = fullContext[0]
handler = handlerMap.get(srcContext)
if handler is None:
@@ -73,7 +76,7 @@ class RemoveItem(ContextMenuCombined):
if mod in fit.modules:
positions.append(fit.modules.index(mod))
self.mainFrame.command.Submit(cmd.GuiRemoveLocalModuleCommand(
fitID=fitID, positions=positions))
fitID=fitID, positions=positions))
def __handleDrone(self, callingWindow, mainItem, selection):
fitID = self.mainFrame.getActiveFit()
@@ -83,7 +86,7 @@ class RemoveItem(ContextMenuCombined):
if drone in fit.drones:
positions.append(fit.drones.index(drone))
self.mainFrame.command.Submit(cmd.GuiRemoveLocalDronesCommand(
fitID=fitID, positions=positions, amount=math.inf))
fitID=fitID, positions=positions, amount=math.inf))
def __handleFighter(self, callingWindow, mainItem, selection):
fitID = self.mainFrame.getActiveFit()
@@ -97,7 +100,7 @@ class RemoveItem(ContextMenuCombined):
if fighter in fit.fighters:
positions.append(fit.fighters.index(fighter))
self.mainFrame.command.Submit(cmd.GuiRemoveLocalFightersCommand(
fitID=fitID, positions=positions))
fitID=fitID, positions=positions))
def __handleImplant(self, callingWindow, mainItem, selection):
fitID = self.mainFrame.getActiveFit()
@@ -107,7 +110,7 @@ class RemoveItem(ContextMenuCombined):
if implant in fit.implants:
positions.append(fit.implants.index(implant))
self.mainFrame.command.Submit(cmd.GuiRemoveImplantsCommand(
fitID=fitID, positions=positions))
fitID=fitID, positions=positions))
def __handleBooster(self, callingWindow, mainItem, selection):
fitID = self.mainFrame.getActiveFit()
@@ -117,19 +120,19 @@ class RemoveItem(ContextMenuCombined):
if booster in fit.boosters:
positions.append(fit.boosters.index(booster))
self.mainFrame.command.Submit(cmd.GuiRemoveBoostersCommand(
fitID=fitID, positions=positions))
fitID=fitID, positions=positions))
def __handleCargo(self, callingWindow, mainItem, selection):
fitID = self.mainFrame.getActiveFit()
itemIDs = [c.itemID for c in selection]
self.mainFrame.command.Submit(cmd.GuiRemoveCargosCommand(
fitID=fitID, itemIDs=itemIDs))
fitID=fitID, itemIDs=itemIDs))
def __handleProjectedItem(self, callingWindow, mainItem, selection):
fitID = self.mainFrame.getActiveFit()
if isinstance(mainItem, EosFit):
self.mainFrame.command.Submit(cmd.GuiRemoveProjectedItemsCommand(
fitID=fitID, items=selection, amount=math.inf))
fitID=fitID, items=selection, amount=math.inf))
elif isinstance(mainItem, EosModule):
if wx.GetMouseState().GetModifiers() in (wx.MOD_ALT, wx.MOD_CONTROL):
fit = Fit.getInstance().getFit(fitID)
@@ -138,10 +141,10 @@ class RemoveItem(ContextMenuCombined):
else:
items = selection
self.mainFrame.command.Submit(cmd.GuiRemoveProjectedItemsCommand(
fitID=fitID, items=items, amount=math.inf))
fitID=fitID, items=items, amount=math.inf))
elif isinstance(mainItem, EosDrone):
self.mainFrame.command.Submit(cmd.GuiRemoveProjectedItemsCommand(
fitID=fitID, items=selection, amount=math.inf))
fitID=fitID, items=selection, amount=math.inf))
elif isinstance(mainItem, EosFighter):
if wx.GetMouseState().GetModifiers() in (wx.MOD_ALT, wx.MOD_CONTROL):
fit = Fit.getInstance().getFit(fitID)
@@ -149,16 +152,16 @@ class RemoveItem(ContextMenuCombined):
else:
items = selection
self.mainFrame.command.Submit(cmd.GuiRemoveProjectedItemsCommand(
fitID=fitID, items=items, amount=math.inf))
fitID=fitID, items=items, amount=math.inf))
else:
self.mainFrame.command.Submit(cmd.GuiRemoveProjectedItemsCommand(
fitID=fitID, items=selection, amount=math.inf))
fitID=fitID, items=selection, amount=math.inf))
def __handleCommandFit(self, callingWindow, mainItem, selection):
fitID = self.mainFrame.getActiveFit()
commandFitIDs = [cf.ID for cf in selection]
self.mainFrame.command.Submit(cmd.GuiRemoveCommandFitsCommand(
fitID=fitID, commandFitIDs=commandFitIDs))
fitID=fitID, commandFitIDs=commandFitIDs))
def __handleGraphItem(self, callingWindow, mainItem, selection):
callingWindow.removeWrappers(selection)

View File

@@ -1,4 +1,5 @@
# noinspection PyPackageRequirements
import wx
import gui.mainFrame
@@ -6,6 +7,8 @@ from gui.contextMenu import ContextMenuSingle
from gui.itemStats import ItemStatsFrame
from service.fit import Fit
_t = wx.GetTranslation
class ItemStats(ContextMenuSingle):
def __init__(self):
@@ -13,16 +16,16 @@ class ItemStats(ContextMenuSingle):
def display(self, callingWindow, srcContext, mainItem):
if srcContext not in (
"marketItemGroup", "marketItemMisc",
"fittingModule", "fittingCharge",
"fittingShip", "baseShip",
"cargoItem", "droneItem",
"implantItem", "boosterItem",
"skillItem", "projectedModule",
"projectedDrone", "projectedCharge",
"itemStats", "fighterItem",
"implantItemChar", "projectedFighter",
"fittingMode"
"marketItemGroup", "marketItemMisc",
"fittingModule", "fittingCharge",
"fittingShip", "baseShip",
"cargoItem", "droneItem",
"implantItem", "boosterItem",
"skillItem", "projectedModule",
"projectedDrone", "projectedCharge",
"itemStats", "fighterItem",
"implantItemChar", "projectedFighter",
"fittingMode"
):
return False
@@ -32,7 +35,7 @@ class ItemStats(ContextMenuSingle):
return True
def getText(self, callingWindow, itmContext, mainItem):
return "{} Stats".format(itmContext if itmContext is not None else "Item")
return _t("{} Stats").format(itmContext if itmContext is not None else _t("Item"))
def activate(self, callingWindow, fullContext, mainItem, i):
srcContext = fullContext[0]

View File

@@ -1,16 +1,18 @@
# noinspection PyPackageRequirements
import wx
import gui.fitCommands as cmd
import gui.mainFrame
from gui.contextMenu import ContextMenuCombined
from gui.fitCommands.helpers import getSimilarModPositions, getSimilarFighters
from gui.fitCommands.helpers import getSimilarFighters, getSimilarModPositions
from service.fit import Fit
from service.market import Market
_t = wx.GetTranslation
class ChangeItemToVariation(ContextMenuCombined):
visibilitySetting = 'metaSwap'
def __init__(self):
@@ -18,15 +20,15 @@ class ChangeItemToVariation(ContextMenuCombined):
def display(self, callingWindow, srcContext, mainItem, selection):
if self.mainFrame.getActiveFit() is None or srcContext not in (
'fittingModule',
'droneItem',
'fighterItem',
'boosterItem',
'implantItem',
'cargoItem',
'projectedModule',
'projectedDrone',
'projectedFighter'
'fittingModule',
'droneItem',
'fighterItem',
'boosterItem',
'implantItem',
'cargoItem',
'projectedModule',
'projectedDrone',
'projectedFighter'
):
return False
@@ -44,7 +46,7 @@ class ChangeItemToVariation(ContextMenuCombined):
return True
def getText(self, callingWindow, itmContext, mainItem, selection):
return 'Variations'
return _t('Variations')
def getSubMenu(self, callingWindow, context, mainItem, selection, rootMenu, i, pitem):
self.moduleLookup = {}
@@ -60,7 +62,8 @@ class ChangeItemToVariation(ContextMenuCombined):
# We want deadspace before officer mods
5: 6, 6: 5,
# For structures we want t1-t2-faction
54: 52, 52: 54}
54: 52, 52: 54
}
metaGroup = sMkt.getMetaGroupByItem(x)
return remap.get(metaGroup.ID, metaGroup.ID) if metaGroup is not None else 0
@@ -86,8 +89,8 @@ class ChangeItemToVariation(ContextMenuCombined):
# Do not show abyssal items
items = list(
i for i in self.mainVariations
if sMkt.getMetaGroupByItem(i) is None or sMkt.getMetaGroupByItem(i).ID != 15)
i for i in self.mainVariations
if sMkt.getMetaGroupByItem(i) is None or sMkt.getMetaGroupByItem(i).ID != 15)
# Sort items by metalevel, and group within that metalevel
# Sort all items by name first
items.sort(key=lambda x: x.name)
@@ -143,7 +146,8 @@ class ChangeItemToVariation(ContextMenuCombined):
'boosterItem': self.__handleBooster,
'projectedModule': self.__handleProjectedModule,
'projectedDrone': self.__handleProjectedDrone,
'projectedFighter': self.__handleProjectedFighter}
'projectedFighter': self.__handleProjectedFighter
}
handler = handlerMap.get(context)
if handler is None:
return
@@ -169,7 +173,7 @@ class ChangeItemToVariation(ContextMenuCombined):
if modVariations == self.mainVariations:
positions.append(fit.modules.index(mod))
self.mainFrame.command.Submit(cmd.GuiChangeLocalModuleMetasCommand(
fitID=fitID, positions=positions, newItemID=varItem.ID))
fitID=fitID, positions=positions, newItemID=varItem.ID))
def __handleDrone(self, varItem):
fitID = self.mainFrame.getActiveFit()
@@ -186,7 +190,7 @@ class ChangeItemToVariation(ContextMenuCombined):
if droneVariations == self.mainVariations:
positions.append(fit.drones.index(drone))
self.mainFrame.command.Submit(cmd.GuiChangeLocalDroneMetasCommand(
fitID=fitID, positions=positions, newItemID=varItem.ID))
fitID=fitID, positions=positions, newItemID=varItem.ID))
def __handleFighter(self, varItem):
fitID = self.mainFrame.getActiveFit()
@@ -207,7 +211,7 @@ class ChangeItemToVariation(ContextMenuCombined):
if fighterVariations == self.mainVariations:
positions.append(fit.fighters.index(fighter))
self.mainFrame.command.Submit(cmd.GuiChangeLocalFighterMetasCommand(
fitID=fitID, positions=positions, newItemID=varItem.ID))
fitID=fitID, positions=positions, newItemID=varItem.ID))
def __handleCargo(self, varItem):
fitID = self.mainFrame.getActiveFit()
@@ -221,7 +225,7 @@ class ChangeItemToVariation(ContextMenuCombined):
if cargoVariations == self.mainVariations:
itemIDs.append(cargo.itemID)
self.mainFrame.command.Submit(cmd.GuiChangeCargoMetasCommand(
fitID=fitID, itemIDs=itemIDs, newItemID=varItem.ID))
fitID=fitID, itemIDs=itemIDs, newItemID=varItem.ID))
def __handleImplant(self, varItem):
fitID = self.mainFrame.getActiveFit()
@@ -230,7 +234,7 @@ class ChangeItemToVariation(ContextMenuCombined):
if implant in fit.implants:
position = fit.implants.index(implant)
self.mainFrame.command.Submit(cmd.GuiChangeImplantMetaCommand(
fitID=fitID, position=position, newItemID=varItem.ID))
fitID=fitID, position=position, newItemID=varItem.ID))
def __handleBooster(self, varItem):
fitID = self.mainFrame.getActiveFit()
@@ -239,7 +243,7 @@ class ChangeItemToVariation(ContextMenuCombined):
if booster in fit.boosters:
position = fit.boosters.index(booster)
self.mainFrame.command.Submit(cmd.GuiChangeBoosterMetaCommand(
fitID=fitID, position=position, newItemID=varItem.ID))
fitID=fitID, position=position, newItemID=varItem.ID))
def __handleProjectedModule(self, varItem):
fitID = self.mainFrame.getActiveFit()
@@ -259,7 +263,7 @@ class ChangeItemToVariation(ContextMenuCombined):
if modVariations == self.mainVariations:
positions.append(fit.projectedModules.index(mod))
self.mainFrame.command.Submit(cmd.GuiChangeProjectedModuleMetasCommand(
fitID=fitID, positions=positions, newItemID=varItem.ID))
fitID=fitID, positions=positions, newItemID=varItem.ID))
def __handleProjectedDrone(self, varItem):
fitID = self.mainFrame.getActiveFit()
@@ -276,7 +280,7 @@ class ChangeItemToVariation(ContextMenuCombined):
if droneVariations == self.mainVariations:
itemIDs.append(drone.itemID)
self.mainFrame.command.Submit(cmd.GuiChangeProjectedDroneMetasCommand(
fitID=fitID, itemIDs=itemIDs, newItemID=varItem.ID))
fitID=fitID, itemIDs=itemIDs, newItemID=varItem.ID))
def __handleProjectedFighter(self, varItem):
fitID = self.mainFrame.getActiveFit()
@@ -297,7 +301,7 @@ class ChangeItemToVariation(ContextMenuCombined):
if fighterVariations == self.mainVariations:
positions.append(fit.projectedFighters.index(fighter))
self.mainFrame.command.Submit(cmd.GuiChangeProjectedFighterMetasCommand(
fitID=fitID, positions=positions, newItemID=varItem.ID))
fitID=fitID, positions=positions, newItemID=varItem.ID))
ChangeItemToVariation.register()

View File

@@ -1,4 +1,5 @@
# noinspection PyPackageRequirements
import wx
import gui.fitCommands as cmd
@@ -9,6 +10,8 @@ from gui.fitCommands.helpers import getSimilarModPositions
from service.ammo import Ammo
from service.fit import Fit
_t = wx.GetTranslation
class ChangeModuleAmmo(ContextMenuCombined):
@@ -16,6 +19,14 @@ class ChangeModuleAmmo(ContextMenuCombined):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
# Format: {type ID: set(loadable, charges)}
self.loadableChargesCache = {}
# Translations for the missile categories, as the text here is auto-generated via damage attributes
self.ddMissileChargeCatTrans = {
'em': _t('EM'),
'thermal': _t('Thermal'),
'explosive': _t('Explosive'),
'kinetic': _t('Kinetic'),
'mixed': _t('Mixed')
}
def display(self, callingWindow, srcContext, mainItem, selection):
if srcContext not in ('fittingModule', 'projectedModule'):
@@ -34,7 +45,7 @@ class ChangeModuleAmmo(ContextMenuCombined):
return True
def getText(self, callingWindow, itmContext, mainItem, selection):
return 'Charge'
return _t('Charge')
def _getAmmo(self, mod):
if mod.itemID is None:
@@ -45,7 +56,7 @@ class ChangeModuleAmmo(ContextMenuCombined):
def _addCharge(self, menu, charge):
id_ = ContextMenuCombined.nextID()
name = charge.name if charge is not None else 'Empty'
name = charge.name if charge is not None else _t('Empty')
self.chargeEventMap[id_] = charge
item = wx.MenuItem(menu, id_, name)
menu.Bind(wx.EVT_MENU, self.handleAmmoSwitch, item)
@@ -68,7 +79,7 @@ class ChangeModuleAmmo(ContextMenuCombined):
self.chargeEventMap = {}
modType, chargeDict = Ammo.getInstance().getModuleStructuredAmmo(self.module, ammo=self.mainCharges)
if modType == 'ddTurret':
self._addSeparator(menu, 'Long Range')
self._addSeparator(menu, _t('Long Range'))
menuItems = []
for charges in chargeDict.values():
if len(charges) == 1:
@@ -80,25 +91,28 @@ class ChangeModuleAmmo(ContextMenuCombined):
subMenu = wx.Menu()
subMenu.Bind(wx.EVT_MENU, self.handleAmmoSwitch)
menuItem.SetSubMenu(subMenu)
self._addSeparator(subMenu, 'Less Damage')
self._addSeparator(subMenu, _t('Less Damage'))
for charge in charges:
subMenu.Append(self._addCharge(rootMenu if msw else subMenu, charge))
self._addSeparator(subMenu, 'More Damage')
self._addSeparator(subMenu, _t('More Damage'))
for menuItem in menuItems:
menu.Append(menuItem)
self._addSeparator(menu, 'Short Range')
self._addSeparator(menu, _t('Short Range'))
elif modType == 'ddMissile':
menuItems = []
for chargeCatName, charges in chargeDict.items():
menuItem = wx.MenuItem(menu, wx.ID_ANY, chargeCatName.capitalize())
menuItem = wx.MenuItem(menu, wx.ID_ANY, self.ddMissileChargeCatTrans.get(chargeCatName, chargeCatName))
bitmap = BitmapLoader.getBitmap("%s_small" % chargeCatName, "gui")
if bitmap is not None:
menuItem.SetBitmap(bitmap)
menuItems.append(menuItem)
subMenu = wx.Menu()
subMenu.Bind(wx.EVT_MENU, self.handleAmmoSwitch)
menuItem.SetSubMenu(subMenu)
self._addSeparator(subMenu, 'Less Damage')
self._addSeparator(subMenu, _t('Less Damage'))
for charge in charges:
subMenu.Append(self._addCharge(rootMenu if msw else subMenu, charge))
self._addSeparator(subMenu, 'More Damage')
self._addSeparator(subMenu, _t('More Damage'))
for menuItem in menuItems:
menu.Append(menuItem)
elif modType == 'general':
@@ -129,9 +143,9 @@ class ChangeModuleAmmo(ContextMenuCombined):
return
positions = getSimilarModPositions(modContainer, self.module)
self.mainFrame.command.Submit(command(
fitID=fitID,
positions=positions,
chargeItemID=charge.ID if charge is not None else None))
fitID=fitID,
positions=positions,
chargeItemID=charge.ID if charge is not None else None))
else:
if self.srcContext == 'fittingModule':
command = cmd.GuiChangeLocalModuleChargesCommand
@@ -148,9 +162,9 @@ class ChangeModuleAmmo(ContextMenuCombined):
if modCharges.issubset(self.mainCharges):
positions.append(position)
self.mainFrame.command.Submit(command(
fitID=fitID,
positions=positions,
chargeItemID=charge.ID if charge is not None else None))
fitID=fitID,
positions=positions,
chargeItemID=charge.ID if charge is not None else None))
ChangeModuleAmmo.register()

View File

@@ -1,11 +1,14 @@
import wx
import gui.fitCommands as cmd
import gui.mainFrame
from gui.contextMenu import ContextMenuSingle
from service.fit import Fit
_t = wx.GetTranslation
class FillWithModule(ContextMenuSingle):
visibilitySetting = 'moduleFill'
def __init__(self):
@@ -18,7 +21,7 @@ class FillWithModule(ContextMenuSingle):
return srcContext == "fittingModule"
def getText(self, callingWindow, itmContext, mainItem):
return "Fill With {0}".format(itmContext if itmContext is not None else "Module")
return _t("Fill With {0}").format(itmContext if itmContext is not None else _t("Module"))
def activate(self, callingWindow, fullContext, mainItem, i):
@@ -30,7 +33,7 @@ class FillWithModule(ContextMenuSingle):
if mainItem in fit.modules:
position = fit.modules.index(mainItem)
self.mainFrame.command.Submit(cmd.GuiFillWithClonedLocalModulesCommand(
fitID=fitID, position=position))
fitID=fitID, position=position))
FillWithModule.register()

View File

@@ -1,8 +1,12 @@
import wx
import gui.mainFrame
from gui.contextMenu import ContextMenuSingle
from gui.utils.clipboard import toClipboard
from service.port.muta import renderMutant
_t = wx.GetTranslation
class ExportMutatedModule(ContextMenuSingle):
@@ -21,7 +25,7 @@ class ExportMutatedModule(ContextMenuSingle):
return True
def getText(self, callingWindow, itmContext, mainItem):
return 'Copy Module to Clipboard'
return _t('Copy Module to Clipboard')
def activate(self, callingWindow, fullContext, mainItem, i):
export = renderMutant(mainItem, prefix=' ')

View File

@@ -1,4 +1,5 @@
# noinspection PyPackageRequirements
import wx
import gui.mainFrame
@@ -6,6 +7,8 @@ from gui.contextMenu import ContextMenuSingle
from gui.fitCommands import GuiConvertMutatedLocalModuleCommand, GuiRevertMutatedLocalModuleCommand
from service.fit import Fit
_t = wx.GetTranslation
class ChangeModuleMutation(ContextMenuSingle):
@@ -27,7 +30,7 @@ class ChangeModuleMutation(ContextMenuSingle):
return True
def getText(self, callingWindow, itmContext, mainItem):
return "Apply Mutaplasmid" if not mainItem.isMutated else "Revert to {}".format(mainItem.baseItem.name)
return _t("Apply Mutaplasmid") if not mainItem.isMutated else _t("Revert to {}").format(mainItem.baseItem.name)
def getSubMenu(self, callingWindow, context, mainItem, rootMenu, i, pitem):
if mainItem.isMutated:
@@ -56,7 +59,7 @@ class ChangeModuleMutation(ContextMenuSingle):
if mod in fit.modules:
position = fit.modules.index(mod)
self.mainFrame.command.Submit(GuiConvertMutatedLocalModuleCommand(
fitID=fitID, position=position, mutaplasmid=mutaplasmid))
fitID=fitID, position=position, mutaplasmid=mutaplasmid))
def activate(self, callingWindow, fullContext, mainItem, i):
fitID = self.mainFrame.getActiveFit()
@@ -64,7 +67,7 @@ class ChangeModuleMutation(ContextMenuSingle):
if mainItem in fit.modules:
position = fit.modules.index(mainItem)
self.mainFrame.command.Submit(GuiRevertMutatedLocalModuleCommand(
fitID=fitID, position=position))
fitID=fitID, position=position))
def getBitmap(self, callingWindow, context, mainItem):
return None

Some files were not shown because too many files have changed in this diff Show More