Compare commits

..

214 Commits

Author SHA1 Message Date
DarkPhoenix
368f2c33a9 Attempt to work around postgres issue on linux 2023-11-14 19:45:22 +06:00
DarkPhoenix
c445bb4423 Add some debug commands to work around postgres issue in image 2023-11-14 19:28:44 +06:00
DarkPhoenix
4b932d210f Bump version 2023-11-14 18:54:09 +06:00
DarkPhoenix
a1ca29fb30 Update effects 2023-11-14 18:53:50 +06:00
DarkPhoenix
876c85ee19 Update icons 2023-11-14 18:41:56 +06:00
DarkPhoenix
ac1d935712 Update static data to 2420589 2023-11-14 18:39:57 +06:00
DarkPhoenix
2ccc829d3b Merge branch 'singularity' 2023-11-14 18:39:01 +06:00
DarkPhoenix
d127dd9a7e Implement RR diminishing returns 2023-11-13 21:45:40 +06:00
DarkPhoenix
e5d95dd4d8 Fix something which was not supposed to be committed 2023-10-31 00:06:31 +06:00
DarkPhoenix
08c5c9a4b7 Fix an omission 2023-10-31 00:05:21 +06:00
DarkPhoenix
a484698a9d Add option to export implants/boosters via ESI 2023-10-31 00:01:16 +06:00
DarkPhoenix
bafaed1d81 Fix character editor search crash 2023-10-30 23:33:35 +06:00
DarkPhoenix
02f7fbf1b1 Do not stacking penalize shield/armor HP bonuses 2023-10-23 06:46:00 +06:00
DarkPhoenix
3ed85112c6 Bump version 2023-10-19 05:45:24 +06:00
DarkPhoenix
fed39b75e3 Add new icons 2023-10-19 05:44:08 +06:00
DarkPhoenix
8a3defded5 Update metadata and effects to 2395039 2023-10-19 05:42:31 +06:00
DarkPhoenix
88970c7a95 Bump version 2023-10-10 02:50:42 +06:00
DarkPhoenix
fddaf27055 Update icons 2023-10-10 02:47:00 +06:00
DarkPhoenix
dd575bd3a0 Update static data and effects 2023-10-10 02:43:44 +06:00
DarkPhoenix
0c9b73727b Fix DD weapon application 2023-10-10 00:15:47 +06:00
DarkPhoenix
ade9fc389a Bump version 2023-09-19 23:52:50 +03:00
DarkPhoenix
b6c5f67085 Update effects 2023-09-19 23:52:24 +03:00
DarkPhoenix
7d86d58993 Add new icons 2023-09-19 23:34:33 +03:00
DarkPhoenix
a7ab046bc6 Update static data to 2363654 2023-09-19 23:11:22 +03:00
DarkPhoenix
c94693a72d Update icons 2023-09-10 17:30:41 +06:00
DarkPhoenix
ea335b7d41 Bump version 2023-09-10 09:12:59 +06:00
DarkPhoenix
4838f69c40 Add effects for new AT ships 2023-09-10 09:12:29 +06:00
DarkPhoenix
fb81e6c043 Add shapash/cybele hardcoded ships 2023-09-10 08:38:39 +06:00
DarkPhoenix
84716af82b Update effect file 2023-09-10 07:09:28 +06:00
DarkPhoenix
30dd77d462 Add renames 2023-09-10 07:03:24 +06:00
DarkPhoenix
9148611a8e Update static data to 2353888 2023-09-10 06:51:03 +06:00
DarkPhoenix
e7be51b70e Remove evepraiisal market source 2023-09-10 05:44:17 +06:00
DarkPhoenix
194e4657eb Fix appimage build 2023-06-14 05:30:12 +06:00
DarkPhoenix
b08986ba74 Duration is not penalized 2023-06-14 01:09:46 +06:00
DarkPhoenix
57d8a672d9 Fix rep systems-related effect stacking penalties 2023-06-14 01:05:16 +06:00
DarkPhoenix
47dbfbd6d5 Bump version 2023-06-13 22:01:44 +06:00
DarkPhoenix
cbbf4863fb Update static data 2023-06-13 21:56:47 +06:00
DarkPhoenix
369f62bd68 Bump version 2023-06-11 04:34:01 +06:00
DarkPhoenix
885ad4deb3 Update effects 2023-06-11 04:28:18 +06:00
DarkPhoenix
0ce3b861a4 Update EVE images 2023-06-11 00:28:05 +06:00
DarkPhoenix
48ee543c00 Update static data to 2291839 2023-06-11 00:26:27 +06:00
Anton Vorobyov
e07e2bc4f7 Merge pull request #2507 from superusercode/patch-1
Replace dead README badges with current CI badge
2023-06-10 21:19:57 +04:00
Code
17dec4d732 Update README.md 2023-05-11 21:36:00 -04:00
Anton Vorobyov
effb7e6429 Bump version 2023-04-28 01:49:55 +06:00
Anton Vorobyov
63f7762e34 Add option to export missing skills in roman / evemon format 2023-04-28 01:49:31 +06:00
Anton Vorobyov
76ff52aea8 Show seconds, not milliseconds 2023-04-28 01:38:26 +06:00
Anton Vorobyov
cd12279404 Add ADC ability duration 2023-04-28 01:36:45 +06:00
Anton Vorobyov
263929b6e3 Update icons 2023-04-28 01:33:03 +06:00
Anton Vorobyov
759135d3fe Add auto targeting system as acronym 2023-04-28 01:31:32 +06:00
Anton Vorobyov
d240f547cc Update effects & add mobiile depot hold 2023-04-28 01:28:55 +06:00
Anton Vorobyov
0a4f3481da Update static data to 2258955 2023-04-27 23:06:33 +06:00
Anton Vorobyov
b248cdefdd Bump version 2023-03-16 17:50:33 +06:00
Anton Vorobyov
6172ceda0f Update static data to 2232464 2023-03-16 17:25:10 +06:00
Anton Vorobyov
ba236bcb54 Update static data and effects to 2228687 2023-03-10 02:26:12 +06:00
Anton Vorobyov
b4e115eb7b Update icons 2023-02-22 19:07:51 +06:00
Anton Vorobyov
52b567a06d Disable effect overrides for AT18 ships, and add effects for them 2023-02-22 19:06:59 +06:00
Anton Vorobyov
dd1f7e224c Update static data to 2218819 2023-02-22 18:12:42 +06:00
Anton Vorobyov
338b298077 Specify requests version 2023-02-18 03:57:42 +06:00
Anton Vorobyov
512b370e3e Bump version 2023-02-14 19:26:03 +06:00
Anton Vorobyov
a14210f356 Add rename mapping 2023-02-14 19:25:45 +06:00
Anton Vorobyov
f81cf4ee7b Update effects 2023-02-14 19:22:15 +06:00
Anton Vorobyov
87b072b567 Update static data to 2214901 2023-02-14 19:18:36 +06:00
Anton Vorobyov
e21789d29c Fix fof missile application hardwiring 2022-12-21 00:16:45 +04:00
Anton Vorobyov
dd93f348e6 Fix loki SB heat bonus 2022-12-21 00:12:03 +04:00
Anton Vorobyov
cae8088ad3 Bump version 2022-12-18 04:47:57 +04:00
Anton Vorobyov
a92cbe92f1 Update static data 2022-12-18 04:47:25 +04:00
Anton Vorobyov
52fd0bb13f Fix fighters export 2022-12-12 04:50:28 +04:00
Anton Vorobyov
afcddeea70 Bump appimage version 2022-12-11 14:04:12 +04:00
Anton Vorobyov
e5eb001cf3 Fix bestla rof bonus and bump version 2022-12-11 13:49:36 +04:00
Anton Vorobyov
0d186ba56b Bump version 2022-12-11 06:09:25 +04:00
Anton Vorobyov
e2273f90b4 Add overrides for new AT ships 2022-12-11 06:08:51 +04:00
Anton Vorobyov
d6501df509 Assign geri and bestla to limited edition ships group 2022-12-11 04:57:59 +04:00
Anton Vorobyov
96d639996a Update effect docstrings & add missing drug effect 2022-12-11 04:56:29 +04:00
Anton Vorobyov
625c52720d Update static data to 2178459 2022-12-11 04:45:11 +04:00
Anton Vorobyov
69221eac24 Ensure that there is always some text in command fit name, even if fit itself has empty name 2022-11-29 20:57:15 +04:00
Anton Vorobyov
74daf99aed Update icons/renders 2022-11-10 04:38:54 +04:00
Anton Vorobyov
eaf637d1d9 Bump version 2022-11-10 04:33:26 +04:00
Anton Vorobyov
c262ea6e35 Update static data to 2154998 2022-11-10 04:33:09 +04:00
DarkPhoenix
1c541c82bf Bump version 2022-11-04 22:29:43 +04:00
DarkPhoenix
1824d1b866 Update static data & other stuff to 2151933 2022-11-04 22:28:34 +04:00
DarkPhoenix
90025f22e5 Bump version 2022-11-02 17:17:11 +04:00
DarkPhoenix
9e71ed88e9 Update using latest sisi data 2022-11-02 17:16:35 +04:00
DarkPhoenix
be07d8e338 Bump version 2022-10-26 21:57:32 +04:00
DarkPhoenix
242fbba6d6 Update staticdata to 2143320 2022-10-26 21:57:00 +04:00
DarkPhoenix
7f1e0fcc58 Bump version 2022-10-25 01:53:07 +04:00
DarkPhoenix
072a53eabc Fix a couple of effects 2022-10-25 01:51:18 +04:00
DarkPhoenix
3115268fb8 Implement effect changes 2022-10-25 01:32:52 +04:00
DarkPhoenix
0631bd65e1 Update static data to 2141324 and update effect doctrings 2022-10-24 22:19:23 +04:00
DarkPhoenix
6b7a4b3f9d Bump appimage version 2022-10-23 08:27:05 +04:00
DarkPhoenix
0ba65cab1f Bump version 2022-10-23 08:02:38 +04:00
Anton Vorobyov
d75419d858 Merge pull request #2470 from pyfa-org/crowdin_master
New Crowdin updates
2022-10-22 20:35:35 +03:00
DarkPhoenix
771dfca1c8 Remove obsolete invasion-related system-wide effects and move destructible beacons one level above 2022-10-22 21:34:36 +04:00
DarkPhoenix
73a5f62d90 Update static data & effects to 2138646 2022-10-21 23:08:02 +04:00
Anton Vorobyov
3982670dff New translations lang.pot (Japanese) 2022-10-21 21:43:38 +03:00
Anton Vorobyov
79d2ded836 New translations lang.pot (Japanese) 2022-10-20 21:38:33 +03:00
Anton Vorobyov
55bc0cd40f New translations lang.pot (Japanese) 2022-10-19 21:11:18 +03:00
Anton Vorobyov
9da09a279e New translations lang.pot (Japanese) 2022-10-17 06:43:14 +03:00
Anton Vorobyov
889047f891 New translations lang.pot (Japanese) 2022-10-16 06:14:15 +03:00
DarkPhoenix
8f645fa425 Sort drone/fighter export the same was as in the additions panel 2022-10-15 07:12:12 +04:00
DarkPhoenix
e3e7f92b8d Add missing renders 2022-09-30 20:52:17 +04:00
DarkPhoenix
22f37995cf Bump appimage version 2022-09-30 19:25:43 +04:00
DarkPhoenix
92119c01f6 Change item comparison highlight implementation 2022-09-30 19:03:43 +04:00
DarkPhoenix
95841c44dc Remove eve.db which slipped in with the merge 2022-09-30 17:47:38 +04:00
Anton Vorobyov
e7b3040c0f Merge pull request #2466 from yeaido/feature/compare_highlight
Feature/compare highlight
2022-09-30 16:40:43 +03:00
DarkPhoenix
78af68cac2 Fix #2467 2022-09-30 17:37:20 +04:00
DarkPhoenix
3e5eb989f9 Bump version 2022-09-30 16:49:37 +04:00
DarkPhoenix
975d6f8776 Update images 2022-09-30 16:48:58 +04:00
DarkPhoenix
4e89a87ec1 Update effects 2022-09-30 16:43:05 +04:00
DarkPhoenix
eef644fb4c Update static data to 2123216 2022-09-30 13:56:52 +04:00
yeaido
8131dd4ace tidy 2022-09-05 08:12:57 +01:00
yeaido
c8059d6132 format 2022-09-04 20:18:11 +01:00
yeaido
cc008a57e1 vscode ignore 2022-09-04 20:16:47 +01:00
yeaido
ce6910fd63 Added highlight feature to the compare item window. Double click and item to highlight and bold it. 2022-09-04 12:32:07 +01:00
DarkPhoenix
7892e637b2 Force min query limit to be 1 for CJK languages in the market browser too 2022-08-29 15:33:47 +04:00
DarkPhoenix
6543a2c225 Revert "Use binary distribution of wx for appimage build"
This reverts commit 1e59d3d6ac.
2022-08-29 15:22:32 +04:00
DarkPhoenix
1e59d3d6ac Use binary distribution of wx for appimage build 2022-08-29 14:36:15 +04:00
DarkPhoenix
11d0566433 Bump version 2022-08-29 02:52:48 +04:00
DarkPhoenix
b8d84d3af2 Add new name conversions 2022-08-29 02:51:55 +04:00
DarkPhoenix
1831fea819 Update effects file 2022-08-29 02:50:00 +04:00
DarkPhoenix
d15322a57c Update static data to 2099371 2022-08-29 02:37:11 +04:00
DarkPhoenix
48981460ab Add drone EHP and shield regen columns 2022-08-29 01:56:15 +04:00
Anton Vorobyov
eaca4a179f Merge pull request #2461 from wereii/fix-appimage
Fix AppImage build
2022-08-28 21:10:18 +03:00
wereii
e249cf917b Fix AppImage build 2022-08-15 17:24:47 +02:00
DarkPhoenix
1de7a4ea82 Update static data to 2073715 2022-07-12 23:42:51 +04:00
DarkPhoenix
289acc099c Fix electropunch damage profile 2022-07-11 03:07:29 +04:00
DarkPhoenix
ce3678debb Fix a couple of effects 2022-07-10 02:50:00 +04:00
DarkPhoenix
0e36794578 Use raw attribute value for maxGroupFitted restriction 2022-07-10 02:49:44 +04:00
DarkPhoenix
6d67b23a7e Update static data to 2072413 2022-07-09 15:39:25 +04:00
DarkPhoenix
a95d69623b Hide mining blitz boosters 2022-07-04 22:22:12 +04:00
DarkPhoenix
7578532949 Update effects' definitions 2022-07-04 05:52:43 +04:00
DarkPhoenix
a067c77c4c Forcefully publish AIR boosters 2022-07-04 05:46:49 +04:00
DarkPhoenix
c6dd22f04f Bump version 2022-07-04 05:24:30 +04:00
DarkPhoenix
2e1f53184a Merge branch 'master' of github.com:pyfa-org/Pyfa 2022-07-04 05:24:13 +04:00
Anton Vorobyov
3159d399a6 Merge pull request #2452 from sajuukthanatoskhar/EFS_BurstJammer_Optimal_Not_Showing
Issue 2450 : ECM Burst Jammers burst range is 0 when exported to EFS
2022-07-04 04:09:38 +03:00
Anton Vorobyov
357dab2964 Merge pull request #2451 from sajuukthanatoskhar/Issue2425
Issue 2425 : Remote Capacitor Transmitters not being correctly written in EFS format
2022-07-04 03:43:53 +03:00
Anton Vorobyov
41c93efd83 Merge pull request #2441 from pyfa-org/crowdin_master
New Crowdin updates
2022-07-04 03:27:24 +03:00
DarkPhoenix
628aa9d905 Update static data to 2069533 2022-07-04 03:45:02 +04:00
DarkPhoenix
f9248dec6f Update effects' descriptions 2022-06-27 01:10:59 +04:00
DarkPhoenix
9d5ea487d5 Update static data to 2064776 2022-06-27 01:01:34 +04:00
DarkPhoenix
e76ce71701 Fix expanded cargohold penalty 2022-06-27 00:44:54 +04:00
Sajuukthanatoskhar
5a91e01746 MOD: version upped to 0.06
ADD: Added Remote Capacitor Transmitters!
2022-06-19 12:56:19 +02:00
Sajuukthanatoskhar
355e6dd0fe MOD: version upped to 0.06
FIX: Added check to correct add the burst jammer's burst radius
2022-06-19 12:45:16 +02:00
Anton Vorobyov
49da362dc3 New translations lang.pot (Chinese Simplified) 2022-06-13 13:20:08 +03:00
Anton Vorobyov
460cf26236 New translations lang.pot (Chinese Simplified) 2022-05-08 19:40:32 +03:00
blitzmann
cceaed8d61 rename gh_pages -> docs 2022-05-08 12:34:00 -04:00
Ryan Holmes
d9df4958a6 Merge pull request #2440 from pyfa-org/merge-gh-pages
Merge gh pages
2022-05-08 12:32:07 -04:00
blitzmann
e43e7ba51e move gh pages files to subdirectory 2022-05-08 12:31:47 -04:00
blitzmann
50e76deab7 Merge branch 'gh-pages' into merge-gh-pages 2022-05-08 12:30:05 -04:00
blitzmann
e109cce36b Update the callback to always allow the code to be shown 2022-05-07 22:44:51 -04:00
Anton Vorobyov
893f9f8467 Merge pull request #2424 from pyfa-org/issue2402
Add option in settings to disregard JWT exp issues
2022-05-05 20:53:49 +03:00
DarkPhoenix
c612545636 Bump version 2022-05-05 21:43:44 +04:00
DarkPhoenix
4fe729c512 Move Bobook to limited issue ships 2022-05-05 21:43:09 +04:00
DarkPhoenix
a7d52c9fc2 Update icons 2022-05-05 21:15:58 +04:00
DarkPhoenix
207e9018a8 Update effects 2022-05-05 21:12:17 +04:00
DarkPhoenix
a9598d4fc9 Update static data 2022-05-05 19:35:51 +04:00
Ryan Holmes
60015fb3b8 Merge branch 'master' into issue2402 2022-05-03 13:31:29 -04:00
DarkPhoenix
ebd7a1a4ad Fix lock amount effect 2022-04-08 21:45:25 +03:00
DarkPhoenix
63c9d98e3f Bump version 2022-04-05 21:20:52 +03:00
DarkPhoenix
14aafef866 Update effects 2022-04-05 21:20:16 +03:00
DarkPhoenix
55d6bb57d6 Process renames 2022-04-05 18:00:47 +03:00
DarkPhoenix
4bb71dbdb8 Update effects 2022-04-05 17:29:01 +03:00
DarkPhoenix
c9117c2a73 Merge branch 'master' of github.com:pyfa-org/Pyfa 2022-04-05 17:04:17 +03:00
DarkPhoenix
0a193939ed Update static data to 2027534 2022-04-05 17:03:42 +03:00
Anton Vorobyov
a0a27720ef Merge pull request #2426 from nmalaguti/feature/fix-readme-linux-standalone
Update README for self-contained Linux AppImage.
2022-04-03 17:19:08 +03:00
Nick Malaguti
d38417de9e Update README for self-contained Linux AppImage.
Also update OS X to macOS.
2022-04-01 21:50:40 -04:00
DarkPhoenix
2de214d7cd Fix orca shield burst bonus 2022-03-31 23:29:19 +03:00
DarkPhoenix
d9d546ca25 Bump version 2022-03-31 23:11:12 +03:00
DarkPhoenix
2c0e6fa73b Update static data to 2024431 2022-03-31 21:14:39 +03:00
Ryan Holmes
9dc18ac81b Add option in settings to disregard JWT exp issues 2022-03-30 15:17:11 -04:00
DarkPhoenix
86e171f13d Add condenser pack damage profiles 2022-03-30 21:49:25 +03:00
DarkPhoenix
20f222b9bf Split team burner damage patterns into their separate group 2022-03-30 21:28:43 +03:00
Ryan Holmes
01721f9dac Merge pull request #2419 from pyfa-org/issue2410
AppImage
2022-03-30 00:39:19 -04:00
Ryan Holmes
e57b7e5a8f Merge pull request #2422 from nmalaguti/feature/jwt-aud-fix
Skip validation of JWT "aud" claim
2022-03-30 00:38:17 -04:00
Nick Malaguti
4ba037d6e1 Skip validation of JWT "aud" claim
Due to unexpected ESI SSO breakage by adding an "aud" claim, skip
validation of the claim. If in the future CCP specifies which "aud"
claim to verify against, this can be changed to pass the appropriate
"audience" value.

