Compare commits
576 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7131cdbac6 | ||
|
|
b70c1a7c6c | ||
|
|
f9fd265280 | ||
|
|
9261d29ac1 | ||
|
|
df658d4950 | ||
|
|
69f68bf4ea | ||
|
|
614f3acc7e | ||
|
|
ec77acda1d | ||
|
|
603553517e | ||
|
|
4c04fd93ae | ||
|
|
f4f92b0821 | ||
|
|
3aede13136 | ||
|
|
d171548936 | ||
|
|
3d0db365af | ||
|
|
2716214816 | ||
|
|
91a46a2dd4 | ||
|
|
9fd70a4ba9 | ||
|
|
400bb10ed3 | ||
|
|
53915eb956 | ||
|
|
5457c31148 | ||
|
|
be9ac7cc9c | ||
|
|
3e2d21ea44 | ||
|
|
be374f4eb4 | ||
|
|
ab200ef74b | ||
|
|
3e1ef6e76d | ||
|
|
9fd0f016aa | ||
|
|
ae188826ae | ||
|
|
0736085676 | ||
|
|
fa4c48c6c2 | ||
|
|
82adccadda | ||
|
|
f100971fbe | ||
|
|
af2da86f6f | ||
|
|
5af211778b | ||
|
|
4c739308f9 | ||
|
|
98e834fd30 | ||
|
|
7ae8d1dc1a | ||
|
|
e57fce39fe | ||
|
|
fd54d2c28c | ||
|
|
b5c411349c | ||
|
|
4d31c8bb38 | ||
|
|
fbf3cace10 | ||
|
|
30b12b04e8 | ||
|
|
9301bb56fa | ||
|
|
bc4c35665e | ||
|
|
64bba0cfdb | ||
|
|
a270dc44d2 | ||
|
|
46fa1eb0c6 | ||
|
|
c7ed6367f9 | ||
|
|
9523c6f349 | ||
|
|
8b0f5f871c | ||
|
|
3fa5ac7858 | ||
|
|
4c0f88cdfa | ||
|
|
0fedb17586 | ||
|
|
960bef2b96 | ||
|
|
82777d0b02 | ||
|
|
a560597a85 | ||
|
|
59fb7bcd1b | ||
|
|
801f51b89c | ||
|
|
0b49bf201f | ||
|
|
cc8575b275 | ||
|
|
51a11edc36 | ||
|
|
4a6c1c3920 | ||
|
|
1cb0081420 | ||
|
|
d61d69188f | ||
|
|
a829efa7ff | ||
|
|
e6599d1a40 | ||
|
|
c4c68a4e93 | ||
|
|
f80244d560 | ||
|
|
a8684ef1b9 | ||
|
|
5ac9604fab | ||
|
|
700e249bf3 | ||
|
|
c2b742304e | ||
|
|
c2b0257449 | ||
|
|
0d90c187f2 | ||
|
|
88acec4241 | ||
|
|
9a6255cb29 | ||
|
|
c721869dfa | ||
|
|
1154435a89 | ||
|
|
6d9e60648e | ||
|
|
4522edb814 | ||
|
|
8139d88a52 | ||
|
|
353b845102 | ||
|
|
c3bffcad34 | ||
|
|
9e6031edf2 | ||
|
|
bb47df2119 | ||
|
|
aab9b39fea | ||
|
|
1ca4c73a3e | ||
|
|
7f870cf675 | ||
|
|
5f8ccb9831 | ||
|
|
c94acd9718 | ||
|
|
1733d6abb8 | ||
|
|
aa9f16d3ad | ||
|
|
c997661f3a | ||
|
|
6174bf8a0b | ||
|
|
36c19fe6e8 | ||
|
|
e6c9db3eef | ||
|
|
336af0f669 | ||
|
|
2800637a90 | ||
|
|
1fb9936893 | ||
|
|
d738ba615e | ||
|
|
e5a694384d | ||
|
|
1d98f889fd | ||
|
|
ad03f907fa | ||
|
|
5579929f83 | ||
|
|
e90e9a5ca1 | ||
|
|
2341650437 | ||
|
|
f2c26af791 | ||
|
|
fc82e45d6c | ||
|
|
1b54f07ce0 | ||
|
|
938fa11d13 | ||
|
|
a08aa77afc | ||
|
|
4cbeb34a3e | ||
|
|
d2fab0a10e | ||
|
|
a8c3612248 | ||
|
|
50e4e6fdcf | ||
|
|
69ada4f3ad | ||
|
|
3fc77d03b4 | ||
|
|
8072bb600c | ||
|
|
fda2c43a1d | ||
|
|
7fc98037a6 | ||
|
|
b51c8d8ecf | ||
|
|
dca2db5a6d | ||
|
|
fbb192404f | ||
|
|
7e41d8e20c | ||
|
|
9460998015 | ||
|
|
86056bf282 | ||
|
|
bacb374ea4 | ||
|
|
8d07f11aa4 | ||
|
|
b6a13b32de | ||
|
|
1f1a16f896 | ||
|
|
444d7af7ed | ||
|
|
e45e0b9444 | ||
|
|
33886aea1b | ||
|
|
1ddc2edd88 | ||
|
|
01b16ec5f0 | ||
|
|
ba337599c2 | ||
|
|
211a83defd | ||
|
|
091a7d7ab8 | ||
|
|
b3030bacf9 | ||
|
|
feb164a48e | ||
|
|
b3a556e70a | ||
|
|
9d322ca862 | ||
|
|
9bde08b1ce | ||
|
|
953a67e2c4 | ||
|
|
2435e08dc0 | ||
|
|
31645d20a5 | ||
|
|
5fa96c5e52 | ||
|
|
278d946f77 | ||
|
|
9b8aa67271 | ||
|
|
af197e56cf | ||
|
|
1d5ba89f2e | ||
|
|
f45ad5ceab | ||
|
|
5dae614fa1 | ||
|
|
c144c16a7f | ||
|
|
10425cd5d9 | ||
|
|
1d208a0cf7 | ||
|
|
db07f9d534 | ||
|
|
ca4eeed8d1 | ||
|
|
292d95f6f8 | ||
|
|
bd5ee32227 | ||
|
|
0a705d1d7f | ||
|
|
be1bd24a05 | ||
|
|
a9fb3501ac | ||
|
|
b8a8f9c422 | ||
|
|
6c29b3f38b | ||
|
|
f784f45b4e | ||
|
|
d59111eef5 | ||
|
|
99a2a38f9c | ||
|
|
768c1d37b1 | ||
|
|
b21cf5673f | ||
|
|
a6b8381e25 | ||
|
|
7d8768ca3e | ||
|
|
96e0a02d5c | ||
|
|
6a2bdade80 | ||
|
|
ea9eb3a8b7 | ||
|
|
9c5fe56981 | ||
|
|
8fed78d596 | ||
|
|
3c5846a983 | ||
|
|
fa0892032f | ||
|
|
ed7dd12258 | ||
|
|
1a5fc31e25 | ||
|
|
facb0b1023 | ||
|
|
6dd737cdd1 | ||
|
|
5d012d6959 | ||
|
|
b00dbbbf42 | ||
|
|
b269381818 | ||
|
|
fa72345bcf | ||
|
|
3229652efa | ||
|
|
c02cccf415 | ||
|
|
54277ebbda | ||
|
|
78c6d4f005 | ||
|
|
37ad2faa8e | ||
|
|
26cba1c47a | ||
|
|
f95420d7bf | ||
|
|
9c79fb666b | ||
|
|
a9a9fd1b1a | ||
|
|
253d3107a0 | ||
|
|
656a7fc784 | ||
|
|
be579cfaeb | ||
|
|
d40a7c2efa | ||
|
|
8ba05409e0 | ||
|
|
2b817c5d22 | ||
|
|
ba445e7d4f | ||
|
|
b836ceb216 | ||
|
|
dfa0373497 | ||
|
|
caefd4fbbb | ||
|
|
b7528d11b2 | ||
|
|
07d333d3d5 | ||
|
|
48ac6cb2af | ||
|
|
87a246204b | ||
|
|
3ef056225b | ||
|
|
4fa63aa2bd | ||
|
|
1edaf021da | ||
|
|
37b44befac | ||
|
|
efd58a80a4 | ||
|
|
e43cce20a6 | ||
|
|
0c7601b6d3 | ||
|
|
4cfcfedc14 | ||
|
|
0024bc5514 | ||
|
|
aacb95df7c | ||
|
|
854d60792e | ||
|
|
d922bf8913 | ||
|
|
703dc93dee | ||
|
|
7fd545aad4 | ||
|
|
a69730085f | ||
|
|
1603201166 | ||
|
|
ead8238d7e | ||
|
|
8380f516e8 | ||
|
|
1b7c23b1d3 | ||
|
|
295368635b | ||
|
|
6291fe1626 | ||
|
|
cdaf5cc168 | ||
|
|
5940625e24 | ||
|
|
549353dba1 | ||
|
|
4dc281b37e | ||
|
|
0242cc845c | ||
|
|
e9c6d98db8 | ||
|
|
86459faf76 | ||
|
|
e8af636831 | ||
|
|
eea7220e3d | ||
|
|
cc56611783 | ||
|
|
0b511af48a | ||
|
|
25bbf3dc03 | ||
|
|
72a602b5b0 | ||
|
|
d107156341 | ||
|
|
8063647bba | ||
|
|
573d8e068c | ||
|
|
f6c6f9a0c9 | ||
|
|
d9c5c9cc0e | ||
|
|
bb7fb022ef | ||
|
|
52c9f4076b | ||
|
|
894231b009 | ||
|
|
34fe530ac7 | ||
|
|
33b91a79ab | ||
|
|
51180a9375 | ||
|
|
6e44963d57 | ||
|
|
8114765236 | ||
|
|
7ddd3a35d1 | ||
|
|
52a68adb11 | ||
|
|
566e7fd046 | ||
|
|
a74cdc59bd | ||
|
|
3c98aad4ba | ||
|
|
0063840cfa | ||
|
|
96077ed115 | ||
|
|
19f02ef914 | ||
|
|
de9ce47bed | ||
|
|
ccd3665115 | ||
|
|
1a992a90ad | ||
|
|
fff07078dc | ||
|
|
81d040fba6 | ||
|
|
a35f04cd9a | ||
|
|
c6c364c451 | ||
|
|
8dcc3f2b51 | ||
|
|
42383cef03 | ||
|
|
579081393b | ||
|
|
2290281024 | ||
|
|
712c49d129 | ||
|
|
ac16b19d93 | ||
|
|
51b3cff4a9 | ||
|
|
768b0b3a3a | ||
|
|
538271d737 | ||
|
|
61da8be732 | ||
|
|
90e275e386 | ||
|
|
8e98af8517 | ||
|
|
9a16c579eb | ||
|
|
8b864692fb | ||
|
|
eaddc942a0 | ||
|
|
82c5ae1fe9 | ||
|
|
5c2df66335 | ||
|
|
afa8c3c53a | ||
|
|
bd33efa875 | ||
|
|
f53c8e9efc | ||
|
|
d2b306d030 | ||
|
|
f58c8ec4f9 | ||
|
|
dd9390384e | ||
|
|
22fc6cb13c | ||
|
|
aaec82e493 | ||
|
|
6333a0c74b | ||
|
|
41711706c0 | ||
|
|
e6309bb8bb | ||
|
|
909c9f7b71 | ||
|
|
becf7c3ff2 | ||
|
|
257df58c3a | ||
|
|
23d945c7f2 | ||
|
|
e3971c995e | ||
|
|
8641c41da6 | ||
|
|
b7f53e8402 | ||
|
|
1ef517d87e | ||
|
|
c3e03f2136 | ||
|
|
4d31c2a2a3 | ||
|
|
b03860e765 | ||
|
|
2e49aa1419 | ||
|
|
647c093451 | ||
|
|
d96146034a | ||
|
|
b944f27fc8 | ||
|
|
df80449b0b | ||
|
|
986ae16eaf | ||
|
|
f81cc4ad93 | ||
|
|
c9b0322c9f | ||
|
|
114d72e23f | ||
|
|
f8e6474b39 | ||
|
|
8d0c2c18d2 | ||
|
|
dddec72f13 | ||
|
|
9cfbaf3450 | ||
|
|
9fc16cb287 | ||
|
|
78836add28 | ||
|
|
f919e23360 | ||
|
|
ec3822a6da | ||
|
|
9bdb4ea967 | ||
|
|
af17a4f1c9 | ||
|
|
2ea3394845 | ||
|
|
65dff8dcf7 | ||
|
|
bfaad631bc | ||
|
|
96a5bf7ea9 | ||
|
|
e665161dc8 | ||
|
|
18e03e46c3 | ||
|
|
d9941945e0 | ||
|
|
75d5b48df8 | ||
|
|
8c8e7825e9 | ||
|
|
af3a7553ed | ||
|
|
f68ee81634 | ||
|
|
4385b3651f | ||
|
|
ed24e7a2a3 | ||
|
|
b9e68504ed | ||
|
|
1fcd95d36f | ||
|
|
4dc70dad3b | ||
|
|
e0a54c14e2 | ||
|
|
839d025885 | ||
|
|
8d183a859d | ||
|
|
09bc1eb9d2 | ||
|
|
c6f2072bb9 | ||
|
|
7d42f8dba6 | ||
|
|
8b86f14ee2 | ||
|
|
ef7195a7cc | ||
|
|
43e88fa78d | ||
|
|
5d0900337f | ||
|
|
a5a9dc0877 | ||
|
|
e36b9661f0 | ||
|
|
c66f80d6e5 | ||
|
|
0dfe6707a7 | ||
|
|
f9eef5ee07 | ||
|
|
dc3b5c916b | ||
|
|
0471cda64e | ||
|
|
b2bcdf0a46 | ||
|
|
cf9d2082ef | ||
|
|
032b1589ad | ||
|
|
410c87ed89 | ||
|
|
b377c1c25f | ||
|
|
fbce3536da | ||
|
|
7ac24ff7ee | ||
|
|
7aba11142f | ||
|
|
704042b4b7 | ||
|
|
21dd9bb6e4 | ||
|
|
509849fbf5 | ||
|
|
55f2ebf4a4 | ||
|
|
e96a836ad0 | ||
|
|
2a224e8882 | ||
|
|
0a00d86c6d | ||
|
|
c3d1eaef2a | ||
|
|
93f23b549b | ||
|
|
b3d0554df6 | ||
|
|
dba54e3ec8 | ||
|
|
2b16a8ed76 | ||
|
|
4cbafb5559 | ||
|
|
d02623e365 | ||
|
|
c8eef489da | ||
|
|
d507927ba3 | ||
|
|
09421db28e | ||
|
|
941edd6715 | ||
|
|
fdac5309ac | ||
|
|
449c7d6aa2 | ||
|
|
b60b190b81 | ||
|
|
3cb8313669 | ||
|
|
ba29376464 | ||
|
|
436113dedc | ||
|
|
9dc0ec67d4 | ||
|
|
194ebb96a7 | ||
|
|
fc04a32913 | ||
|
|
deee6fd6ab | ||
|
|
a4fae73a1e | ||
|
|
7bad3bc376 | ||
|
|
7dd1c63898 | ||
|
|
c8eea45454 | ||
|
|
3ed949395e | ||
|
|
6ebc90b8aa | ||
|
|
7769179104 | ||
|
|
cbd1a34c68 | ||
|
|
e0c389a643 | ||
|
|
6a27ae7525 | ||
|
|
591dcffa43 | ||
|
|
b0317ea560 | ||
|
|
9eea99f600 | ||
|
|
d55d6c3e5e | ||
|
|
eeef2104c2 | ||
|
|
2098ff6da1 | ||
|
|
fb5d62304c | ||
|
|
8baac1e207 | ||
|
|
4324b846e0 | ||
|
|
143606d8f8 | ||
|
|
dfc0a896c4 | ||
|
|
980c84b911 | ||
|
|
41b6000f6e | ||
|
|
28fc845250 | ||
|
|
193faaafe7 | ||
|
|
ce9db79552 | ||
|
|
672fd77bec | ||
|
|
89656b04ad | ||
|
|
0997a54324 | ||
|
|
59569d46ae | ||
|
|
3bc1ce195c | ||
|
|
98e6781077 | ||
|
|
f2deb0e6c7 | ||
|
|
a5efea56ab | ||
|
|
1fe35f5aab | ||
|
|
07b8f5b914 | ||
|
|
1f50e7cb51 | ||
|
|
572d337935 | ||
|
|
01f8c65304 | ||
|
|
a1ee8b49ef | ||
|
|
0745ed50e0 | ||
|
|
76e66a99ff | ||
|
|
3259cc3e50 | ||
|
|
5f237e578b | ||
|
|
c645c089dd | ||
|
|
436bee1e85 | ||
|
|
dc5bd7f627 | ||
|
|
d6825fb8b7 | ||
|
|
b9ec89e9c8 | ||
|
|
cc63e62154 | ||
|
|
cc134c36e2 | ||
|
|
17313bd67b | ||
|
|
b831dfbc7f | ||
|
|
b739b791d4 | ||
|
|
0480673460 | ||
|
|
7ffced2151 | ||
|
|
3297ef8975 | ||
|
|
acba971e70 | ||
|
|
dd8169adb4 | ||
|
|
857a625ae2 | ||
|
|
ac3a7386aa | ||
|
|
3eed5bfc64 | ||
|
|
d0992ed56f | ||
|
|
af37ec21e9 | ||
|
|
51ef3ec758 | ||
|
|
f66da9870e | ||
|
|
ca46984a6b | ||
|
|
fe063cf19a | ||
|
|
3bdb12cc5d | ||
|
|
6819dc87a6 | ||
|
|
2ba6c4bc08 | ||
|
|
bb548b796a | ||
|
|
6f8fca7525 | ||
|
|
ff8ea205db | ||
|
|
453536cf14 | ||
|
|
080d94e299 | ||
|
|
ae23fba6b7 | ||
|
|
b8f53f9bb3 | ||
|
|
e143a79b06 | ||
|
|
fa7c93d99a | ||
|
|
f48ce43c0c | ||
|
|
ba12d97c1d | ||
|
|
03e8b8522b | ||
|
|
7a8baac5bd | ||
|
|
58ceff6144 | ||
|
|
7bc82e229f | ||
|
|
74ebd3415c | ||
|
|
de752cbe0a | ||
|
|
25c5abffee | ||
|
|
ec1a2035cd | ||
|
|
b3fbc080db | ||
|
|
f289a72121 | ||
|
|
e6b2d15468 | ||
|
|
e76dc2e92b | ||
|
|
10572c7dbd | ||
|
|
e83e081548 | ||
|
|
85a834d1a3 | ||
|
|
46c95d722c | ||
|
|
70831bb5e4 | ||
|
|
12227cd016 | ||
|
|
2749426a7c | ||
|
|
0a23c3cabb | ||
|
|
5a0670838d | ||
|
|
2dfdead656 | ||
|
|
5fdae11bb1 | ||
|
|
c991562662 | ||
|
|
b4eb6e7fc3 | ||
|
|
d4e8ac761e | ||
|
|
30ff2e0dae | ||
|
|
4f0f8fcdfc | ||
|
|
a1c3d26b73 | ||
|
|
aa3043b0ca | ||
|
|
2d9dcc624c | ||
|
|
aa80a4812d | ||
|
|
5b03d01d32 | ||
|
|
3228c7f74d | ||
|
|
5b60abf4b6 | ||
|
|
47a97772cf | ||
|
|
f4123310ae | ||
|
|
f05439989d | ||
|
|
1df7c0aff8 | ||
|
|
29fde786fb | ||
|
|
4833fc68a0 | ||
|
|
3f0fc3c44b | ||
|
|
375e8de33f | ||
|
|
9d04f06f69 | ||
|
|
0297ec47f6 | ||
|
|
75e1e48ba8 | ||
|
|
89ff9a3d77 | ||
|
|
6fa1593ddc | ||
|
|
d404d10bfe | ||
|
|
194c159379 | ||
|
|
791b6e15d4 | ||
|
|
882e39417d | ||
|
|
8b6d32fe3b | ||
|
|
715f9427d5 | ||
|
|
78b281cf3a | ||
|
|
bbede00cc4 | ||
|
|
e6da57ab57 | ||
|
|
9e08783802 | ||
|
|
1dc98ce33d | ||
|
|
c97750a593 | ||
|
|
aa7e3bd69d | ||
|
|
5a6b9114e2 | ||
|
|
61abcf3018 | ||
|
|
4845b3b0ce | ||
|
|
8f0e8f72cd | ||
|
|
96269a7777 | ||
|
|
bdcc05b7b6 | ||
|
|
060b512bcf | ||
|
|
3907c8c29a | ||
|
|
c786012b28 | ||
|
|
37a084e1d1 | ||
|
|
b9c3675894 | ||
|
|
60ecc95049 | ||
|
|
59d9d47a56 | ||
|
|
c619efa68e | ||
|
|
05e895e7b7 | ||
|
|
58daf2a543 | ||
|
|
0294684bb8 | ||
|
|
fa9b3be41c | ||
|
|
74bf3fbc8b | ||
|
|
dc2a4d4446 | ||
|
|
b0895611d6 | ||
|
|
f664a1cad3 | ||
|
|
f39ba27a13 | ||
|
|
fd43f33871 | ||
|
|
36bf4ef9ca | ||
|
|
63f9847406 | ||
|
|
46f5a592ce | ||
|
|
38f1314c05 | ||
|
|
46ece5da0c | ||
|
|
d21ccef269 | ||
|
|
d788abcab2 | ||
|
|
d2b601dd8f | ||
|
|
c27032ef64 | ||
|
|
7374b00883 |
145
.appveyor.yml
145
.appveyor.yml
@@ -1,5 +1,4 @@
|
||||
environment:
|
||||
|
||||
global:
|
||||
# SDK v7.0 MSVC Express 2008's SetEnv.cmd script will fail if the
|
||||
# /E:ON and /V:ON options are not enabled in the batch script intepreter
|
||||
@@ -8,76 +7,11 @@ environment:
|
||||
|
||||
matrix:
|
||||
|
||||
# Python 2.7.10 is the latest version and is not pre-installed.
|
||||
|
||||
- PYTHON: "C:\\Python27.10"
|
||||
PYTHON_VERSION: "2.7.10"
|
||||
- PYTHON: "C:\\Python36"
|
||||
PYTHON_VERSION: "3.6.x"
|
||||
PYTHON_ARCH: "32"
|
||||
|
||||
#- PYTHON: "C:\\Python27.10-x64"
|
||||
# PYTHON_VERSION: "2.7.10"
|
||||
# PYTHON_ARCH: "64"
|
||||
|
||||
# Pre-installed Python versions, which Appveyor may upgrade to
|
||||
# a later point release.
|
||||
# See: http://www.appveyor.com/docs/installed-software#python
|
||||
|
||||
#- PYTHON: "C:\\Python27"
|
||||
# PYTHON_VERSION: "2.7.x" # currently 2.7.9
|
||||
# PYTHON_ARCH: "32"
|
||||
|
||||
#- PYTHON: "C:\\Python27-x64"
|
||||
# PYTHON_VERSION: "2.7.x" # currently 2.7.9
|
||||
# PYTHON_ARCH: "64"
|
||||
|
||||
#- PYTHON: "C:\\Python33"
|
||||
# PYTHON_VERSION: "3.3.x" # currently 3.3.5
|
||||
# PYTHON_ARCH: "32"
|
||||
|
||||
#- PYTHON: "C:\\Python33-x64"
|
||||
# PYTHON_VERSION: "3.3.x" # currently 3.3.5
|
||||
# PYTHON_ARCH: "64"
|
||||
|
||||
#- PYTHON: "C:\\Python34"
|
||||
# PYTHON_VERSION: "3.4.x" # currently 3.4.3
|
||||
# PYTHON_ARCH: "32"
|
||||
|
||||
#- PYTHON: "C:\\Python34-x64"
|
||||
# PYTHON_VERSION: "3.4.x" # currently 3.4.3
|
||||
# PYTHON_ARCH: "64"
|
||||
|
||||
# Python versions not pre-installed
|
||||
|
||||
# Python 2.6.6 is the latest Python 2.6 with a Windows installer
|
||||
# See: https://github.com/ogrisel/python-appveyor-demo/issues/10
|
||||
|
||||
#- PYTHON: "C:\\Python266"
|
||||
# PYTHON_VERSION: "2.6.6"
|
||||
# PYTHON_ARCH: "32"
|
||||
|
||||
#- PYTHON: "C:\\Python266-x64"
|
||||
# PYTHON_VERSION: "2.6.6"
|
||||
# PYTHON_ARCH: "64"
|
||||
|
||||
#- PYTHON: "C:\\Python35"
|
||||
# PYTHON_VERSION: "3.5.0"
|
||||
# PYTHON_ARCH: "32"
|
||||
|
||||
#- PYTHON: "C:\\Python35-x64"
|
||||
# PYTHON_VERSION: "3.5.0"
|
||||
# PYTHON_ARCH: "64"
|
||||
|
||||
# Major and minor releases (i.e x.0.0 and x.y.0) prior to 3.3.0 use
|
||||
# a different naming scheme.
|
||||
|
||||
#- PYTHON: "C:\\Python270"
|
||||
# PYTHON_VERSION: "2.7.0"
|
||||
# PYTHON_ARCH: "32"
|
||||
|
||||
#- PYTHON: "C:\\Python270-x64"
|
||||
# PYTHON_VERSION: "2.7.0"
|
||||
# PYTHON_ARCH: "64"
|
||||
|
||||
init:
|
||||
- ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
install:
|
||||
# If there is a newer build queued for the same PR, cancel this one.
|
||||
# The AppVeyor 'rollout builds' option is supposed to serve the same
|
||||
@@ -89,34 +23,23 @@ install:
|
||||
Where-Object pullRequestId -eq $env:APPVEYOR_PULL_REQUEST_NUMBER)[0].buildNumber) { `
|
||||
throw "There are newer queued builds for this pull request, failing early." }
|
||||
|
||||
# Install wxPython
|
||||
- 'ECHO Downloading wxPython.'
|
||||
- "appveyor DownloadFile https://goo.gl/yvO8PB -FileName C:\\wxpython.exe"
|
||||
#- "appveyor DownloadFile https://goo.gl/Uj0jV3 -FileName C:\\wxpython64.exe"
|
||||
|
||||
- 'ECHO Install wxPython'
|
||||
- "C:\\wxpython.exe /SP- /VERYSILENT /NORESTART"
|
||||
#- "C:\\wxpython64.exe /SP- /VERYSILENT /NORESTART"
|
||||
|
||||
- ECHO "Filesystem root:"
|
||||
- ps: "ls \"C:/\""
|
||||
|
||||
- ECHO "Filesystem projects root:"
|
||||
- ps: "ls \"C:\\projects\\\""
|
||||
|
||||
- ECHO "Filesystem pyfa root:"
|
||||
- ps: "ls \"C:\\projects\\pyfa\\\""
|
||||
- ps: "ls \"C:\\projects\\$env:APPVEYOR_PROJECT_SLUG\""
|
||||
|
||||
- ECHO "Installed SDKs:"
|
||||
- ps: "ls \"C:/Program Files/Microsoft SDKs/Windows\""
|
||||
|
||||
# Install Python (from the official .msi of http://python.org) and pip when
|
||||
# not already installed.
|
||||
# - ps: if (-not(Test-Path($env:PYTHON))) { & appveyor\install.ps1 }
|
||||
|
||||
# Prepend newly installed Python to the PATH of this build (this cannot be
|
||||
# done from inside the powershell script as it would require to restart
|
||||
# the parent CMD process).
|
||||
- "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%"
|
||||
|
||||
# Check that we have the expected version and architecture for Python
|
||||
- "python --version"
|
||||
- "python -c \"import struct; print(struct.calcsize('P') * 8)\""
|
||||
|
||||
@@ -128,19 +51,36 @@ install:
|
||||
# compiled extensions and are not provided as pre-built wheel packages,
|
||||
# pip will build them from source using the MSVC compiler matching the
|
||||
# target Python version and architecture
|
||||
# C:\\projects\\eve-gnosis\\
|
||||
- ECHO "Install pip requirements:"
|
||||
- "pip install -r requirements.txt"
|
||||
- "pip install -r requirements_test.txt"
|
||||
- "pip install -r requirements_build_windows.txt"
|
||||
- "pip install PyInstaller"
|
||||
|
||||
before_build:
|
||||
# directory that will contain the built files
|
||||
- ps: $env:PYFA_DIST_DIR = "c:\projects\$env:APPVEYOR_PROJECT_SLUG\dist"
|
||||
- ps: $env:PYFA_VERSION = (python ./scripts/dump_version.py)
|
||||
- ps: echo("pyfa version ")
|
||||
- ps: echo ($env:PYFA_VERSION)
|
||||
|
||||
build_script:
|
||||
# Build the compiled extension
|
||||
# - "python setup.py build"
|
||||
- ECHO "Build pyfa:"
|
||||
#- copy C:\projects\pyfa\dist_assets\win\pyfa.spec C:\projects\pyfa\pyfa.spec
|
||||
- "python C:\\projects\\pyfa\\setup.py build"
|
||||
|
||||
##########
|
||||
# PyInstaller - create binaries for pyfa
|
||||
##########
|
||||
# Build command for PyInstaller
|
||||
- "python -m PyInstaller --noupx --clean --windowed --noconsole -y pyfa.spec"
|
||||
# Copy over manifest (See pyfa-org/pyfa#1622)
|
||||
- ps: xcopy /y dist_assets\win\pyfa.exe.manifest $env:PYFA_DIST_DIR\pyfa\
|
||||
# Not really sure if this is needed, but why not
|
||||
- ps: xcopy /y dist_assets\win\Microsoft.VC90.CRT.manifest $env:PYFA_DIST_DIR\pyfa\
|
||||
|
||||
##########
|
||||
# InnoScript EXE building
|
||||
# This is in a separate script because I don't feel like copying over the logic to AppVeyor script right now...
|
||||
##########
|
||||
- "python dist_assets/win/dist.py"
|
||||
- ps: dir $env:PYFA_DIST_DIR/
|
||||
#- ECHO "Build pyfa (Debug):"
|
||||
#- copy C:\projects\pyfa\dist_assets\win\pyfa_debug.spec C:\projects\pyfa\pyfa_debug.spec
|
||||
#- "pyinstaller.exe --clean --noconfirm --windowed --upx-dir=C:\\projects\\pyfa\\scripts\\upx.exe C:\\projects\\pyfa\\pyfa_debug.spec"
|
||||
@@ -150,12 +90,11 @@ build: on
|
||||
after_build:
|
||||
- ps: "ls \"./\""
|
||||
#- ps: "ls \"C:\\projects\\pyfa\\build\\pyfa\\\""
|
||||
- ps: "ls \"C:\\projects\\pyfa\\build\\\""
|
||||
- ps: "ls \"C:\\projects\\pyfa\\build\\exe.win32-2.7\\\""
|
||||
# - ps: "ls \"C:\\projects\\$env:APPVEYOR_PROJECT_SLUG\\build\\exe.win32-2.7\\\""
|
||||
# Zip
|
||||
# APPVEYOR_PULL_REQUEST_NUMBER -and $env:APPVEYOR_BUILD_NUMBER
|
||||
#- 7z a build.zip -r C:\projects\pyfa\build\pyfa\*.*
|
||||
- 7z a pyfa.zip -r C:\projects\pyfa\build\exe.win32-2.7\*.*
|
||||
- ps: 7z a "pyfa-$env:PYFA_VERSION-win.zip" -r "$env:PYFA_DIST_DIR\pyfa\*.*"
|
||||
#- 7z a pyfa_debug.zip -r C:\projects\pyfa\dist\pyfa_debug\*.*
|
||||
|
||||
on_success:
|
||||
@@ -176,11 +115,21 @@ after_test:
|
||||
|
||||
artifacts:
|
||||
# Archive the generated packages in the ci.appveyor.com build report.
|
||||
- path: pyfa.zip
|
||||
name: 'pyfa.zip'
|
||||
- path: pyfa*-win.zip
|
||||
- path: pyfa*-win.exe
|
||||
#- path: pyfa_debug.zip
|
||||
# name: Pyfa_debug
|
||||
|
||||
deploy:
|
||||
tag: $(pyfa_version)
|
||||
release: pyfa $(pyfa_version)
|
||||
description: 'Release description'
|
||||
provider: GitHub
|
||||
auth_token:
|
||||
secure: BfNHO66ff5hVx2O2ORbl49X0U/5h2V2T0IuRZDwm7fd1HvsVluF0wRCbl29oRp1M
|
||||
draft: true
|
||||
on:
|
||||
APPVEYOR_REPO_TAG: true # deploy on tag push only
|
||||
#on_success:
|
||||
# - TODO: upload the content of dist/*.whl to a public wheelhouse
|
||||
#
|
||||
#
|
||||
|
||||
59
.travis.yml
59
.travis.yml
@@ -1,36 +1,29 @@
|
||||
dist: trusty
|
||||
sudo: required
|
||||
os: linux
|
||||
language: python
|
||||
cache: pip
|
||||
python:
|
||||
- '3.6'
|
||||
env:
|
||||
- TOXENV=pep8
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- 3.6
|
||||
matrix:
|
||||
include:
|
||||
- os: osx
|
||||
osx_image: xcode7.3
|
||||
language: generic
|
||||
env: PYTHON=3.6.1
|
||||
before_install:
|
||||
- sudo apt-get update && sudo apt-get --reinstall install -qq language-pack-en language-pack-ru language-pack-he language-pack-zh-hans
|
||||
- pip install tox
|
||||
# We're not actually installing Tox, but have to run it before we install wxPython via Conda. This is fugly but vOv
|
||||
- tox
|
||||
- pip install -U -f https://extras.wxpython.org/wxPython4/extras/linux/gtk2/ubuntu-14.04 wxPython==4.0.0b2
|
||||
# # get Conda
|
||||
# - if [[ "$TRAVIS_PYTHON_VERSION" == "2.7" ]]; then
|
||||
# wget https://repo.continuum.io/miniconda/Miniconda-latest-Linux-x86_64.sh -O miniconda.sh;
|
||||
# else
|
||||
# wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh;
|
||||
# fi
|
||||
# - bash miniconda.sh -b -p $HOME/miniconda
|
||||
# - export PATH="$HOME/miniconda/bin:$PATH"
|
||||
# - hash -r
|
||||
# - conda config --set always_yes yes --set changeps1 no
|
||||
# - conda update -q conda
|
||||
# # Useful for debugging any issues with conda
|
||||
# - conda info -a
|
||||
#install:
|
||||
# install wxPython 3.0.0.0
|
||||
# - conda install -c https://conda.anaconda.org/travis wxpython=4.0.0b2
|
||||
script:
|
||||
- tox
|
||||
|
||||
- bash scripts/setup-osx.sh
|
||||
install:
|
||||
- export PYFA_VERSION="$(python3 scripts/dump_version.py)"
|
||||
- bash scripts/package-osx.sh
|
||||
before_deploy:
|
||||
- export RELEASE_PKG_FILE=$(ls *.deb)
|
||||
- echo "deploying $RELEASE_PKG_FILE to GitHub releases"
|
||||
deploy:
|
||||
provider: releases
|
||||
api_key:
|
||||
secure: Xfu0xApoB0zUPLXl29aYUulVC3iA4/3bXQwwADKCfAKZwxgNon4dLbO7Rie5/7Ukf2POL0KwmRaQGN3kOr+XSoIVTE4M5sXxnhiaaLGKQ+48hDizLE6JuXcZGJvkxUaghaTzIdCwHsG7VGBsPfQgfGsjJcfBp8tFNLmRyM/Jpsr8T6BR2MxtBIEUVy8zrOWFNZqnmWrY2pWMsB9fYt3JFNdpqeIgRAYqbBsBcZQ1MngLTi3ztuYS5IaF+lk06RrnBlHmUsJu/5nCvIpvPvD0i2BLZ3Uu0+Fn+8QWUgjJEL9MNseXZMXynu05xd8YRk7Ajc9CUrzQIIbAktyteYp85kE3pUJHmrMLcXhh7nqkwttR5/47Zwa3OLJLJFKBxMx6wY5jFkJjkV08850B7aWrmTFl/Eqc3Q5nZMuiEt3wFRbjxHi9h1mTN/fkxfRRHg8u3ENGPR+ZPiFC3J18qtks/B/hsKjjHvZP1i79OYlET4V/zyLyyQkCbpDaARQANuotLYJyZ7tH+KWEyRsvTi0M9Yev9mNNw6aI4vzh4HfkEhvcvnWnYwckPj1dnjQ573Qpw0Z9wsconoWfHAn+hBDt3+YLMrrFZl++mCRskHH1mZChX3aGMDi49zD0kfxBUkYPOAhguc6PwudBxHUZP+O6T/SoHylff6EizCE/k5dGeAk=
|
||||
file_glob: true
|
||||
file: "dist/pyfa-*.zip"
|
||||
skip_cleanup: true
|
||||
draft: true
|
||||
on:
|
||||
tags: true
|
||||
repo: pyfa-org/Pyfa
|
||||
|
||||
@@ -129,7 +129,8 @@ def Saveddata():
|
||||
from eos.saveddata.ship import Ship
|
||||
from eos.saveddata.fit import Fit
|
||||
from eos.saveddata.character import Character
|
||||
from eos.saveddata.module import Module, State
|
||||
from eos.saveddata.module import Module
|
||||
from eos.const import FittingModuleState
|
||||
from eos.saveddata.citadel import Citadel
|
||||
from eos.saveddata.booster import Booster
|
||||
|
||||
@@ -139,7 +140,7 @@ def Saveddata():
|
||||
'Fit' : Fit,
|
||||
'Character': Character,
|
||||
'Module' : Module,
|
||||
'State' : State,
|
||||
'State' : FittingModuleState,
|
||||
'Booster' : Booster,
|
||||
}
|
||||
return helper
|
||||
|
||||
33
config.py
33
config.py
@@ -1,9 +1,12 @@
|
||||
import os
|
||||
import sys
|
||||
import yaml
|
||||
import wx
|
||||
|
||||
from logbook import CRITICAL, DEBUG, ERROR, FingersCrossedHandler, INFO, Logger, NestedSetup, NullHandler, \
|
||||
StreamHandler, TimedRotatingFileHandler, WARNING
|
||||
import hashlib
|
||||
from eos.const import FittingSlot
|
||||
|
||||
from cryptography.fernet import Fernet
|
||||
|
||||
@@ -22,12 +25,6 @@ debug = False
|
||||
# Defines if our saveddata will be in pyfa root or not
|
||||
saveInRoot = False
|
||||
|
||||
# Version data
|
||||
|
||||
version = "2.6.0"
|
||||
tag = "Stable"
|
||||
expansionName = "Onslaught"
|
||||
expansionVersion = "1.0"
|
||||
evemonMinVersion = "4081"
|
||||
|
||||
minItemSearchLength = 3
|
||||
@@ -52,6 +49,13 @@ LOGLEVEL_MAP = {
|
||||
"debug": DEBUG,
|
||||
}
|
||||
|
||||
slotColourMap = {
|
||||
FittingSlot.LOW: wx.Colour(250, 235, 204), # yellow = low slots
|
||||
FittingSlot.MED: wx.Colour(188, 215, 241), # blue = mid slots
|
||||
FittingSlot.HIGH: wx.Colour(235, 204, 209), # red = high slots
|
||||
FittingSlot.RIG: '',
|
||||
FittingSlot.SUBSYSTEM: ''
|
||||
}
|
||||
|
||||
def getClientSecret():
|
||||
return clientHash
|
||||
@@ -79,12 +83,7 @@ def getPyfaRoot():
|
||||
|
||||
|
||||
def getVersion():
|
||||
if os.path.isfile(os.path.join(pyfaPath, '.version')):
|
||||
with open(os.path.join(pyfaPath, '.version')) as f:
|
||||
gitVersion = f.readline()
|
||||
return gitVersion
|
||||
# if no version file exists, then user is running from source or not an official build
|
||||
return version + " (git)"
|
||||
return version
|
||||
|
||||
|
||||
def getDefaultSave():
|
||||
@@ -101,6 +100,7 @@ def defPaths(customSavePath=None):
|
||||
global logPath
|
||||
global cipher
|
||||
global clientHash
|
||||
global version
|
||||
|
||||
pyfalog.debug("Configuring Pyfa")
|
||||
|
||||
@@ -110,6 +110,12 @@ def defPaths(customSavePath=None):
|
||||
if pyfaPath is None:
|
||||
pyfaPath = getPyfaRoot()
|
||||
|
||||
# Version data
|
||||
|
||||
with open(os.path.join(pyfaPath, "version.yml"), 'r') as file:
|
||||
data = yaml.load(file, Loader=yaml.SafeLoader)
|
||||
version = data['version']
|
||||
|
||||
# Where we store the saved fits etc, default is the current users home directory
|
||||
if saveInRoot is True:
|
||||
savePath = getattr(configforced, "savePath", None)
|
||||
@@ -165,9 +171,6 @@ def defPaths(customSavePath=None):
|
||||
eos.config.saveddata_connectionstring = "sqlite:///" + saveDB + "?check_same_thread=False"
|
||||
eos.config.gamedata_connectionstring = "sqlite:///" + gameDB + "?check_same_thread=False"
|
||||
|
||||
print(eos.config.saveddata_connectionstring)
|
||||
print(eos.config.gamedata_connectionstring)
|
||||
|
||||
# initialize the settings
|
||||
from service.settings import EOSSettings
|
||||
eos.config.settings = EOSSettings.getInstance().EOSSettings # this is kind of confusing, but whatever
|
||||
|
||||
@@ -24,16 +24,18 @@ added_files = [
|
||||
('../../eve.db', '.'),
|
||||
('../../README.md', '.'),
|
||||
('../../LICENSE', '.'),
|
||||
('../../.version', '.'),
|
||||
('../../version.yml', '.'),
|
||||
]
|
||||
|
||||
|
||||
import_these = []
|
||||
import_these = [
|
||||
'numpy.core._dtype_ctypes' # https://github.com/pyinstaller/pyinstaller/issues/3982
|
||||
]
|
||||
|
||||
icon = os.path.join(os.getcwd(), "dist_assets", "mac", "pyfa.icns")
|
||||
|
||||
# Walk directories that do dynamic importing
|
||||
paths = ('eos/effects', 'eos/db/migrations', 'service/conversions')
|
||||
paths = ('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("_"):
|
||||
@@ -54,8 +56,10 @@ a = Analysis([r'../../pyfa.py'],
|
||||
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,
|
||||
a.binaries,
|
||||
@@ -70,10 +74,16 @@ exe = EXE(pyz,
|
||||
icon=icon,
|
||||
)
|
||||
|
||||
app = BUNDLE(exe,
|
||||
name='pyfa.app',
|
||||
icon=icon,
|
||||
bundle_identifier=None,
|
||||
info_plist={
|
||||
'NSHighResolutionCapable': 'True'
|
||||
})
|
||||
app = BUNDLE(
|
||||
exe,
|
||||
name='pyfa.app',
|
||||
icon=icon,
|
||||
bundle_identifier=None,
|
||||
info_plist={
|
||||
'NSHighResolutionCapable': 'True',
|
||||
'NSPrincipalClass': 'NSApplication',
|
||||
'CFBundleName': 'pyfa',
|
||||
'CFBundleDisplayName': 'pyfa',
|
||||
'CFBundleIdentifier': 'org.pyfaorg.pyfa',
|
||||
}
|
||||
)
|
||||
@@ -3,44 +3,35 @@
|
||||
import os.path
|
||||
from subprocess import call
|
||||
import zipfile
|
||||
from packaging.version import Version
|
||||
import yaml
|
||||
|
||||
|
||||
def zipdir(path, zip):
|
||||
for root, dirs, files in os.walk(path):
|
||||
for file in files:
|
||||
zip.write(os.path.join(root, file))
|
||||
with open("version.yml", 'r') as file:
|
||||
data = yaml.load(file, Loader=yaml.SafeLoader)
|
||||
version = data['version']
|
||||
|
||||
config = {}
|
||||
os.environ["PYFA_DIST_DIR"] = os.path.join(os.getcwd(), 'dist')
|
||||
|
||||
exec(compile(open("config.py").read(), "config.py", 'exec'), config)
|
||||
os.environ["PYFA_VERSION"] = version
|
||||
iscc = "C:\Program Files (x86)\Inno Setup 5\ISCC.exe" # inno script location via wine
|
||||
|
||||
iscc = "C:\Program Files (x86)\Inno Setup 5\ISCC.exe" # inno script location via wine
|
||||
source = os.path.join(os.environ["PYFA_DIST_DIR"], "pyfa")
|
||||
|
||||
print("Creating archive")
|
||||
|
||||
source = os.path.join(os.getcwd(), "dist", "pyfa")
|
||||
|
||||
fileName = "pyfa-{}-{}-{}-win".format(
|
||||
config['version'],
|
||||
config['expansionName'].lower(),
|
||||
config['expansionVersion']
|
||||
)
|
||||
|
||||
archive = zipfile.ZipFile(os.path.join(os.getcwd(), "dist", fileName + ".zip"), 'w', compression=zipfile.ZIP_DEFLATED)
|
||||
zipdir(source, archive)
|
||||
archive.close()
|
||||
fileName = "pyfa-{}-win".format(os.environ["PYFA_VERSION"])
|
||||
|
||||
print("Compiling EXE")
|
||||
|
||||
expansion = "%s %s" % (config['expansionName'], config['expansionVersion']),
|
||||
v = Version(version)
|
||||
|
||||
print(v)
|
||||
|
||||
call([
|
||||
iscc,
|
||||
os.path.join(os.getcwd(), "dist_assets", "win", "pyfa-setup.iss"),
|
||||
"/dMyAppVersion=%s" % (config['version']),
|
||||
"/dMyAppExpansion=%s" % expansion,
|
||||
"/dMyAppVersion=%s" % v,
|
||||
"/dMyAppDir=%s" % source,
|
||||
"/dMyOutputDir=%s" % os.path.join(os.getcwd(), "dist"),
|
||||
"/dMyOutputDir=%s" % os.path.join(os.getcwd()),
|
||||
"/dMyOutputFile=%s" % fileName]) # stdout=devnull, stderr=devnull
|
||||
|
||||
print("Done")
|
||||
|
||||
@@ -7,15 +7,12 @@
|
||||
#ifndef MyAppVersion
|
||||
#define MyAppVersion "2.1.0"
|
||||
#endif
|
||||
#ifndef MyAppExpansion
|
||||
#define MyAppExpansion "Vanguard 1.0"
|
||||
#endif
|
||||
|
||||
; Other config
|
||||
|
||||
#define MyAppName "pyfa"
|
||||
#define MyAppPublisher "pyfa"
|
||||
#define MyAppURL "https://forums.eveonline.com/t/27156"
|
||||
#define MyAppURL "https://github.com/pyfa-org/Pyfa/"
|
||||
#define MyAppExeName "pyfa.exe"
|
||||
|
||||
; What version starts with the new structure (1.x.0). This is used to determine if we run directory structure cleanup
|
||||
@@ -23,7 +20,7 @@
|
||||
#define MinorVersionFlag 0
|
||||
|
||||
#ifndef MyOutputFile
|
||||
#define MyOutputFile LowerCase(StringChange(MyAppName+'-'+MyAppVersion+'-'+MyAppExpansion+'-win-wx3', " ", "-"))
|
||||
#define MyOutputFile LowerCase(StringChange(MyAppName+'-'+MyAppVersion+'-win', " ", "-"))
|
||||
#endif
|
||||
#ifndef MyAppDir
|
||||
#define MyAppDir "pyfa"
|
||||
@@ -39,7 +36,7 @@
|
||||
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
|
||||
AppId={{3DA39096-C08D-49CD-90E0-1D177F32C8AA}
|
||||
AppName={#MyAppName}
|
||||
AppVersion={#MyAppVersion} ({#MyAppExpansion})
|
||||
AppVersion={#MyAppVersion}
|
||||
AppPublisher={#MyAppPublisher}
|
||||
AppPublisherURL={#MyAppURL}
|
||||
AppSupportURL={#MyAppURL}
|
||||
@@ -51,10 +48,8 @@ LicenseFile={#MyAppDir}\LICENSE
|
||||
OutputDir={#MyOutputDir}
|
||||
OutputBaseFilename={#MyOutputFile}
|
||||
SetupIconFile={#MyAppDir}\pyfa.ico
|
||||
Compression=lzma
|
||||
SolidCompression=yes
|
||||
CloseApplications=yes
|
||||
AppReadmeFile=https://github.com/pyfa-org/Pyfa/blob/v{#MyAppVersion}/readme.txt
|
||||
|
||||
[Languages]
|
||||
Name: "english"; MessagesFile: "compiler:Default.isl"
|
||||
|
||||
@@ -5,8 +5,7 @@ from itertools import chain
|
||||
import subprocess
|
||||
import requests.certs
|
||||
|
||||
label = subprocess.check_output([
|
||||
"git", "describe", "--tags"]).strip()
|
||||
label = subprocess.check_output(["git", "describe", "--tags"]).strip()
|
||||
|
||||
with open('.version', 'w+') as f:
|
||||
f.write(label.decode())
|
||||
@@ -18,7 +17,7 @@ added_files = [
|
||||
('../../imgs/gui/*.gif', 'imgs/gui'),
|
||||
('../../imgs/icons/*.png', 'imgs/icons'),
|
||||
('../../imgs/renders/*.png', 'imgs/renders'),
|
||||
('../../service/jargon/*.yaml', 'service/jargon'),
|
||||
('../../service/jargon/*.yaml', 'service/jargon'),
|
||||
('../../dist_assets/win/pyfa.ico', '.'),
|
||||
('../../dist_assets/win/pyfa.exe.manifest', '.'),
|
||||
('../../dist_assets/win/Microsoft.VC90.CRT.manifest', '.'),
|
||||
@@ -26,13 +25,15 @@ added_files = [
|
||||
('../../eve.db', '.'),
|
||||
('../../README.md', '.'),
|
||||
('../../LICENSE', '.'),
|
||||
('../../.version', '.'),
|
||||
('../../version.yml', '.'),
|
||||
]
|
||||
|
||||
import_these = []
|
||||
import_these = [
|
||||
'numpy.core._dtype_ctypes' # https://github.com/pyinstaller/pyinstaller/issues/3982
|
||||
]
|
||||
|
||||
# Walk directories that do dynamic importing
|
||||
paths = ('eos/effects', 'eos/db/migrations', 'service/conversions')
|
||||
paths = ('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("_"):
|
||||
|
||||
@@ -19,13 +19,14 @@ if istravis is True or hasattr(sys, '_called_from_test'):
|
||||
# Running in Travis. Run saveddata database in memory.
|
||||
saveddata_connectionstring = 'sqlite:///:memory:'
|
||||
else:
|
||||
saveddata_connectionstring = 'sqlite:///' + realpath(join(dirname(abspath(__file__)), "..", "saveddata", "saveddata-py3-db.db"))
|
||||
saveddata_connectionstring = 'sqlite:///' + realpath(join(dirname(abspath(__file__)), "..", "saveddata", "saveddata.db"))
|
||||
|
||||
pyfalog.debug("Saveddata connection string: {0}", saveddata_connectionstring)
|
||||
|
||||
settings = {
|
||||
"useStaticAdaptiveArmorHardener": False,
|
||||
"strictSkillLevels": True,
|
||||
"globalDefaultSpoolupPercentage": 1.0
|
||||
}
|
||||
|
||||
# Autodetect path, only change if the autodetection bugs out.
|
||||
|
||||
95
eos/const.py
Normal file
95
eos/const.py
Normal file
@@ -0,0 +1,95 @@
|
||||
# =============================================================================
|
||||
# Copyright (C) 2019 Ryan Holmes
|
||||
#
|
||||
# This file is part of pyfa.
|
||||
#
|
||||
# pyfa is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# pyfa is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
|
||||
# =============================================================================
|
||||
|
||||
from enum import IntEnum,unique
|
||||
|
||||
|
||||
@unique
|
||||
class FittingSlot(IntEnum):
|
||||
"""
|
||||
Contains slots for ship fittings
|
||||
"""
|
||||
# These are self-explanatory
|
||||
LOW = 1
|
||||
MED = 2
|
||||
HIGH = 3
|
||||
RIG = 4
|
||||
SUBSYSTEM = 5
|
||||
# not a real slot, need for pyfa display rack separation
|
||||
MODE = 6
|
||||
# system effects. They are projected "modules" and pyfa assumes all modules
|
||||
# have a slot. In this case, make one up.
|
||||
SYSTEM = 7
|
||||
# used for citadel services
|
||||
SERVICE = 8
|
||||
# fighter 'slots'. Just easier to put them here...
|
||||
F_LIGHT = 10
|
||||
F_SUPPORT = 11
|
||||
F_HEAVY = 12
|
||||
# fighter 'slots' (for structures)
|
||||
FS_LIGHT = 13
|
||||
FS_SUPPORT = 14
|
||||
FS_HEAVY = 15
|
||||
|
||||
|
||||
@unique
|
||||
class ImplantLocation(IntEnum):
|
||||
"""
|
||||
Contains location of the implant
|
||||
"""
|
||||
FIT = 0
|
||||
CHARACTER = 1
|
||||
|
||||
|
||||
@unique
|
||||
class CalcType(IntEnum):
|
||||
"""
|
||||
Contains location of the calculation
|
||||
"""
|
||||
LOCAL = 0
|
||||
PROJECTED = 1
|
||||
COMMAND = 2
|
||||
|
||||
|
||||
@unique
|
||||
class FittingModuleState(IntEnum):
|
||||
"""
|
||||
Contains the state of a fitting module
|
||||
"""
|
||||
OFFLINE = -1
|
||||
ONLINE = 0
|
||||
ACTIVE = 1
|
||||
OVERHEATED = 2
|
||||
|
||||
|
||||
@unique
|
||||
class FittingHardpoint(IntEnum):
|
||||
"""
|
||||
Contains the types of a fitting hardpoint
|
||||
"""
|
||||
NONE = 0
|
||||
MISSILE = 1
|
||||
TURRET = 2
|
||||
|
||||
|
||||
@unique
|
||||
class SpoolType(IntEnum):
|
||||
SCALE = 0 # [0..1]
|
||||
TIME = 1 # Expressed via time in seconds since spool up started
|
||||
CYCLES = 2 # Expressed in amount of cycles since spool up started
|
||||
@@ -39,6 +39,8 @@ attributes_table = Table("dgmattribs", gamedata_meta,
|
||||
Column("displayName", String),
|
||||
Column("highIsGood", Boolean),
|
||||
Column("iconID", Integer),
|
||||
Column("attributeCategory", Integer),
|
||||
Column("tooltipDescription", Integer),
|
||||
Column("unitID", Integer, ForeignKey("dgmunits.unitID")))
|
||||
|
||||
mapper(Attribute, typeattributes_table,
|
||||
|
||||
@@ -40,7 +40,8 @@ items_table = Table("invtypes", gamedata_meta,
|
||||
Column("marketGroupID", Integer, ForeignKey("invmarketgroups.marketGroupID")),
|
||||
Column("iconID", Integer),
|
||||
Column("graphicID", Integer),
|
||||
Column("groupID", Integer, ForeignKey("invgroups.groupID"), index=True))
|
||||
Column("groupID", Integer, ForeignKey("invgroups.groupID"), index=True),
|
||||
Column("replacements", String))
|
||||
|
||||
from .metaGroup import metatypes_table # noqa
|
||||
from .traits import traits_table # noqa
|
||||
|
||||
@@ -272,6 +272,15 @@ def getMarketGroup(lookfor, eager=None):
|
||||
return marketGroup
|
||||
|
||||
|
||||
def getMarketTreeNodeIds(rootNodeIds):
|
||||
allIds = set()
|
||||
addedIds = set(rootNodeIds)
|
||||
while addedIds:
|
||||
allIds.update(addedIds)
|
||||
addedIds = {mg.ID for mg in gamedata_session.query(MarketGroup).filter(MarketGroup.parentGroupID.in_(addedIds))}
|
||||
return allIds
|
||||
|
||||
|
||||
@cachedQuery(2, "where", "filter")
|
||||
def getItemsByCategory(filter, where=None, eager=None):
|
||||
if isinstance(filter, int):
|
||||
|
||||
18
eos/db/migrations/upgrade29.py
Normal file
18
eos/db/migrations/upgrade29.py
Normal file
@@ -0,0 +1,18 @@
|
||||
"""
|
||||
Migration 29
|
||||
|
||||
- adds spoolType and spoolAmount to modules table
|
||||
"""
|
||||
import sqlalchemy
|
||||
|
||||
|
||||
def upgrade(saveddata_engine):
|
||||
try:
|
||||
saveddata_engine.execute("SELECT spoolType FROM modules LIMIT 1")
|
||||
except sqlalchemy.exc.DatabaseError:
|
||||
saveddata_engine.execute("ALTER TABLE modules ADD COLUMN spoolType INT;")
|
||||
|
||||
try:
|
||||
saveddata_engine.execute("SELECT spoolAmount FROM modules LIMIT 1")
|
||||
except sqlalchemy.exc.DatabaseError:
|
||||
saveddata_engine.execute("ALTER TABLE modules ADD COLUMN spoolAmount FLOAT;")
|
||||
17
eos/db/migrations/upgrade30.py
Normal file
17
eos/db/migrations/upgrade30.py
Normal file
@@ -0,0 +1,17 @@
|
||||
"""
|
||||
Migration 30
|
||||
|
||||
- changes to prices table
|
||||
"""
|
||||
|
||||
|
||||
import sqlalchemy
|
||||
|
||||
|
||||
def upgrade(saveddata_engine):
|
||||
try:
|
||||
saveddata_engine.execute("SELECT status FROM prices LIMIT 1")
|
||||
except sqlalchemy.exc.DatabaseError:
|
||||
# Just drop table, table will be re-created by sqlalchemy and
|
||||
# data will be re-fetched
|
||||
saveddata_engine.execute("DROP TABLE prices;")
|
||||
@@ -23,7 +23,7 @@ import datetime
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.db.saveddata.implant import charImplants_table
|
||||
from eos.effectHandlerHelpers import HandledImplantBoosterList, HandledSsoCharacterList
|
||||
from eos.effectHandlerHelpers import HandledImplantList, HandledSsoCharacterList
|
||||
from eos.saveddata.implant import Implant
|
||||
from eos.saveddata.user import User
|
||||
from eos.saveddata.character import Character, Skill
|
||||
@@ -75,7 +75,7 @@ mapper(Character, characters_table,
|
||||
cascade="all,delete-orphan"),
|
||||
"_Character__implants" : relation(
|
||||
Implant,
|
||||
collection_class=HandledImplantBoosterList,
|
||||
collection_class=HandledImplantList,
|
||||
cascade='all,delete-orphan',
|
||||
backref='character',
|
||||
single_parent=True,
|
||||
|
||||
@@ -31,7 +31,7 @@ from eos.db.saveddata.drone import drones_table
|
||||
from eos.db.saveddata.fighter import fighters_table
|
||||
from eos.db.saveddata.implant import fitImplants_table
|
||||
from eos.db.saveddata.module import modules_table
|
||||
from eos.effectHandlerHelpers import HandledDroneCargoList, HandledImplantBoosterList, HandledModuleList, HandledProjectedDroneList, HandledProjectedModList
|
||||
from eos.effectHandlerHelpers import HandledDroneCargoList, HandledImplantList, HandledBoosterList, HandledModuleList, HandledProjectedDroneList, HandledProjectedModList
|
||||
from eos.saveddata.booster import Booster
|
||||
from eos.saveddata.cargo import Cargo
|
||||
from eos.saveddata.character import Character
|
||||
@@ -183,7 +183,7 @@ mapper(es_Fit, fits_table,
|
||||
"shipID": fits_table.c.shipID,
|
||||
"_Fit__boosters": relation(
|
||||
Booster,
|
||||
collection_class=HandledImplantBoosterList,
|
||||
collection_class=HandledBoosterList,
|
||||
cascade='all, delete, delete-orphan',
|
||||
backref='owner',
|
||||
single_parent=True),
|
||||
@@ -219,7 +219,7 @@ mapper(es_Fit, fits_table,
|
||||
primaryjoin=and_(fighters_table.c.fitID == fits_table.c.ID, fighters_table.c.projected == True)), # noqa
|
||||
"_Fit__implants": relation(
|
||||
Implant,
|
||||
collection_class=HandledImplantBoosterList,
|
||||
collection_class=HandledImplantList,
|
||||
cascade='all, delete, delete-orphan',
|
||||
backref='owner',
|
||||
single_parent=True,
|
||||
|
||||
@@ -23,7 +23,7 @@ import datetime
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.db.saveddata.implant import implantsSetMap_table
|
||||
from eos.effectHandlerHelpers import HandledImplantBoosterList
|
||||
from eos.effectHandlerHelpers import HandledImplantList
|
||||
from eos.saveddata.implant import Implant
|
||||
from eos.saveddata.implantSet import ImplantSet
|
||||
|
||||
@@ -38,7 +38,7 @@ mapper(ImplantSet, implant_set_table,
|
||||
properties={
|
||||
"_ImplantSet__implants": relation(
|
||||
Implant,
|
||||
collection_class=HandledImplantBoosterList,
|
||||
collection_class=HandledImplantList,
|
||||
cascade='all, delete, delete-orphan',
|
||||
backref='set',
|
||||
single_parent=True,
|
||||
|
||||
@@ -38,49 +38,58 @@ class DefaultDatabaseValues(object):
|
||||
["[Generic]Thermal", "0", "100", "0", "0"], ["[Generic]Kinetic", "0", "0", "100", "0"],
|
||||
["[Generic]Explosive", "0", "0", "0", "100"],
|
||||
["[NPC][Asteroid] Blood Raiders", "5067", "4214", "0", "0"],
|
||||
["[Bombs]Concussion Bomb", "0", "0", "6400", "0"],
|
||||
["[Bombs]Electron Bomb", "6400", "0", "0", "0"],
|
||||
["[Bombs]Scorch Bomb", "0", "6400", "0", "0"],
|
||||
["[Bombs]Concussion Bomb", "0", "0", "6400", "0"],
|
||||
["[Bombs]Shrapnel Bomb", "0", "0", "0", "6400"],
|
||||
["[Frequency Crystals][T2] Conflagration", "61.6", "61.6", "0", "0"],
|
||||
["[Frequency Crystals][T2] Scorch", "72", "16", "0", "0"],
|
||||
["[Frequency Crystals][T2] Gleam", "56", "56", "0", "0"],
|
||||
["[Frequency Crystals][T2] Aurora", "40", "24", "0", "0"],
|
||||
["[Frequency Crystals][T2] Scorch", "72", "16", "0", "0"],
|
||||
["[Frequency Crystals][T2] Conflagration", "61.6", "61.6", "0", "0"],
|
||||
["[Frequency Crystals]Multifrequency", "61.6", "44", "0", "0"],
|
||||
["[Frequency Crystals]Gamma", "61.6", "35.2", "0", "0"],
|
||||
["[Frequency Crystals]Xray", "52.8", "35.2", "0", "0"],
|
||||
["[Frequency Crystals]Ultraviolet", "52.8", "26.4", "0", "0"],
|
||||
["[Frequency Crystals]Standard", "44", "26.4", "0", "0"],
|
||||
["[Frequency Crystals]Infrared", "44", "17.6", "0", "0"],
|
||||
["[Frequency Crystals]Microwave", "35.2", "17.6", "0", "0"],
|
||||
["[Frequency Crystals]Multifrequency", "61.6", "44", "0", "0"],
|
||||
["[Frequency Crystals]Radio", "44", "0", "0", "0"],
|
||||
["[Frequency Crystals]Standard", "44", "26.4", "0", "0"],
|
||||
["[Frequency Crystals]Ultraviolet", "52.8", "26.4", "0", "0"],
|
||||
["[Frequency Crystals]Xray", "52.8", "35.2", "0", "0"],
|
||||
["[Hybrid Charges][T2] Void", "0", "61.6", "61.6", "0"],
|
||||
["[Hybrid Charges][T2] Null", "0", "48", "40", "0"],
|
||||
["[Hybrid Charges][T2] Javelin", "0", "64", "48", "0"],
|
||||
["[Hybrid Charges][T2] Spike", "0", "32", "32", "0"],
|
||||
["[Hybrid Charges]Antimatter", "0", "48", "67.2", "0"],
|
||||
["[Hybrid Charges]Iridium", "0", "28.8", "38.4", "0"],
|
||||
["[Hybrid Charges]Iron", "0", "19.2", "28.8", "0"],
|
||||
["[Hybrid Charges]Lead", "0", "28.8", "48", "0"],
|
||||
["[Hybrid Charges]Plutonium", "0", "48", "57.6", "0"],
|
||||
["[Hybrid Charges]Thorium", "0", "38.4", "48", "0"],
|
||||
["[Hybrid Charges]Tungsten", "0", "19.2", "38.4", "0"],
|
||||
["[Hybrid Charges]Uranium", "0", "38.4", "57.6", "0"],
|
||||
["[Missiles]Mjolnir", "100", "0", "0", "0"], ["[Missiles]Inferno", "0", "100", "0", "0"],
|
||||
["[Missiles]Scourge", "0", "0", "100", "0"], ["[Missiles]Nova", "0", "0", "0", "100"],
|
||||
["[Hybrid Charges]Thorium", "0", "38.4", "48", "0"],
|
||||
["[Hybrid Charges]Lead", "0", "28.8", "48", "0"],
|
||||
["[Hybrid Charges]Iridium", "0", "28.8", "38.4", "0"],
|
||||
["[Hybrid Charges]Tungsten", "0", "19.2", "38.4", "0"],
|
||||
["[Hybrid Charges]Iron", "0", "19.2", "28.8", "0"],
|
||||
["[Missiles]Mjolnir", "100", "0", "0", "0"],
|
||||
["[Missiles]Inferno", "0", "100", "0", "0"],
|
||||
["[Missiles]Scourge", "0", "0", "100", "0"],
|
||||
["[Missiles]Nova", "0", "0", "0", "100"],
|
||||
["[Missiles][Structure] Standup Missile", "100", "100", "100", "100"],
|
||||
["[Projectile Ammo][T2] Tremor", "0", "0", "24", "40"],
|
||||
["[Projectile Ammo][T2] Quake", "0", "0", "40", "72"],
|
||||
["[Projectile Ammo][T2] Hail", "0", "0", "26.4", "96.8"],
|
||||
["[Projectile Ammo][T2] Barrage", "0", "0", "40", "48"],
|
||||
["[Projectile Ammo]Carbonized Lead", "0", "0", "35.2", "8.8"],
|
||||
["[Projectile Ammo]Depleted Uranium", "0", "26.4", "17.6", "26.4"],
|
||||
["[Projectile Ammo][T2] Quake", "0", "0", "40", "72"],
|
||||
["[Projectile Ammo][T2] Tremor", "0", "0", "24", "40"],
|
||||
["[Projectile Ammo]EMP", "79.2", "0", "8.8", "17.6"],
|
||||
["[Projectile Ammo]Fusion", "0", "0", "17.6", "88"],
|
||||
["[Projectile Ammo]Nuclear", "0", "0", "8.8", "35.2"],
|
||||
["[Projectile Ammo]Phased Plasma", "0", "88", "17.6", "0"],
|
||||
["[Projectile Ammo]Proton", "26.4", "0", "17.6", "0"],
|
||||
["[Projectile Ammo]Fusion", "0", "0", "17.6", "88"],
|
||||
["[Projectile Ammo]Depleted Uranium", "0", "26.4", "17.6", "26.4"],
|
||||
["[Projectile Ammo]Titanium Sabot", "0", "0", "52.8", "176"],
|
||||
["[Projectile Ammo]Proton", "26.4", "0", "17.6", "0"],
|
||||
["[Projectile Ammo]Carbonized Lead", "0", "0", "35.2", "8.8"],
|
||||
["[Projectile Ammo]Nuclear", "0", "0", "8.8", "35.2"],
|
||||
# Different sizes of plasma do different damage, the values here are
|
||||
# average of proportions across sizes
|
||||
["[Exotic Plasma][T2] Occult", "0", "55863", "0", "44137"],
|
||||
["[Exotic Plasma][T2] Mystic", "0", "66319", "0", "33681"],
|
||||
["[Exotic Plasma]Tetryon", "0", "69208", "0", "30792"],
|
||||
["[Exotic Plasma]Baryon", "0", "59737", "0", "40263"],
|
||||
["[Exotic Plasma]Meson", "0", "60519", "0", "39481"],
|
||||
["[NPC][Burner] Cruor (Blood Raiders)", "90", "90", "0", "0"],
|
||||
["[NPC][Burner] Dramiel (Angel)", "55", "0", "20", "96"],
|
||||
["[NPC][Burner] Daredevil (Serpentis)", "0", "110", "154", "0"],
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
# ===============================================================================
|
||||
|
||||
from sqlalchemy import Table, Column, Integer, ForeignKey, CheckConstraint, Boolean, DateTime
|
||||
from sqlalchemy import Table, Column, Integer, Float, ForeignKey, CheckConstraint, Boolean, DateTime
|
||||
from sqlalchemy.orm.collections import attribute_mapped_collection
|
||||
from sqlalchemy.orm import relation, mapper
|
||||
import datetime
|
||||
@@ -40,6 +40,8 @@ modules_table = Table("modules", saveddata_meta,
|
||||
Column("position", Integer),
|
||||
Column("created", DateTime, nullable=True, default=datetime.datetime.now),
|
||||
Column("modified", DateTime, nullable=True, onupdate=datetime.datetime.now),
|
||||
Column("spoolType", Integer, nullable=True),
|
||||
Column("spoolAmount", Float, nullable=True),
|
||||
CheckConstraint('("dummySlot" = NULL OR "itemID" = NULL) AND "dummySlot" != "itemID"'))
|
||||
|
||||
mapper(Module, modules_table,
|
||||
|
||||
@@ -17,18 +17,19 @@
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
# ===============================================================================
|
||||
|
||||
|
||||
from sqlalchemy import Table, Column, Float, Integer
|
||||
from sqlalchemy.orm import mapper
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.saveddata.price import Price
|
||||
|
||||
|
||||
prices_table = Table("prices", saveddata_meta,
|
||||
Column("typeID", Integer, primary_key=True),
|
||||
Column("price", Float, default=0.0),
|
||||
Column("time", Integer, nullable=False),
|
||||
Column("failed", Integer))
|
||||
Column("status", Integer, nullable=False))
|
||||
|
||||
mapper(Price, prices_table, properties={
|
||||
"_Price__price": prices_table.c.price,
|
||||
})
|
||||
|
||||
mapper(Price, prices_table)
|
||||
|
||||
@@ -21,6 +21,7 @@ import sys
|
||||
|
||||
from sqlalchemy.sql import and_
|
||||
from sqlalchemy import desc, select
|
||||
from sqlalchemy import func
|
||||
|
||||
from eos.db import saveddata_session, sd_lock
|
||||
from eos.db.saveddata.fit import projectedFits_table
|
||||
@@ -283,6 +284,12 @@ def countAllFits():
|
||||
return count
|
||||
|
||||
|
||||
def countFitGroupedByShip():
|
||||
with sd_lock:
|
||||
count = eos.db.saveddata_session.query(Fit.shipID, func.count(Fit.shipID)).group_by(Fit.shipID).all()
|
||||
return count
|
||||
|
||||
|
||||
def countFitsWithShip(lookfor, ownerID=None, where=None, eager=None):
|
||||
"""
|
||||
Get all the fits using a certain ship.
|
||||
@@ -542,8 +549,17 @@ def commit():
|
||||
with sd_lock:
|
||||
try:
|
||||
saveddata_session.commit()
|
||||
saveddata_session.flush()
|
||||
except Exception as ex:
|
||||
except Exception:
|
||||
saveddata_session.rollback()
|
||||
exc_info = sys.exc_info()
|
||||
raise exc_info[0](exc_info[1]).with_traceback(exc_info[2])
|
||||
|
||||
|
||||
def flush():
|
||||
with sd_lock:
|
||||
try:
|
||||
saveddata_session.flush()
|
||||
except Exception:
|
||||
saveddata_session.rollback()
|
||||
exc_info = sys.exc_info()
|
||||
raise exc_info[0](exc_info[1]).with_traceback(exc_info[2])
|
||||
|
||||
@@ -18,8 +18,11 @@
|
||||
# ===============================================================================
|
||||
|
||||
from logbook import Logger
|
||||
|
||||
from eos.exception import HandledListActionError
|
||||
from utils.deprecated import deprecated
|
||||
|
||||
|
||||
pyfalog = Logger(__name__)
|
||||
|
||||
|
||||
@@ -112,6 +115,11 @@ class HandledList(list):
|
||||
thing.itemID = 0
|
||||
list.remove(self, thing)
|
||||
|
||||
def sort(self, *args, **kwargs):
|
||||
# We need it here to prevent external users from accidentally sorting the list as alot of
|
||||
# external logic relies on keeping modules at their places
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class HandledModuleList(HandledList):
|
||||
|
||||
@@ -125,11 +133,11 @@ class HandledModuleList(HandledList):
|
||||
emptyPosition = currPos
|
||||
|
||||
if emptyPosition < len(self):
|
||||
del self[emptyPosition]
|
||||
mod.position = emptyPosition
|
||||
HandledList.insert(self, emptyPosition, mod)
|
||||
self.__toModule(emptyPosition, mod)
|
||||
if mod.isInvalid:
|
||||
self.remove(mod)
|
||||
self.__toDummy(mod.position)
|
||||
raise HandledListActionError(mod)
|
||||
return
|
||||
|
||||
self.appendIgnoreEmpty(mod)
|
||||
@@ -139,45 +147,82 @@ class HandledModuleList(HandledList):
|
||||
HandledList.append(self, mod)
|
||||
if mod.isInvalid:
|
||||
self.remove(mod)
|
||||
return
|
||||
raise HandledListActionError(mod)
|
||||
|
||||
def insert(self, index, mod):
|
||||
mod.position = index
|
||||
i = index
|
||||
def replace(self, idx, mod):
|
||||
try:
|
||||
oldMod = self[idx]
|
||||
except IndexError:
|
||||
raise HandledListActionError(mod)
|
||||
self.__toModule(idx, mod)
|
||||
if mod.isInvalid:
|
||||
self.__toModule(idx, oldMod)
|
||||
raise HandledListActionError(mod)
|
||||
|
||||
def replaceRackPosition(self, rackPosition, mod):
|
||||
listPositions = []
|
||||
for currPos in range(len(self)):
|
||||
currMod = self[currPos]
|
||||
if currMod.slot == mod.slot:
|
||||
listPositions.append(currPos)
|
||||
listPositions.sort()
|
||||
try:
|
||||
modListPosition = listPositions[rackPosition]
|
||||
except IndexError:
|
||||
self.appendIgnoreEmpty(mod)
|
||||
else:
|
||||
oldMod = self[modListPosition]
|
||||
if mod.isEmpty:
|
||||
self.__toDummy(modListPosition)
|
||||
else:
|
||||
self.__toModule(modListPosition, mod)
|
||||
# If new module cannot be appended, restore old state
|
||||
if mod.isInvalid:
|
||||
if oldMod.isEmpty:
|
||||
self.__toDummy(modListPosition)
|
||||
else:
|
||||
self.__toModule(modListPosition, oldMod)
|
||||
raise HandledListActionError(mod)
|
||||
|
||||
def insert(self, idx, mod):
|
||||
mod.position = idx
|
||||
i = idx
|
||||
while i < len(self):
|
||||
self[i].position += 1
|
||||
i += 1
|
||||
HandledList.insert(self, index, mod)
|
||||
HandledList.insert(self, idx, mod)
|
||||
if mod.isInvalid:
|
||||
self.remove(mod)
|
||||
raise HandledListActionError(mod)
|
||||
|
||||
|
||||
def remove(self, mod):
|
||||
HandledList.remove(self, mod)
|
||||
oldPos = mod.position
|
||||
|
||||
mod.position = None
|
||||
for i in range(oldPos, len(self)):
|
||||
self[i].position -= 1
|
||||
|
||||
def toDummy(self, index):
|
||||
def free(self, idx):
|
||||
self.__toDummy(idx)
|
||||
|
||||
def __toDummy(self, index):
|
||||
mod = self[index]
|
||||
if not mod.isEmpty:
|
||||
dummy = mod.buildEmpty(mod.slot)
|
||||
dummy.position = index
|
||||
self[index] = dummy
|
||||
mod.position = None
|
||||
|
||||
def toModule(self, index, mod):
|
||||
def __toModule(self, index, mod):
|
||||
oldMod = self[index]
|
||||
mod.position = index
|
||||
self[index] = mod
|
||||
|
||||
@deprecated
|
||||
def freeSlot(self, slot):
|
||||
for i in range(len(self)):
|
||||
mod = self[i]
|
||||
if mod.getModifiedItemAttr("subSystemSlot") == slot:
|
||||
self.toDummy(i)
|
||||
break
|
||||
oldMod.position = None
|
||||
|
||||
|
||||
class HandledDroneCargoList(HandledList):
|
||||
|
||||
def find(self, item):
|
||||
for o in self:
|
||||
if o.item == item:
|
||||
@@ -189,35 +234,101 @@ class HandledDroneCargoList(HandledList):
|
||||
|
||||
def append(self, thing):
|
||||
HandledList.append(self, thing)
|
||||
|
||||
if thing.isInvalid:
|
||||
self.remove(thing)
|
||||
raise HandledListActionError(thing)
|
||||
|
||||
|
||||
class HandledImplantBoosterList(HandledList):
|
||||
def append(self, thing):
|
||||
def insert(self, idx, thing):
|
||||
HandledList.insert(self, idx, thing)
|
||||
if thing.isInvalid:
|
||||
HandledList.append(self, thing)
|
||||
self.remove(thing)
|
||||
return
|
||||
raise HandledListActionError(thing)
|
||||
|
||||
self.makeRoom(thing)
|
||||
HandledList.append(self, thing)
|
||||
|
||||
def makeRoom(self, thing):
|
||||
class HandledImplantList(HandledList):
|
||||
|
||||
def append(self, implant):
|
||||
if implant.isInvalid:
|
||||
HandledList.append(self, implant)
|
||||
self.remove(implant)
|
||||
raise HandledListActionError(implant)
|
||||
if self.__slotCheck(implant):
|
||||
HandledList.append(self, implant)
|
||||
self.remove(implant)
|
||||
raise HandledListActionError(implant)
|
||||
HandledList.append(self, implant)
|
||||
|
||||
def insert(self, idx, implant):
|
||||
if implant.isInvalid:
|
||||
HandledList.insert(self, idx, implant)
|
||||
self.remove(implant)
|
||||
raise HandledListActionError(implant)
|
||||
if self.__slotCheck(implant):
|
||||
HandledList.insert(self, idx, implant)
|
||||
self.remove(implant)
|
||||
raise HandledListActionError(implant)
|
||||
HandledList.append(self, implant)
|
||||
|
||||
def makeRoom(self, implant):
|
||||
# if needed, remove booster that was occupying slot
|
||||
oldObj = next((m for m in self if m.slot == thing.slot), None)
|
||||
if oldObj:
|
||||
pyfalog.info("Slot {0} occupied with {1}, replacing with {2}", thing.slot, oldObj.item.name,
|
||||
thing.item.name)
|
||||
itemID = oldObj.itemID
|
||||
oldObj = next((i for i in self if i.slot == implant.slot), None)
|
||||
if oldObj is not None:
|
||||
pyfalog.info("Slot {0} occupied with {1}, replacing with {2}", implant.slot, oldObj.item.name, implant.item.name)
|
||||
position = self.index(oldObj)
|
||||
from gui.fitCommands.helpers import ImplantInfo
|
||||
implantInfo = ImplantInfo.fromImplant(oldObj)
|
||||
oldObj.itemID = 0 # hack to remove from DB. See GH issue #324
|
||||
self.remove(oldObj)
|
||||
return itemID
|
||||
return None
|
||||
return position, implantInfo
|
||||
return None, None
|
||||
|
||||
def __slotCheck(self, implant):
|
||||
return any(i.slot == implant.slot for i in self)
|
||||
|
||||
|
||||
class HandledBoosterList(HandledList):
|
||||
|
||||
def append(self, booster):
|
||||
if booster.isInvalid:
|
||||
HandledList.append(self, booster)
|
||||
self.remove(booster)
|
||||
raise HandledListActionError(booster)
|
||||
if self.__slotCheck(booster):
|
||||
HandledList.append(self, booster)
|
||||
self.remove(booster)
|
||||
raise HandledListActionError(booster)
|
||||
HandledList.append(self, booster)
|
||||
|
||||
def insert(self, idx, booster):
|
||||
if booster.isInvalid:
|
||||
HandledList.insert(self, idx, booster)
|
||||
self.remove(booster)
|
||||
raise HandledListActionError(booster)
|
||||
if self.__slotCheck(booster):
|
||||
HandledList.insert(self, idx, booster)
|
||||
self.remove(booster)
|
||||
raise HandledListActionError(booster)
|
||||
HandledList.append(self, booster)
|
||||
|
||||
def makeRoom(self, booster):
|
||||
# if needed, remove booster that was occupying slot
|
||||
oldObj = next((b for b in self if b.slot == booster.slot), None)
|
||||
if oldObj is not None:
|
||||
pyfalog.info("Slot {0} occupied with {1}, replacing with {2}", booster.slot, oldObj.item.name, booster.item.name)
|
||||
position = self.index(oldObj)
|
||||
from gui.fitCommands.helpers import BoosterInfo
|
||||
boosterInfo = BoosterInfo.fromBooster(oldObj)
|
||||
oldObj.itemID = 0 # hack to remove from DB. See GH issue #324
|
||||
self.remove(oldObj)
|
||||
return position, boosterInfo
|
||||
return None, None
|
||||
|
||||
def __slotCheck(self, booster):
|
||||
return any(b.slot == booster.slot for b in self)
|
||||
|
||||
|
||||
class HandledSsoCharacterList(list):
|
||||
|
||||
def append(self, character):
|
||||
old = next((x for x in self if x.client == character.client), None)
|
||||
if old is not None:
|
||||
@@ -228,38 +339,63 @@ class HandledSsoCharacterList(list):
|
||||
|
||||
|
||||
class HandledProjectedModList(HandledList):
|
||||
|
||||
def append(self, proj):
|
||||
if proj.isInvalid:
|
||||
# we must include it before we remove it. doing it this way ensures
|
||||
# rows and relationships in database are removed as well
|
||||
HandledList.append(self, proj)
|
||||
self.remove(proj)
|
||||
return
|
||||
raise HandledListActionError(proj)
|
||||
|
||||
proj.projected = True
|
||||
isSystemEffect = proj.item.group.name == "Effect Beacon"
|
||||
|
||||
if isSystemEffect:
|
||||
self.makeRoom(proj)
|
||||
|
||||
HandledList.append(self, proj)
|
||||
|
||||
# Remove non-projectable modules
|
||||
if not proj.item.isType("projected") and not isSystemEffect:
|
||||
if not proj.item.isType("projected") and not proj.isExclusiveSystemEffect:
|
||||
self.remove(proj)
|
||||
raise HandledListActionError(proj)
|
||||
|
||||
def insert(self, idx, proj):
|
||||
if proj.isInvalid:
|
||||
# we must include it before we remove it. doing it this way ensures
|
||||
# rows and relationships in database are removed as well
|
||||
HandledList.insert(self, idx, proj)
|
||||
self.remove(proj)
|
||||
raise HandledListActionError(proj)
|
||||
|
||||
proj.projected = True
|
||||
|
||||
HandledList.insert(self, idx, proj)
|
||||
|
||||
# Remove non-projectable modules
|
||||
if not proj.item.isType("projected") and not proj.isExclusiveSystemEffect:
|
||||
self.remove(proj)
|
||||
raise HandledListActionError(proj)
|
||||
|
||||
@property
|
||||
def currentSystemEffect(self):
|
||||
return next((m for m in self if m.isExclusiveSystemEffect), None)
|
||||
|
||||
def makeRoom(self, proj):
|
||||
# remove other system effects - only 1 per fit plz
|
||||
oldEffect = next((m for m in self if m.item.group.name == "Effect Beacon"), None)
|
||||
if proj.isExclusiveSystemEffect:
|
||||
# remove other system effects - only 1 per fit plz
|
||||
mod = self.currentSystemEffect
|
||||
|
||||
if oldEffect:
|
||||
pyfalog.info("System effect occupied with {0}, replacing with {1}", oldEffect.item.name, proj.item.name)
|
||||
self.remove(oldEffect)
|
||||
return oldEffect.itemID
|
||||
return None
|
||||
if mod:
|
||||
pyfalog.info("System effect occupied with {0}, removing it to make space for {1}".format(mod.item.name, proj.item.name))
|
||||
position = self.index(mod)
|
||||
# We need to pack up this info, so whatever...
|
||||
from gui.fitCommands.helpers import ModuleInfo
|
||||
modInfo = ModuleInfo.fromModule(mod)
|
||||
self.remove(mod)
|
||||
return position, modInfo
|
||||
return None, None
|
||||
|
||||
|
||||
class HandledProjectedDroneList(HandledDroneCargoList):
|
||||
|
||||
def append(self, proj):
|
||||
proj.projected = True
|
||||
HandledList.append(self, proj)
|
||||
@@ -267,6 +403,20 @@ class HandledProjectedDroneList(HandledDroneCargoList):
|
||||
# Remove invalid or non-projectable drones
|
||||
if proj.isInvalid or not proj.item.isType("projected"):
|
||||
self.remove(proj)
|
||||
proj.projected = False
|
||||
raise HandledListActionError(proj)
|
||||
return True
|
||||
|
||||
def insert(self, idx, proj):
|
||||
proj.projected = True
|
||||
HandledList.insert(self, idx, proj)
|
||||
|
||||
# Remove invalid or non-projectable drones
|
||||
if proj.isInvalid or not proj.item.isType("projected"):
|
||||
self.remove(proj)
|
||||
proj.projected = False
|
||||
raise HandledListActionError(proj)
|
||||
return True
|
||||
|
||||
|
||||
class HandledItem(object):
|
||||
|
||||
35626
eos/effects.py
Normal file
35626
eos/effects.py
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,19 +0,0 @@
|
||||
# ===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
# 2010 Anton Vorobyov
|
||||
#
|
||||
# This file, as well as all files in this folder, are part of eos.
|
||||
#
|
||||
# eos is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# eos is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
# ===============================================================================
|
||||
@@ -1,10 +0,0 @@
|
||||
# accerationControlCapNeedBonusPostPercentCapacitorNeedLocationShipGroupAfterburner
|
||||
#
|
||||
# Used by:
|
||||
# Modules named like: Dynamic Fuel Valve (8 of 8)
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, container, context):
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Propulsion Module",
|
||||
"capacitorNeed", container.getModifiedItemAttr("capNeedBonus"))
|
||||
@@ -1,12 +0,0 @@
|
||||
# accerationControlSkillAb&MwdSpeedBoost
|
||||
#
|
||||
# Used by:
|
||||
# Implant: Zor's Custom Navigation Hyper-Link
|
||||
# Skill: Acceleration Control
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, container, context):
|
||||
level = container.level if "skill" in context else 1
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Propulsion Module",
|
||||
"speedFactor", container.getModifiedItemAttr("speedFBonus") * level)
|
||||
@@ -1,10 +0,0 @@
|
||||
# accerationControlSpeedFBonusPostPercentSpeedFactorLocationShipGroupAfterburner
|
||||
#
|
||||
# Used by:
|
||||
# Implants named like: Eifyr and Co. 'Rogue' Acceleration Control AC (6 of 6)
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, implant, context):
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Propulsion Module",
|
||||
"speedFactor", implant.getModifiedItemAttr("speedFBonus"))
|
||||
@@ -1,13 +0,0 @@
|
||||
# accessDifficultyBonusModifierRequiringArchaelogy
|
||||
#
|
||||
# Used by:
|
||||
# Modules named like: Emission Scope Sharpener (8 of 8)
|
||||
# Implant: Poteque 'Prospector' Archaeology AC-905
|
||||
# Implant: Poteque 'Prospector' Environmental Analysis EY-1005
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, container, context):
|
||||
fit.modules.filteredItemIncrease(lambda module: module.item.requiresSkill("Archaeology"),
|
||||
"accessDifficultyBonus",
|
||||
container.getModifiedItemAttr("accessDifficultyBonusModifier"), position="post")
|
||||
@@ -1,14 +0,0 @@
|
||||
# accessDifficultyBonusModifierRequiringHacking
|
||||
#
|
||||
# Used by:
|
||||
# Modules named like: Memetic Algorithm Bank (8 of 8)
|
||||
# Implant: Neural Lace 'Blackglass' Net Intrusion 920-40
|
||||
# Implant: Poteque 'Prospector' Environmental Analysis EY-1005
|
||||
# Implant: Poteque 'Prospector' Hacking HC-905
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, container, context):
|
||||
fit.modules.filteredItemIncrease(lambda c: c.item.requiresSkill("Hacking"),
|
||||
"accessDifficultyBonus",
|
||||
container.getModifiedItemAttr("accessDifficultyBonusModifier"), position="post")
|
||||
@@ -1,128 +0,0 @@
|
||||
# adaptiveArmorHardener
|
||||
#
|
||||
# Used by:
|
||||
# Module: Reactive Armor Hardener
|
||||
from logbook import Logger
|
||||
import eos.config
|
||||
|
||||
pyfalog = Logger(__name__)
|
||||
|
||||
runTime = "late"
|
||||
type = "active"
|
||||
|
||||
|
||||
def handler(fit, module, context):
|
||||
damagePattern = fit.damagePattern
|
||||
# pyfalog.debug("==============================")
|
||||
|
||||
static_adaptive_behavior = eos.config.settings['useStaticAdaptiveArmorHardener']
|
||||
|
||||
if (damagePattern.emAmount == damagePattern.thermalAmount == damagePattern.kineticAmount == damagePattern.explosiveAmount) and static_adaptive_behavior:
|
||||
# pyfalog.debug("Setting adaptivearmorhardener resists to uniform profile.")
|
||||
for attr in ("armorEmDamageResonance", "armorThermalDamageResonance", "armorKineticDamageResonance", "armorExplosiveDamageResonance"):
|
||||
fit.ship.multiplyItemAttr(attr, module.getModifiedItemAttr(attr), stackingPenalties=True, penaltyGroup="preMul")
|
||||
return
|
||||
|
||||
# Skip if there is no damage pattern. Example: projected ships or fleet boosters
|
||||
if damagePattern:
|
||||
|
||||
# Populate a tuple with the damage profile modified by current armor resists.
|
||||
baseDamageTaken = (
|
||||
damagePattern.emAmount * fit.ship.getModifiedItemAttr('armorEmDamageResonance'),
|
||||
damagePattern.thermalAmount * fit.ship.getModifiedItemAttr('armorThermalDamageResonance'),
|
||||
damagePattern.kineticAmount * fit.ship.getModifiedItemAttr('armorKineticDamageResonance'),
|
||||
damagePattern.explosiveAmount * fit.ship.getModifiedItemAttr('armorExplosiveDamageResonance'),
|
||||
)
|
||||
# pyfalog.debug("Damage Adjusted for Armor Resists: %f/%f/%f/%f" % (baseDamageTaken[0], baseDamageTaken[1], baseDamageTaken[2], baseDamageTaken[3]))
|
||||
|
||||
resistanceShiftAmount = module.getModifiedItemAttr(
|
||||
'resistanceShiftAmount') / 100 # The attribute is in percent and we want a fraction
|
||||
RAHResistance = [
|
||||
module.getModifiedItemAttr('armorEmDamageResonance'),
|
||||
module.getModifiedItemAttr('armorThermalDamageResonance'),
|
||||
module.getModifiedItemAttr('armorKineticDamageResonance'),
|
||||
module.getModifiedItemAttr('armorExplosiveDamageResonance'),
|
||||
]
|
||||
|
||||
# Simulate RAH cycles until the RAH either stops changing or enters a loop.
|
||||
# The number of iterations is limited to prevent an infinite loop if something goes wrong.
|
||||
cycleList = []
|
||||
loopStart = -20
|
||||
for num in range(50):
|
||||
# pyfalog.debug("Starting cycle %d." % num)
|
||||
# The strange order is to emulate the ingame sorting when different types have taken the same amount of damage.
|
||||
# This doesn't take into account stacking penalties. In a few cases fitting a Damage Control causes an inaccurate result.
|
||||
damagePattern_tuples = [
|
||||
(0, baseDamageTaken[0] * RAHResistance[0], RAHResistance[0]),
|
||||
(3, baseDamageTaken[3] * RAHResistance[3], RAHResistance[3]),
|
||||
(2, baseDamageTaken[2] * RAHResistance[2], RAHResistance[2]),
|
||||
(1, baseDamageTaken[1] * RAHResistance[1], RAHResistance[1]),
|
||||
]
|
||||
|
||||
# Sort the tuple to drop the highest damage value to the bottom
|
||||
sortedDamagePattern_tuples = sorted(damagePattern_tuples, key=lambda damagePattern: damagePattern[1])
|
||||
|
||||
if sortedDamagePattern_tuples[2][1] == 0:
|
||||
# One damage type: the top damage type takes from the other three
|
||||
# Since the resistances not taking damage will end up going to the type taking damage we just do the whole thing at once.
|
||||
change0 = 1 - sortedDamagePattern_tuples[0][2]
|
||||
change1 = 1 - sortedDamagePattern_tuples[1][2]
|
||||
change2 = 1 - sortedDamagePattern_tuples[2][2]
|
||||
change3 = -(change0 + change1 + change2)
|
||||
elif sortedDamagePattern_tuples[1][1] == 0:
|
||||
# Two damage types: the top two damage types take from the other two
|
||||
# Since the resistances not taking damage will end up going equally to the types taking damage we just do the whole thing at once.
|
||||
change0 = 1 - sortedDamagePattern_tuples[0][2]
|
||||
change1 = 1 - sortedDamagePattern_tuples[1][2]
|
||||
change2 = -(change0 + change1) / 2
|
||||
change3 = -(change0 + change1) / 2
|
||||
else:
|
||||
# Three or four damage types: the top two damage types take from the other two
|
||||
change0 = min(resistanceShiftAmount, 1 - sortedDamagePattern_tuples[0][2])
|
||||
change1 = min(resistanceShiftAmount, 1 - sortedDamagePattern_tuples[1][2])
|
||||
change2 = -(change0 + change1) / 2
|
||||
change3 = -(change0 + change1) / 2
|
||||
|
||||
RAHResistance[sortedDamagePattern_tuples[0][0]] = sortedDamagePattern_tuples[0][2] + change0
|
||||
RAHResistance[sortedDamagePattern_tuples[1][0]] = sortedDamagePattern_tuples[1][2] + change1
|
||||
RAHResistance[sortedDamagePattern_tuples[2][0]] = sortedDamagePattern_tuples[2][2] + change2
|
||||
RAHResistance[sortedDamagePattern_tuples[3][0]] = sortedDamagePattern_tuples[3][2] + change3
|
||||
# pyfalog.debug("Resistances shifted to %f/%f/%f/%f" % ( RAHResistance[0], RAHResistance[1], RAHResistance[2], RAHResistance[3]))
|
||||
|
||||
# See if the current RAH profile has been encountered before, indicating a loop.
|
||||
for i, val in enumerate(cycleList):
|
||||
tolerance = 1e-06
|
||||
if abs(RAHResistance[0] - val[0]) <= tolerance and \
|
||||
abs(RAHResistance[1] - val[1]) <= tolerance and \
|
||||
abs(RAHResistance[2] - val[2]) <= tolerance and \
|
||||
abs(RAHResistance[3] - val[3]) <= tolerance:
|
||||
loopStart = i
|
||||
# pyfalog.debug("Loop found: %d-%d" % (loopStart, num))
|
||||
break
|
||||
if loopStart >= 0:
|
||||
break
|
||||
|
||||
cycleList.append(list(RAHResistance))
|
||||
|
||||
# if loopStart < 0:
|
||||
# pyfalog.error("Reactive Armor Hardener failed to find equilibrium. Damage profile after armor: {0}/{1}/{2}/{3}".format(
|
||||
# baseDamageTaken[0], baseDamageTaken[1], baseDamageTaken[2], baseDamageTaken[3]))
|
||||
|
||||
# Average the profiles in the RAH loop, or the last 20 if it didn't find a loop.
|
||||
loopCycles = cycleList[loopStart:]
|
||||
numCycles = len(loopCycles)
|
||||
average = [0, 0, 0, 0]
|
||||
for cycle in loopCycles:
|
||||
for i in range(4):
|
||||
average[i] += cycle[i]
|
||||
|
||||
for i in range(4):
|
||||
average[i] = round(average[i] / numCycles, 3)
|
||||
|
||||
# Set the new resistances
|
||||
# pyfalog.debug("Setting new resist profile: %f/%f/%f/%f" % ( average[0], average[1], average[2],average[3]))
|
||||
for i, attr in enumerate((
|
||||
'armorEmDamageResonance', 'armorThermalDamageResonance', 'armorKineticDamageResonance',
|
||||
'armorExplosiveDamageResonance')):
|
||||
module.increaseItemAttr(attr, average[i] - module.getModifiedItemAttr(attr))
|
||||
fit.ship.multiplyItemAttr(attr, average[i], stackingPenalties=True, penaltyGroup="preMul")
|
||||
@@ -1,10 +0,0 @@
|
||||
# addToSignatureRadius2
|
||||
#
|
||||
# Used by:
|
||||
# Modules from group: Missile Launcher Bomb (2 of 2)
|
||||
# Modules from group: Shield Extender (36 of 36)
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, module, context):
|
||||
fit.ship.increaseItemAttr("signatureRadius", module.getModifiedItemAttr("signatureRadiusAdd"))
|
||||
@@ -1,13 +0,0 @@
|
||||
# afterburnerDurationBonusPostPercentDurationLocationShipModulesRequiringAfterburner
|
||||
#
|
||||
# Used by:
|
||||
# Implants named like: Eifyr and Co. 'Rogue' Afterburner AB (6 of 6)
|
||||
# Implant: Zor's Custom Navigation Link
|
||||
# Skill: Afterburner
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, container, context):
|
||||
level = container.level if "skill" in context else 1
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Afterburner"),
|
||||
"duration", container.getModifiedItemAttr("durationBonus") * level)
|
||||
@@ -1,9 +0,0 @@
|
||||
# agilityBonus
|
||||
#
|
||||
# Used by:
|
||||
# Subsystems named like: Propulsion Interdiction Nullifier (4 of 4)
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, src, context):
|
||||
fit.ship.increaseItemAttr("agility", src.getModifiedItemAttr("agilityBonusAdd"))
|
||||
@@ -1,13 +0,0 @@
|
||||
# agilityMultiplierEffect
|
||||
#
|
||||
# Used by:
|
||||
# Modules from group: Inertial Stabilizer (7 of 7)
|
||||
# Modules from group: Nanofiber Internal Structure (7 of 7)
|
||||
# Modules from group: Reinforced Bulkhead (8 of 8)
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, module, context):
|
||||
fit.ship.boostItemAttr("agility",
|
||||
module.getModifiedItemAttr("agilityMultiplier"),
|
||||
stackingPenalties=True)
|
||||
@@ -1,9 +0,0 @@
|
||||
# agilityMultiplierEffectPassive
|
||||
#
|
||||
# Used by:
|
||||
# Modules named like: Polycarbon Engine Housing (8 of 8)
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, module, context):
|
||||
fit.ship.boostItemAttr("agility", module.getModifiedItemAttr("agilityBonus"), stackingPenalties=True)
|
||||
@@ -1,14 +0,0 @@
|
||||
# ammoFallofMultiplier
|
||||
#
|
||||
# Used by:
|
||||
# Charges from group: Advanced Artillery Ammo (8 of 8)
|
||||
# Charges from group: Advanced Autocannon Ammo (8 of 8)
|
||||
# Charges from group: Advanced Beam Laser Crystal (8 of 8)
|
||||
# Charges from group: Advanced Blaster Charge (8 of 8)
|
||||
# Charges from group: Advanced Pulse Laser Crystal (8 of 8)
|
||||
# Charges from group: Advanced Railgun Charge (8 of 8)
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, module, context):
|
||||
module.multiplyItemAttr("falloff", module.getModifiedChargeAttr("fallofMultiplier") or 1)
|
||||
@@ -1,13 +0,0 @@
|
||||
# ammoInfluenceCapNeed
|
||||
#
|
||||
# Used by:
|
||||
# Items from category: Charge (493 of 947)
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, module, context):
|
||||
# Dirty hack to work around cap charges setting cap booster
|
||||
# injection amount to zero
|
||||
rawAttr = module.item.getAttribute("capacitorNeed")
|
||||
if rawAttr is not None and rawAttr >= 0:
|
||||
module.boostItemAttr("capacitorNeed", module.getModifiedChargeAttr("capNeedBonus") or 0)
|
||||
@@ -1,9 +0,0 @@
|
||||
# ammoInfluenceRange
|
||||
#
|
||||
# Used by:
|
||||
# Items from category: Charge (587 of 947)
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, module, context):
|
||||
module.multiplyItemAttr("maxRange", module.getModifiedChargeAttr("weaponRangeMultiplier"))
|
||||
@@ -1,12 +0,0 @@
|
||||
# ammoSpeedMultiplier
|
||||
#
|
||||
# Used by:
|
||||
# Charges from group: Festival Charges (23 of 23)
|
||||
# Charges from group: Interdiction Probe (2 of 2)
|
||||
# Charges from group: Structure Festival Charges (3 of 3)
|
||||
# Special Edition Assetss from group: Festival Charges Expired (2 of 2)
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, module, context):
|
||||
module.multiplyItemAttr("speed", module.getModifiedChargeAttr("speedMultiplier") or 1)
|
||||
@@ -1,10 +0,0 @@
|
||||
# ammoTrackingMultiplier
|
||||
#
|
||||
# Used by:
|
||||
# Items from category: Charge (182 of 947)
|
||||
# Charges from group: Projectile Ammo (128 of 128)
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, module, context):
|
||||
module.multiplyItemAttr("trackingSpeed", module.getModifiedChargeAttr("trackingSpeedMultiplier"))
|
||||
@@ -1,14 +0,0 @@
|
||||
# angelsetbonus
|
||||
#
|
||||
# Used by:
|
||||
# Implants named like: grade Halo (18 of 18)
|
||||
runTime = "early"
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, implant, context):
|
||||
fit.appliedImplants.filteredItemMultiply(
|
||||
lambda implant: "signatureRadiusBonus" in implant.itemModifiedAttributes and
|
||||
"implantSetAngel" in implant.itemModifiedAttributes,
|
||||
"signatureRadiusBonus",
|
||||
implant.getModifiedItemAttr("implantSetAngel"))
|
||||
@@ -1,9 +0,0 @@
|
||||
# antiWarpScramblingPassive
|
||||
#
|
||||
# Used by:
|
||||
# Modules from group: Warp Core Stabilizer (8 of 8)
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, module, context):
|
||||
fit.ship.increaseItemAttr("warpScrambleStatus", module.getModifiedItemAttr("warpScrambleStrength"))
|
||||
@@ -1,16 +0,0 @@
|
||||
# aoe_beacon_bioluminescence_cloud
|
||||
#
|
||||
# Used by:
|
||||
# Celestials named like: Bioluminescence Cloud (3 of 3)
|
||||
runTime = "early"
|
||||
type = ("projected", "passive", "gang")
|
||||
|
||||
|
||||
def handler(fit, beacon, context, **kwargs):
|
||||
for x in range(1, 3):
|
||||
if beacon.getModifiedItemAttr("warfareBuff{}ID".format(x)):
|
||||
value = beacon.getModifiedItemAttr("warfareBuff{}Value".format(x))
|
||||
id = beacon.getModifiedItemAttr("warfareBuff{}ID".format(x))
|
||||
|
||||
if id:
|
||||
fit.addCommandBonus(id, value, beacon, kwargs['effect'], 'early')
|
||||
@@ -1,16 +0,0 @@
|
||||
# aoe_beacon_caustic_cloud
|
||||
#
|
||||
# Used by:
|
||||
# Celestials named like: Caustic Cloud (3 of 3)
|
||||
runTime = "early"
|
||||
type = ("projected", "passive", "gang")
|
||||
|
||||
|
||||
def handler(fit, beacon, context, **kwargs):
|
||||
for x in range(1, 3):
|
||||
if beacon.getModifiedItemAttr("warfareBuff{}ID".format(x)):
|
||||
value = beacon.getModifiedItemAttr("warfareBuff{}Value".format(x))
|
||||
id = beacon.getModifiedItemAttr("warfareBuff{}ID".format(x))
|
||||
|
||||
if id:
|
||||
fit.addCommandBonus(id, value, beacon, kwargs['effect'], 'early')
|
||||
@@ -1,16 +0,0 @@
|
||||
# aoe_beacon_filament_cloud
|
||||
#
|
||||
# Used by:
|
||||
# Celestials named like: Filament Cloud (3 of 3)
|
||||
runTime = "early"
|
||||
type = ("projected", "passive", "gang")
|
||||
|
||||
|
||||
def handler(fit, beacon, context, **kwargs):
|
||||
for x in range(1, 3):
|
||||
if beacon.getModifiedItemAttr("warfareBuff{}ID".format(x)):
|
||||
value = beacon.getModifiedItemAttr("warfareBuff{}Value".format(x))
|
||||
id = beacon.getModifiedItemAttr("warfareBuff{}ID".format(x))
|
||||
|
||||
if id:
|
||||
fit.addCommandBonus(id, value, beacon, kwargs['effect'], 'early')
|
||||
@@ -1,14 +0,0 @@
|
||||
# archaeologySkillVirusBonus
|
||||
#
|
||||
# Used by:
|
||||
# Modules named like: Emission Scope Sharpener (8 of 8)
|
||||
# Implant: Poteque 'Prospector' Archaeology AC-905
|
||||
# Implant: Poteque 'Prospector' Environmental Analysis EY-1005
|
||||
# Skill: Archaeology
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, container, context):
|
||||
level = container.level if "skill" in context else 1
|
||||
fit.modules.filteredItemIncrease(lambda mod: mod.item.requiresSkill("Archaeology"),
|
||||
"virusCoherence", container.getModifiedItemAttr("virusCoherenceBonus") * level)
|
||||
@@ -1,13 +0,0 @@
|
||||
# armorAllRepairSystemsAmountBonusPassive
|
||||
#
|
||||
# Used by:
|
||||
# Implants named like: Agency 'Hardshell' TB Dose (4 of 4)
|
||||
# Implants named like: Exile Booster (4 of 4)
|
||||
# Implant: Antipharmakon Kosybo
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, booster, context):
|
||||
fit.modules.filteredItemBoost(
|
||||
lambda mod: mod.item.requiresSkill("Repair Systems") or mod.item.requiresSkill("Capital Repair Systems"),
|
||||
"armorDamageAmount", booster.getModifiedItemAttr("armorDamageAmountBonus") or 0)
|
||||
@@ -1,11 +0,0 @@
|
||||
# armorDamageAmountBonusCapitalArmorRepairers
|
||||
#
|
||||
# Used by:
|
||||
# Modules named like: Auxiliary Nano Pump (8 of 8)
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, implant, context):
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Repair Systems"),
|
||||
"armorDamageAmount", implant.getModifiedItemAttr("repairBonus"),
|
||||
stackingPenalties=True)
|
||||
@@ -1,11 +0,0 @@
|
||||
# armoredCommandDurationBonus
|
||||
#
|
||||
# Used by:
|
||||
# Skill: Armored Command
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, src, context):
|
||||
lvl = src.level
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Armored Command"), "buffDuration",
|
||||
src.getModifiedItemAttr("durationBonus") * lvl)
|
||||
@@ -1,20 +0,0 @@
|
||||
# armoredCommandMindlink
|
||||
#
|
||||
# Used by:
|
||||
# Implant: Armored Command Mindlink
|
||||
# Implant: Federation Navy Command Mindlink
|
||||
# Implant: Imperial Navy Command Mindlink
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, src, context):
|
||||
fit.modules.filteredChargeBoost(lambda mod: mod.item.requiresSkill("Armored Command"), "warfareBuff2Multiplier",
|
||||
src.getModifiedItemAttr("mindlinkBonus"))
|
||||
fit.modules.filteredChargeBoost(lambda mod: mod.item.requiresSkill("Armored Command"), "warfareBuff1Multiplier",
|
||||
src.getModifiedItemAttr("mindlinkBonus"))
|
||||
fit.modules.filteredChargeBoost(lambda mod: mod.item.requiresSkill("Armored Command"), "warfareBuff4Multiplier",
|
||||
src.getModifiedItemAttr("mindlinkBonus"))
|
||||
fit.modules.filteredChargeBoost(lambda mod: mod.item.requiresSkill("Armored Command"), "warfareBuff3Multiplier",
|
||||
src.getModifiedItemAttr("mindlinkBonus"))
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Armored Command"), "buffDuration",
|
||||
src.getModifiedItemAttr("mindlinkBonus"))
|
||||
@@ -1,17 +0,0 @@
|
||||
# armoredCommandStrengthBonus
|
||||
#
|
||||
# Used by:
|
||||
# Skill: Armored Command Specialist
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, src, context):
|
||||
lvl = src.level
|
||||
fit.modules.filteredChargeBoost(lambda mod: mod.item.requiresSkill("Armored Command"), "warfareBuff1Multiplier",
|
||||
src.getModifiedItemAttr("commandStrengthBonus") * lvl)
|
||||
fit.modules.filteredChargeBoost(lambda mod: mod.item.requiresSkill("Armored Command"), "warfareBuff2Multiplier",
|
||||
src.getModifiedItemAttr("commandStrengthBonus") * lvl)
|
||||
fit.modules.filteredChargeBoost(lambda mod: mod.item.requiresSkill("Armored Command"), "warfareBuff4Multiplier",
|
||||
src.getModifiedItemAttr("commandStrengthBonus") * lvl)
|
||||
fit.modules.filteredChargeBoost(lambda mod: mod.item.requiresSkill("Armored Command"), "warfareBuff3Multiplier",
|
||||
src.getModifiedItemAttr("commandStrengthBonus") * lvl)
|
||||
@@ -1,9 +0,0 @@
|
||||
# armorHPBonusAdd
|
||||
#
|
||||
# Used by:
|
||||
# Modules from group: Armor Reinforcer (51 of 51)
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, module, context):
|
||||
fit.ship.increaseItemAttr("armorHP", module.getModifiedItemAttr("armorHPBonusAdd"))
|
||||
@@ -1,9 +0,0 @@
|
||||
# armorHPBonusAddPassive
|
||||
#
|
||||
# Used by:
|
||||
# Subsystems from group: Defensive Systems (9 of 12)
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, module, context):
|
||||
fit.ship.increaseItemAttr("armorHP", module.getModifiedItemAttr("armorHPBonusAdd") or 0)
|
||||
@@ -1,10 +0,0 @@
|
||||
# armorHPMultiply
|
||||
#
|
||||
# Used by:
|
||||
# Modules from group: Armor Coating (202 of 202)
|
||||
# Modules from group: Armor Plating Energized (187 of 187)
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, module, context):
|
||||
fit.ship.multiplyItemAttr("armorHP", module.getModifiedItemAttr("armorHPMultiplier"))
|
||||
@@ -1,9 +0,0 @@
|
||||
# armorReinforcerMassAdd
|
||||
#
|
||||
# Used by:
|
||||
# Modules from group: Armor Reinforcer (51 of 51)
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, module, context):
|
||||
fit.ship.increaseItemAttr("mass", module.getModifiedItemAttr("massAddition"))
|
||||
@@ -1,12 +0,0 @@
|
||||
# armorRepair
|
||||
#
|
||||
# Used by:
|
||||
# Modules from group: Armor Repair Unit (108 of 108)
|
||||
runTime = "late"
|
||||
type = "active"
|
||||
|
||||
|
||||
def handler(fit, module, context):
|
||||
amount = module.getModifiedItemAttr("armorDamageAmount")
|
||||
speed = module.getModifiedItemAttr("duration") / 1000.0
|
||||
fit.extraAttributes.increase("armorRepair", amount / speed)
|
||||
@@ -1,10 +0,0 @@
|
||||
# armorRepairAmountBonusSubcap
|
||||
#
|
||||
# Used by:
|
||||
# Implants named like: grade Asklepian (15 of 18)
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, src, context):
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Repair Systems"),
|
||||
"armorDamageAmount", src.getModifiedItemAttr("armorRepairBonus"))
|
||||
@@ -1,16 +0,0 @@
|
||||
# armorRepairProjectorFalloffBonus
|
||||
#
|
||||
# Used by:
|
||||
# Variations of ship: Navitas (2 of 2)
|
||||
# Ship: Augoror
|
||||
# Ship: Deacon
|
||||
# Ship: Exequror
|
||||
# Ship: Inquisitor
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, src, context):
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Remote Armor Repairer", "falloffEffectiveness",
|
||||
src.getModifiedItemAttr("falloffBonus"))
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Ancillary Remote Armor Repairer",
|
||||
"falloffEffectiveness", src.getModifiedItemAttr("falloffBonus"))
|
||||
@@ -1,16 +0,0 @@
|
||||
# armorRepairProjectorMaxRangeBonus
|
||||
#
|
||||
# Used by:
|
||||
# Variations of ship: Navitas (2 of 2)
|
||||
# Ship: Augoror
|
||||
# Ship: Deacon
|
||||
# Ship: Exequror
|
||||
# Ship: Inquisitor
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, src, context):
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Remote Armor Repairer", "maxRange",
|
||||
src.getModifiedItemAttr("maxRangeBonus"))
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Ancillary Remote Armor Repairer", "maxRange",
|
||||
src.getModifiedItemAttr("maxRangeBonus"))
|
||||
@@ -1,11 +0,0 @@
|
||||
# armorUpgradesMassPenaltyReductionBonus
|
||||
#
|
||||
# Used by:
|
||||
# Skill: Armor Layering
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, container, context):
|
||||
level = container.level
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Armor Reinforcer",
|
||||
"massAddition", container.getModifiedItemAttr("massPenaltyReduction") * level)
|
||||
@@ -1,14 +0,0 @@
|
||||
# astrogeologyMiningAmountBonusPostPercentMiningAmountLocationShipModulesRequiringMining
|
||||
#
|
||||
# Used by:
|
||||
# Implants named like: Inherent Implants 'Highwall' Mining MX (3 of 3)
|
||||
# Implant: Michi's Excavation Augmentor
|
||||
# Skill: Astrogeology
|
||||
# Skill: Mining
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, container, context):
|
||||
level = container.level if "skill" in context else 1
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Mining"),
|
||||
"miningAmount", container.getModifiedItemAttr("miningAmountBonus") * level)
|
||||
@@ -1,12 +0,0 @@
|
||||
# baseMaxScanDeviationModifierModuleOnline2None
|
||||
#
|
||||
# Used by:
|
||||
# Variations of module: Scan Pinpointing Array I (2 of 2)
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, module, context):
|
||||
fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("Astrometrics"),
|
||||
"baseMaxScanDeviation",
|
||||
module.getModifiedItemAttr("maxScanDeviationModifierModule"),
|
||||
stackingPenalties=True)
|
||||
@@ -1,14 +0,0 @@
|
||||
# baseMaxScanDeviationModifierRequiringAstrometrics
|
||||
#
|
||||
# Used by:
|
||||
# Implants named like: Poteque 'Prospector' Astrometric Pinpointing AP (3 of 3)
|
||||
# Skill: Astrometric Pinpointing
|
||||
# Skill: Astrometrics
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, container, context):
|
||||
level = container.level if "skill" in context else 1
|
||||
fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("Astrometrics"),
|
||||
"baseMaxScanDeviation",
|
||||
container.getModifiedItemAttr("maxScanDeviationModifier") * level)
|
||||
@@ -1,11 +0,0 @@
|
||||
# baseSensorStrengthModifierModule
|
||||
#
|
||||
# Used by:
|
||||
# Variations of module: Scan Rangefinding Array I (2 of 2)
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, module, context):
|
||||
fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("Astrometrics"),
|
||||
"baseSensorStrength", module.getModifiedItemAttr("scanStrengthBonusModule"),
|
||||
stackingPenalties=True)
|
||||
@@ -1,18 +0,0 @@
|
||||
# baseSensorStrengthModifierRequiringAstrometrics
|
||||
#
|
||||
# Used by:
|
||||
# Modules from group: Scan Probe Launcher (4 of 7)
|
||||
# Implants named like: Poteque 'Prospector' Astrometric Rangefinding AR (3 of 3)
|
||||
# Implants named like: grade Virtue (10 of 12)
|
||||
# Modules named like: Gravity Capacitor Upgrade (8 of 8)
|
||||
# Skill: Astrometric Rangefinding
|
||||
# Skill: Astrometrics
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, container, context):
|
||||
level = container.level if "skill" in context else 1
|
||||
penalized = False if "skill" in context or "implant" in context else True
|
||||
fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("Astrometrics"),
|
||||
"baseSensorStrength", container.getModifiedItemAttr("scanStrengthBonus") * level,
|
||||
stackingPenalties=penalized)
|
||||
@@ -1,11 +0,0 @@
|
||||
# battlecruiserDroneSpeed
|
||||
#
|
||||
# Used by:
|
||||
# Ship: Myrmidon
|
||||
# Ship: Prophecy
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, ship, context):
|
||||
fit.drones.filteredItemBoost(lambda drone: drone.item.requiresSkill("Drones"),
|
||||
"maxVelocity", ship.getModifiedItemAttr("roleBonusCBC"))
|
||||
@@ -1,12 +0,0 @@
|
||||
# battlecruiserMETRange
|
||||
#
|
||||
# Used by:
|
||||
# Ships named like: Harbinger (2 of 2)
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, ship, context):
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Medium Energy Turret"),
|
||||
"maxRange", ship.getModifiedItemAttr("roleBonusCBC"))
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Medium Energy Turret"),
|
||||
"falloff", ship.getModifiedItemAttr("roleBonusCBC"))
|
||||
@@ -1,13 +0,0 @@
|
||||
# battlecruiserMHTRange
|
||||
#
|
||||
# Used by:
|
||||
# Ships named like: Brutix (2 of 2)
|
||||
# Ship: Ferox
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, ship, context):
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Medium Hybrid Turret"),
|
||||
"maxRange", ship.getModifiedItemAttr("roleBonusCBC"))
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Medium Hybrid Turret"),
|
||||
"falloff", ship.getModifiedItemAttr("roleBonusCBC"))
|
||||
@@ -1,11 +0,0 @@
|
||||
# battlecruiserMissileRange
|
||||
#
|
||||
# Used by:
|
||||
# Ships named like: Drake (2 of 2)
|
||||
# Ship: Cyclone
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, skill, context):
|
||||
fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("Missile Launcher Operation"),
|
||||
"maxVelocity", skill.getModifiedItemAttr("roleBonusCBC"))
|
||||
@@ -1,12 +0,0 @@
|
||||
# battlecruiserMPTRange
|
||||
#
|
||||
# Used by:
|
||||
# Ships named like: Hurricane (2 of 2)
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, ship, context):
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Medium Projectile Turret"),
|
||||
"maxRange", ship.getModifiedItemAttr("roleBonusCBC"))
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Medium Projectile Turret"),
|
||||
"falloff", ship.getModifiedItemAttr("roleBonusCBC"))
|
||||
@@ -1,10 +0,0 @@
|
||||
# bcLargeEnergyTurretCapacitorNeedBonus
|
||||
#
|
||||
# Used by:
|
||||
# Ship: Oracle
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, ship, context):
|
||||
fit.modules.filteredItemMultiply(lambda mod: mod.item.requiresSkill("Large Energy Turret"),
|
||||
"capacitorNeed", ship.getModifiedItemAttr("bcLargeTurretCap"))
|
||||
@@ -1,10 +0,0 @@
|
||||
# bcLargeEnergyTurretCPUNeedBonus
|
||||
#
|
||||
# Used by:
|
||||
# Ship: Oracle
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, ship, context):
|
||||
fit.modules.filteredItemMultiply(lambda mod: mod.item.requiresSkill("Large Energy Turret"),
|
||||
"cpu", ship.getModifiedItemAttr("bcLargeTurretCPU"))
|
||||
@@ -1,10 +0,0 @@
|
||||
# bcLargeEnergyTurretPowerNeedBonus
|
||||
#
|
||||
# Used by:
|
||||
# Ship: Oracle
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, ship, context):
|
||||
fit.modules.filteredItemMultiply(lambda mod: mod.item.requiresSkill("Large Energy Turret"),
|
||||
"power", ship.getModifiedItemAttr("bcLargeTurretPower"))
|
||||
@@ -1,11 +0,0 @@
|
||||
# bcLargeHybridTurretCapacitorNeedBonus
|
||||
#
|
||||
# Used by:
|
||||
# Ship: Naga
|
||||
# Ship: Talos
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, ship, context):
|
||||
fit.modules.filteredItemMultiply(lambda mod: mod.item.requiresSkill("Large Hybrid Turret"),
|
||||
"capacitorNeed", ship.getModifiedItemAttr("bcLargeTurretCap"))
|
||||
@@ -1,11 +0,0 @@
|
||||
# bcLargeHybridTurretCPUNeedBonus
|
||||
#
|
||||
# Used by:
|
||||
# Ship: Naga
|
||||
# Ship: Talos
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, ship, context):
|
||||
fit.modules.filteredItemMultiply(lambda mod: mod.item.requiresSkill("Large Hybrid Turret"),
|
||||
"cpu", ship.getModifiedItemAttr("bcLargeTurretCPU"))
|
||||
@@ -1,11 +0,0 @@
|
||||
# bcLargeHybridTurretPowerNeedBonus
|
||||
#
|
||||
# Used by:
|
||||
# Ship: Naga
|
||||
# Ship: Talos
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, ship, context):
|
||||
fit.modules.filteredItemMultiply(lambda mod: mod.item.requiresSkill("Large Hybrid Turret"),
|
||||
"power", ship.getModifiedItemAttr("bcLargeTurretPower"))
|
||||
@@ -1,10 +0,0 @@
|
||||
# bcLargeProjectileTurretCPUNeedBonus
|
||||
#
|
||||
# Used by:
|
||||
# Ship: Tornado
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, ship, context):
|
||||
fit.modules.filteredItemMultiply(lambda mod: mod.item.requiresSkill("Large Projectile Turret"),
|
||||
"cpu", ship.getModifiedItemAttr("bcLargeTurretCPU"))
|
||||
@@ -1,10 +0,0 @@
|
||||
# bcLargeProjectileTurretPowerNeedBonus
|
||||
#
|
||||
# Used by:
|
||||
# Ship: Tornado
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, ship, context):
|
||||
fit.modules.filteredItemMultiply(lambda mod: mod.item.requiresSkill("Large Projectile Turret"),
|
||||
"power", ship.getModifiedItemAttr("bcLargeTurretPower"))
|
||||
@@ -1,12 +0,0 @@
|
||||
# biologyTimeBonusFixed
|
||||
#
|
||||
# Used by:
|
||||
# Implants named like: Eifyr and Co. 'Alchemist' Biology BY (2 of 2)
|
||||
# Skill: Biology
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, container, context):
|
||||
level = container.level if "skill" in context else 1
|
||||
fit.boosters.filteredItemBoost(lambda bst: True, "boosterDuration",
|
||||
container.getModifiedItemAttr("durationBonus") * level)
|
||||
@@ -1,12 +0,0 @@
|
||||
# blockadeRunnerCloakCpuPercentBonus
|
||||
#
|
||||
# Used by:
|
||||
# Ships from group: Blockade Runner (4 of 4)
|
||||
type = "passive"
|
||||
runTime = "early"
|
||||
|
||||
|
||||
def handler(fit, ship, context):
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Cloaking Device",
|
||||
"cpu", ship.getModifiedItemAttr("eliteIndustrialCovertCloakBonus"),
|
||||
skill="Transport Ships")
|
||||
@@ -1,15 +0,0 @@
|
||||
# boosterArmorHpPenalty
|
||||
#
|
||||
# Used by:
|
||||
# Implants named like: Booster (12 of 35)
|
||||
type = "boosterSideEffect"
|
||||
|
||||
# User-friendly name for the side effect
|
||||
displayName = "Armor Capacity"
|
||||
|
||||
# Attribute that this effect targets
|
||||
attr = "boosterArmorHPPenalty"
|
||||
|
||||
|
||||
def handler(fit, booster, context):
|
||||
fit.ship.boostItemAttr("armorHP", booster.getModifiedItemAttr(attr))
|
||||
@@ -1,18 +0,0 @@
|
||||
# boosterArmorRepairAmountPenalty
|
||||
#
|
||||
# Used by:
|
||||
# Implants named like: Drop Booster (3 of 4)
|
||||
# Implants named like: Mindflood Booster (3 of 4)
|
||||
# Implants named like: Sooth Sayer Booster (3 of 4)
|
||||
type = "boosterSideEffect"
|
||||
|
||||
# User-friendly name for the side effect
|
||||
displayName = "Armor Repair Amount"
|
||||
|
||||
# Attribute that this effect targets
|
||||
attr = "boosterArmorRepairAmountPenalty"
|
||||
|
||||
|
||||
def handler(fit, booster, context):
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Armor Repair Unit",
|
||||
"armorDamageAmount", booster.getModifiedItemAttr(attr))
|
||||
@@ -1,16 +0,0 @@
|
||||
# boosterCapacitorCapacityPenalty
|
||||
#
|
||||
# Used by:
|
||||
# Implants named like: Blue Pill Booster (3 of 5)
|
||||
# Implants named like: Exile Booster (3 of 4)
|
||||
type = "boosterSideEffect"
|
||||
|
||||
# User-friendly name for the side effect
|
||||
displayName = "Cap Capacity"
|
||||
|
||||
# Attribute that this effect targets
|
||||
attr = "boosterCapacitorCapacityPenalty"
|
||||
|
||||
|
||||
def handler(fit, booster, context):
|
||||
fit.ship.boostItemAttr("capacitorCapacity", booster.getModifiedItemAttr(attr))
|
||||
@@ -1,16 +0,0 @@
|
||||
# boosterMaxVelocityPenalty
|
||||
#
|
||||
# Used by:
|
||||
# Implants named like: Crash Booster (3 of 4)
|
||||
# Items from market group: Implants & Boosters > Booster > Booster Slot 02 (9 of 13)
|
||||
type = "boosterSideEffect"
|
||||
|
||||
# User-friendly name for the side effect
|
||||
displayName = "Velocity"
|
||||
|
||||
# Attribute that this effect targets
|
||||
attr = "boosterMaxVelocityPenalty"
|
||||
|
||||
|
||||
def handler(fit, booster, context):
|
||||
fit.ship.boostItemAttr("maxVelocity", booster.getModifiedItemAttr(attr))
|
||||
@@ -1,17 +0,0 @@
|
||||
# boosterMissileExplosionCloudPenaltyFixed
|
||||
#
|
||||
# Used by:
|
||||
# Implants named like: Exile Booster (3 of 4)
|
||||
# Implants named like: Mindflood Booster (3 of 4)
|
||||
type = "boosterSideEffect"
|
||||
|
||||
# User-friendly name for the side effect
|
||||
displayName = "Missile Explosion Radius"
|
||||
|
||||
# Attribute that this effect targets
|
||||
attr = "boosterMissileAOECloudPenalty"
|
||||
|
||||
|
||||
def handler(fit, booster, context):
|
||||
fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("Missile Launcher Operation"),
|
||||
"aoeCloudSize", booster.getModifiedItemAttr(attr))
|
||||
@@ -1,16 +0,0 @@
|
||||
# boosterMissileExplosionVelocityPenalty
|
||||
#
|
||||
# Used by:
|
||||
# Implants named like: Blue Pill Booster (3 of 5)
|
||||
type = "boosterSideEffect"
|
||||
|
||||
# User-friendly name for the side effect
|
||||
displayName = "Missile Explosion Velocity"
|
||||
|
||||
# Attribute that this effect targets
|
||||
attr = "boosterAOEVelocityPenalty"
|
||||
|
||||
|
||||
def handler(fit, booster, context):
|
||||
fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("Missile Launcher Operation"),
|
||||
"aoeVelocity", booster.getModifiedItemAttr(attr))
|
||||
@@ -1,17 +0,0 @@
|
||||
# boosterMissileVelocityPenalty
|
||||
#
|
||||
# Used by:
|
||||
# Implants named like: Crash Booster (3 of 4)
|
||||
# Implants named like: X Instinct Booster (3 of 4)
|
||||
type = "boosterSideEffect"
|
||||
|
||||
# User-friendly name for the side effect
|
||||
displayName = "Missile Velocity"
|
||||
|
||||
# Attribute that this effect targets
|
||||
attr = "boosterMissileVelocityPenalty"
|
||||
|
||||
|
||||
def handler(fit, booster, context):
|
||||
fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill("Missile Launcher Operation"),
|
||||
"maxVelocity", booster.getModifiedItemAttr(attr))
|
||||
@@ -1,15 +0,0 @@
|
||||
# boosterModifyBoosterArmorPenalties
|
||||
#
|
||||
# Used by:
|
||||
# Implants named like: Eifyr and Co. 'Alchemist' Neurotoxin Control NC (2 of 2)
|
||||
# Implants named like: grade Edge (10 of 12)
|
||||
# Skill: Neurotoxin Control
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, container, context):
|
||||
level = container.level if "skill" in context else 1
|
||||
attrs = ("boosterArmorHPPenalty", "boosterArmorRepairAmountPenalty")
|
||||
for attr in attrs:
|
||||
fit.boosters.filteredItemBoost(lambda booster: True, attr,
|
||||
container.getModifiedItemAttr("boosterAttributeModifier") * level)
|
||||
@@ -1,15 +0,0 @@
|
||||
# boosterModifyBoosterMaxVelocityAndCapacitorPenalty
|
||||
#
|
||||
# Used by:
|
||||
# Implants named like: Eifyr and Co. 'Alchemist' Neurotoxin Control NC (2 of 2)
|
||||
# Implants named like: grade Edge (10 of 12)
|
||||
# Skill: Neurotoxin Control
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, container, context):
|
||||
level = container.level if "skill" in context else 1
|
||||
attrs = ("boosterCapacitorCapacityPenalty", "boosterMaxVelocityPenalty")
|
||||
for attr in attrs:
|
||||
fit.boosters.filteredItemBoost(lambda booster: True, attr,
|
||||
container.getModifiedItemAttr("boosterAttributeModifier") * level)
|
||||
@@ -1,15 +0,0 @@
|
||||
# boosterModifyBoosterMissilePenalty
|
||||
#
|
||||
# Used by:
|
||||
# Implants named like: Eifyr and Co. 'Alchemist' Neurotoxin Control NC (2 of 2)
|
||||
# Implants named like: grade Edge (10 of 12)
|
||||
# Skill: Neurotoxin Control
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, container, context):
|
||||
level = container.level if "skill" in context else 1
|
||||
attrs = ("boosterAOEVelocityPenalty", "boosterMissileAOECloudPenalty", "boosterMissileVelocityPenalty")
|
||||
for attr in attrs:
|
||||
fit.boosters.filteredItemBoost(lambda booster: True, attr,
|
||||
container.getModifiedItemAttr("boosterAttributeModifier") * level)
|
||||
@@ -1,17 +0,0 @@
|
||||
# boosterModifyBoosterShieldPenalty
|
||||
#
|
||||
# Used by:
|
||||
# Implants named like: Eifyr and Co. 'Alchemist' Neurotoxin Control NC (2 of 2)
|
||||
# Implants named like: grade Edge (10 of 12)
|
||||
# Skill: Neurotoxin Control
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, container, context):
|
||||
level = container.level if "skill" in context else 1
|
||||
attrs = ("boosterShieldBoostAmountPenalty", "boosterShieldCapacityPenalty", "shieldBoostMultiplier")
|
||||
for attr in attrs:
|
||||
# shieldBoostMultiplier can be positive (Blue Pill) and negative value (other boosters)
|
||||
# We're interested in decreasing only side-effects
|
||||
fit.boosters.filteredItemBoost(lambda booster: booster.getModifiedItemAttr(attr) < 0,
|
||||
attr, container.getModifiedItemAttr("boosterAttributeModifier") * level)
|
||||
@@ -1,15 +0,0 @@
|
||||
# boosterModifyBoosterTurretPenalty
|
||||
#
|
||||
# Used by:
|
||||
# Implants named like: Eifyr and Co. 'Alchemist' Neurotoxin Control NC (2 of 2)
|
||||
# Implants named like: grade Edge (10 of 12)
|
||||
# Skill: Neurotoxin Control
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, container, context):
|
||||
level = container.level if "skill" in context else 1
|
||||
attrs = ("boosterTurretFalloffPenalty", "boosterTurretOptimalRangePenalty", "boosterTurretTrackingPenalty")
|
||||
for attr in attrs:
|
||||
fit.boosters.filteredItemBoost(lambda booster: True, attr,
|
||||
container.getModifiedItemAttr("boosterAttributeModifier") * level)
|
||||
@@ -1,20 +0,0 @@
|
||||
# boosterShieldBoostAmountPenaltyShieldSkills
|
||||
#
|
||||
# Used by:
|
||||
# Implants named like: Crash Booster (3 of 4)
|
||||
# Implants named like: Frentix Booster (3 of 4)
|
||||
# Implants named like: Mindflood Booster (3 of 4)
|
||||
type = "boosterSideEffect"
|
||||
|
||||
# User-friendly name for the side effect
|
||||
displayName = "Shield Boost"
|
||||
|
||||
# Attribute that this effect targets
|
||||
attr = "boosterShieldBoostAmountPenalty"
|
||||
|
||||
|
||||
def handler(fit, src, context):
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Shield Operation"), "shieldBonus",
|
||||
src.getModifiedItemAttr("boosterShieldBoostAmountPenalty"))
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Shield Operation"), "shieldBonus",
|
||||
src.getModifiedItemAttr("boosterShieldBoostAmountPenalty"))
|
||||
@@ -1,15 +0,0 @@
|
||||
# boosterShieldCapacityPenalty
|
||||
#
|
||||
# Used by:
|
||||
# Implants from group: Booster (12 of 69)
|
||||
type = "boosterSideEffect"
|
||||
|
||||
# User-friendly name for the side effect
|
||||
displayName = "Shield Capacity"
|
||||
|
||||
# Attribute that this effect targets
|
||||
attr = "boosterShieldCapacityPenalty"
|
||||
|
||||
|
||||
def handler(fit, booster, context):
|
||||
fit.ship.boostItemAttr("shieldCapacity", booster.getModifiedItemAttr(attr))
|
||||
@@ -1,17 +0,0 @@
|
||||
# boosterTurretFalloffPenalty
|
||||
#
|
||||
# Used by:
|
||||
# Implants named like: Drop Booster (3 of 4)
|
||||
# Implants named like: X Instinct Booster (3 of 4)
|
||||
type = "boosterSideEffect"
|
||||
|
||||
# User-friendly name for the side effect
|
||||
displayName = "Turret Falloff"
|
||||
|
||||
# Attribute that this effect targets
|
||||
attr = "boosterTurretFalloffPenalty"
|
||||
|
||||
|
||||
def handler(fit, booster, context):
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Gunnery"),
|
||||
"falloff", booster.getModifiedItemAttr(attr))
|
||||
@@ -1,18 +0,0 @@
|
||||
# boosterTurretOptimalRangePenalty
|
||||
#
|
||||
# Used by:
|
||||
# Implants named like: Blue Pill Booster (3 of 5)
|
||||
# Implants named like: Mindflood Booster (3 of 4)
|
||||
# Implants named like: Sooth Sayer Booster (3 of 4)
|
||||
type = "boosterSideEffect"
|
||||
|
||||
# User-friendly name for the side effect
|
||||
displayName = "Turret Optimal Range"
|
||||
|
||||
# Attribute that this effect targets
|
||||
attr = "boosterTurretOptimalRangePenalty"
|
||||
|
||||
|
||||
def handler(fit, booster, context):
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Gunnery"),
|
||||
"maxRange", booster.getModifiedItemAttr(attr))
|
||||
@@ -1,17 +0,0 @@
|
||||
# boosterTurretTrackingPenalty
|
||||
#
|
||||
# Used by:
|
||||
# Implants named like: Exile Booster (3 of 4)
|
||||
# Implants named like: Frentix Booster (3 of 4)
|
||||
type = "boosterSideEffect"
|
||||
|
||||
# User-friendly name for the side effect
|
||||
displayName = "Turret Tracking"
|
||||
|
||||
# Attribute that this effect targets
|
||||
attr = "boosterTurretTrackingPenalty"
|
||||
|
||||
|
||||
def handler(fit, booster, context):
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Gunnery"),
|
||||
"trackingSpeed", booster.getModifiedItemAttr(attr))
|
||||
@@ -1,12 +0,0 @@
|
||||
# caldarisetbonus3
|
||||
#
|
||||
# Used by:
|
||||
# Implants named like: High grade Talon (6 of 6)
|
||||
runTime = "early"
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, implant, context):
|
||||
fit.appliedImplants.filteredItemMultiply(lambda target: target.item.requiresSkill("Cybernetics"),
|
||||
"scanGravimetricStrengthPercent",
|
||||
implant.getModifiedItemAttr("implantSetCaldariNavy"))
|
||||
@@ -1,12 +0,0 @@
|
||||
# caldarisetLGbonus
|
||||
#
|
||||
# Used by:
|
||||
# Implants named like: Low grade Talon (6 of 6)
|
||||
runTime = "early"
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, implant, context):
|
||||
fit.appliedImplants.filteredItemMultiply(lambda target: target.item.requiresSkill("Cybernetics"),
|
||||
"scanGravimetricStrengthModifier",
|
||||
implant.getModifiedItemAttr("implantSetLGCaldariNavy"))
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user