Fixes #2421
2022-03-28 21:36:49 -04:00
Ryan Holmes
f89061a9d8 Merge branch 'master' into issue2410 2022-03-27 09:31:39 -04:00
Ryan Holmes
52b8b4bc6c Merge pull request #2356 from pyfa-org/crowdin_master
New Crowdin updates
2022-03-24 00:07:28 -04:00
Ryan Holmes
51e351d1ba Merge branch 'master' into crowdin_master 2022-03-24 00:07:01 -04:00
blitzmann
518b4abf8c fix crowdin error for PRs 2022-03-23 22:55:22 -04:00
blitzmann
67119fcff1 fix crowdin error for PRs 2022-03-23 22:32:54 -04:00
blitzmann
b1beebda26 Convert makefile to shell commands in appveyor config, various other tweaks 2022-03-23 10:28:04 -04:00
blitzmann
f7ea438ebc Merge tag 'v2.39.2docker' into issue2410 2022-03-23 10:27:12 -04:00
DarkPhoenix
ee6b57ecc1 Rename burner damage profiles and fix sentinel profile 2022-03-19 12:59:53 +03:00
Tomas S
e17fe434ee Update with GTK3 Info 2022-03-17 12:02:19 +01:00
wereii
7cad0b2658 AppImage build 2022-03-16 20:39:55 +01:00
DarkPhoenix
9e06106a1c Save & restore RAH-specific damage pattern through do-undo actions 2022-03-12 13:49:18 +03:00
DarkPhoenix
ae115b640a Allow RAH-specific pattern control 2022-03-12 02:19:03 +03:00
DarkPhoenix
0c292e8d6e Add more burner profiles 2022-03-09 19:20:00 +03:00
DarkPhoenix
68fad93282 Bump version 2022-03-09 00:38:19 +03:00
DarkPhoenix
9067c0b8b3 Update effects 2022-03-09 00:37:01 +03:00
DarkPhoenix
3d4849799b Update static data to 2013787 2022-03-09 00:33:10 +03:00
DarkPhoenix
fc848cd2d0 More mobility data for burners 2022-03-09 00:19:49 +03:00
DarkPhoenix
72b18f7935 Add mobility data to burners 2022-03-05 17:19:00 +03:00
DarkPhoenix
014d389dc8 Update static data to 2010918 2022-03-01 13:11:41 +03:00
DarkPhoenix
bded2d505f Update staticdata to 2008716 2022-02-23 22:24:27 +03:00
Anton Vorobyov
bb38ba6564 New translations lang.pot (Spanish) 2022-01-10 15:44:16 +03:00
Anton Vorobyov
3f6aa91966 New translations lang.pot (Spanish) 2022-01-09 15:36:47 +03:00
Anton Vorobyov
e86e5933b5 New translations lang.pot (French) 2022-01-04 01:03:43 +03:00
Anton Vorobyov
000c1bc38f New translations lang.pot (French) 2022-01-03 01:04:57 +03:00
Anton Vorobyov
8b1553df03 New translations lang.pot (Korean) 2021-11-04 02:22:53 +03:00
Ryan Holmes
2731e9962b Implement pyfa callback 2021-10-19 00:13:21 -04:00
Anton Vorobyov
89d0ee4c77 New translations lang.pot (Korean) 2021-10-18 14:10:48 +03:00
Ryan Holmes
76536a5dcc Create callback.html 2021-10-16 12:56:11 -04:00
Ryan Holmes
41d6828024 Create index.md 2021-10-16 12:53:08 -04:00
Ryan Holmes
bf4b4ab3c0 Set theme jekyll-theme-midnight 2021-10-16 12:49:45 -04:00
Anton Vorobyov
d7d4643a33 New translations lang.pot (Korean) 2021-10-08 13:37:45 +03:00
Anton Vorobyov
166635d0a1 New translations lang.pot (Korean) 2021-10-07 13:17:56 +03:00
Anton Vorobyov
076e1999af New translations lang.pot (Korean) 2021-10-01 14:20:45 +03:00
Anton Vorobyov
69caff50c3 New translations lang.pot (Korean) 2021-09-30 13:56:01 +03:00
Anton Vorobyov
0db72f7a8c New translations lang.pot (Korean) 2021-09-29 13:59:34 +03:00
Anton Vorobyov
43ac76ac1f New translations lang.pot (Korean) 2021-09-28 04:36:38 +03:00
Anton Vorobyov
279c912703 New translations lang.pot (Korean) 2021-09-27 04:33:56 +03:00
Anton Vorobyov
e54cec47f2 New translations lang.pot (Korean) 2021-09-26 04:38:53 +03:00
Anton Vorobyov
50293081d1 New translations lang.pot (Russian) 2021-09-11 17:48:52 +03:00
Anton Vorobyov
4f526d7cc4 New translations lang.pot (Russian) 2021-09-10 17:52:14 +03:00
304 changed files with 517964 additions and 135155 deletions

View File

@@ -1,9 +1,88 @@
image:
- Visual Studio 2019
- Ubuntu
- macos
clone_depth: 400
clone_depth: 1
for:
-
matrix:
only:
- image: Ubuntu
environment:
APPVEYOR_SSH_KEY: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDJDW/+oYNGOiPvwuwAL9tc/LQgg58aosIVpMYfepQZ20V+VZnHpZh8IRDA8Jo5xht19p2PksA+hFgqA0kpKtrSkuiWdE8rATQItfk4gf7yB0yGasJGGQZYazy9k/9XtmYkq2HHOOeEqdxvrICddJQ88MLCLT9lJENSUP/YS/yGcjZFXVxE11pTeIcqlCRU+3eYa1v7BeNvXIKNhZoK5orXWrtuH3cy8jrSns/u70aYfJ6B2jA8CnWnDbuvpeQtEY61SQqlKUsSArNa8NAsXj41wr3Ar9gAG9330w7EMTqlutk8HZO35uHI0q5qinUhaQYufPPrVkb2L/N+ZCfu0fnh appveyor"
APPIMAGE_TOOL: appimagetool-x86_64.AppImage
PYTHON_APPIMAGE: python3.7.17-cp37-cp37m-manylinux2014_x86_64.AppImage
DEPLOY_DIR: AppDir/opt/pyfa
# APPVEYOR_SSH_BLOCK: true
cache:
- /home/appveyor/.cache/pip -> requirements.txt
init:
- sh: curl -sflL 'https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-ssh.sh' | bash -e -
install:
- sh: git fetch --prune --unshallow # to fix the version dump issues
- sh: sudo DEBIAN_FRONTEND=noninteractive sed -i '/postgres/d' /etc/apt/sources.list # As of 2023-11-14, postgres repo fail to update, but we don't need them anyway
- sh: sudo DEBIAN_FRONTEND=noninteractive apt-get -y update
- sh: sudo DEBIAN_FRONTEND=noninteractive apt-get -y install python3.7-dev libgtk-3-dev python3-pip libwebkit2gtk-4.0-dev
before_build:
- sh: mkdir build && cd build
- sh: curl -LO https://github.com/AppImage/AppImageKit/releases/download/13/$APPIMAGE_TOOL && chmod +x $APPIMAGE_TOOL
- sh: curl -LO https://github.com/niess/python-appimage/releases/download/python3.7/$PYTHON_APPIMAGE && chmod +x $PYTHON_APPIMAGE
build_script:
# Prepare Python base AppImage, stripping Python metadata
- sh: ./$PYTHON_APPIMAGE --appimage-extract
- sh: mv squashfs-root AppDir
- sh: rm AppDir/python*.desktop
- sh: rm AppDir/usr/share/applications/*.desktop
- sh: rm AppDir/usr/share/metainfo/*.appdata.xml
- sh: unlink AppDir/AppRun
- sh: mkdir -p $DEPLOY_DIR
# run install pyfa packages and any other requirements
- sh: AppDir/usr/bin/python -s -m pip install -U pip setuptools==41.6.0 wheel pathlib2
- sh: AppDir/usr/bin/python -s -m pip install -r ../requirements.txt
# Speedup, but causes runtime incompatiblities
#- sh: AppDir/usr/bin/python -s -m pip install -f https://extras.wxpython.org/wxPython4/extras/linux/gtk3/ubuntu-18.04 -r ../requirements.txt
# Run scripts to prep pyfa data and build database
- sh: cd ../
- sh: find locale/ -type f -name "*.po" -exec msgen "{}" -o "{}" \;
- sh: build/AppDir/usr/bin/python scripts/compile_lang.py
- sh: build/AppDir/usr/bin/python scripts/dump_crowdin_progress.py
- sh: build/AppDir/usr/bin/python db_update.py
- sh: export PYFA_VERSION="$(python3.7 scripts/dump_version.py)"
# Copy pyfa files to host
- sh: cp -r eos graphs gui imgs locale service utils eve.db config.py pyfa.py db_update.py README.md LICENSE version.yml ./build/$DEPLOY_DIR
- sh: find ./build/$DEPLOY_DIR | grep -E "(__pycache__|\.pyc|\.pyo$)" | xargs rm -rf
# Copy static AppImage files
- sh: cd dist_assets/linux
- sh: chmod +x AppRun
- sh: cp AppRun pyfa.desktop ../../build/AppDir/
- sh: cp pyfa.desktop ../../build/AppDir/usr/share/applications/
- sh: cp pyfa.appdata.xml ../../build/AppDir/usr/share/metainfo/
- sh: chmod +x pyfa && cp pyfa ../../build/AppDir/usr/bin
- sh: cd ../../
# Package it all up
- sh: mkdir dist
- sh: ./build/$APPIMAGE_TOOL build/AppDir dist/pyfa-$PYFA_VERSION-linux.AppImage
after_build:
- sh: ls -la build
artifacts:
- path: dist/pyfa-$PYFA_VERSION-linux.AppImage
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:
@@ -13,7 +92,11 @@ for:
# Should be enabled only for build process debugging
# init:
# - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
cache:
- C:\users\appveyor\appdata\local\pip\cache\ -> requirements.txt
install:
- cmd: git fetch --prune --unshallow # to fix the version dump issues
- ps: echo("OS version:")
- ps: "[System.Environment]::OSVersion.Version"
@@ -96,11 +179,15 @@ for:
matrix:
only:
- image: macos
# Should be enabled only for build process debugging
environment:
APPVEYOR_SSH_KEY: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDJDW/+oYNGOiPvwuwAL9tc/LQgg58aosIVpMYfepQZ20V+VZnHpZh8IRDA8Jo5xht19p2PksA+hFgqA0kpKtrSkuiWdE8rATQItfk4gf7yB0yGasJGGQZYazy9k/9XtmYkq2HHOOeEqdxvrICddJQ88MLCLT9lJENSUP/YS/yGcjZFXVxE11pTeIcqlCRU+3eYa1v7BeNvXIKNhZoK5orXWrtuH3cy8jrSns/u70aYfJ6B2jA8CnWnDbuvpeQtEY61SQqlKUsSArNa8NAsXj41wr3Ar9gAG9330w7EMTqlutk8HZO35uHI0q5qinUhaQYufPPrVkb2L/N+ZCfu0fnh appveyor"
cache:
- /Users/appveyor/Library/Caches/pip/ -> requirements.txt
init:
# - sh: curl -sflL 'https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-ssh.sh' | bash -e -
- sh: source ~/venv3.7/bin/activate
install:
- sh: git fetch --prune --unshallow # to fix the version dump issues
- sh: bash scripts/osx-setup.sh
build_script:
- sh: bash scripts/osx-translations.sh
@@ -110,6 +197,9 @@ for:
after_build:
- sh: export PYFA_VERSION="$(python3 scripts/dump_version.py)"
- sh: bash scripts/osx-package.sh
# on_finish:
# - sh: export APPVEYOR_SSH_BLOCK=true
# - sh: curl -sflL 'https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-ssh.sh' | bash -e -
artifacts:
- path: dist/pyfa*-mac.zip
before_deploy:

4
.gitignore vendored
View File

@@ -90,6 +90,7 @@ target/
# pyenv
.python-version
PyfaEnv/
# celery beat schedule file
celerybeat-schedule
@@ -123,3 +124,6 @@ gitversion
*.fsdbinary
/locale/progress.json
# vscode settings
.vscode

View File

@@ -1,27 +1,30 @@
# pyfa
[![Join us on Slack!](https://pyfainvite.azurewebsites.net/badge.svg)](https://pyfainvite.azurewebsites.net/) [![Build Status](https://travis-ci.org/pyfa-org/Pyfa.svg?branch=master)](https://travis-ci.org/pyfa-org/Pyfa)
[![Build Status](https://ci.appveyor.com/api/projects/status/github/pyfa-org/pyfa?branch=master&svg=true)]([https://travis-ci.org/pyfa-org/Pyfa](https://ci.appveyor.com/project/pyfa-org/pyfa))
![pyfa](https://user-images.githubusercontent.com/275209/66119992-864be080-e5e2-11e9-994a-3a4368c9fad7.png)
## What is it?
Pyfa, short for **py**thon **f**itting **a**ssistant, allows you to create, experiment with, and save ship fittings without being in game. Open source and written in Python, it is available on any platform where Python 3 and wxWidgets are available, including Windows, Mac OS X, and Linux.
Pyfa, short for **py**thon **f**itting **a**ssistant, allows you to create, experiment with, and save ship fittings without being in game. Open source and written in Python, it is available on any platform where Python 3 and wxWidgets are available, including Windows, macOS, and Linux.
## Latest Version and Changelogs
The latest version along with release notes can always be found on the project's [releases](https://github.com/pyfa-org/Pyfa/releases) page. Pyfa will notify you if you are running an outdated version.
## Installation
Windows and OS X users are supplied self-contained builds of pyfa on the [latest releases](https://github.com/pyfa-org/Pyfa/releases/latest) page. An `.exe` installer is also available for Windows builds. Linux users can run pyfa using their distribution's Python interpreter. There is no official self-contained package for Linux, however, there are a number of third-party packages available through distribution-specific repositories.
Windows, macOS, and Linux users are supplied self-contained builds of pyfa on the [latest releases](https://github.com/pyfa-org/Pyfa/releases/latest) page.
### OS X
Apart from the official release, there is also a [Homebrew](http://brew.sh) option for installing pyfa on OS X. Please note this is maintained by a third-party and is not tested by pyfa developers. Simply fire up in terminal:
### Third Party Packages
Please note that these packages are maintained by third-parties and are not evaluated by the pyfa developers.
#### macOS
Apart from the official release, there is also a [Homebrew](https://formulae.brew.sh/cask/pyfa) option for installing pyfa on macOS. Simply fire up in terminal:
```
$ brew install Caskroom/cask/pyfa
$ brew install --cask pyfa
```
### Linux Distro-specific Packages
The following is a list of pyfa packages available for certain distributions. Please note that these packages are maintained by third-parties and are not evaluated by the pyfa developers.
#### Linux Distro-specific Packages
The following is a list of pyfa packages available for certain distributions.
* Arch: https://aur.archlinux.org/packages/pyfa/
* Gentoo: https://github.com/ZeroPointEnergy/gentoo-pyfa-overlay

View File

@@ -28,6 +28,7 @@ saveInRoot = False
evemonMinVersion = "4081"
minItemSearchLength = 3
minItemSearchLengthCjk = 1
pyfaPath = None
savePath = None

View File

@@ -117,8 +117,7 @@ def update_db():
for k, v in compiled_data.items():
row = {}
row.update(v)
if keyIdName not in row:
row[keyIdName] = int(k)
row[keyIdName] = int(k)
data.append(row)
return data
@@ -139,16 +138,18 @@ def update_db():
for row in data:
if (
# Apparently people really want Civilian modules available
(row['typeName_en-us'].startswith('Civilian') and "Shuttle" not in row['typeName_en-us']) or
row['typeName_en-us'] == 'Capsule' or
row['groupID'] == 4033 # destructible effect beacons
(row['typeName_en-us'].startswith('Civilian') and "Shuttle" not in row['typeName_en-us'])
or row['typeName_en-us'] == 'Capsule'
or row['groupID'] == 4033 # destructible effect beacons
or re.match('AIR .+Booster.*', row['typeName_en-us'])
):
row['published'] = True
# Nearly useless and clutter search results too much
elif (
row['typeName_en-us'].startswith('Limited Synth ') or
row['typeName_en-us'].startswith('Expired ') or
row['typeName_en-us'].endswith(' Filament') and (
row['typeName_en-us'].startswith('Limited Synth ')
or row['typeName_en-us'].startswith('Expired ')
or re.match('Mining Blitz .+ Booster Dose .+', row['typeName_en-us'])
or row['typeName_en-us'].endswith(' Filament') and (
"'Needlejack'" not in row['typeName_en-us'] and
"'Devana'" not in row['typeName_en-us'] and
"'Pochven'" not in row['typeName_en-us'] and
@@ -616,6 +617,16 @@ def update_db():
eos.db.gamedata_session.delete(cat)
# Unused normally, can be useful for customizing items
def _copyItem(srcName, tgtTypeID, tgtName):
eveType = eos.db.gamedata_session.query(eos.gamedata.Item).filter(eos.gamedata.Item.name == srcName).one()
eos.db.gamedata_session.expunge(eveType)
sqlalchemy.orm.make_transient(eveType)
eveType.ID = tgtTypeID
for suffix in eos.config.translation_mapping.values():
setattr(eveType, f'typeName{suffix}', tgtName)
eos.db.gamedata_session.add(eveType)
eos.db.gamedata_session.flush()
def _hardcodeAttribs(typeID, attrMap):
for attrName, value in attrMap.items():
try:
@@ -624,7 +635,7 @@ def update_db():
except sqlalchemy.orm.exc.NoResultFound:
attrInfo = eos.db.gamedata_session.query(eos.gamedata.AttributeInfo).filter(eos.gamedata.AttributeInfo.name == attrName).one()
attr = eos.gamedata.Attribute()
attr.ID = attrInfo.ID
attr.attributeID = attrInfo.ID
attr.typeID = typeID
attr.value = value
eos.db.gamedata_session.add(attr)
@@ -640,6 +651,152 @@ def update_db():
effect.effectName = effectName
item.effects[effectName] = effect
def hardcodeShapash():
shapashTypeID = 1000000
_copyItem(srcName='Utu', tgtTypeID=shapashTypeID, tgtName='Shapash')
attrMap = {
# Fitting
'powerOutput': 50,
'cpuOutput': 225,
'capacitorCapacity': 420,
'rechargeRate': 187500,
# Slots
'hiSlots': 3,
'medSlots': 4,
'lowSlots': 4,
'launcherSlotsLeft': 0,
'turretSlotsLeft': 3,
# Rigs
'rigSlots': 2,
'rigSize': 1,
'upgradeCapacity': 400,
# Shield
'shieldCapacity': 575,
'shieldRechargeRate': 625000,
'shieldEmDamageResonance': 1 - 0.0,
'shieldThermalDamageResonance': 1 - 0.6,
'shieldKineticDamageResonance': 1 - 0.85,
'shieldExplosiveDamageResonance': 1 - 0.5,
# Armor
'armorHP': 1015,
'armorEmDamageResonance': 1 - 0.5,
'armorThermalDamageResonance': 1 - 0.675,
'armorKineticDamageResonance': 1 - 0.8375,
'armorExplosiveDamageResonance': 1 - 0.1,
# Structure
'hp': 1274,
'emDamageResonance': 1 - 0.33,
'thermalDamageResonance': 1 - 0.33,
'kineticDamageResonance': 1 - 0.33,
'explosiveDamageResonance': 1 - 0.33,
'mass': 1215000,
'volume': 29500,
'capacity': 165,
# Navigation
'maxVelocity': 325,
'agility': 3.467,
'warpSpeedMultiplier': 5.5,
# Drones
'droneCapacity': 75,
'droneBandwidth': 25,
# Targeting
'maxTargetRange': 49000,
'maxLockedTargets': 6,
'scanRadarStrength': 0,
'scanLadarStrength': 0,
'scanMagnetometricStrength': 9,
'scanGravimetricStrength': 0,
'signatureRadius': 39,
'scanResolution': 550,
# Misc
'energyWarfareResistance': 0,
'stasisWebifierResistance': 0,
'weaponDisruptionResistance': 0}
effectMap = {
100100: 'pyfaCustomShapashAfArAmount',
100101: 'pyfaCustomShapashAfShtTrackingOptimal',
100102: 'pyfaCustomShapashGfShtDamage',
100103: 'pyfaCustomShapashGfPointRange',
100104: 'pyfaCustomShapashGfPropOverheat',
100105: 'pyfaCustomShapashRolePlateMass',
100106: 'pyfaCustomShapashRoleHeat'}
_hardcodeAttribs(shapashTypeID, attrMap)
_hardcodeEffects(shapashTypeID, effectMap)
def hardcodeCybele():
cybeleTypeID = 1000001
_copyItem(srcName='Adrestia', tgtTypeID=cybeleTypeID, tgtName='Cybele')
attrMap = {
# Fitting
'powerOutput': 1284,
'cpuOutput': 400,
'capacitorCapacity': 2400,
'rechargeRate': 334000,
'hiSlots': 5,
'medSlots': 4,
'lowSlots': 6,
'launcherSlotsLeft': 0,
'turretSlotsLeft': 5,
# Rigs
'rigSlots': 2,
'rigSize': 2,
'upgradeCapacity': 400,
# Shield
'shieldCapacity': 1200,
'shieldRechargeRate': 1250000,
'shieldEmDamageResonance': 1 - 0.0,
'shieldThermalDamageResonance': 1 - 0.5,
'shieldKineticDamageResonance': 1 - 0.9,
'shieldExplosiveDamageResonance': 1 - 0.5,
# Armor
'armorHP': 1900,
'armorEmDamageResonance': 1 - 0.5,
'armorThermalDamageResonance': 1 - 0.69,
'armorKineticDamageResonance': 1 - 0.85,
'armorExplosiveDamageResonance': 1 - 0.1,
# Structure
'hp': 2300,
'emDamageResonance': 1 - 0.33,
'thermalDamageResonance': 1 - 0.33,
'kineticDamageResonance': 1 - 0.33,
'explosiveDamageResonance': 1 - 0.33,
'mass': 11100000,
'volume': 112000,
'capacity': 450,
# Navigation
'maxVelocity': 235,
'agility': 0.457,
'warpSpeedMultiplier': 4.5,
# Drones
'droneCapacity': 100,
'droneBandwidth': 50,
# Targeting
'maxTargetRange': 60000,
'maxLockedTargets': 6,
'scanRadarStrength': 0,
'scanLadarStrength': 0,
'scanMagnetometricStrength': 15,
'scanGravimetricStrength': 0,
'signatureRadius': 115,
'scanResolution': 330,
# Misc
'energyWarfareResistance': 0,
'stasisWebifierResistance': 0,
'weaponDisruptionResistance': 0}
effectMap = {
100200: 'pyfaCustomCybeleHacMhtFalloff',
100201: 'pyfaCustomCybeleHacMhtTracking',
100202: 'pyfaCustomCybeleGcMhtDamage',
100203: 'pyfaCustomCybeleGcArAmount',
100204: 'pyfaCustomCybeleGcPointRange',
100205: 'pyfaCustomCybeleRoleVelocity',
100206: 'pyfaCustomCybeleRolePlateMass'}
_hardcodeAttribs(cybeleTypeID, attrMap)
_hardcodeEffects(cybeleTypeID, effectMap)
hardcodeShapash()
hardcodeCybele()
eos.db.gamedata_session.commit()
eos.db.gamedata_engine.execute('VACUUM')

19
dist_assets/linux/AppRun Executable file
View File

@@ -0,0 +1,19 @@
#! /bin/bash -i
# Export APPRUN if running from an extracted image
self="$(readlink -f -- $0)"
here="${self%/*}"
APPDIR="${APPDIR:-${here}}"
# Export TCl/Tk
export TCL_LIBRARY="${APPDIR}/usr/share/tcltk/tcl8.4"
export TK_LIBRARY="${APPDIR}/usr/share/tcltk/tk8.4"
export TKPATH="${TK_LIBRARY}"
# Export SSL certificate
export SSL_CERT_FILE="${APPDIR}/opt/_internal/certs.pem"
# Call the entry point
#! /bin/bash -i
${APPDIR}/usr/bin/pyfa "$@"

3
dist_assets/linux/pyfa Normal file
View File

@@ -0,0 +1,3 @@
#! /bin/bash
${APPDIR}/usr/bin/python3.7 -s "${APPDIR}/opt/pyfa/pyfa.py" "$@"

View File

@@ -1,70 +0,0 @@
# -*- mode: python -*-
import os
from itertools import chain
import subprocess
label = subprocess.check_output([
"git", "describe", "--tags"]).strip()
with open('gitversion', 'w+') as f:
f.write(label.decode())
block_cipher = None
added_files = [
( 'imgs/gui/*.png', 'imgs/gui' ),
( 'imgs/gui/*.gif', 'imgs/gui' ),
( 'imgs/icons/*.png', 'imgs/icons' ),
( 'imgs/renders/*.png', 'imgs/renders' ),
( 'dist_assets/win/pyfa.ico', '.' ),
( 'dist_assets/cacert.pem', '.' ),
( 'eve.db', '.' ),
( 'README.md', '.' ),
( 'LICENSE', '.' ),
( 'gitversion', '.' ),
]
import_these = []
# Walk directories that do dynamic importing
paths = ('eos/effects', 'eos/db/migrations', 'service/conversions')
for root, folders, files in chain.from_iterable(os.walk(path) for path in paths):
for file_ in files:
if file_.endswith(".py") and not file_.startswith("_"):
mod_name = "{}.{}".format(
root.replace("/", "."),
file_.split(".py")[0],
)
import_these.append(mod_name)
a = Analysis(['pyfa.py'],
pathex=[],
binaries=[],
datas=added_files,
hiddenimports=import_these,
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
exclude_binaries=True,
name='pyfa',
debug=False,
strip=False,
upx=True,
console=True )
coll = COLLECT(exe,
a.binaries,
a.zipfiles,
a.datas,
strip=False,
upx=True,
name='pyfa')

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop-application">
<id>org.pyfa.pyfa</id>
<metadata_license>MIT</metadata_license>
<project_license>GPL-3</project_license>
<name>Pyfa</name>
<summary>Pyfa </summary>
<description>
<p> Python Fitting Assitant for EVE Online
</p>
</description>
<launchable type="desktop-id">pyfa.desktop</launchable>
<url type="homepage">https://github.com/pyfa-org/Pyfa</url>
<provides>
<binary>pyfa</binary>
</provides>
</component>

View File

@@ -0,0 +1,7 @@
[Desktop Entry]
Type=Application
Name=Pyfa
Exec=pyfa
Comment=Python Fitting Assistant for EVE: Online
Icon=python
Categories=Game;

1
docs/_config.yml Normal file
View File

@@ -0,0 +1 @@
theme: jekyll-theme-midnight

104
docs/callback.html Normal file
View File

@@ -0,0 +1,104 @@
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>pyfa Authentication Proxy</title>
<style type="text/css">
body { width: 700px; margin: 150px auto; }
h1 { font-size: 40px; }
h2 { font-size: 32px; }
body { font: 20px Helvetica, sans-serif; color: #333; }
#article { display: block; text-align: left; width: 650px; margin: 0 auto; }
.hidden { display:none; }
.success { color: #28a745; }
.error { color: #dc3545; }
textarea { width: 100%; height: 100px; }
hr { border-width: 1px 0 0 0; border-style: solid; border-color: #333; }
button { cursor: pointer; background-color: white; border: 1px solid #333; color: #333; padding: 8px 11px; text-align: center; text-decoration: none; display: inline-block; }
@media (prefers-color-scheme: dark) {
body { background-color: #333; color: white; }
textarea { width: 100%; height: 100px; background-color: #aaa;}
button { background-color: #333; border: 1px solid white; color: white; }
hr { border-color: white; }
}
</style>
</head>
<body>
<!-- Layout from Short Circuit's CREST login. Shout out! https://github.com/farshield/shortcircuit -->
<h1>pyfa</h1>
<div id="mode0" class="hidden">
<p id="mode0-msg">Processing request...</p>
<button id="showBtn" onClick="showCode()">Show Code</button>
</div>
<div id="mode1" class="hidden">
<p id="mode1-p">Please copy and paste the token below into pyfa.</p>
<textarea id="authCodeText" readonly></textarea>
</div>
</div>
<script>
debugger;
function showCode() {
var element = document.getElementById(`mode1`);
element.classList.remove("hidden");
element = document.getElementById(`showBtn`);
element.classList.add("hidden");
}
function httpPostAsync(url, callback)
{
var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == XMLHttpRequest.DONE)
callback(xmlHttp);
}
xmlHttp.open("GET", url, true); // true for asynchronous
xmlHttp.send(null);
}
const urlSearchParams = new URLSearchParams(window.location.search);
const params = Object.fromEntries(urlSearchParams.entries());
let stateInfo;
try {
stateInfo = JSON.parse(atob(params.state))
} catch (err) {
// something has happened and we cannot continue.
// todo: show a simple message and exit.
throw err;
}
// we always want to show the text box for manual.
var element = document.getElementById(`mode${stateInfo.mode}`);
element.classList.remove("hidden");
if (stateInfo.mode === 0) {
let p = document.getElementById(`mode1-p`);
p.prepend(document.createElement("hr"))
}
debugger;
document.getElementById(`authCodeText`).value = btoa(JSON.stringify(params))
if (stateInfo.mode == 0) { // auto / server mode
httpPostAsync(stateInfo.redirect + window.location.search, (req)=>{
debugger;
const msgDiv = document.getElementById(`mode0-msg`);
if (req.status === 200) {
msgDiv.innerHTML ="<span class='success'>Success!</span> You may close this window and return to the application.";
return;
} else if (req.status === 0){
msgDiv.innerHTML = "<span class='error'>Error!</span> Server response not received.<p><small>The local pyfa server may have timed out, or may not have started correctly.</small></p>";
} else if (req.status === 400){
msgDiv.innerHTML = `<span class='error'>Error!</span> <p><small>${req.responseText}</small></p>`
} else {
msgDiv.innerHTML = `<span class='error'>Error!</span> <p><small>There was an unknown error. Please report this to the pyfa issues page.</p><p><textarea readdonly>${req.responseText}</textarea></small></p>`
}
showCode()
// todo: bad request error when it's not an error itself, but rather
})
// todo: post message to local EVE server
}
</script>
</body>
</html>

37
docs/index.md Normal file
View File

@@ -0,0 +1,37 @@
## Welcome to GitHub Pages
You can use the [editor on GitHub](https://github.com/pyfa-org/Pyfa/edit/gh-pages/index.md) to maintain and preview the content for your website in Markdown files.
Whenever you commit to this repository, GitHub Pages will run [Jekyll](https://jekyllrb.com/) to rebuild the pages in your site, from the content in your Markdown files.
### Markdown
Markdown is a lightweight and easy-to-use syntax for styling your writing. It includes conventions for
```markdown
Syntax highlighted code block
# Header 1
## Header 2
### Header 3
- Bulleted
- List
1. Numbered
2. List
**Bold** and _Italic_ and `Code` text
[Link](url) and ![Image](src)
```
For more details see [GitHub Flavored Markdown](https://guides.github.com/features/mastering-markdown/).
### Jekyll Themes
Your Pages site will use the layout and styles from the Jekyll theme you have selected in your [repository settings](https://github.com/pyfa-org/Pyfa/settings/pages). The name of this theme is saved in the Jekyll `_config.yml` configuration file.
### Support or Contact
Having trouble with Pages? Check out our [documentation](https://docs.github.com/categories/github-pages-basics/) or [contact support](https://support.github.com/contact) and well help you sort it out.

File diff suppressed because it is too large Load Diff

View File

@@ -59,106 +59,115 @@ BUILTINS = OrderedDict([
(-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)),
# Different sizes of packs do different damage ratios, the values here
# are average of ratios across sizes
(-23, (_c(_t('Condenser Packs')) + '|' + _t('[T2] StrikeSnipe'), 51817, 0, 48183, 0)),
(-24, (_c(_t('Condenser Packs')) + _t('MesmerFlux'), 76476, 0, 23524, 0)),
(-25, (_c(_t('Condenser Packs')) + _t('SlamBolt'), 23376, 0, 76624, 0)),
(-26, (_c(_t('Condenser Packs')) + _t('BlastShot'), 19820, 0, 80180, 0)),
(-27, (_c(_t('Condenser Packs')) + _t('GalvaSurge'), 80206, 0, 19794, 0)),
(-28, (_c(_t('Condenser Packs')) + '|' + _t('[T2] ElectroPunch'), 50547, 0, 49453, 0)),
(-29, (_c(_t('Hybrid Charges')) + '|' + _t('[T2] Spike'), 0, 4, 4, 0)),
(-30, (_c(_t('Hybrid Charges')) + '|' + _t('[T2] Null'), 0, 6, 5, 0)),
(-31, (_c(_t('Hybrid Charges')) + _t('Iron'), 0, 2, 3, 0)),
(-32, (_c(_t('Hybrid Charges')) + _t('Tungsten'), 0, 2, 4, 0)),
(-33, (_c(_t('Hybrid Charges')) + _t('Iridium'), 0, 3, 4, 0)),
(-34, (_c(_t('Hybrid Charges')) + _t('Lead'), 0, 3, 5, 0)),
(-35, (_c(_t('Hybrid Charges')) + _t('Thorium'), 0, 4, 5, 0)),
(-36, (_c(_t('Hybrid Charges')) + _t('Uranium'), 0, 4, 6, 0)),
(-37, (_c(_t('Hybrid Charges')) + _t('Plutonium'), 0, 5, 6, 0)),
(-38, (_c(_t('Hybrid Charges')) + _t('Antimatter'), 0, 5, 7, 0)),
(-39, (_c(_t('Hybrid Charges')) + '|' + _t('[T2] Javelin'), 0, 8, 6, 0)),
(-40, (_c(_t('Hybrid Charges')) + '|' + _t('[T2] Void'), 0, 7.7, 7.7, 0)),
(-41, (_c(_t('Projectile Ammo')) + '|' + _t('[T2] Tremor'), 0, 0, 3, 5)),
(-42, (_c(_t('Projectile Ammo')) + '|' + _t('[T2] Barrage'), 0, 0, 5, 6)),
(-43, (_c(_t('Projectile Ammo')) + _t('Carbonized Lead'), 0, 0, 4, 1)),
(-44, (_c(_t('Projectile Ammo')) + _t('Nuclear'), 0, 0, 1, 4)),
(-45, (_c(_t('Projectile Ammo')) + _t('Proton'), 3, 0, 2, 0)),
(-46, (_c(_t('Projectile Ammo')) + _t('Depleted Uranium'), 0, 3, 2, 3)),
(-47, (_c(_t('Projectile Ammo')) + _t('Titanium Sabot'), 0, 0, 6, 2)),
(-48, (_c(_t('Projectile Ammo')) + _t('EMP'), 9, 0, 1, 2)),
(-49, (_c(_t('Projectile Ammo')) + _t('Phased Plasma'), 0, 10, 2, 0)),
(-50, (_c(_t('Projectile Ammo')) + _t('Fusion'), 0, 0, 2, 10)),
(-51, (_c(_t('Projectile Ammo')) + '|' + _t('[T2] Quake'), 0, 0, 5, 9)),
(-52, (_c(_t('Projectile Ammo')) + '|' + _t('[T2] Hail'), 0, 0, 3.3, 12.1)),
(-53, (_c(_t('Missiles')) + _t('Mjolnir'), 1, 0, 0, 0)),
(-54, (_c(_t('Missiles')) + _t('Inferno'), 0, 1, 0, 0)),
(-55, (_c(_t('Missiles')) + _t('Scourge'), 0, 0, 1, 0)),
(-56, (_c(_t('Missiles')) + _t('Nova'), 0, 0, 0, 1)),
(-57, (_c(_t('Bombs')) + _t('Electron Bomb'), 6400, 0, 0, 0)),
(-58, (_c(_t('Bombs')) + _t('Scorch Bomb'), 0, 6400, 0, 0)),
(-59, (_c(_t('Bombs')) + _t('Concussion Bomb'), 0, 0, 6400, 0)),
(-60, (_c(_t('Bombs')) + _t('Shrapnel Bomb'), 0, 0, 0, 6400)),
# Source: ticket #2067 and #2265
(-55, (_c(_t('NPC')) + _c(_t('Abyssal')) + _t('All'), 126, 427, 218, 230)),
(-109, (_c(_t('NPC')) + _c(_t('Abyssal')) + _t('Angel'), 450, 72, 80, 398)),
(-107, (_c(_t('NPC')) + _c(_t('Abyssal')) + _t('Concord'), 53, 559, 94, 295)),
(-56, (_c(_t('NPC')) + _c(_t('Abyssal')) + _t('Drifter'), 250, 250, 250, 250)),
(-57, (_c(_t('NPC')) + _c(_t('Abyssal')) + _t('Drones'), 250, 250, 250, 250)),
(-58, (_c(_t('NPC')) + _c(_t('Abyssal')) + _t('Overmind'), 0, 410, 590, 0)),
(-108, (_c(_t('NPC')) + _c(_t('Abyssal')) + _t('Sansha'), 569, 431, 0, 0)),
(-59, (_c(_t('NPC')) + _c(_t('Abyssal')) + _t('Seeker'), 402, 402, 98, 98)),
(-60, (_c(_t('NPC')) + _c(_t('Abyssal')) + _t('Sleeper'), 313, 313, 187, 187)),
(-61, (_c(_t('NPC')) + _c(_t('Abyssal')) + _t('Triglavian'), 0, 615, 0, 385)),
(-62, (_c(_t('NPC')) + _c(_t('Asteroid')) + _t('Angel Cartel'), 1838, 562, 2215, 3838)),
(-63, (_c(_t('NPC')) + _c(_t('Asteroid')) + _t('Blood Raiders'), 5067, 4214, 0, 0)),
(-64, (_c(_t('NPC')) + _c(_t('Asteroid')) + _t('Guristas'), 0, 1828, 7413, 0)),
(-65, (_c(_t('NPC')) + _c(_t('Asteroid')) + _t('Rogue Drone'), 394, 666, 1090, 1687)),
(-66, (_c(_t('NPC')) + _c(_t('Asteroid')) + _t('Sanshas Nation'), 5586, 4112, 0, 0)),
(-67, (_c(_t('NPC')) + _c(_t('Asteroid')) + _t('Serpentis'), 0, 5373, 4813, 0)),
(-68, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Cruor (Blood Raiders)'), 90, 90, 0, 0)),
(-69, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Dramiel (Angel)'), 55, 0, 20, 96)),
(-70, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Daredevil (Serpentis)'), 0, 110, 154, 0)),
(-71, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Succubus (Sanshas Nation)'), 135, 30, 0, 0)),
(-72, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Worm (Guristas)'), 0, 0, 228, 0)),
(-73, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Enyo'), 0, 147, 147, 0)),
(-74, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Hawk'), 0, 0, 247, 0)),
(-75, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Jaguar'), 36, 0, 50, 182)),
(-76, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Vengeance'), 232, 0, 0, 0)),
(-77, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Ashimmu (Blood Raiders)'), 260, 100, 0, 0)),
(-78, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Talos'), 0, 413, 413, 0)),
(-79, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Sentinel'), 0, 75, 0, 90)),
(-80, (_c(_t('NPC')) + _c(_t('Deadspace')) + _t('Angel Cartel'), 369, 533, 1395, 3302)),
(-81, (_c(_t('NPC')) + _c(_t('Deadspace')) + _t('Blood Raiders'), 6040, 5052, 10, 15)),
(-82, (_c(_t('NPC')) + _c(_t('Deadspace')) + _t('Guristas'), 0, 1531, 9680, 0)),
(-83, (_c(_t('NPC')) + _c(_t('Deadspace')) + _t('Rogue Drone'), 276, 1071, 1069, 871)),
(-84, (_c(_t('NPC')) + _c(_t('Deadspace')) + _t('Sanshas Nation'), 3009, 2237, 0, 0)),
(-85, (_c(_t('NPC')) + _c(_t('Deadspace')) + _t('Serpentis'), 0, 3110, 1929, 0)),
(-61, (_c(_t('NPC')) + _c(_t('Abyssal')) + _t('All'), 126, 427, 218, 230)),
(-62, (_c(_t('NPC')) + _c(_t('Abyssal')) + _t('Angel'), 450, 72, 80, 398)),
(-63, (_c(_t('NPC')) + _c(_t('Abyssal')) + _t('Concord'), 53, 559, 94, 295)),
(-64, (_c(_t('NPC')) + _c(_t('Abyssal')) + _t('Drifter'), 250, 250, 250, 250)),
(-65, (_c(_t('NPC')) + _c(_t('Abyssal')) + _t('Drones'), 250, 250, 250, 250)),
(-66, (_c(_t('NPC')) + _c(_t('Abyssal')) + _t('Overmind'), 0, 410, 590, 0)),
(-67, (_c(_t('NPC')) + _c(_t('Abyssal')) + _t('Sansha'), 569, 431, 0, 0)),
(-68, (_c(_t('NPC')) + _c(_t('Abyssal')) + _t('Seeker'), 402, 402, 98, 98)),
(-69, (_c(_t('NPC')) + _c(_t('Abyssal')) + _t('Sleeper'), 313, 313, 187, 187)),
(-70, (_c(_t('NPC')) + _c(_t('Abyssal')) + _t('Triglavian'), 0, 615, 0, 385)),
(-71, (_c(_t('NPC')) + _c(_t('Asteroid')) + _t('Angel Cartel'), 1838, 562, 2215, 3838)),
(-72, (_c(_t('NPC')) + _c(_t('Asteroid')) + _t('Blood Raiders'), 5067, 4214, 0, 0)),
(-73, (_c(_t('NPC')) + _c(_t('Asteroid')) + _t('Guristas'), 0, 1828, 7413, 0)),
(-74, (_c(_t('NPC')) + _c(_t('Asteroid')) + _t('Rogue Drone'), 394, 666, 1090, 1687)),
(-75, (_c(_t('NPC')) + _c(_t('Asteroid')) + _t('Sanshas Nation'), 5586, 4112, 0, 0)),
(-76, (_c(_t('NPC')) + _c(_t('Asteroid')) + _t('Serpentis'), 0, 5373, 4813, 0)),
(-77, (_c(_t('NPC')) + _c(_t('Burner')) + _c(_t('Team')) + _t('Enyo'), 0, 147, 147, 0)),
(-78, (_c(_t('NPC')) + _c(_t('Burner')) + _c(_t('Team')) + _t('Hawk'), 0, 0, 247, 0)),
(-79, (_c(_t('NPC')) + _c(_t('Burner')) + _c(_t('Team')) + _t('Jaguar'), 36, 0, 50, 182)),
(-80, (_c(_t('NPC')) + _c(_t('Burner')) + _c(_t('Team')) + _t('Vengeance'), 232, 0, 0, 0)),
(-81, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Cruor'), 90, 90, 0, 0)),
(-82, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Dramiel'), 55, 0, 20, 96)),
(-83, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Daredevil'), 0, 110, 154, 0)),
(-84, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Succubus'), 135, 30, 0, 0)),
(-85, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Worm'), 0, 0, 228, 0)),
(-86, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Ashimmu'), 260, 100, 0, 0)),
(-87, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Talos'), 0, 413, 413, 0)),
(-88, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Sentinel'), 0, 0, 75, 90)),
(-89, (_c(_t('NPC')) + _c(_t('Deadspace')) + _t('Angel Cartel'), 369, 533, 1395, 3302)),
(-90, (_c(_t('NPC')) + _c(_t('Deadspace')) + _t('Blood Raiders'), 6040, 5052, 10, 15)),
(-91, (_c(_t('NPC')) + _c(_t('Deadspace')) + _t('Guristas'), 0, 1531, 9680, 0)),
(-92, (_c(_t('NPC')) + _c(_t('Deadspace')) + _t('Rogue Drone'), 276, 1071, 1069, 871)),
(-93, (_c(_t('NPC')) + _c(_t('Deadspace')) + _t('Sanshas Nation'), 3009, 2237, 0, 0)),
(-94, (_c(_t('NPC')) + _c(_t('Deadspace')) + _t('Serpentis'), 0, 3110, 1929, 0)),
# Source: ticket #2067
(-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)),
(-95, (_c(_t('NPC')) + _c(_t('Invasion')) + _c(_t('Triglavian Entities')) + _t('Dread'), 0, 417, 0, 583)),
(-96, (_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')) +
(-97, (_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')) +
(-98, (_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')) +
(-99, (_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))])
(-100, (_c(_t('NPC')) + _c(_t('Invasion')) + _c(_t('Amarr EDENCOM Entities')) + _t('Dread/Subcaps'), 583, 417, 0, 0)),
(-101, (_c(_t('NPC')) + _c(_t('Invasion')) + _c(_t('Caldari EDENCOM Entities')) + _t('Dread'), 1000, 0, 0, 0)),
(-102, (_c(_t('NPC')) + _c(_t('Invasion')) + _c(_t('Caldari EDENCOM Entities')) + _t('Subcaps'), 511, 21, 29, 440)),
(-103, (_c(_t('NPC')) + _c(_t('Invasion')) + _c(_t('Gallente EDENCOM Entities')) + _t('Dread/Subcaps'), 0, 417, 583, 0)),
(-104, (_c(_t('NPC')) + _c(_t('Invasion')) + _c(_t('Minmatar EDENCOM Entities')) + _t('Dread'), 0, 0, 583, 417)),
(-105, (_c(_t('NPC')) + _c(_t('Invasion')) + _c(_t('Minmatar EDENCOM Entities')) + _t('Subcaps'), 302, 136, 328, 234)),
(-106, (_c(_t('NPC')) + _c(_t('Invasion')) + _t('Drifter Entities'), 250, 250, 250, 250)),
(-107, (_c(_t('NPC')) + _c(_t('Invasion')) + _t('Sleeper Entities'), 265, 265, 235, 235)),
(-108, (_c(_t('NPC')) + _c(_t('Invasion')) + _t('Rogue Drone Entities'), 250, 250, 250, 250)),
(-109, (_c(_t('NPC')) + _c(_t('Mission')) + _t('Amarr Empire'), 4464, 3546, 97, 0)),
(-110, (_c(_t('NPC')) + _c(_t('Mission')) + _t('Caldari State'), 0, 2139, 4867, 0)),
(-111, (_c(_t('NPC')) + _c(_t('Mission')) + _t('CONCORD'), 336, 134, 212, 412)),
(-112, (_c(_t('NPC')) + _c(_t('Mission')) + _t('Gallente Federation'), 9, 3712, 2758, 0)),
(-113, (_c(_t('NPC')) + _c(_t('Mission')) + _t('Khanid'), 612, 483, 43, 6)),
(-114, (_c(_t('NPC')) + _c(_t('Mission')) + _t('Minmatar Republic'), 1024, 388, 1655, 4285)),
(-115, (_c(_t('NPC')) + _c(_t('Mission')) + _t('Mordus Legion'), 25, 262, 625, 0)),
(-116, (_c(_t('NPC')) + _c(_t('Mission')) + _t('Thukker'), 0, 52, 10, 79)),
(-117, (_c(_t('NPC')) + _t('Sansha Incursion'), 1682, 1347, 3678, 3678)),
(-118, (_c(_t('NPC')) + _t('Sleepers'), 1472, 1472, 1384, 1384))])
class DamagePattern:
@@ -207,11 +216,11 @@ class DamagePattern:
pattern.builtin = True
cls._builtins[id] = pattern
def calculateEhp(self, fit):
def calculateEhp(self, item):
ehp = {}
for (type, attr) in (('shield', 'shieldCapacity'), ('armor', 'armorHP'), ('hull', 'hp')):
rawCapacity = fit.ship.getModifiedItemAttr(attr)
ehp[type] = self.effectivify(fit, rawCapacity, type)
rawCapacity = item.getModifiedItemAttr(attr)
ehp[type] = self.effectivify(item, rawCapacity, type)
return ehp
@@ -227,10 +236,10 @@ class DamagePattern:
ereps = {}
for field in tankInfo:
if field in typeMap:
ereps[field] = self.effectivify(fit, tankInfo[field], typeMap[field])
ereps[field] = self.effectivify(fit.ship, tankInfo[field], typeMap[field])
return ereps
def effectivify(self, fit, amount, type):
def effectivify(self, item, amount, type):
type = type if type != "hull" else ""
totalDamage = sum((self.emAmount, self.thermalAmount, self.kineticAmount, self.explosiveAmount))
specificDivider = 0
@@ -239,7 +248,7 @@ class DamagePattern:
attrName = "%s%sDamageResonance" % (type, damageType.capitalize())
attrName = attrName[0].lower() + attrName[1:]
resonance = fit.ship.getModifiedItemAttr(attrName)
resonance = item.getModifiedItemAttr(attrName)
damage = getattr(self, "%sAmount" % damageType)
specificDivider += damage / float(totalDamage or 1) * resonance

View File

@@ -82,6 +82,7 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut, Mu
self.__baseRRAmount = None
self.__miningYield = None
self.__miningWaste = None
self.__ehp = None
self.__itemModifiedAttributes = ModifiedAttributeDict()
self.__itemModifiedAttributes.original = self._item.attributes
self.__itemModifiedAttributes.overrides = self._item.overrides
@@ -287,6 +288,29 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut, Mu
if delay is not None and speed is not None:
return delay / 1000.0 * speed
@property
def hp(self):
hp = {}
for (type, attr) in (('shield', 'shieldCapacity'), ('armor', 'armorHP'), ('hull', 'hp')):
hp[type] = self.getModifiedItemAttr(attr)
return hp
@property
def ehp(self):
if self.__ehp is None:
if self.owner is None or self.owner.damagePattern is None:
ehp = self.hp
else:
ehp = self.owner.damagePattern.calculateEhp(self)
self.__ehp = ehp
return self.__ehp
def calculateShieldRecharge(self):
capacity = self.getModifiedItemAttr("shieldCapacity")
rechargeRate = self.getModifiedItemAttr("shieldRechargeRate") / 1000.0
return 10 / rechargeRate * math.sqrt(0.25) * (1 - math.sqrt(0.25)) * capacity
# Had to add this to match the falloff property in modules.py
# Fscking ship scanners. If you find any other falloff attributes,
# Put them in the attrs tuple.
@@ -318,6 +342,7 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut, Mu
self.__baseRRAmount = None
self.__miningYield = None
self.__miningWaste = None
self.__ehp = None
self.itemModifiedAttributes.clear()
self.chargeModifiedAttributes.clear()

View File

@@ -96,6 +96,7 @@ class Fighter(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
self.__charge = None
self.__baseVolley = None
self.__miningyield = None
self.__ehp = None
self.__itemModifiedAttributes = ModifiedAttributeDict()
self.__chargeModifiedAttributes = ModifiedAttributeDict()
@@ -345,6 +346,29 @@ class Fighter(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
if falloff is not None:
return falloff
@property
def hp(self):
hp = {}
for (type, attr) in (('shield', 'shieldCapacity'), ('armor', 'armorHP'), ('hull', 'hp')):
hp[type] = self.getModifiedItemAttr(attr)
return hp
@property
def ehp(self):
if self.__ehp is None:
if self.owner is None or self.owner.damagePattern is None:
ehp = self.hp
else:
ehp = self.owner.damagePattern.calculateEhp(self)
self.__ehp = ehp
return self.__ehp
def calculateShieldRecharge(self):
capacity = self.getModifiedItemAttr("shieldCapacity")
rechargeRate = self.getModifiedItemAttr("shieldRechargeRate") / 1000.0
return 10 / rechargeRate * math.sqrt(0.25) * (1 - math.sqrt(0.25)) * capacity
@validates("ID", "itemID", "chargeID", "amount")
def validator(self, key, val):
map = {
@@ -361,6 +385,7 @@ class Fighter(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
def clear(self):
self.__baseVolley = None
self.__miningyield = None
self.__ehp = None
self.itemModifiedAttributes.clear()
self.chargeModifiedAttributes.clear()
[x.clear() for x in self.abilities]

View File

@@ -159,6 +159,12 @@ class Fit:
self.gangBoosts = None
self.__ecmProjectedList = []
self.commandBonuses = {}
# Reps received, as a list of (amount, cycle time in seconds)
self._hullRr = []
self._armorRr = []
self._armorRrPreSpool = []
self._armorRrFullSpool = []
self._shieldRr = []
def clearFactorReloadDependentData(self):
# Here we clear all data known to rely on cycle parameters
@@ -550,6 +556,12 @@ class Fit:
if stuff is not None and stuff != self:
stuff.clear()
self._hullRr.clear()
self._armorRr.clear()
self._armorRrPreSpool.clear()
self._armorRrFullSpool.clear()
self._shieldRr.clear()
# If this is the active fit that we are clearing, not a projected fit,
# then this will run and clear the projected ships and flag the next
# iteration to skip this part to prevent recursion.
@@ -621,7 +633,7 @@ class Fit:
"duration", value)
if warfareBuffID == 12: # Shield Burst: Shield Extension: Shield HP
self.ship.boostItemAttr("shieldCapacity", value, stackingPenalties=True)
self.ship.boostItemAttr("shieldCapacity", value)
if warfareBuffID == 13: # Armor Burst: Armor Energizing: Armor Resistance
for damageType in ("Em", "Thermal", "Explosive", "Kinetic"):
@@ -640,7 +652,7 @@ class Fit:
"duration", value)
if warfareBuffID == 15: # Armor Burst: Armor Reinforcement: Armor HP
self.ship.boostItemAttr("armorHP", value, stackingPenalties=True)
self.ship.boostItemAttr("armorHP", value)
if warfareBuffID == 16: # Information Burst: Sensor Optimization: Scan Resolution
self.ship.boostItemAttr("scanResolution", value, stackingPenalties=True)
@@ -734,7 +746,7 @@ class Fit:
self.ship.boostItemAttr(attr, value, stackingPenalties=True)
if warfareBuffID == 42: # Erebus Effect Generator : Armor HP bonus
self.ship.boostItemAttr("armorHP", value, stackingPenalties=True)
self.ship.boostItemAttr("armorHP", value)
if warfareBuffID == 43: # Erebus Effect Generator : Explosive resistance bonus
for attr in ("armorExplosiveDamageResonance", "shieldExplosiveDamageResonance", "explosiveDamageResonance"):
@@ -756,7 +768,7 @@ class Fit:
self.ship.boostItemAttr(attr, value, stackingPenalties=True)
if warfareBuffID == 48: # Leviathan Effect Generator : Shield HP bonus
self.ship.boostItemAttr("shieldCapacity", value, stackingPenalties=True)
self.ship.boostItemAttr("shieldCapacity", value)
if warfareBuffID == 49: # Leviathan Effect Generator : EM resistance bonus
for attr in ("armorEmDamageResonance", "shieldEmDamageResonance", "emDamageResonance"):
@@ -1469,7 +1481,7 @@ class Fit:
if self.damagePattern is None:
ehp = self.hp
else:
ehp = self.damagePattern.calculateEhp(self)
ehp = self.damagePattern.calculateEhp(self.ship)
self.__ehp = ehp
return self.__ehp
@@ -1478,11 +1490,11 @@ class Fit:
def tank(self):
reps = {
"passiveShield": self.calculateShieldRecharge(),
"shieldRepair": self.extraAttributes["shieldRepair"],
"armorRepair": self.extraAttributes["armorRepair"],
"armorRepairPreSpool": self.extraAttributes["armorRepairPreSpool"],
"armorRepairFullSpool": self.extraAttributes["armorRepairFullSpool"],
"hullRepair": self.extraAttributes["hullRepair"]
"shieldRepair": self.extraAttributes["shieldRepair"] + self._getAppliedShieldRr(),
"armorRepair": self.extraAttributes["armorRepair"] + self._getAppliedArmorRr(),
"armorRepairPreSpool": self.extraAttributes["armorRepairPreSpool"] + self._getAppliedArmorPreSpoolRr(),
"armorRepairFullSpool": self.extraAttributes["armorRepairFullSpool"] + self._getAppliedArmorFullSpoolRr(),
"hullRepair": self.extraAttributes["hullRepair"] + self._getAppliedHullRr()
}
return reps
@@ -1519,11 +1531,11 @@ class Fit:
if self.__sustainableTank is None:
sustainable = {
"passiveShield": self.calculateShieldRecharge(),
"shieldRepair": self.extraAttributes["shieldRepair"],
"armorRepair": self.extraAttributes["armorRepair"],
"armorRepairPreSpool": self.extraAttributes["armorRepairPreSpool"],
"armorRepairFullSpool": self.extraAttributes["armorRepairFullSpool"],
"hullRepair": self.extraAttributes["hullRepair"]
"shieldRepair": self.extraAttributes["shieldRepair"] + self._getAppliedShieldRr(),
"armorRepair": self.extraAttributes["armorRepair"] + self._getAppliedArmorRr(),
"armorRepairPreSpool": self.extraAttributes["armorRepairPreSpool"] + self._getAppliedArmorPreSpoolRr(),
"armorRepairFullSpool": self.extraAttributes["armorRepairFullSpool"] + self._getAppliedArmorFullSpoolRr(),
"hullRepair": self.extraAttributes["hullRepair"] + self._getAppliedHullRr()
}
if not self.capStable or self.factorReload:
# Map a local repairer type to the attribute it uses
@@ -1760,6 +1772,38 @@ class Fit:
mults.setdefault(stackingGroup, []).append((1 + strength / 100, None))
return calculateMultiplier(mults)
def _getAppliedHullRr(self):
return self.__getAppliedRr(self._hullRr)
def _getAppliedArmorRr(self):
return self.__getAppliedRr(self._armorRr)
def _getAppliedArmorPreSpoolRr(self):
return self.__getAppliedRr(self._armorRrPreSpool)
def _getAppliedArmorFullSpoolRr(self):
return self.__getAppliedRr(self._armorRrFullSpool)
def _getAppliedShieldRr(self):
return self.__getAppliedRr(self._shieldRr)
@staticmethod
def __getAppliedRr(rrList):
totalRaw = 0
for amount, cycleTime in rrList:
# That's right, for considerations of RR diminishing returns cycle time is rounded this way
totalRaw += amount / int(cycleTime)
RR_ADDITION = 7000
RR_MULTIPLIER = 10
appliedRr = 0
for amount, cycleTime in rrList:
rrps = amount / int(cycleTime)
modified_rrps = RR_ADDITION + (rrps * RR_MULTIPLIER)
rrps_mult = 1 - (((rrps + modified_rrps) / (totalRaw + modified_rrps)) - 1) ** 2
appliedRr += rrps_mult * amount / cycleTime
return appliedRr
def __deepcopy__(self, memo=None):
fitCopy = Fit()
# Character and owner are not copied

View File

@@ -122,6 +122,8 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut, M
if self.__charge and self.__charge.category.name != "Charge":
self.__charge = None
self.rahPatternOverride = None
self.__baseVolley = None
self.__baseRRAmount = None
self.__miningYield = None
@@ -475,7 +477,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut, M
# Some delay attributes have non-0 default value, so we have to pick according to effects
if {'superWeaponAmarr', 'superWeaponCaldari', 'superWeaponGallente', 'superWeaponMinmatar', 'lightningWeapon'}.intersection(self.item.effects):
dmgDelay = self.getModifiedItemAttr("damageDelayDuration", 0)
elif {'doomsdayBeamDOT', 'doomsdaySlash', 'doomsdayConeDOT'}.intersection(self.item.effects):
elif {'doomsdayBeamDOT', 'doomsdaySlash', 'doomsdayConeDOT', 'debuffLance'}.intersection(self.item.effects):
dmgDelay = self.getModifiedItemAttr("doomsdayWarningDuration", 0)
else:
dmgDelay = 0
@@ -694,16 +696,22 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut, M
return False
# Check max group fitted
max = self.getModifiedItemAttr("maxGroupFitted")
if max:
current = 0 # if self.owner != fit else -1 # Disabled, see #1278
for mod in fit.modules:
if (mod.item and mod.item.groupID == self.item.groupID and
self.getModPosition(fit) != mod.getModPosition(fit)):
current += 1
# use raw value, since it seems what EVE uses. Example is FAXes with their capacitor boosters,
# which have unmodified value of 10, and modified of 1, and you can actually fit multiples
try:
max = self.item.attributes.get('maxGroupFitted').value
except AttributeError:
pass
else:
if max:
current = 0 # if self.owner != fit else -1 # Disabled, see #1278
for mod in fit.modules:
if (mod.item and mod.item.groupID == self.item.groupID and
self.getModPosition(fit) != mod.getModPosition(fit)):
current += 1
if current >= max:
return False
if current >= max:
return False
# Check this only if we're told to do so
if hardpointLimit:
@@ -1075,6 +1083,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut, M
copy.spoolType = self.spoolType
copy.spoolAmount = self.spoolAmount
copy.projectionRange = self.projectionRange
copy.rahPatternOverride = self.rahPatternOverride
self._mutaApplyMutators(mutatorClass=MutatorModule, targetInstance=copy)
return copy
@@ -1085,6 +1094,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut, M
spoolType = self.spoolType
spoolAmount = self.spoolAmount
projectionRange = self.projectionRange
rahPatternOverride = self.rahPatternOverride
Module.__init__(self, item, self.baseItem, self.mutaplasmid)
self.state = state
@@ -1093,6 +1103,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut, M
self.spoolType = spoolType
self.spoolAmount = spoolAmount
self.projectionRange = projectionRange
self.rahPatternOverride = rahPatternOverride
self._mutaApplyMutators(mutatorClass=MutatorModule)
def __repr__(self):

View File

@@ -78,158 +78,166 @@ BUILTINS = OrderedDict([
(-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)),
# Anomic Team, source: client data dump
(-40, (_c(_t('NPC')) + _c(_t('Burner')) + _c(_t('Team')) + _t('Enyo'), 0.575, 0.724, 0.862, 0.235, 1020, 37, 39)),
(-41, (_c(_t('NPC')) + _c(_t('Burner')) + _c(_t('Team')) + _t('Navitas'), 0.681, 0.586, 0.522, 0.49, 870, 30, 35)),
(-42, (_c(_t('NPC')) + _c(_t('Burner')) + _c(_t('Team')) + _t('Hawk'), 0.3, 0.86, 0.79, 0.65, 1122, 48, 39)),
(-43, (_c(_t('NPC')) + _c(_t('Burner')) + _c(_t('Team')) + _t('Bantam'), 0.344, 0.475, 0.606, 0.672, 1016, 45, 27)),
(-44, (_c(_t('NPC')) + _c(_t('Burner')) + _c(_t('Team')) + _t('Jaguar'), 0.781, 0.65, 0.475, 0.563, 1400, 42, 31)),
(-45, (_c(_t('NPC')) + _c(_t('Burner')) + _c(_t('Team')) + _t('Burst'), 0.344, 0.475, 0.606, 0.672, 1174, 39, 31)),
(-46, (_c(_t('NPC')) + _c(_t('Burner')) + _c(_t('Team')) + _t('Vengeance'), 0.66, 0.558, 0.745, 0.864, 1050, 37, 40)),
(-47, (_c(_t('NPC')) + _c(_t('Burner')) + _c(_t('Team')) + _t('Inquisitor'), 0.681, 0.586, 0.522, 0.49, 920, 29, 20.5)),
# Anomic Agent & Base, source: client data dump
(-48, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Cruor'), 0.795, 0.734, 0.693, 0.672, 900, 18, 20.5)),
(-49, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Dramiel'), 0.351, 0.481, 0.611, 0.676, 2100, 11, 25)),
(-50, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Daredevil'), 0.685, 0.59, 0.59, 0.433, 1200, 18, 25)),
(-51, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Succubus'), 0.351, 0.481, 0.611, 0.676, 4750, 30, 59)),
(-52, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Worm'), 0.475, 0.58, 0.685, 0.738, 360, 70, 39)),
(-53, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Ashimmu'), 0.8, 0.76, 0.68, 0.7, 500, 120, 137)),
(-54, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Sentinel'), 0.575, 0.448, 0.522, 0.66, 500, 50, 39)),
(-55, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Talos'), 0.681, 0.586, 0.586, 0.426, 150, 125, 266)),
(-56, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Dragonfly'), 0.35, 0.72, 0.70, 0.55, 1200, 15, 35)),
(-57, (_c(_t('NPC')) + _c(_t('Burner')) + _t('Mantis'), 0.60, 0.52, 0.71, 0.71, 900, 25, 35)),
# Source: ticket #2067
(-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)),
(-58, (_c(_t('NPC')) + _c(_t('Invasion')) + _t('Triglavian Entities'), 0.422, 0.367, 0.453, 0.411)),
(-59, (_c(_t('NPC')) + _c(_t('Invasion')) + _t('Amarr EDENCOM Entities'), 0.360, 0.310, 0.441, 0.602)),
(-60, (_c(_t('NPC')) + _c(_t('Invasion')) + _t('Caldari EDENCOM Entities'), 0.303, 0.610, 0.487, 0.401)),
(-61, (_c(_t('NPC')) + _c(_t('Invasion')) + _t('Gallente EDENCOM Entities'), 0.383, 0.414, 0.578, 0.513)),
(-62, (_c(_t('NPC')) + _c(_t('Invasion')) + _t('Minmatar EDENCOM Entities'), 0.620, 0.422, 0.355, 0.399)),
(-63, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Dark Matter All Tiers')) + _t('Drones'), 0.439, 0.522, 0.529, 0.435)),
(-64, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Dark Matter All Tiers')) + _t('Overmind'), 0.643, 0.593, 0.624, 0.639)),
(-65, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Dark Matter All Tiers')) + _t('Seeker'), 0.082, 0.082, 0.082, 0.082)),
(-66, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Dark Matter All Tiers')) + _t('Triglavian'), 0.494, 0.41, 0.464, 0.376)),
(-67, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Dark Matter All Tiers')) + _t('Drifter'), 0.415, 0.415, 0.415, 0.415)),
(-68, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Dark Matter All Tiers')) + _t('Sleeper'), 0.435, 0.435, 0.435, 0.435)),
(-69, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Dark Matter All Tiers')) + _t('All'), 0.508, 0.474, 0.495, 0.488)),
(-70, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T0/T1/T2')) + _t('Drones'), 0.323, 0.522, 0.529, 0.435)),
(-71, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T0/T1/T2')) + _t('Overmind'), 0.542, 0.593, 0.624, 0.639)),
(-72, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T0/T1/T2')) + _t('Seeker'), 0, 0.082, 0.082, 0.082)),
(-73, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T0/T1/T2')) + _t('Triglavian'), 0.356, 0.41, 0.464, 0.376)),
(-74, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T0/T1/T2')) + _t('Drifter'), 0.277, 0.415, 0.415, 0.415)),
(-75, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T0/T1/T2')) + _t('Sleeper'), 0.329, 0.435, 0.435, 0.435)),
(-76, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T0/T1/T2')) + _t('All'), 0.381, 0.474, 0.495, 0.488)),
(-77, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T3 (Some T5 Rooms)')) + _t('Drones'), 0.255, 0.522, 0.529, 0.435)),
(-78, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T3 (Some T5 Rooms)')) + _t('Overmind'), 0.48, 0.593, 0.624, 0.639)),
(-79, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T3 (Some T5 Rooms)')) + _t('Seeker'), 0, 0.082, 0.082, 0.0822)),
(-80, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T3 (Some T5 Rooms)')) + _t('Triglavian'), 0.268, 0.41, 0.464, 0.376)),
(-81, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T3 (Some T5 Rooms)')) + _t('Drifter'), 0.191, 0.415, 0.415, 0.415)),
(-82, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T3 (Some T5 Rooms)')) + _t('Sleeper'), 0.268, 0.435, 0.435, 0.435)),
(-83, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T3 (Some T5 Rooms)')) + _t('All'), 0.308, 0.474, 0.495, 0.488)),
(-84, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T4/T5/T6')) + _t('Drones'), 0.193, 0.522, 0.529, 0.435)),
(-85, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T4/T5/T6')) + _t('Overmind'), 0.423, 0.593, 0.624, 0.639)),
(-86, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T4/T5/T6')) + _t('Seeker'), 0, 0.082, 0.082, 0.082)),
(-87, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T4/T5/T6')) + _t('Triglavian'), 0.206, 0.41, 0.464, 0.376)),
(-88, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T4/T5/T6')) + _t('Drifter'), 0.111, 0.415, 0.415, 0.415)),
(-89, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T4/T5/T6')) + _t('Sleeper'), 0.215, 0.435, 0.435, 0.435)),
(-90, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T4/T5/T6')) + _t('All'), 0.247, 0.474, 0.495, 0.488)),
(-91, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T0/T1/T2')) + _t('Drones'), 0.461, 0.425, 0.541, 0.443)),
(-92, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T0/T1/T2')) + _t('Overmind'), 0.666, 0.489, 0.634, 0.646)),
(-93, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T0/T1/T2')) + _t('Seeker'), 0.084, 0, 0.084, 0.084)),
(-94, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T0/T1/T2')) + _t('Triglavian'), 0.537, 0.269, 0.489, 0.371)),
(-95, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T0/T1/T2')) + _t('Drifter'), 0.43, 0.289, 0.43, 0.43)),
(-96, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T0/T1/T2')) + _t('Sleeper'), 0.512, 0.402, 0.512, 0.512)),
(-97, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T0/T1/T2')) + _t('All'), 0.537, 0.352, 0.512, 0.495)),
(-98, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T3 (Some T5 Rooms)')) + _t('Drones'), 0.461, 0.36, 0.541, 0.443)),
(-99, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T3 (Some T5 Rooms)')) + _t('Overmind'), 0.666, 0.413, 0.634, 0.646)),
(-100, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T3 (Some T5 Rooms)')) + _t('Seeker'), 0.084, 0, 0.084, 0.084)),
(-101, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T3 (Some T5 Rooms)')) + _t('Triglavian'), 0.537, 0.166, 0.489, 0.371)),
(-102, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T3 (Some T5 Rooms)')) + _t('Drifter'), 0.43, 0.201, 0.43, 0.43)),
(-103, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T3 (Some T5 Rooms)')) + _t('Sleeper'), 0.512, 0.337, 0.512, 0.512)),
(-104, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T3 (Some T5 Rooms)')) + _t('All'), 0.537, 0.269, 0.512, 0.495)),
(-105, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T4/T5/T6')) + _t('Drones'), 0.461, 0.305, 0.541, 0.443)),
(-106, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T4/T5/T6')) + _t('Overmind'), 0.666, 0.345, 0.634, 0.646)),
(-107, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T4/T5/T6')) + _t('Seeker'), 0.084, 0, 0.084, 0.084)),
(-108, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T4/T5/T6')) + _t('Triglavian'), 0.537, 0.085, 0.489, 0.371)),
(-109, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T4/T5/T6')) + _t('Drifter'), 0.43, 0.117, 0.43, 0.43)),
(-110, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T4/T5/T6')) + _t('Sleeper'), 0.512, 0.276, 0.512, 0.512)),
(-111, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T4/T5/T6')) + _t('All'), 0.537, 0.201, 0.512, 0.495)),
(-112, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T0/T1/T2')) + _t('Drones'), 0.439, 0.522, 0.417, 0.435)),
(-113, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T0/T1/T2')) + _t('Overmind'), 0.643, 0.593, 0.511, 0.639)),
(-114, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T0/T1/T2')) + _t('Seeker'), 0.082, 0.082, 0, 0.082)),
(-115, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T0/T1/T2')) + _t('Triglavian'), 0.494, 0.41, 0.304, 0.376)),
(-116, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T0/T1/T2')) + _t('Drifter'), 0.415, 0.415, 0.277, 0.415)),
(-117, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T0/T1/T2')) + _t('Sleeper'), 0.435, 0.435, 0.329, 0.435)),
(-118, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T0/T1/T2')) + _t('All'), 0.508, 0.474, 0.359, 0.488)),
(-119, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T3 (Some T5 Rooms)')) + _t('Drones'), 0.439, 0.522, 0.351, 0.435)),
(-120, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T3 (Some T5 Rooms)')) + _t('Overmind'), 0.643, 0.593, 0.435, 0.639)),
(-121, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T3 (Some T5 Rooms)')) + _t('Seeker'), 0.082, 0.082, 0, 0.082)),
(-122, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T3 (Some T5 Rooms)')) + _t('Triglavian'), 0.494, 0.41, 0.198, 0.376)),
(-123, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T3 (Some T5 Rooms)')) + _t('Drifter'), 0.415, 0.415, 0.191, 0.415)),
(-124, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T3 (Some T5 Rooms)')) + _t('Sleeper'), 0.435, 0.435, 0.268, 0.435)),
(-125, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T3 (Some T5 Rooms)')) + _t('All'), 0.508, 0.474, 0.276, 0.488)),
(-126, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T4/T5/T6')) + _t('Drones'), 0.439, 0.522, 0.293, 0.435)),
(-127, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T4/T5/T6')) + _t('Overmind'), 0.643, 0.593, 0.362, 0.639)),
(-128, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T4/T5/T6')) + _t('Seeker'), 0.082, 0.082, 0, 0.082)),
(-129, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T4/T5/T6')) + _t('Triglavian'), 0.494, 0.41, 0.122, 0.376)),
(-130, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T4/T5/T6')) + _t('Drifter'), 0.415, 0.415, 0.111, 0.415)),
(-131, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T4/T5/T6')) + _t('Sleeper'), 0.435, 0.435, 0.215, 0.435)),
(-132, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T4/T5/T6')) + _t('All'), 0.508, 0.474, 0.208, 0.488)),
(-133, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T0/T1/T2')) + _t('Drones'), 0.449, 0.54, 0.549, 0.336)),
(-134, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T0/T1/T2')) + _t('Overmind'), 0.619, 0.574, 0.612, 0.522)),
(-135, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T0/T1/T2')) + _t('Seeker'), 0.085, 0.085, 0.085, 0)),
(-136, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T0/T1/T2')) + _t('Triglavian'), 0.477, 0.4, 0.461, 0.202)),
(-137, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T0/T1/T2')) + _t('Drifter'), 0.437, 0.437, 0.437, 0.295)),
(-138, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T0/T1/T2')) + _t('Sleeper'), 0.435, 0.435, 0.435, 0.329)),
(-139, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T0/T1/T2')) + _t('All'), 0.493, 0.468, 0.492, 0.35)),
(-140, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T3 (Some T5 Rooms)')) + _t('Drones'), 0.449, 0.54, 0.549, 0.264)),
(-141, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T3 (Some T5 Rooms)')) + _t('Overmind'), 0.619, 0.574, 0.612, 0.449)),
(-142, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T3 (Some T5 Rooms)')) + _t('Seeker'), 0.085, 0.085, 0.085, 0)),
(-143, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T3 (Some T5 Rooms)')) + _t('Triglavian'), 0.477, 0.4, 0.461, 0.081)),
(-144, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T3 (Some T5 Rooms)')) + _t('Drifter'), 0.437, 0.437, 0.437, 0.206)),
(-145, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T3 (Some T5 Rooms)')) + _t('Sleeper'), 0.435, 0.435, 0.435, 0.268)),
(-146, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T3 (Some T5 Rooms)')) + _t('All'), 0.493, 0.468, 0.492, 0.264)),
(-147, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T4/T5/T6')) + _t('Drones'), 0.449, 0.54, 0.549, 0.197)),
(-148, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T4/T5/T6')) + _t('Overmind'), 0.619, 0.574, 0.612, 0.379)),
(-149, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T4/T5/T6')) + _t('Seeker'), 0.085, 0.085, 0.085, 0)),
(-150, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T4/T5/T6')) + _t('Triglavian'), 0.477, 0.4, 0.461, 0.034)),
(-151, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T4/T5/T6')) + _t('Drifter'), 0.437, 0.437, 0.437, 0.121)),
(-152, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T4/T5/T6')) + _t('Sleeper'), 0.435, 0.435, 0.435, 0.215)),
(-153, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T4/T5/T6')) + _t('All'), 0.493, 0.468, 0.492, 0.196)),
# Source: ticket #2265
(-148, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Dark Matter All Tiers')) + _t('Concord'), 0.324, 0.318, 0.369, 0.372)),
(-149, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Dark Matter All Tiers')) + _t('Sansha'), 0.137, 0.331, 0.332, 0.322)),
(-150, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Dark Matter All Tiers')) + _t('Angel'), 0.582, 0.508, 0.457, 0.416)),
(-151, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T0/T1/T2')) + _t('Concord'), 0.121, 0.318, 0.369, 0.372)),
(-152, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T0/T1/T2')) + _t('Sansha'), 0.034, 0.331, 0.332, 0.322)),
(-153, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T0/T1/T2')) + _t('Angel'), 0.456, 0.508, 0.457, 0.416)),
(-154, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T3 (Some T5 Rooms)')) + _t('Concord'), 0.025, 0.318, 0.369, 0.372)),
(-155, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T3 (Some T5 Rooms)')) + _t('Sansha'), 0.018, 0.331, 0.332, 0.322)),
(-156, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T3 (Some T5 Rooms)')) + _t('Angel'), 0.373, 0.508, 0.457, 0.416)),
(-157, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T4/T5/T6')) + _t('Concord'), 0.008, 0.318, 0.369, 0.372)),
(-158, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T4/T5/T6')) + _t('Sansha'), 0.009, 0.331, 0.332, 0.322)),
(-159, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T4/T5/T6')) + _t('Angel'), 0.3, 0.508, 0.457, 0.416)),
(-160, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T0/T1/T2')) + _t('Concord'), 0.324, 0.107, 0.369, 0.372)),
(-161, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T0/T1/T2')) + _t('Sansha'), 0.148, 0.181, 0.329, 0.328)),
(-162, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T0/T1/T2')) + _t('Angel'), 0.587, 0.342, 0.439, 0.39)),
(-163, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T3 (Some T5 Rooms)')) + _t('Concord'), 0.324, 0.016, 0.369, 0.372)),
(-164, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T3 (Some T5 Rooms)')) + _t('Sansha'), 0.148, 0.14, 0.329, 0.328)),
(-165, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T3 (Some T5 Rooms)')) + _t('Angel'), 0.587, 0.241, 0.439, 0.39)),
(-166, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T4/T5/T6')) + _t('Concord'), 0.324, 0.004, 0.369, 0.372)),
(-167, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T4/T5/T6')) + _t('Sansha'), 0.148, 0.106, 0.329, 0.328)),
(-168, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T4/T5/T6')) + _t('Angel'), 0.587, 0.172, 0.439, 0.39)),
(-169, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T0/T1/T2')) + _t('Concord'), 0.324, 0.318, 0.18, 0.372)),
(-170, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T0/T1/T2')) + _t('Sansha'), 0.137, 0.331, 0.166, 0.322)),
(-171, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T0/T1/T2')) + _t('Angel'), 0.582, 0.508, 0.295, 0.416)),
(-172, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T3 (Some T5 Rooms)')) + _t('Concord'), 0.324, 0.318, 0.089, 0.372)),
(-173, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T3 (Some T5 Rooms)')) + _t('Sansha'), 0.137, 0.331, 0.108, 0.322)),
(-174, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T3 (Some T5 Rooms)')) + _t('Angel'), 0.582, 0.508, 0.203, 0.416)),
(-175, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T4/T5/T6')) + _t('Concord'), 0.324, 0.318, 0.068, 0.372)),
(-176, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T4/T5/T6')) + _t('Sansha'), 0.137, 0.331, 0.073, 0.322)),
(-177, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T4/T5/T6')) + _t('Angel'), 0.582, 0.508, 0.14, 0.416)),
(-178, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T0/T1/T2')) + _t('Concord'), 0.324, 0.318, 0.369, 0.203)),
(-179, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T0/T1/T2')) + _t('Sansha'), 0.137, 0.355, 0.352, 0.16)),
(-180, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T0/T1/T2')) + _t('Angel'), 0.59, 0.528, 0.477, 0.286)),
(-181, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T3 (Some T5 Rooms)')) + _t('Concord'), 0.324, 0.318, 0.369, 0.112)),
(-182, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T3 (Some T5 Rooms)')) + _t('Sansha'), 0.137, 0.355, 0.352, 0.05)),
(-183, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T3 (Some T5 Rooms)')) + _t('Angel'), 0.59, 0.528, 0.477, 0.197)),
(-184, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T4/T5/T6')) + _t('Concord'), 0.324, 0.318, 0.369, 0.086)),
(-185, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T4/T5/T6')) + _t('Sansha'), 0.137, 0.355, 0.352, 0)),
(-186, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T4/T5/T6')) + _t('Angel'), 0.59, 0.528, 0.477, 0.126)),
(-187, (_c(_t('NPC')) + _c(_t('Invasion')) + _t('Drifter Entities'), 0.128, 0.375, 0.383, 0.383)),
(-188, (_c(_t('NPC')) + _c(_t('Invasion')) + _t('Rogue Drone Entities'), 0.104, 0.147, 0.147, 0.102)),
(-189, (_c(_t('NPC')) + _c(_t('Invasion')) + _t('Sleeper Entities'), 0.563, 0.563, 0.563, 0.563))])
(-154, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Dark Matter All Tiers')) + _t('Concord'), 0.324, 0.318, 0.369, 0.372)),
(-155, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Dark Matter All Tiers')) + _t('Sansha'), 0.137, 0.331, 0.332, 0.322)),
(-156, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Dark Matter All Tiers')) + _t('Angel'), 0.582, 0.508, 0.457, 0.416)),
(-157, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T0/T1/T2')) + _t('Concord'), 0.121, 0.318, 0.369, 0.372)),
(-158, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T0/T1/T2')) + _t('Sansha'), 0.034, 0.331, 0.332, 0.322)),
(-159, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T0/T1/T2')) + _t('Angel'), 0.456, 0.508, 0.457, 0.416)),
(-160, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T3 (Some T5 Rooms)')) + _t('Concord'), 0.025, 0.318, 0.369, 0.372)),
(-161, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T3 (Some T5 Rooms)')) + _t('Sansha'), 0.018, 0.331, 0.332, 0.322)),
(-162, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T3 (Some T5 Rooms)')) + _t('Angel'), 0.373, 0.508, 0.457, 0.416)),
(-163, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T4/T5/T6')) + _t('Concord'), 0.008, 0.318, 0.369, 0.372)),
(-164, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T4/T5/T6')) + _t('Sansha'), 0.009, 0.331, 0.332, 0.322)),
(-165, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Electrical T4/T5/T6')) + _t('Angel'), 0.3, 0.508, 0.457, 0.416)),
(-166, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T0/T1/T2')) + _t('Concord'), 0.324, 0.107, 0.369, 0.372)),
(-167, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T0/T1/T2')) + _t('Sansha'), 0.148, 0.181, 0.329, 0.328)),
(-168, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T0/T1/T2')) + _t('Angel'), 0.587, 0.342, 0.439, 0.39)),
(-169, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T3 (Some T5 Rooms)')) + _t('Concord'), 0.324, 0.016, 0.369, 0.372)),
(-170, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T3 (Some T5 Rooms)')) + _t('Sansha'), 0.148, 0.14, 0.329, 0.328)),
(-171, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T3 (Some T5 Rooms)')) + _t('Angel'), 0.587, 0.241, 0.439, 0.39)),
(-172, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T4/T5/T6')) + _t('Concord'), 0.324, 0.004, 0.369, 0.372)),
(-173, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T4/T5/T6')) + _t('Sansha'), 0.148, 0.106, 0.329, 0.328)),
(-174, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Firestorm T4/T5/T6')) + _t('Angel'), 0.587, 0.172, 0.439, 0.39)),
(-175, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T0/T1/T2')) + _t('Concord'), 0.324, 0.318, 0.18, 0.372)),
(-176, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T0/T1/T2')) + _t('Sansha'), 0.137, 0.331, 0.166, 0.322)),
(-177, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T0/T1/T2')) + _t('Angel'), 0.582, 0.508, 0.295, 0.416)),
(-178, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T3 (Some T5 Rooms)')) + _t('Concord'), 0.324, 0.318, 0.089, 0.372)),
(-179, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T3 (Some T5 Rooms)')) + _t('Sansha'), 0.137, 0.331, 0.108, 0.322)),
(-180, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T3 (Some T5 Rooms)')) + _t('Angel'), 0.582, 0.508, 0.203, 0.416)),
(-181, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T4/T5/T6')) + _t('Concord'), 0.324, 0.318, 0.068, 0.372)),
(-182, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T4/T5/T6')) + _t('Sansha'), 0.137, 0.331, 0.073, 0.322)),
(-183, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Exotic T4/T5/T6')) + _t('Angel'), 0.582, 0.508, 0.14, 0.416)),
(-184, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T0/T1/T2')) + _t('Concord'), 0.324, 0.318, 0.369, 0.203)),
(-185, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T0/T1/T2')) + _t('Sansha'), 0.137, 0.355, 0.352, 0.16)),
(-186, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T0/T1/T2')) + _t('Angel'), 0.59, 0.528, 0.477, 0.286)),
(-187, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T3 (Some T5 Rooms)')) + _t('Concord'), 0.324, 0.318, 0.369, 0.112)),
(-188, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T3 (Some T5 Rooms)')) + _t('Sansha'), 0.137, 0.355, 0.352, 0.05)),
(-189, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T3 (Some T5 Rooms)')) + _t('Angel'), 0.59, 0.528, 0.477, 0.197)),
(-190, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T4/T5/T6')) + _t('Concord'), 0.324, 0.318, 0.369, 0.086)),
(-191, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T4/T5/T6')) + _t('Sansha'), 0.137, 0.355, 0.352, 0)),
(-192, (_c(_t('NPC')) + _c(_t('Abyssal')) + _c(_t('Gamma T4/T5/T6')) + _t('Angel'), 0.59, 0.528, 0.477, 0.126)),
(-193, (_c(_t('NPC')) + _c(_t('Invasion')) + _t('Drifter Entities'), 0.128, 0.375, 0.383, 0.383)),
(-194, (_c(_t('NPC')) + _c(_t('Invasion')) + _t('Rogue Drone Entities'), 0.104, 0.147, 0.147, 0.102)),
(-195, (_c(_t('NPC')) + _c(_t('Invasion')) + _t('Sleeper Entities'), 0.563, 0.563, 0.563, 0.563))])
class TargetProfile:

View File

@@ -211,7 +211,7 @@ def getDoomsdayMult(mod, tgt, distance, tgtSigRadius):
# Disallow only against subcaps, allow against caps and tgt profiles
if tgt.isFit and not tgt.item.ship.item.requiresSkill('Capital Ships'):
return 0
damageSig = mod.getModifiedItemAttr('doomsdayDamageRadius') or mod.getModifiedItemAttr('signatureRadius')
damageSig = mod.getModifiedItemAttr('signatureRadius')
if not damageSig:
return 1
return min(1, tgtSigRadius / damageSig)

View File

@@ -66,7 +66,7 @@ class FitShieldRegenGraph(FitGraph):
('shieldAmount', '%'): lambda v, src, tgt: v / 100 * src.item.ship.getModifiedItemAttr('shieldCapacity'),
('shieldAmountT0', '%'): lambda v, src, tgt: None if v is None else v / 100 * src.item.ship.getModifiedItemAttr('shieldCapacity'),
# Needed only for "x mark" support, to convert EHP x into normalized value
('shieldAmount', 'EHP'): lambda v, src, tgt: v / src.item.damagePattern.effectivify(src.item, 1, 'shield')}
('shieldAmount', 'EHP'): lambda v, src, tgt: v / src.item.damagePattern.effectivify(src.item.ship, 1, 'shield')}
_limiters = {
'shieldAmount': lambda src, tgt: (0, src.item.ship.getModifiedItemAttr('shieldCapacity')),
'shieldAmountT0': lambda src, tgt: (0, src.item.ship.getModifiedItemAttr('shieldCapacity'))}
@@ -77,5 +77,5 @@ class FitShieldRegenGraph(FitGraph):
('shieldAmount', 'shieldRegen'): ShieldAmount2ShieldRegenGetter}
_denormalizers = {
('shieldAmount', '%'): lambda v, src, tgt: v * 100 / src.item.ship.getModifiedItemAttr('shieldCapacity'),
('shieldAmount', 'EHP'): lambda v, src, tgt: src.item.damagePattern.effectivify(src.item, v, 'shield'),
('shieldRegen', 'EHP/s'): lambda v, src, tgt: src.item.damagePattern.effectivify(src.item, v, 'shield')}
('shieldAmount', 'EHP'): lambda v, src, tgt: src.item.damagePattern.effectivify(src.item.ship, v, 'shield'),
('shieldRegen', 'EHP/s'): lambda v, src, tgt: src.item.damagePattern.effectivify(src.item.ship, v, 'shield')}

View File

@@ -199,7 +199,7 @@ def _getAutoResists(fit):
armorHp = hpData['armor']
hullHp = hpData['hull']
uniformDamagePattern = DamagePattern(emAmount=25, thermalAmount=25, kineticAmount=25, explosiveAmount=25)
ehpData = uniformDamagePattern.calculateEhp(fit)
ehpData = uniformDamagePattern.calculateEhp(fit.ship)
shieldEhp = ehpData['shield']
armorEhp = ehpData['armor']
hullEhp = ehpData['hull']

View File

@@ -66,6 +66,8 @@ class DroneView(Display):
"Max Range",
"Miscellanea",
"attr:maxVelocity",
"Drone HP",
"Drone Regen",
"Price",
]

View File

@@ -151,6 +151,8 @@ class FighterDisplay(d.Display):
# "Max Range",
# "Miscellanea",
"attr:maxVelocity",
"Drone HP",
"Drone Regen",
"Fighter Abilities",
"Price",
]

View File

@@ -11,6 +11,7 @@ from gui.builtinContextMenus import graphFitAmmoPicker
from gui.builtinContextMenus import shipModeChange
from gui.builtinContextMenus import moduleAmmoChange
from gui.builtinContextMenus import moduleSpool
from gui.builtinContextMenus import moduleRahPattern
from gui.builtinContextMenus import boosterSideEffects
from gui.builtinContextMenus import fighterAbilities
from gui.builtinContextMenus import resistMode

View File

@@ -44,7 +44,6 @@ class AddCommandFit(ContextMenuUnconditional):
def display(self, callingWindow, srcContext):
if self.mainFrame.getActiveFit() is None or len(self.__class__.commandFits) == 0 or srcContext != "commandView":
return False
return True
def getText(self, callingWindow, itmContext):
@@ -52,6 +51,8 @@ class AddCommandFit(ContextMenuUnconditional):
def addFit(self, menu, fit, includeShip=False):
label = fit.name if not includeShip else "({}) {}".format(fit.ship.item.name, fit.name)
if not label:
label = ' '
id = ContextMenuUnconditional.nextID()
self.fitMenuItemIds[id] = fit
menuItem = wx.MenuItem(menu, id, label)

View File

@@ -1,20 +1,16 @@
from collections import OrderedDict
from itertools import chain
# noinspection PyPackageRequirements
import wx
import gui.globalEvents as GE
import gui.mainFrame
from gui.builtinContextMenus.shared.patterns import DamagePatternMixin
from gui.contextMenu import ContextMenuUnconditional
from gui.utils.sorter import smartSort
from service.damagePattern import DamagePattern as DmgPatternSvc
from service.fit import Fit
_t = wx.GetTranslation
class ChangeDamagePattern(ContextMenuUnconditional):
class ChangeDamagePattern(ContextMenuUnconditional, DamagePatternMixin):
def __init__(self):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
@@ -27,29 +23,12 @@ class ChangeDamagePattern(ContextMenuUnconditional):
return self.mainFrame.getActiveFit() is not None
def getText(self, callingWindow, itmContext):
sDP = DmgPatternSvc.getInstance()
sFit = Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
self.fit = sFit.getFit(fitID)
builtinPatterns = sDP.getBuiltinDamagePatternList()
userPatterns = sorted(sDP.getUserDamagePatternList(), key=lambda p: smartSort(p.fullName))
# 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"])
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()))
shortName = _t(pattern.shortName) if pattern.builtin else pattern.shortName
container[0][shortName] = pattern
self.patterns = self._getPatterns()
self.items = self._getItems(self.patterns)
return list(self.items[0].keys()) + list(self.items[1].keys())
def _addPattern(self, parentMenu, pattern, name):

View File

@@ -123,9 +123,7 @@ class AddEnvironmentEffect(ContextMenuUnconditional):
data.groups[_t('Abyssal Weather')] = self.getAbyssalWeather()
data.groups[_t('Sansha Incursion')] = self.getEffectBeacons(
_t('ContextMenu|ProjectedEffectManipulation|Sansha Incursion'))
data.groups[_t('Triglavian Invasion')] = self.getEffectBeacons(
_t('ContextMenu|ProjectedEffectManipulation|Triglavian Invasion'))
data.groups[_t('Triglavian Invasion')].groups[_t('Destructible Beacons')] = self.getDestructibleBeacons()
data.groups[_t('Triglavian Invasion')] = self.getInvasionBeacons()
return data
def getEffectBeacons(self, *groups, extra_garbage=()):
@@ -233,5 +231,12 @@ class AddEnvironmentEffect(ContextMenuUnconditional):
data.sort()
return data
def getInvasionBeacons(self):
data = self.getDestructibleBeacons()
# Turnur weather
item = Market.getInstance().getItem(74002)
data.items.append(Entry(item.ID, item.name, item.name))
return data
AddEnvironmentEffect.register()

View File

@@ -0,0 +1,97 @@
from collections import OrderedDict
# noinspection PyPackageRequirements
import wx
import gui.globalEvents as GE
import gui.mainFrame
from gui.builtinContextMenus.shared.patterns import DamagePatternMixin
from gui.contextMenu import ContextMenuSingle
from service.fit import Fit
_t = wx.GetTranslation
class ChangeRahPattern(ContextMenuSingle, DamagePatternMixin):
def __init__(self):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
def display(self, callingWindow, srcContext, mainItem):
if srcContext != 'fittingModule':
return False
if self.mainFrame.getActiveFit() is None:
return False
if (mainItem is None or getattr(mainItem, "isEmpty", False)) and srcContext != "fittingShip":
return False
if mainItem.item.group.name != 'Armor Resistance Shift Hardener':
return False
self.module = mainItem
self.patternEventMap = {}
self.patterns = self._getPatterns()
self.items = self._getItems(self.patterns)
return True
def getText(self, callingWindow, itmContext, mainItem):
return _t('RAH Damage Pattern')
def _addPattern(self, parentMenu, pattern, name):
id = ContextMenuSingle.nextID()
self.patternEventMap[id] = pattern
menuItem = wx.MenuItem(parentMenu, id, name, kind=wx.ITEM_CHECK)
parentMenu.Bind(wx.EVT_MENU, self.handlePatternSwitch, menuItem)
checked = self.module.rahPatternOverride is pattern
return menuItem, checked
def _addCategory(self, parentMenu, name):
id = ContextMenuSingle.nextID()
menuItem = wx.MenuItem(parentMenu, id, name)
parentMenu.Bind(wx.EVT_MENU, self.handlePatternSwitch, menuItem)
return menuItem
def getSubMenu(self, callingWindow, context, mainItem, rootMenu, i, pitem):
# Category as menu item - expands further
msw = "wxMSW" in wx.PlatformInfo
def makeMenu(container, parentMenu, root=False):
menu = wx.Menu()
if root:
menuItem, checked = self._addPattern(rootMenu if msw else parentMenu, None, 'Fit Pattern')
menu.Append(menuItem)
menuItem.Check(checked)
menuItem, checked = self._addPattern(rootMenu if msw else parentMenu, 'disable', 'Do Not Adapt')
menu.Append(menuItem)
menuItem.Check(checked)
menu.AppendSeparator()
for name, subcontainer in container[1].items():
menuItem = self._addCategory(rootMenu if msw else parentMenu, name)
subMenu = makeMenu(subcontainer, menu)
menuItem.SetSubMenu(subMenu)
menu.Append(menuItem)
for name, pattern in container[0].items():
menuItem, checked = self._addPattern(rootMenu if msw else parentMenu, pattern, name)
menu.Append(menuItem)
menuItem.Check(checked)
menu.Bind(wx.EVT_MENU, self.handlePatternSwitch)
return menu
subMenu = makeMenu(self.items, rootMenu, root=True)
return subMenu
def handlePatternSwitch(self, event):
pattern = self.patternEventMap.get(event.Id, False)
if pattern is False:
event.Skip()
return
sFit = Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
sFit.setRahPattern(fitID, self.module, pattern)
wx.PostEvent(self.mainFrame, GE.FitChanged(fitIDs=(fitID,)))
ChangeRahPattern.register()

View File

@@ -0,0 +1,35 @@
from collections import OrderedDict
from itertools import chain
# noinspection PyPackageRequirements
import wx
from gui.utils.sorter import smartSort
from service.damagePattern import DamagePattern as DmgPatternSvc
_t = wx.GetTranslation
class DamagePatternMixin:
def _getPatterns(self):
sDP = DmgPatternSvc.getInstance()
builtinPatterns = sDP.getBuiltinDamagePatternList()
userPatterns = sorted(sDP.getUserDamagePatternList(), key=lambda p: smartSort(p.fullName))
# Order here is important: patterns with duplicate names from the latter will overwrite
# patterns from the former
patterns = sorted(
chain(builtinPatterns, userPatterns),
key=lambda p: p.fullName not in ["Uniform", "Selected Ammo"])
return patterns
def _getItems(self, patterns):
items = (OrderedDict(), OrderedDict())
for pattern in patterns:
container = items
for categoryName in pattern.hierarchy:
categoryName = _t(categoryName) if pattern.builtin else categoryName
container = container[1].setdefault(categoryName, (OrderedDict(), OrderedDict()))
shortName = _t(pattern.shortName) if pattern.builtin else pattern.shortName
container[0][shortName] = pattern
return items

View File

@@ -36,6 +36,8 @@ class ItemCompare(wx.Panel):
self.item = item
self.items = sorted(items, key=defaultSort)
self.attrs = {}
self.HighlightOn = wx.Colour(255, 255, 0, wx.ALPHA_OPAQUE)
self.highlightedNames = []
# get a dict of attrName: attrInfo of all unique attributes across all items
for item in self.items:
@@ -88,6 +90,21 @@ class ItemCompare(wx.Panel):
self.toggleViewBtn.Bind(wx.EVT_TOGGLEBUTTON, self.ToggleViewMode)
self.Bind(wx.EVT_LIST_COL_CLICK, self.SortCompareCols)
self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.HighlightRow)
def HighlightRow(self, event):
itemIdx = event.GetIndex()
name = self.paramList.GetItem(itemIdx).Text
if name in self.highlightedNames:
self.highlightedNames.remove(name)
else:
self.highlightedNames.append(name)
self.Freeze()
self.paramList.ClearAll()
self.PopulateList()
self.Thaw()
event.Skip()
def SortCompareCols(self, event):
self.Freeze()
self.paramList.ClearAll()
@@ -155,6 +172,8 @@ class ItemCompare(wx.Panel):
self.paramList.InsertColumn(len(self.attrs) + 1, _t("Price"))
self.paramList.SetColumnWidth(len(self.attrs) + 1, 60)
toHighlight = []
for item in self.items:
i = self.paramList.InsertItem(self.paramList.GetItemCount(), item.name)
for x, attr in enumerate(self.attrs.keys()):
@@ -172,10 +191,19 @@ class ItemCompare(wx.Panel):
# Add prices
self.paramList.SetItem(i, len(self.attrs) + 1, formatAmount(item.price.price, 3, 3, 9, currency=True) if item.price.price else "")
if item.name in self.highlightedNames:
toHighlight.append(i)
self.paramList.RefreshRows()
self.Layout()
# Highlight after layout, otherwise colors are getting overwritten
for itemIdx in toHighlight:
listItem = self.paramList.GetItem(itemIdx)
listItem.SetBackgroundColour(self.HighlightOn)
listItem.SetFont(listItem.GetFont().MakeBold())
self.paramList.SetItem(listItem)
@staticmethod
def TranslateValueUnit(value, unitName, unitDisplayName):
def itemIDCallback():

View File

@@ -57,12 +57,6 @@ class PFFittingEnginePref(PreferenceView):
mainSizer.Add(self.cbStrictSkillLevels, 0, wx.ALL | wx.EXPAND, 5)
self.cbUniversalAdaptiveArmorHardener = wx.CheckBox(panel, wx.ID_ANY,
_t("When damage profile is Uniform, set Reactive Armor "
"Hardener to match (old behavior)."),
wx.DefaultPosition, wx.DefaultSize, 0)
mainSizer.Add(self.cbUniversalAdaptiveArmorHardener, 0, wx.ALL | wx.EXPAND, 5)
spoolup_sizer = wx.BoxSizer(wx.HORIZONTAL)
self.spool_up_label = wx.StaticText(panel, wx.ID_ANY, _t("Global Default Spoolup Percentage:"), wx.DefaultPosition, wx.DefaultSize, 0)
@@ -110,9 +104,6 @@ class PFFittingEnginePref(PreferenceView):
self.cbStrictSkillLevels.SetValue(self.engine_settings.get("strictSkillLevels"))
self.cbStrictSkillLevels.Bind(wx.EVT_CHECKBOX, self.OnCBStrictSkillLevelsChange)
self.cbUniversalAdaptiveArmorHardener.SetValue(self.engine_settings.get("useStaticAdaptiveArmorHardener"))
self.cbUniversalAdaptiveArmorHardener.Bind(wx.EVT_CHECKBOX, self.OnCBUniversalAdaptiveArmorHardenerChange)
self.spoolup_value.SetValue(int(self.engine_settings.get("globalDefaultSpoolupPercentage") * 100))
self.spoolup_value.Bind(wx.lib.intctrl.EVT_INT, self.OnSpoolupChange)
@@ -129,8 +120,6 @@ class PFFittingEnginePref(PreferenceView):
def OnCBStrictSkillLevelsChange(self, event):
self.engine_settings.set("strictSkillLevels", self.cbStrictSkillLevels.GetValue())
def OnCBUniversalAdaptiveArmorHardenerChange(self, event):
self.engine_settings.set("useStaticAdaptiveArmorHardener", self.cbUniversalAdaptiveArmorHardener.GetValue())
def getImage(self):
return BitmapLoader.getBitmap("settings_fitting", "gui")

View File

@@ -34,6 +34,13 @@ class PFEsiPref(PreferenceView):
self.stInfo.Wrap(dlgWidth - 50)
mainSizer.Add(self.stInfo, 0, wx.EXPAND | wx.TOP | wx.BOTTOM, 5)
self.enforceJwtExpiration = wx.CheckBox(panel, wx.ID_ANY, _t("Enforce Token Expiration"), wx.DefaultPosition,
wx.DefaultSize,
0)
self.enforceJwtExpiration.SetToolTip(wx.ToolTip(_t("This option is a workaround in case you cannot log into EVE SSO "
"due to 'Signature has expired' error")))
mainSizer.Add(self.enforceJwtExpiration, 0, wx.ALL | wx.EXPAND, 5)
rbSizer = wx.BoxSizer(wx.HORIZONTAL)
self.rbMode = wx.RadioBox(panel, -1, _t("Login Authentication Method"), wx.DefaultPosition, wx.DefaultSize,
[_t('Local Server'), _t('Manual')], 1, wx.RA_SPECIFY_COLS)
@@ -43,11 +50,12 @@ class PFEsiPref(PreferenceView):
" character login. Use this if having issues with the local server."))
self.rbMode.SetSelection(self.settings.get('loginMode'))
self.enforceJwtExpiration.SetValue(self.settings.get("enforceJwtExpiration" or True))
rbSizer.Add(self.rbMode, 1, wx.TOP | wx.RIGHT, 5)
self.rbMode.Bind(wx.EVT_RADIOBOX, self.OnModeChange)
self.enforceJwtExpiration.Bind(wx.EVT_CHECKBOX, self.OnEnforceChange)
mainSizer.Add(rbSizer, 1, wx.ALL | wx.EXPAND, 0)
panel.SetSizer(mainSizer)
@@ -59,6 +67,10 @@ class PFEsiPref(PreferenceView):
def OnModeChange(self, event):
self.settings.set('loginMode', event.GetInt())
def OnEnforceChange(self, event):
self.settings.set('enforceJwtExpiration', self.enforceJwtExpiration.GetValue())
event.Skip()
def getImage(self):
return BitmapLoader.getBitmap("eve", "gui")

View File

@@ -127,7 +127,9 @@ class TargetingMiscViewMinimal(StatsView):
("specialSalvageHoldCapacity", _t("Salvage hold")),
("specialCommandCenterHoldCapacity", _t("Command center hold")),
("specialPlanetaryCommoditiesHoldCapacity", _t("Planetary goods hold")),
("specialQuafeHoldCapacity", _t("Quafe hold"))))
("specialQuafeHoldCapacity", _t("Quafe hold")),
("specialMobileDepotHoldCapacity", _t("Mobile depot hold")),
))
cargoValues = {
"main": lambda: fit.ship.getModifiedItemAttr("capacity"),
@@ -148,7 +150,8 @@ class TargetingMiscViewMinimal(StatsView):
"specialSalvageHoldCapacity": lambda: fit.ship.getModifiedItemAttr("specialSalvageHoldCapacity"),
"specialCommandCenterHoldCapacity": lambda: fit.ship.getModifiedItemAttr("specialCommandCenterHoldCapacity"),
"specialPlanetaryCommoditiesHoldCapacity": lambda: fit.ship.getModifiedItemAttr("specialPlanetaryCommoditiesHoldCapacity"),
"specialQuafeHoldCapacity": lambda: fit.ship.getModifiedItemAttr("specialQuafeHoldCapacity")
"specialQuafeHoldCapacity": lambda: fit.ship.getModifiedItemAttr("specialQuafeHoldCapacity"),
"specialMobileDepotHoldCapacity": lambda: fit.ship.getModifiedItemAttr("specialMobileDepotHoldCapacity"),
}
stats = (("labelTargets", {"main": lambda: fit.maxTargets}, 3, 0, 0, ""),

View File

@@ -0,0 +1,87 @@
# =============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of pyfa.
#
# pyfa is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# pyfa is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
import gui.mainFrame
from eos.saveddata.drone import Drone
from eos.saveddata.fighter import Fighter
from service.attribute import Attribute
from gui.viewColumn import ViewColumn
from gui.bitmap_loader import BitmapLoader
from gui.utils.numberFormatter import formatAmount
_t = wx.GetTranslation
class DroneEhpColumn(ViewColumn):
name = "Drone HP"
def __init__(self, fittingView, params=None):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
if params is None:
params = {"showIcon": True, "displayName": False}
ViewColumn.__init__(self, fittingView)
sAttr = Attribute.getInstance()
info = sAttr.getAttributeInfo("shieldCapacity")
self.info = info
if params["showIcon"]:
iconFile = info.iconID
if iconFile:
self.imageId = fittingView.imageList.GetImageIndex(iconFile, "icons")
self.bitmap = BitmapLoader.getBitmap(iconFile, "icons")
else:
self.imageId = -1
self.mask = wx.LIST_MASK_IMAGE
else:
self.imageId = -1
if params["displayName"] or self.imageId == -1:
self.columnText = info.displayName if info.displayName != "" else info.name
self.mask |= wx.LIST_MASK_TEXT
def getText(self, stuff):
if not isinstance(stuff, (Drone, Fighter)):
return ""
if self.mainFrame.statsPane.nameViewMap["resistancesViewFull"].showEffective:
ehp = sum(stuff.ehp.values())
else:
ehp = sum(stuff.hp.values())
return formatAmount(ehp, 3, 0, 9)
def getImageId(self, mod):
return -1
def getParameters(self):
return ("displayName", bool, False), ("showIcon", bool, True)
def getToolTip(self, stuff):
if not isinstance(stuff, (Drone, Fighter)):
return ""
if self.mainFrame.statsPane.nameViewMap["resistancesViewFull"].showEffective:
return _t("Effective HP")
else:
return _t("HP")
DroneEhpColumn.register()

View File

@@ -0,0 +1,81 @@
# =============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of pyfa.
#
# pyfa is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# pyfa is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
import gui.mainFrame
from eos.saveddata.drone import Drone
from eos.saveddata.fighter import Fighter
from gui.viewColumn import ViewColumn
from gui.bitmap_loader import BitmapLoader
from gui.utils.numberFormatter import formatAmount
_t = wx.GetTranslation
class DroneRegenColumn(ViewColumn):
name = "Drone Regen"
def __init__(self, fittingView, params=None):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
if params is None:
params = {"showIcon": True, "displayName": False}
ViewColumn.__init__(self, fittingView)
if params["showIcon"]:
self.imageId = fittingView.imageList.GetImageIndex("shieldPassive_small", "gui")
self.bitmap = BitmapLoader.getBitmap("shieldPassive_small", "gui")
self.mask = wx.LIST_MASK_IMAGE
else:
self.imageId = -1
if params["displayName"] or self.imageId == -1:
self.columnText = _("Misc data")
self.mask |= wx.LIST_MASK_TEXT
def getText(self, stuff):
if not isinstance(stuff, (Drone, Fighter)):
return ""
regen = stuff.calculateShieldRecharge()
if (
self.mainFrame.statsPane.nameViewMap["resistancesViewFull"].showEffective
and stuff.owner and stuff.owner.damagePattern is not None
):
regen = stuff.owner.damagePattern.effectivify(stuff, regen, 'shield')
return '{}/s'.format(formatAmount(regen, 3, 0, 9))
def getImageId(self, mod):
return -1
def getParameters(self):
return ("displayName", bool, False), ("showIcon", bool, True)
def getToolTip(self, stuff):
if not isinstance(stuff, (Drone, Fighter)):
return ""
if self.mainFrame.statsPane.nameViewMap["resistancesViewFull"].showEffective:
return _t("Effective Shield Regeneration")
else:
return _t("Shield Regeneration")
DroneRegenColumn.register()

View File

@@ -182,6 +182,13 @@ class Miscellanea(ViewColumn):
text = "{0} | {1}".format(formatAmount(strength, 3, 0, 3), formatAmount(coherence, 3, 0, 3))
tooltip = "Virus strength and coherence"
return text, tooltip
elif itemGroup == "Damage Control":
duration = stuff.getModifiedItemAttr("duration")
if not duration:
return "", None
text = "{0}s".format(formatAmount(duration / 1000, 3, 0, 0))
tooltip = "Assault ability duration"
return text, tooltip
elif itemGroup in ("Warp Scrambler", "Warp Core Stabilizer", "Structure Warp Scrambler"):
scramStr = stuff.getModifiedItemAttr("warpScrambleStrength")
if not scramStr:

View File

@@ -516,7 +516,10 @@ class SkillTreeView(wx.Panel):
def populateSkillTreeSkillSearch(self, event=None):
sChar = Character.getInstance()
char = self.charEditor.entityEditor.getActiveEntity()
search = self.searchInput.GetLineText(0)
try:
search = self.searchInput.GetLineText(0)
except AttributeError:
search = self.searchInput.GetValue()
root = self.root
tree = self.skillTreeListCtrl

View File

@@ -22,6 +22,7 @@ import traceback
# noinspection PyPackageRequirements
import wx
import roman
from logbook import Logger
import config
@@ -105,6 +106,9 @@ class CharacterSelection(wx.Panel):
exportItem = menu.Append(wx.ID_ANY, _t("Copy Missing Skills"))
self.Bind(wx.EVT_MENU, self.exportSkills, exportItem)
exportItem = menu.Append(wx.ID_ANY, _t("Copy Missing Skills (EVEMon)"))
self.Bind(wx.EVT_MENU, self.exportSkillsEveMon, exportItem)
self.PopupMenu(menu, pos)
event.Skip()
@@ -264,6 +268,15 @@ class CharacterSelection(wx.Panel):
toClipboard(list)
def exportSkillsEveMon(self, evt):
skillsMap = self._buildSkillsTooltipCondensed(self.reqs, skillsMap={})
list = ""
for key in sorted(skillsMap):
list += "%s %s\n" % (key, roman.toRoman(skillsMap[key][0]))
toClipboard(list)
def _buildSkillsTooltip(self, reqs, currItem="", tabulationLevel=0):
tip = ""
sCharacter = Character.getInstance()

View File

@@ -193,7 +193,7 @@ class CopySelectDialog(wx.Dialog):
def exportEsi(self, options, callback):
fit = getFit(self.mainFrame.getActiveFit())
Port.exportESI(fit, True, callback)
Port.exportESI(fit, False, False, False, callback)
def exportXml(self, options, callback):
fit = getFit(self.mainFrame.getActiveFit())

View File

@@ -283,7 +283,7 @@ class ExportToEve(AuxiliaryFrame):
def __init__(self, parent):
super().__init__(
parent, id=wx.ID_ANY, title=_t("Export fit to EVE"), pos=wx.DefaultPosition,
size=wx.Size(400, 140) if "wxGTK" in wx.PlatformInfo else wx.Size(350, 115), resizeable=True)
size=wx.Size(400, 175) if "wxGTK" in wx.PlatformInfo else wx.Size(350, 145), resizeable=True)
self.mainFrame = parent
@@ -305,6 +305,16 @@ class ExportToEve(AuxiliaryFrame):
self.exportChargesCb.Bind(wx.EVT_CHECKBOX, self.OnChargeExportChange)
mainSizer.Add(self.exportChargesCb, 0, 0, 5)
self.exportImplantsCb = wx.CheckBox(self, wx.ID_ANY, _t('Export Implants'), wx.DefaultPosition, wx.DefaultSize, 0)
self.exportImplantsCb.SetValue(EsiSettings.getInstance().get('exportImplants'))
self.exportImplantsCb.Bind(wx.EVT_CHECKBOX, self.OnImplantsExportChange)
mainSizer.Add(self.exportImplantsCb, 0, 0, 5)
self.exportBoostersCb = wx.CheckBox(self, wx.ID_ANY, _t('Export Boosters'), wx.DefaultPosition, wx.DefaultSize, 0)
self.exportBoostersCb.SetValue(EsiSettings.getInstance().get('exportBoosters'))
self.exportBoostersCb.Bind(wx.EVT_CHECKBOX, self.OnBoostersExportChange)
mainSizer.Add(self.exportBoostersCb, 0, 0, 5)
self.exportBtn.Bind(wx.EVT_BUTTON, self.exportFitting)
self.statusbar = wx.StatusBar(self)
@@ -324,6 +334,14 @@ class ExportToEve(AuxiliaryFrame):
EsiSettings.getInstance().set('exportCharges', self.exportChargesCb.GetValue())
event.Skip()
def OnImplantsExportChange(self, event):
EsiSettings.getInstance().set('exportImplants', self.exportImplantsCb.GetValue())
event.Skip()
def OnBoostersExportChange(self, event):
EsiSettings.getInstance().set('exportBoosters', self.exportBoostersCb.GetValue())
event.Skip()
def updateCharList(self):
sEsi = Esi.getInstance()
chars = sEsi.getSsoCharacters()
@@ -360,8 +378,10 @@ class ExportToEve(AuxiliaryFrame):
sFit = Fit.getInstance()
exportCharges = self.exportChargesCb.GetValue()
exportImplants = self.exportImplantsCb.GetValue()
exportBoosters = self.exportBoostersCb.GetValue()
try:
data = sPort.exportESI(sFit.getFit(fitID), exportCharges)
data = sPort.exportESI(sFit.getFit(fitID), exportCharges, exportImplants, exportBoosters)
except ESIExportException as e:
msg = str(e)
if not msg:

View File

@@ -58,7 +58,9 @@ class InternalCommandHistory:
class ModuleInfo:
def __init__(self, itemID, baseItemID=None, mutaplasmidID=None, mutations=None, chargeID=None, state=None, spoolType=None, spoolAmount=None):
def __init__(
self, itemID, baseItemID=None, mutaplasmidID=None, mutations=None, chargeID=None,
state=None, spoolType=None, spoolAmount=None, rahPattern=None):
self.itemID = itemID
self.baseItemID = baseItemID
self.mutaplasmidID = mutaplasmidID
@@ -67,6 +69,7 @@ class ModuleInfo:
self.state = state
self.spoolType = spoolType
self.spoolAmount = spoolAmount
self.rahPattern = rahPattern
@classmethod
def fromModule(cls, mod, unmutate=False):
@@ -81,7 +84,8 @@ class ModuleInfo:
chargeID=mod.chargeID,
state=mod.state,
spoolType=mod.spoolType,
spoolAmount=mod.spoolAmount)
spoolAmount=mod.spoolAmount,
rahPattern=mod.rahPatternOverride)
else:
info = cls(
itemID=mod.itemID,
@@ -91,7 +95,8 @@ class ModuleInfo:
chargeID=mod.chargeID,
state=mod.state,
spoolType=mod.spoolType,
spoolAmount=mod.spoolAmount)
spoolAmount=mod.spoolAmount,
rahPattern=mod.rahPatternOverride)
return info
def toModule(self, fallbackState=None):
@@ -119,6 +124,8 @@ class ModuleInfo:
mod.spoolType = self.spoolType
mod.spoolAmount = self.spoolAmount
mod.rahPatternOverride = self.rahPattern
if self.state is not None:
if mod.isValidState(self.state):
mod.state = self.state
@@ -148,12 +155,13 @@ class ModuleInfo:
self.chargeID == other.chargeID,
self.state == other.state,
self.spoolType == other.spoolType,
self.spoolAmount == other.spoolAmount))
self.spoolAmount == other.spoolAmount,
self.rahPattern == other.rahPattern))
def __repr__(self):
return makeReprStr(self, [
'itemID', 'baseItemID', 'mutaplasmidID', 'mutations',
'chargeID', 'state', 'spoolType', 'spoolAmount'])
'chargeID', 'state', 'spoolType', 'spoolAmount', 'rahPattern'])
class DroneInfo:

View File

@@ -78,6 +78,8 @@ from gui.builtinViewColumns import ( # noqa: E402, F401
baseName,
capacitorUse,
dampScanRes,
droneEhp,
droneRegen,
graphColor,
graphLightness,
graphLineStyle,

Binary file not shown.

After

Width:  |  Height:  |  Size: 662 B

BIN
imgs/icons/1168@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 857 B

BIN
imgs/icons/1168@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 812 B

After

Width:  |  Height:  |  Size: 433 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 944 B

BIN
imgs/icons/21831@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 812 B

BIN
imgs/icons/21831@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
imgs/icons/21894@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 808 B

BIN
imgs/icons/21894@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
imgs/icons/24296@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

BIN
imgs/icons/24296@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
imgs/icons/24404@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 676 B

BIN
imgs/icons/24404@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
imgs/icons/24409@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 701 B

BIN
imgs/icons/24409@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
imgs/icons/24411@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 849 B

BIN
imgs/icons/24411@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
imgs/icons/24419@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 640 B

BIN
imgs/icons/24419@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 822 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

BIN
imgs/icons/24585@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 878 B

BIN
imgs/icons/24585@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 796 B

After

Width:  |  Height:  |  Size: 787 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
imgs/icons/25240@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 784 B

BIN
imgs/icons/25240@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
imgs/icons/25241@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 808 B

BIN
imgs/icons/25241@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
imgs/icons/25242@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 829 B

BIN
imgs/icons/25242@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
imgs/icons/25243@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 833 B

BIN
imgs/icons/25243@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
imgs/icons/25250@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 782 B

BIN
imgs/icons/25250@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
imgs/icons/25251@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 816 B

BIN
imgs/icons/25251@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
imgs/icons/25252@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 823 B

BIN
imgs/icons/25252@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
imgs/icons/25253@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 814 B

BIN
imgs/icons/25253@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
imgs/icons/25255@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 787 B

BIN
imgs/icons/25255@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
imgs/icons/25256@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 836 B

BIN
imgs/icons/25256@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
imgs/icons/25257@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 846 B

BIN
imgs/icons/25257@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
imgs/icons/25258@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 848 B

BIN
imgs/icons/25258@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
imgs/icons/25259@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 816 B

BIN
imgs/icons/25259@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
imgs/icons/25260@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 778 B

BIN
imgs/icons/25260@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
imgs/icons/25261@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 835 B

BIN
imgs/icons/25261@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

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