Compare commits

...

156 Commits

Author SHA1 Message Date
willyb321
6922cfd047 2.9.11 2018-04-26 09:19:57 +10:00
willyb321
d93fc1d2d0 just update everything when applying a special 2018-04-26 09:06:18 +10:00
willyb321
48290b2e75 2.9.10 2018-04-25 20:00:36 +10:00
willyb321
b62abef618 2.9.9 2018-04-25 19:55:05 +10:00
willyb321
e0c0778d82 Lowercase in import 2018-04-25 18:45:24 +10:00
willyb321
b4a82ae7c2 fix crash with not having modifications key 2018-04-25 18:00:01 +10:00
willyb321
fc73102b30 Merge remote-tracking branch 'origin/develop' into develop 2018-04-25 15:07:23 +10:00
willyb321
b14e7473f3 add guardian powerplant, gauss cannon and also plasma charger 2018-04-25 15:07:13 +10:00
willyb321
f4cc9fc722 fix typo 2018-04-25 14:20:45 +10:00
William
8d19ef7783 Merge pull request #256 from ExitCode/develop
Fixed bp preset highlight when specials alter on the same values
2018-04-24 14:49:39 +10:00
willyb321
32be186ec5 remove unused var 2018-04-23 18:15:44 +10:00
willyb321
abb0c7f90d remove debug logs 2018-04-23 18:15:24 +10:00
willyb321
71ddbdfe75 add specials tooltip 2018-04-23 14:51:45 +10:00
ExitCode
38463ad9a6 Fixed bp preset highlight when specials alter on the same values 2018-04-23 01:16:13 +02:00
willyb321
70375f94c8 bump 2018-04-23 07:38:24 +10:00
William
2d4336116a Merge pull request #254 from ExitCode/develop
Value highlights for bp presets
2018-04-23 07:36:12 +10:00
willyb321
f52880765e fix legacy mods showing up 2018-04-23 07:34:52 +10:00
ExitCode
dbfe68decb Implemented active selected blueprint value highlight; updated look and feel 2018-04-22 05:36:19 +02:00
ExitCode
659f337de9 Added a spacer between the mod values 2018-04-22 05:34:25 +02:00
ExitCode
1d36d41da1 Tuned visibility of components in mod menu 2018-04-22 05:33:47 +02:00
ExitCode
0f90efaa54 Implemented a func to determine the current percentage level of a mod 2018-04-22 05:31:16 +02:00
willyb321
4442930a82 bump 2018-04-22 12:26:06 +10:00
William
912a775088 Merge pull request #253 from ExitCode/develop
blue print workflow (easier editing of modules)
2018-04-22 12:08:01 +10:00
ExitCode
24a229d818 Implemented workflow on bp assignment; applied some styles 2018-04-22 03:43:57 +02:00
ExitCode
66afb61494 added new style for inline menu buttons 2018-04-22 03:41:21 +02:00
William
e7511cc05b Merge pull request #252 from ExitCode/develop
(optional) changed roll presets to 0-50-100
2018-04-22 09:09:37 +10:00
ExitCode
926f19a936 added default init 100% on bp selection as the new system makes it obvious to reach 100% 2018-04-22 00:59:44 +02:00
ExitCode
9e6f86b963 (optional) changed roll presets to 0-50-100 2018-04-22 00:28:04 +02:00
William
059de43a9a Merge pull request #251 from ExitCode/develop
reused random functionality as it worked better on percentage rolls between min max
2018-04-22 08:10:30 +10:00
ExitCode
e246b737b2 reused random functionality as it worked better on percentage rolls between min/max 2018-04-21 23:53:02 +02:00
willyb321
38842417b0 bump 2018-04-22 06:59:08 +10:00
willyb321
82d485a98e fix preset rolls locked to low value 2018-04-22 06:49:43 +10:00
willyb321
fac71feea7 Lowercase armour check
Fixes #231
2018-04-21 12:56:51 +10:00
willyb321
445c63878b add guard for tooltips crashing the import 2018-04-21 11:39:02 +10:00
willyb321
7df5953824 bump 2018-04-21 11:05:19 +10:00
willyb321
e391b563fb change preset rolls to 100%, 75%, 50% and random 2018-04-21 11:03:23 +10:00
willyb321
53f62f96d0 Merge branch 'master' into develop 2018-04-21 07:17:11 +10:00
willyb321
18745979a0 update about page 2018-04-20 19:20:47 +10:00
willyb321
c1966a38ff Merge branch 'master' into develop 2018-04-20 12:49:10 +10:00
willyb321
d86973f3b1 specify appVersion for bugsnag 2018-04-20 12:48:46 +10:00
willyb321
56b8d19649 Merge branch 'release/2.9.4' 2018-04-19 07:17:21 +10:00
willyb321
7cb037e0bc bump 2018-04-19 07:17:06 +10:00
willyb321
56e1b3f9e9 Revert "prep for guardian"
This reverts commit 7e67bd80dd.
2018-04-19 07:14:24 +10:00
willyb321
c792323a8a misc bits 2018-04-19 07:14:13 +10:00
willyb321
4d2865de13 fix resistance blueprint values 2018-04-19 07:14:02 +10:00
willyb321
0d360bc367 bugsnag update 2018-04-19 07:13:20 +10:00
willyb321
91c9b46b91 clean up webpack configs 2018-04-19 06:44:02 +10:00
willyb321
7e67bd80dd prep for guardian 2018-04-19 06:26:53 +10:00
willyb321
2f775ea09b Merge branch 'release/2.9.3' 2018-04-18 18:04:42 +10:00
willyb321
0603c55089 bump 2018-04-18 18:04:28 +10:00
willyb321
41f25a44e9 Merge branch 'master' into develop 2018-04-18 10:33:17 +10:00
willyb321
35440b7273 allow specials in internal and standard slots 2018-04-18 10:33:11 +10:00
willyb321
7d68b91018 Merge branch 'release/2.9.2' 2018-04-17 17:33:45 +10:00
willyb321
deaa61b848 bump version 2018-04-17 17:32:56 +10:00
willyb321
2d00cbc41b fix more values (hopefully done)
also, Fixes #247 by changing passengers to pax
2018-04-17 17:31:11 +10:00
willyb321
57c1e83c67 apply new experimentals structure 2018-04-17 15:01:09 +10:00
William
b7079dbd4e Merge pull request #246 from pnellesen/feature/bugfix_245
Fix for issue 245
2018-04-17 12:38:21 +10:00
willyb321
be642a5373 Merge branch 'master' into develop 2018-04-17 07:59:42 +10:00
willyb321
ffc691c1a2 Merge branch 'release/2.9.1' 2018-04-17 07:57:44 +10:00
willyb321
6122d99369 version bump 2018-04-17 07:57:13 +10:00
willyb321
b73a8bcdab hopefully fix some values and crashes
resistances are buggered on shields and armour by the looks of things
2018-04-17 07:55:17 +10:00
willyb321
dd624537b7 fix hardpoints / internals having the wrong mod applied 2018-04-17 07:50:57 +10:00
willyb321
50a67f73fd get rid of some redundant code 2018-04-17 07:50:13 +10:00
willyb321
2262a980d4 Merge remote-tracking branch 'origin/develop' into develop 2018-04-17 07:46:35 +10:00
willyb321
84964ceb5f add source maps to assist with debugging.
also upload them to bugsnag
2018-04-17 07:46:26 +10:00
William Blythe
c4bdb7a66e Merge remote-tracking branch 'origin/master' into develop 2018-04-16 13:11:44 +10:00
Pat
21309e129f Fix for issue 245 - check that the passenger property is defined for a slot before calculating total passenger capacity 2018-04-14 08:50:48 -05:00
willyb321
928e02c718 Merge branch 'release/2.9.0' 2018-04-14 16:53:08 +10:00
willyb321
7f494dd200 bump 2018-04-14 16:52:05 +10:00
William
f38e743e59 Merge pull request #244 from EDCD/feature/beyond-coriolis
Engineer mods.
2018-04-14 15:14:13 +10:00
Willyb321
58b55eb3da Engineers. Are. Back. Probably. 2018-04-14 14:50:37 +10:00
willyb321
8375ad95b3 Merge branch 'master' into feature/beyond-coriolis 2018-04-14 10:16:20 +10:00
willyb321
506d027a2d Merge branch 'develop' 2018-04-14 09:52:03 +10:00
willyb321
fbeb6237cf fix webpack 2018-04-14 09:51:46 +10:00
willyb321
bd95e2c5a5 Merge branch 'master' into develop 2018-04-14 09:48:03 +10:00
willyb321
f3276e557a Merge branch 'release/2.5.3' 2018-04-14 09:47:08 +10:00
willyb321
8b813e0e7f bump 2018-04-14 09:46:41 +10:00
willyb321
d660d2959f more roles fixing
use a smaller shield, add boosters, d rate some internals
2018-04-14 09:44:29 +10:00
willyb321
014ebda7d2 start fixing suggested roles. Thanks to rinzler + others 2018-04-14 08:06:44 +10:00
William
607398d364 Merge pull request #241 from Blackth0rn/fix/#240_incorrect_passenger_counts
Fix/#240 incorrect passenger counts
2018-04-13 16:20:52 +10:00
willyb321
97d141ce2b update lockfile version 2018-04-13 16:17:59 +10:00
willyb321
9f492db9c6 source map 2018-04-13 16:16:42 +10:00
willyb321
6ed82b366c update bugsnag 2018-04-13 16:16:01 +10:00
willyb321
a7ca037f48 loadout event prep 2018-04-13 14:38:22 +10:00
willyb321
6e21d0e74a Work on engineering import 2018-04-13 13:39:33 +10:00
willyb321
e6c75bf2af Merge branch 'develop' into feature/beyond-coriolis 2018-04-13 09:16:23 +10:00
willyb321
270c2f386e Merge branch 'release/2.5.2' 2018-04-13 07:56:38 +10:00
willyb321
83f7880c58 bump version 2018-04-13 07:51:07 +10:00
William
51d29aee38 Merge pull request #235 from pnellesen/feature/fueltank_column
Added fuel tank column to Core Module Classes on Shipyard
2018-04-13 07:38:07 +10:00
William
c7754c0365 Merge pull request #234 from joelgarboden/feature/remote_testing
Disable 'localhost' host header requirement
2018-04-13 07:34:59 +10:00
Greg Matthews
94037cea38 Fix #240: Added passenger count to individual ship page 2018-04-11 21:09:57 -07:00
Greg Matthews
5c1a9d9eea Fix #240: There is no size 7 passenger cabin so use the new findMaxInternal function to get the biggest one that fits in the slot 2018-04-11 21:07:00 -07:00
Greg Matthews
3835c73ffd Add findMaxInternal function to find the biggest module of a given group, rating, slotsize 2018-04-11 21:06:07 -07:00
Pat
b8c1effecb Update for issue #183 - use first letter of bulkhead instead of "Max Rating" value 2018-04-09 23:10:28 -05:00
Pat
dd07241dd9 Added fuel tank column to Core Module Classes on Shipyard 2018-04-07 18:57:54 -05:00
Joel Garboden
5ad828a613 Disable 'localhost' limit
Disale host header so webpack allows more than localhost access
2018-04-07 22:34:50 +00:00
Unknown
9856df5527 Portiguese 2018-03-22 22:00:19 +00:00
Unknown
7b249900ec Portuguese 2018-03-22 21:59:50 +00:00
Unknown
e3b9267c3f Merge remote-tracking branch 'origin/feature/beyond-coriolis' into develop 2018-03-22 21:59:37 +00:00
willyb321
a996b8135a inital engineerless import working 2018-03-23 08:51:48 +11:00
willyb321
5e1237390b Initial work on 3.0 imports.
Decided to split journal imports to a separate file.
2018-03-22 16:22:59 +11:00
Willyb321
83571b4bef add .editorconfig
Makes contributing and not messing up the codestyle easier
2018-03-22 12:07:19 +11:00
Willyb321
c2a0dad9a8 Export textarea select
Fixes #146
2018-03-22 12:06:36 +11:00
Unknown
f6f057689c Merge branch 'feature/chieftain' into develop 2018-01-27 11:47:17 +00:00
willyb321
4378f0020e add chieftain to map
also remove console logs that i forgot to remove
2018-01-27 10:55:37 +11:00
Unknown
2e9e7c4fc6 Merge branch 'release/2.5.1' 2018-01-24 09:18:58 +00:00
Unknown
b7b8ee5580 Merge branch 'release/2.5.1' into develop 2018-01-24 09:18:36 +00:00
Unknown
c630dbbed0 Version Bump 2018-01-24 09:18:21 +00:00
Unknown
fa6703a3b8 Merge remote-tracking branch 'Blackth0rn/feature/#186-passenger-totals' into develop 2018-01-24 08:45:54 +00:00
Unknown
bdcb64c9d1 Merge remote-tracking branch 'willyb321/feature/fix-engineer-values' into develop 2018-01-24 08:45:48 +00:00
Unknown
a1afc869a7 Merge remote-tracking branch 'Ghnuberath/feature/ax-modules' into develop 2018-01-24 08:45:44 +00:00
Unknown
d8ce26c7cf Merge remote-tracking branch 'origin/master' into develop 2018-01-24 08:44:45 +00:00
Sean McIntyre
95c474dc05 Recategorizing experimental modules into an "experimental" category 2018-01-22 16:48:10 -05:00
Sean McIntyre
56ca73b4ad Forgot Remote Release Flak Launcher 2018-01-22 16:43:29 -05:00
Sean McIntyre
d82cd6a89e Removing unnecessary change 2018-01-22 15:21:59 -05:00
Sean McIntyre
bf20d32364 Adding AX modules 2018-01-22 15:20:41 -05:00
willyb321
e968e62fca Fix clip size (hopefully) 2018-01-16 08:14:21 +11:00
Unknown
b9c9ca9fa1 Merge branch 'release/2.5.0' 2018-01-11 21:59:31 +00:00
Unknown
6e965e2e98 Version Bump 2018-01-11 21:59:20 +00:00
Unknown
7d569f9036 Merge branch 'feature/fix-engineers' into develop 2018-01-11 21:51:35 +00:00
Unknown
df5a77199d Merge branch 'develop' 2018-01-11 21:50:28 +00:00
Greg Matthews
3c8dfebfdc Issue #186. Added passenger totals to shipyard screen 2018-01-10 21:20:27 -08:00
Unknown
3cc422596f Something something consistant naming 2017-12-24 09:47:49 +00:00
Unknown
4ed167de22 Add T10 2017-12-24 09:47:33 +00:00
Unknown
b420647501 Something something consistant naming 2017-12-24 09:46:49 +00:00
Unknown
0c318b5e68 Add T10 2017-12-23 12:03:21 +00:00
willyb321
1c627297b8 shorten the terrible _addModifications call 2017-12-19 16:39:42 +11:00
willyb321
f41e2d0552 fix indent and hopefully fix ammo clip
dont know if it was broken, if someone has it DM it to me thanks
2017-12-19 16:28:05 +11:00
willyb321
1a1d539c60 fix engagement range slider and armour integrity
hopefully
2017-12-19 16:18:20 +11:00
willyb321
ba2e46f88f fix rate of fire
probably
2017-12-19 14:49:04 +11:00
willyb321
c2f1fa81af remove console logs 2017-12-17 18:48:24 +11:00
willyb321
752e03fa0f possible armour fix
need more data to confirm however
2017-12-17 18:24:34 +11:00
willyb321
1da69664d7 shields should be accurate now
dont now what the issue with hull is
if you see it let me know
2017-12-17 14:49:51 +11:00
willyb321
9aa986a133 thanks webstorm 2017-12-17 12:48:13 +11:00
willyb321
bdbfb28c4a missed a spot 2017-12-17 12:47:02 +11:00
willyb321
162156bb2b fix random weird indents 2017-12-17 12:46:18 +11:00
willyb321
64c5d542e9 more work on mods 2017-12-17 12:27:04 +11:00
willyb321
31dc789f6e initial (re)implementation of engineer mods
still some kinds to work out.
2017-12-17 11:16:50 +11:00
Unknown
b0e2cfd7db Merge branch 'feature/#112_ship_table_highlights' into develop 2017-12-04 09:41:54 +00:00
Greg Matthews
54ddb0d014 Rename sortValue and tmpSortValue to be more meaningful 2017-11-11 13:29:59 -08:00
Greg Matthews
e19688e96f Add alternate row highlighting for sorted value 2017-11-11 13:25:17 -08:00
Greg Matthews
4f53d75999 Fix whitespace in html 2017-11-11 13:24:57 -08:00
Unknown
7277460060 Merge branch 'release/2.4.2' 2017-11-09 17:23:46 +00:00
Unknown
93c4f6f3c0 Merge branch 'release/2.4.2' into develop 2017-11-09 17:23:32 +00:00
Unknown
c6919a7518 Bumps and changelog 2017-11-09 17:23:15 +00:00
Unknown
ca428e67dc Package Lock and D3 2017-11-09 17:18:55 +00:00
Unknown
c6726cf020 Merge remote-tracking branch 'BenJuan26/feature/fix-tests' into develop 2017-11-09 17:15:06 +00:00
Unknown
56ae1378da Merge branch 'feature/slot-commas' into develop 2017-11-09 17:14:49 +00:00
Unknown
e982ab1a3b Merge branch 'feature/ship-purchase-requirements' into develop 2017-11-09 17:11:32 +00:00
Unknown
0d6aa87e89 Update coriolis to use directory basis 2017-11-09 17:04:23 +00:00
Joshua Campbell
94d06e4025 Show ship purchase requirements on outfitting page 2017-11-07 01:46:58 -05:00
Benjamin Schubert
cee5b297ac Add create-react-class 2017-11-02 12:02:15 -04:00
Benjamin Schubert
c549213ce0 Switch to babel-preset-env 2017-11-02 11:44:53 -04:00
Benjamin Schubert
f3f9112767 Change jest version 2017-11-02 11:25:32 -04:00
Benjamin Schubert
fb325ea3e2 Add commas to slot cost 2017-11-01 15:56:51 -04:00
Unknown
3773f6f7ec Merge branch 'release/2.4.1' into develop 2017-10-31 16:52:51 +00:00
43 changed files with 14460 additions and 1332 deletions

View File

@@ -1,3 +1,3 @@
{
"presets": ["es2015", "react", "stage-0"]
}
"presets": ["env", "react", "stage-0"]
}

21
.editorconfig Normal file
View File

@@ -0,0 +1,21 @@
root = true
[*]
# change these settings to your own preference
indent_style = space
indent_size = 4
# we recommend you to keep these unchanged
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
[{package,bower}.json]
indent_style = space
indent_size = 2

View File

@@ -1,3 +1,21 @@
#2.5.1
* Passenger count on main page
* AX Modules
* Engineering fixes
* Use coriolis-data 2.5.1
#2.5.0
* willyb321 and myself have conquered engineering. Mainly him though...
* Use coriolis-data 2.5.0
#2.4.2
Lots of kind people have helped out for this release! Check out the PR history!
* Uses coriolis-data update:
* Fixes issues with repair limpets
* Adds requirement data
* Adds requirements panel
* Adds comma formatting to tooltip numbers
#2.4.1
* Small patches and changes

878
d3.js vendored
View File

@@ -1340,6 +1340,12 @@ Selection.prototype = selection.prototype = {
dispatch: selection_dispatch
};
var select = function(selector) {
return typeof selector === "string"
? new Selection([[document.querySelector(selector)]], [document.documentElement])
: new Selection([[selector]], root);
};
var define = function(constructor, factory, prototype) {
constructor.prototype = factory.prototype = prototype;
prototype.constructor = constructor;
@@ -6947,861 +6953,7 @@ var cool = cubehelixLong(cubehelix(260, 0.75, 0.35), cubehelix(80, 1.50, 0.8));
var rainbow = cubehelix();
var xhtml$1 = "http://www.w3.org/1999/xhtml";
var namespaces$1 = {
svg: "http://www.w3.org/2000/svg",
xhtml: xhtml$1,
xlink: "http://www.w3.org/1999/xlink",
xml: "http://www.w3.org/XML/1998/namespace",
xmlns: "http://www.w3.org/2000/xmlns/"
};
var namespace$1 = function(name) {
var prefix = name += "", i = prefix.indexOf(":");
if (i >= 0 && (prefix = name.slice(0, i)) !== "xmlns") name = name.slice(i + 1);
return namespaces$1.hasOwnProperty(prefix) ? {space: namespaces$1[prefix], local: name} : name;
};
function creatorInherit$1(name) {
return function() {
var document = this.ownerDocument,
uri = this.namespaceURI;
return uri === xhtml$1 && document.documentElement.namespaceURI === xhtml$1
? document.createElement(name)
: document.createElementNS(uri, name);
};
}
function creatorFixed$1(fullname) {
return function() {
return this.ownerDocument.createElementNS(fullname.space, fullname.local);
};
}
var creator$1 = function(name) {
var fullname = namespace$1(name);
return (fullname.local
? creatorFixed$1
: creatorInherit$1)(fullname);
};
var matcher$2 = function(selector) {
return function() {
return this.matches(selector);
};
};
if (typeof document !== "undefined") {
var element$2 = document.documentElement;
if (!element$2.matches) {
var vendorMatches$1 = element$2.webkitMatchesSelector
|| element$2.msMatchesSelector
|| element$2.mozMatchesSelector
|| element$2.oMatchesSelector;
matcher$2 = function(selector) {
return function() {
return vendorMatches$1.call(this, selector);
};
};
}
}
var matcher$3 = matcher$2;
var filterEvents$1 = {};
var event$1 = null;
if (typeof document !== "undefined") {
var element$3 = document.documentElement;
if (!("onmouseenter" in element$3)) {
filterEvents$1 = {mouseenter: "mouseover", mouseleave: "mouseout"};
}
}
function filterContextListener$1(listener, index, group) {
listener = contextListener$1(listener, index, group);
return function(event) {
var related = event.relatedTarget;
if (!related || (related !== this && !(related.compareDocumentPosition(this) & 8))) {
listener.call(this, event);
}
};
}
function contextListener$1(listener, index, group) {
return function(event1) {
var event0 = event$1; // Events can be reentrant (e.g., focus).
event$1 = event1;
try {
listener.call(this, this.__data__, index, group);
} finally {
event$1 = event0;
}
};
}
function parseTypenames$2(typenames) {
return typenames.trim().split(/^|\s+/).map(function(t) {
var name = "", i = t.indexOf(".");
if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i);
return {type: t, name: name};
});
}
function onRemove$1(typename) {
return function() {
var on = this.__on;
if (!on) return;
for (var j = 0, i = -1, m = on.length, o; j < m; ++j) {
if (o = on[j], (!typename.type || o.type === typename.type) && o.name === typename.name) {
this.removeEventListener(o.type, o.listener, o.capture);
} else {
on[++i] = o;
}
}
if (++i) on.length = i;
else delete this.__on;
};
}
function onAdd$1(typename, value, capture) {
var wrap = filterEvents$1.hasOwnProperty(typename.type) ? filterContextListener$1 : contextListener$1;
return function(d, i, group) {
var on = this.__on, o, listener = wrap(value, i, group);
if (on) for (var j = 0, m = on.length; j < m; ++j) {
if ((o = on[j]).type === typename.type && o.name === typename.name) {
this.removeEventListener(o.type, o.listener, o.capture);
this.addEventListener(o.type, o.listener = listener, o.capture = capture);
o.value = value;
return;
}
}
this.addEventListener(typename.type, listener, capture);
o = {type: typename.type, name: typename.name, value: value, listener: listener, capture: capture};
if (!on) this.__on = [o];
else on.push(o);
};
}
var selection_on$1 = function(typename, value, capture) {
var typenames = parseTypenames$2(typename + ""), i, n = typenames.length, t;
if (arguments.length < 2) {
var on = this.node().__on;
if (on) for (var j = 0, m = on.length, o; j < m; ++j) {
for (i = 0, o = on[j]; i < n; ++i) {
if ((t = typenames[i]).type === o.type && t.name === o.name) {
return o.value;
}
}
}
return;
}
on = value ? onAdd$1 : onRemove$1;
if (capture == null) capture = false;
for (i = 0; i < n; ++i) this.each(on(typenames[i], value, capture));
return this;
};
function none$1() {}
var selector$1 = function(selector) {
return selector == null ? none$1 : function() {
return this.querySelector(selector);
};
};
var selection_select$1 = function(select) {
if (typeof select !== "function") select = selector$1(select);
for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) {
if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) {
if ("__data__" in node) subnode.__data__ = node.__data__;
subgroup[i] = subnode;
}
}
}
return new Selection$2(subgroups, this._parents);
};
function empty$2() {
return [];
}
var selectorAll$1 = function(selector) {
return selector == null ? empty$2 : function() {
return this.querySelectorAll(selector);
};
};
var selection_selectAll$1 = function(select) {
if (typeof select !== "function") select = selectorAll$1(select);
for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) {
for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
if (node = group[i]) {
subgroups.push(select.call(node, node.__data__, i, group));
parents.push(node);
}
}
}
return new Selection$2(subgroups, parents);
};
var selection_filter$1 = function(match) {
if (typeof match !== "function") match = matcher$3(match);
for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) {
if ((node = group[i]) && match.call(node, node.__data__, i, group)) {
subgroup.push(node);
}
}
}
return new Selection$2(subgroups, this._parents);
};
var sparse$1 = function(update) {
return new Array(update.length);
};
var selection_enter$1 = function() {
return new Selection$2(this._enter || this._groups.map(sparse$1), this._parents);
};
function EnterNode$1(parent, datum) {
this.ownerDocument = parent.ownerDocument;
this.namespaceURI = parent.namespaceURI;
this._next = null;
this._parent = parent;
this.__data__ = datum;
}
EnterNode$1.prototype = {
constructor: EnterNode$1,
appendChild: function(child) { return this._parent.insertBefore(child, this._next); },
insertBefore: function(child, next) { return this._parent.insertBefore(child, next); },
querySelector: function(selector) { return this._parent.querySelector(selector); },
querySelectorAll: function(selector) { return this._parent.querySelectorAll(selector); }
};
var constant$10 = function(x) {
return function() {
return x;
};
};
var keyPrefix$2 = "$"; // Protect against keys like “__proto__”.
function bindIndex$1(parent, group, enter, update, exit, data) {
var i = 0,
node,
groupLength = group.length,
dataLength = data.length;
// Put any non-null nodes that fit into update.
// Put any null nodes into enter.
// Put any remaining data into enter.
for (; i < dataLength; ++i) {
if (node = group[i]) {
node.__data__ = data[i];
update[i] = node;
} else {
enter[i] = new EnterNode$1(parent, data[i]);
}
}
// Put any non-null nodes that dont fit into exit.
for (; i < groupLength; ++i) {
if (node = group[i]) {
exit[i] = node;
}
}
}
function bindKey$1(parent, group, enter, update, exit, data, key) {
var i,
node,
nodeByKeyValue = {},
groupLength = group.length,
dataLength = data.length,
keyValues = new Array(groupLength),
keyValue;
// Compute the key for each node.
// If multiple nodes have the same key, the duplicates are added to exit.
for (i = 0; i < groupLength; ++i) {
if (node = group[i]) {
keyValues[i] = keyValue = keyPrefix$2 + key.call(node, node.__data__, i, group);
if (keyValue in nodeByKeyValue) {
exit[i] = node;
} else {
nodeByKeyValue[keyValue] = node;
}
}
}
// Compute the key for each datum.
// If there a node associated with this key, join and add it to update.
// If there is not (or the key is a duplicate), add it to enter.
for (i = 0; i < dataLength; ++i) {
keyValue = keyPrefix$2 + key.call(parent, data[i], i, data);
if (node = nodeByKeyValue[keyValue]) {
update[i] = node;
node.__data__ = data[i];
nodeByKeyValue[keyValue] = null;
} else {
enter[i] = new EnterNode$1(parent, data[i]);
}
}
// Add any remaining nodes that were not bound to data to exit.
for (i = 0; i < groupLength; ++i) {
if ((node = group[i]) && (nodeByKeyValue[keyValues[i]] === node)) {
exit[i] = node;
}
}
}
var selection_data$1 = function(value, key) {
if (!value) {
data = new Array(this.size()), j = -1;
this.each(function(d) { data[++j] = d; });
return data;
}
var bind = key ? bindKey$1 : bindIndex$1,
parents = this._parents,
groups = this._groups;
if (typeof value !== "function") value = constant$10(value);
for (var m = groups.length, update = new Array(m), enter = new Array(m), exit = new Array(m), j = 0; j < m; ++j) {
var parent = parents[j],
group = groups[j],
groupLength = group.length,
data = value.call(parent, parent && parent.__data__, j, parents),
dataLength = data.length,
enterGroup = enter[j] = new Array(dataLength),
updateGroup = update[j] = new Array(dataLength),
exitGroup = exit[j] = new Array(groupLength);
bind(parent, group, enterGroup, updateGroup, exitGroup, data, key);
// Now connect the enter nodes to their following update node, such that
// appendChild can insert the materialized enter node before this node,
// rather than at the end of the parent node.
for (var i0 = 0, i1 = 0, previous, next; i0 < dataLength; ++i0) {
if (previous = enterGroup[i0]) {
if (i0 >= i1) i1 = i0 + 1;
while (!(next = updateGroup[i1]) && ++i1 < dataLength);
previous._next = next || null;
}
}
}
update = new Selection$2(update, parents);
update._enter = enter;
update._exit = exit;
return update;
};
var selection_exit$1 = function() {
return new Selection$2(this._exit || this._groups.map(sparse$1), this._parents);
};
var selection_merge$1 = function(selection) {
for (var groups0 = this._groups, groups1 = selection._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j) {
for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) {
if (node = group0[i] || group1[i]) {
merge[i] = node;
}
}
}
for (; j < m0; ++j) {
merges[j] = groups0[j];
}
return new Selection$2(merges, this._parents);
};
var selection_order$1 = function() {
for (var groups = this._groups, j = -1, m = groups.length; ++j < m;) {
for (var group = groups[j], i = group.length - 1, next = group[i], node; --i >= 0;) {
if (node = group[i]) {
if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next);
next = node;
}
}
}
return this;
};
var selection_sort$1 = function(compare) {
if (!compare) compare = ascending$2;
function compareNode(a, b) {
return a && b ? compare(a.__data__, b.__data__) : !a - !b;
}
for (var groups = this._groups, m = groups.length, sortgroups = new Array(m), j = 0; j < m; ++j) {
for (var group = groups[j], n = group.length, sortgroup = sortgroups[j] = new Array(n), node, i = 0; i < n; ++i) {
if (node = group[i]) {
sortgroup[i] = node;
}
}
sortgroup.sort(compareNode);
}
return new Selection$2(sortgroups, this._parents).order();
};
function ascending$2(a, b) {
return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
}
var selection_call$1 = function() {
var callback = arguments[0];
arguments[0] = this;
callback.apply(null, arguments);
return this;
};
var selection_nodes$1 = function() {
var nodes = new Array(this.size()), i = -1;
this.each(function() { nodes[++i] = this; });
return nodes;
};
var selection_node$1 = function() {
for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) {
for (var group = groups[j], i = 0, n = group.length; i < n; ++i) {
var node = group[i];
if (node) return node;
}
}
return null;
};
var selection_size$1 = function() {
var size = 0;
this.each(function() { ++size; });
return size;
};
var selection_empty$1 = function() {
return !this.node();
};
var selection_each$1 = function(callback) {
for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) {
for (var group = groups[j], i = 0, n = group.length, node; i < n; ++i) {
if (node = group[i]) callback.call(node, node.__data__, i, group);
}
}
return this;
};
function attrRemove$2(name) {
return function() {
this.removeAttribute(name);
};
}
function attrRemoveNS$2(fullname) {
return function() {
this.removeAttributeNS(fullname.space, fullname.local);
};
}
function attrConstant$2(name, value) {
return function() {
this.setAttribute(name, value);
};
}
function attrConstantNS$2(fullname, value) {
return function() {
this.setAttributeNS(fullname.space, fullname.local, value);
};
}
function attrFunction$2(name, value) {
return function() {
var v = value.apply(this, arguments);
if (v == null) this.removeAttribute(name);
else this.setAttribute(name, v);
};
}
function attrFunctionNS$2(fullname, value) {
return function() {
var v = value.apply(this, arguments);
if (v == null) this.removeAttributeNS(fullname.space, fullname.local);
else this.setAttributeNS(fullname.space, fullname.local, v);
};
}
var selection_attr$1 = function(name, value) {
var fullname = namespace$1(name);
if (arguments.length < 2) {
var node = this.node();
return fullname.local
? node.getAttributeNS(fullname.space, fullname.local)
: node.getAttribute(fullname);
}
return this.each((value == null
? (fullname.local ? attrRemoveNS$2 : attrRemove$2) : (typeof value === "function"
? (fullname.local ? attrFunctionNS$2 : attrFunction$2)
: (fullname.local ? attrConstantNS$2 : attrConstant$2)))(fullname, value));
};
var defaultView = function(node) {
return (node.ownerDocument && node.ownerDocument.defaultView) // node is a Node
|| (node.document && node) // node is a Window
|| node.defaultView; // node is a Document
};
function styleRemove$2(name) {
return function() {
this.style.removeProperty(name);
};
}
function styleConstant$2(name, value, priority) {
return function() {
this.style.setProperty(name, value, priority);
};
}
function styleFunction$2(name, value, priority) {
return function() {
var v = value.apply(this, arguments);
if (v == null) this.style.removeProperty(name);
else this.style.setProperty(name, v, priority);
};
}
var selection_style$1 = function(name, value, priority) {
var node;
return arguments.length > 1
? this.each((value == null
? styleRemove$2 : typeof value === "function"
? styleFunction$2
: styleConstant$2)(name, value, priority == null ? "" : priority))
: defaultView(node = this.node())
.getComputedStyle(node, null)
.getPropertyValue(name);
};
function propertyRemove$1(name) {
return function() {
delete this[name];
};
}
function propertyConstant$1(name, value) {
return function() {
this[name] = value;
};
}
function propertyFunction$1(name, value) {
return function() {
var v = value.apply(this, arguments);
if (v == null) delete this[name];
else this[name] = v;
};
}
var selection_property$1 = function(name, value) {
return arguments.length > 1
? this.each((value == null
? propertyRemove$1 : typeof value === "function"
? propertyFunction$1
: propertyConstant$1)(name, value))
: this.node()[name];
};
function classArray$1(string) {
return string.trim().split(/^|\s+/);
}
function classList$1(node) {
return node.classList || new ClassList$1(node);
}
function ClassList$1(node) {
this._node = node;
this._names = classArray$1(node.getAttribute("class") || "");
}
ClassList$1.prototype = {
add: function(name) {
var i = this._names.indexOf(name);
if (i < 0) {
this._names.push(name);
this._node.setAttribute("class", this._names.join(" "));
}
},
remove: function(name) {
var i = this._names.indexOf(name);
if (i >= 0) {
this._names.splice(i, 1);
this._node.setAttribute("class", this._names.join(" "));
}
},
contains: function(name) {
return this._names.indexOf(name) >= 0;
}
};
function classedAdd$1(node, names) {
var list = classList$1(node), i = -1, n = names.length;
while (++i < n) list.add(names[i]);
}
function classedRemove$1(node, names) {
var list = classList$1(node), i = -1, n = names.length;
while (++i < n) list.remove(names[i]);
}
function classedTrue$1(names) {
return function() {
classedAdd$1(this, names);
};
}
function classedFalse$1(names) {
return function() {
classedRemove$1(this, names);
};
}
function classedFunction$1(names, value) {
return function() {
(value.apply(this, arguments) ? classedAdd$1 : classedRemove$1)(this, names);
};
}
var selection_classed$1 = function(name, value) {
var names = classArray$1(name + "");
if (arguments.length < 2) {
var list = classList$1(this.node()), i = -1, n = names.length;
while (++i < n) if (!list.contains(names[i])) return false;
return true;
}
return this.each((typeof value === "function"
? classedFunction$1 : value
? classedTrue$1
: classedFalse$1)(names, value));
};
function textRemove$1() {
this.textContent = "";
}
function textConstant$2(value) {
return function() {
this.textContent = value;
};
}
function textFunction$2(value) {
return function() {
var v = value.apply(this, arguments);
this.textContent = v == null ? "" : v;
};
}
var selection_text$1 = function(value) {
return arguments.length
? this.each(value == null
? textRemove$1 : (typeof value === "function"
? textFunction$2
: textConstant$2)(value))
: this.node().textContent;
};
function htmlRemove$1() {
this.innerHTML = "";
}
function htmlConstant$1(value) {
return function() {
this.innerHTML = value;
};
}
function htmlFunction$1(value) {
return function() {
var v = value.apply(this, arguments);
this.innerHTML = v == null ? "" : v;
};
}
var selection_html$1 = function(value) {
return arguments.length
? this.each(value == null
? htmlRemove$1 : (typeof value === "function"
? htmlFunction$1
: htmlConstant$1)(value))
: this.node().innerHTML;
};
function raise$2() {
if (this.nextSibling) this.parentNode.appendChild(this);
}
var selection_raise$1 = function() {
return this.each(raise$2);
};
function lower$1() {
if (this.previousSibling) this.parentNode.insertBefore(this, this.parentNode.firstChild);
}
var selection_lower$1 = function() {
return this.each(lower$1);
};
var selection_append$1 = function(name) {
var create = typeof name === "function" ? name : creator$1(name);
return this.select(function() {
return this.appendChild(create.apply(this, arguments));
});
};
function constantNull$1() {
return null;
}
var selection_insert$1 = function(name, before) {
var create = typeof name === "function" ? name : creator$1(name),
select = before == null ? constantNull$1 : typeof before === "function" ? before : selector$1(before);
return this.select(function() {
return this.insertBefore(create.apply(this, arguments), select.apply(this, arguments) || null);
});
};
function remove$1() {
var parent = this.parentNode;
if (parent) parent.removeChild(this);
}
var selection_remove$1 = function() {
return this.each(remove$1);
};
var selection_datum$1 = function(value) {
return arguments.length
? this.property("__data__", value)
: this.node().__data__;
};
function dispatchEvent$1(node, type, params) {
var window = defaultView(node),
event = window.CustomEvent;
if (event) {
event = new event(type, params);
} else {
event = window.document.createEvent("Event");
if (params) event.initEvent(type, params.bubbles, params.cancelable), event.detail = params.detail;
else event.initEvent(type, false, false);
}
node.dispatchEvent(event);
}
function dispatchConstant$1(type, params) {
return function() {
return dispatchEvent$1(this, type, params);
};
}
function dispatchFunction$1(type, params) {
return function() {
return dispatchEvent$1(this, type, params.apply(this, arguments));
};
}
var selection_dispatch$1 = function(type, params) {
return this.each((typeof params === "function"
? dispatchFunction$1
: dispatchConstant$1)(type, params));
};
var root$2 = [null];
function Selection$2(groups, parents) {
this._groups = groups;
this._parents = parents;
}
function selection$2() {
return new Selection$2([[document.documentElement]], root$2);
}
Selection$2.prototype = selection$2.prototype = {
constructor: Selection$2,
select: selection_select$1,
selectAll: selection_selectAll$1,
filter: selection_filter$1,
data: selection_data$1,
enter: selection_enter$1,
exit: selection_exit$1,
merge: selection_merge$1,
order: selection_order$1,
sort: selection_sort$1,
call: selection_call$1,
nodes: selection_nodes$1,
node: selection_node$1,
size: selection_size$1,
empty: selection_empty$1,
each: selection_each$1,
attr: selection_attr$1,
style: selection_style$1,
property: selection_property$1,
classed: selection_classed$1,
text: selection_text$1,
html: selection_html$1,
raise: selection_raise$1,
lower: selection_lower$1,
append: selection_append$1,
insert: selection_insert$1,
remove: selection_remove$1,
datum: selection_datum$1,
on: selection_on$1,
dispatch: selection_dispatch$1
};
var select$1 = function(selector) {
return typeof selector === "string"
? new Selection$2([[document.querySelector(selector)]], [document.documentElement])
: new Selection$2([[selector]], root$2);
};
var constant$11 = function(x) {
return function constant() {
return x;
};
@@ -7850,7 +7002,7 @@ function y$3(p) {
var line = function() {
var x$$1 = x$3,
y$$1 = y$3,
defined = constant$11(true),
defined = constant$10(true),
context = null,
curve = curveLinear,
output = null;
@@ -7876,15 +7028,15 @@ var line = function() {
}
line.x = function(_) {
return arguments.length ? (x$$1 = typeof _ === "function" ? _ : constant$11(+_), line) : x$$1;
return arguments.length ? (x$$1 = typeof _ === "function" ? _ : constant$10(+_), line) : x$$1;
};
line.y = function(_) {
return arguments.length ? (y$$1 = typeof _ === "function" ? _ : constant$11(+_), line) : y$$1;
return arguments.length ? (y$$1 = typeof _ === "function" ? _ : constant$10(+_), line) : y$$1;
};
line.defined = function(_) {
return arguments.length ? (defined = typeof _ === "function" ? _ : constant$11(!!_), line) : defined;
return arguments.length ? (defined = typeof _ === "function" ? _ : constant$10(!!_), line) : defined;
};
line.curve = function(_) {
@@ -7924,7 +7076,7 @@ function slope2(that, t) {
// According to https://en.wikipedia.org/wiki/Cubic_Hermite_spline#Representations
// "you can express cubic Hermite interpolation in terms of cubic Bézier curves
// with respect to the four values p0, p0 + m0 / 3, p1 - m1 / 3, p1".
function point$6(that, t0, t1) {
function point$5(that, t0, t1) {
var x0 = that._x0,
y0 = that._y0,
x1 = that._x1,
@@ -7953,7 +7105,7 @@ MonotoneX.prototype = {
lineEnd: function() {
switch (this._point) {
case 2: this._context.lineTo(this._x1, this._y1); break;
case 3: point$6(this, this._t0, slope2(this, this._t0)); break;
case 3: point$5(this, this._t0, slope2(this, this._t0)); break;
}
if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
this._line = 1 - this._line;
@@ -7966,8 +7118,8 @@ MonotoneX.prototype = {
switch (this._point) {
case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
case 1: this._point = 2; break;
case 2: this._point = 3; point$6(this, slope2(this, t1 = slope3(this, x, y)), t1); break;
default: point$6(this, this._t0, t1 = slope3(this, x, y)); break;
case 2: this._point = 3; point$5(this, slope2(this, t1 = slope3(this, x, y)), t1); break;
default: point$5(this, this._t0, t1 = slope3(this, x, y)); break;
}
this._x0 = this._x1, this._x1 = x;
@@ -8153,7 +7305,7 @@ exports.line = line;
exports.scaleBand = band;
exports.scaleLinear = linear$2;
exports.scaleOrdinal = ordinal;
exports.select = select$1;
exports.select = select;
Object.defineProperty(exports, '__esModule', { value: true });

6
d3.min.js vendored

File diff suppressed because one or more lines are too long

1
devServer.js Normal file → Executable file
View File

@@ -5,6 +5,7 @@ var config = require('./webpack.config.dev');
new WebpackDevServer(webpack(config), {
publicPath: config.output.publicPath,
hot: true,
disableHostCheck: true,
headers: { "Access-Control-Allow-Origin": "*" },
historyApiFallback: {
rewrites: [

12852
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "coriolis_shipyard",
"version": "2.4.1",
"version": "2.9.11",
"repository": {
"type": "git",
"url": "https://github.com/EDCD/coriolis"
@@ -19,12 +19,14 @@
"test": "jest",
"prod-serve": "nginx -p $(pwd) -c nginx.conf",
"prod-stop": "kill -QUIT $(cat nginx.pid)",
"build": "npm run clean && NODE_ENV=production webpack -p --config webpack.config.prod.js",
"build": "npm run clean && cross-env NODE_ENV=production webpack -p --config webpack.config.prod.js",
"rsync": "rsync -ae \"ssh -i $CORIOLIS_PEM\" --delete build/ $CORIOLIS_USER@$CORIOLIS_HOST:~/wwws",
"deploy": "npm run lint && npm test && npm run build && npm run rsync"
},
"jest": {
"transform": {".*": "<rootDir>/node_modules/babel-jest"},
"transform": {
".*": "<rootDir>/node_modules/babel-jest"
},
"testRegex": "(/__tests__/test-.*|\\.(test|spec))\\.js$",
"moduleFileExtensions": [
"js",
@@ -37,6 +39,7 @@
"<rootDir>/node_modules/lodash",
"<rootDir>/node_modules/react",
"<rootDir>/node_modules/react-dom",
"<rootDir>/node_modules/react-transition-group",
"<rootDir>/node_modules/react-testutils-additions",
"<rootDir>/node_modules/fbjs",
"<rootDir>/node_modules/fbemitter",
@@ -58,10 +61,12 @@
"babel-eslint": "*",
"babel-jest": "*",
"babel-loader": "*",
"babel-preset-es2015": "*",
"babel-preset-env": "*",
"babel-preset-react": "*",
"babel-preset-stage-0": "*",
"create-react-class": "^15.6.2",
"css-loader": "^0.28.0",
"cross-env": "^5.1.4",
"d3-selection": "1",
"eslint": "3.19.0",
"eslint-plugin-react": "^6.10.3",
@@ -70,7 +75,7 @@
"extract-text-webpack-plugin": "2.1.0",
"file-loader": "^0.11.1",
"html-webpack-plugin": "^2.28.0",
"jest-cli": "^19.0.2",
"jest-cli": "^21.2.1",
"jsen": "^0.6.4",
"json-loader": "^0.5.4",
"less": "^2.7.2",
@@ -78,20 +83,23 @@
"react-addons-perf": "^15.4.2",
"react-measure": "^1.4.7",
"react-testutils-additions": "^15.2.0",
"react-transition-group": "^1.1.2",
"rimraf": "^2.6.1",
"rollup": "0.41",
"rollup-plugin-node-resolve": "3",
"style-loader": "^0.16.1",
"uglify-js": "^2.4.11",
"url-loader": "^0.5.8",
"webpack": "^2.4.1",
"webpack-dev-server": "^2.4.4",
"uglify-js": "^2.4.11"
"webpack-notifier": "^1.6.0",
"webpack-bugsnag-plugins": "^1.1.1"
},
"dependencies": {
"babel-polyfill": "*",
"browserify-zlib-next": "^1.0.1",
"classnames": "^2.2.5",
"coriolis-data": "EDCD/coriolis-data",
"coriolis-data": "../coriolis-data",
"d3": "4.8.0",
"detect-browser": "^1.7.0",
"fbemitter": "^2.1.1",

View File

@@ -12,6 +12,7 @@ import ModalHelp from './components/ModalHelp';
import ModalImport from './components/ModalImport';
import ModalPermalink from './components/ModalPermalink';
import * as CompanionApiUtils from './utils/CompanionApiUtils';
import * as JournalUtils from './utils/JournalUtils';
import AboutPage from './pages/AboutPage';
import NotFoundPage from './pages/NotFoundPage';
@@ -92,7 +93,14 @@ export default class Coriolis extends React.Component {
// Need to decode and gunzip the data, then build the ship
const data = zlib.inflate(new Buffer(r.params.data, 'base64'), { to: 'string' });
const json = JSON.parse(data);
const ship = CompanionApiUtils.shipFromJson(json);
console.log('Ship import data: ');
console.log(json);
let ship;
if (json && json.modules) {
ship = CompanionApiUtils.shipFromJson(json);
} else if (json && json.Modules) {
ship = JournalUtils.shipFromLoadoutJSON(json);
}
r.params.ship = ship.id;
r.params.code = ship.toString();
this._setPage(OutfittingPage, r);
@@ -126,9 +134,9 @@ export default class Coriolis extends React.Component {
console && console.error && console.error(arguments); // eslint-disable-line no-console
if (errObj) {
if (errObj instanceof Error) {
Bugsnag.notifyException(errObj) // eslint-disable-line
bugsnagClient.notify(errObj) // eslint-disable-line
} else if (errObj instanceof String) {
Bugsnag.notify(msg, errObj) // eslint-disable-line
bugsnagClient.notify(msg, errObj) // eslint-disable-line
}
}
this.setState({

View File

@@ -37,10 +37,13 @@ const GRPCAT = {
'ml': 'lasers',
'c': 'projectiles',
'mc': 'projectiles',
'axmc': 'experimental',
'fc': 'projectiles',
'rfl': 'experimental',
'pa': 'projectiles',
'rg': 'projectiles',
'mr': 'ordnance',
'axmr': 'experimental',
'tp': 'ordnance',
'nl': 'ordnance',
'sc': 'scanners',
@@ -49,9 +52,15 @@ const GRPCAT = {
'cs': 'scanners',
'kw': 'scanners',
'ws': 'scanners',
'xs': 'scanners',
'ch': 'defence',
'po': 'defence',
'ec': 'defence',
'sfn': 'defence',
// Standard
'gpp': 'guardian',
'gpc': 'guardian',
'ggc': 'guardian'
};
// Order here is the order in which items will be shown in the modules menu
const CATEGORIES = {
@@ -76,6 +85,11 @@ const CATEGORIES = {
'hs': ['hs'],
'defence': ['ch', 'po', 'ec'],
'scanners': ['sc', 'ss', 'cs', 'kw', 'ws'], // Overloaded with internal scanners
// Experimental
'experimental': ['axmc', 'axmr', 'rfl', 'xs', 'sfn'],
// Guardian
'guardian': ['gpp', 'gpc', 'ggc']
};
/**
@@ -192,8 +206,8 @@ export default class AvailableModulesMenu extends TranslatedComponent {
/**
* Generate React Components for Module Group
* @param {Function} translate Translate function
* @param {Objecy} mountedModule Mounted Module
* @param {Funciton} warningFunc Warning function
* @param {Object} mountedModule Mounted Module
* @param {Function} warningFunc Warning function
* @param {number} mass Mass
* @param {function} onSelect Select/Mount callback
* @param {string} grp Group name
@@ -201,7 +215,7 @@ export default class AvailableModulesMenu extends TranslatedComponent {
* @return {React.Component} Available Module Group contents
*/
_buildGroup(translate, mountedModule, warningFunc, mass, onSelect, grp, modules) {
let prevClass = null, prevRating = null;
let prevClass = null, prevRating = null, prevName;
let elems = [];
const sortedModules = modules.sort(this._moduleOrder);
@@ -216,6 +230,7 @@ export default class AvailableModulesMenu extends TranslatedComponent {
let m = sortedModules[i];
let mount = null;
let disabled = false;
prevName = m.name
if (ModuleUtils.isShieldGenerator(m.grp)) {
// Shield generators care about maximum hull mass
disabled = mass > m.maxmass;
@@ -251,7 +266,10 @@ export default class AvailableModulesMenu extends TranslatedComponent {
case 'G': mount = <MountGimballed className={'lg'}/>; break;
case 'T': mount = <MountTurret className={'lg'}/>; break;
}
if (m.name && m.name === prevName) {
// elems.push(<br key={'b' + m.grp + i} />);
itemsOnThisRow = 0;
}
if (itemsOnThisRow == 6 || i > 0 && sortedModules.length > 3 && itemsPerClass > 2 && m.class != prevClass && (m.rating != prevRating || m.mount)) {
elems.push(<br key={'b' + m.grp + i} />);
itemsOnThisRow = 0;
@@ -266,6 +284,7 @@ export default class AvailableModulesMenu extends TranslatedComponent {
itemsOnThisRow++;
prevClass = m.class;
prevRating = m.rating;
prevName = m.name;
}
return <ul key={'modules' + grp} >{elems}</ul>;

View File

@@ -25,7 +25,7 @@ export default class EngagementRange extends TranslatedComponent {
const { ship } = props;
const maxRange = this._calcMaxRange(ship);
const maxRange = Math.round(this._calcMaxRange(ship));
this.state = {
maxRange

View File

@@ -33,6 +33,9 @@ export default class InternalSlot extends Slot {
let modTT = translate('modified');
if (m && m.blueprint && m.blueprint.name) {
modTT = translate(m.blueprint.name) + ' ' + translate('grade') + ' ' + m.blueprint.grade;
if (m.blueprint.special && m.blueprint.special.id >= 0) {
modTT += ', ' + translate(m.blueprint.special.name);
}
modTT = (
<div>
<div>{modTT}</div>

View File

@@ -6,7 +6,14 @@ import { isEmpty, stopCtxPropagation } from '../utils/UtilityFunctions';
import cn from 'classnames';
import { Modifications } from 'coriolis-data/dist';
import Modification from './Modification';
import { getBlueprint, blueprintTooltip, setWorst, setBest, setExtreme, setRandom } from '../utils/BlueprintFunctions';
import {
getBlueprint,
blueprintTooltip,
setPercent,
getPercent,
setRandom,
specialToolTip
} from '../utils/BlueprintFunctions'
/**
* Modifications menu
@@ -30,14 +37,14 @@ export default class ModificationsMenu extends TranslatedComponent {
this._toggleBlueprintsMenu = this._toggleBlueprintsMenu.bind(this);
this._toggleSpecialsMenu = this._toggleSpecialsMenu.bind(this);
this._rollWorst = this._rollWorst.bind(this);
this._rollFifty = this._rollFifty.bind(this);
this._rollRandom = this._rollRandom.bind(this);
this._rollBest = this._rollBest.bind(this);
this._rollExtreme = this._rollExtreme.bind(this);
this._rollWorst = this._rollWorst.bind(this);
this._reset = this._reset.bind(this);
this.state = {
blueprintMenuOpened: false,
blueprintMenuOpened: !(props.m.blueprint && props.m.blueprint.name),
specialMenuOpened: false
};
}
@@ -86,15 +93,33 @@ export default class ModificationsMenu extends TranslatedComponent {
const { m } = props;
const { language, tooltip, termtip } = context;
const translate = language.translate;
const specials = [];
const specialsId = m.missile && Modifications.modules[m.grp]['specials_' + m.missile] ? 'specials_' + m.missile : 'specials';
if (Modifications.modules[m.grp][specialsId] && Modifications.modules[m.grp][specialsId].length > 0) {
const close = this._specialSelected.bind(this, null);
specials.push(<div style={{ cursor: 'pointer' }} key={ 'none' } onClick={ close }>{translate('PHRASE_NO_SPECIAL')}</div>);
specials.push(<div style={{ cursor: 'pointer', fontWeight: 'bold' }} className={ 'button-inline-menu warning' } key={ 'none' } onClick={ close }>{translate('PHRASE_NO_SPECIAL')}</div>);
for (const specialName of Modifications.modules[m.grp][specialsId]) {
if (Modifications.specials[specialName].name.search('Legacy') >= 0) {
continue;
}
const classes = cn('button-inline-menu', {
active: m.blueprint && m.blueprint.special && m.blueprint.special.edname == specialName
});
const close = this._specialSelected.bind(this, specialName);
specials.push(<div style={{ cursor: 'pointer' }} key={ specialName } onClick={ close }>{translate(Modifications.specials[specialName].name)}</div>);
if (m.blueprint && m.blueprint.name) {
let tmp = {};
if (m.blueprint.special) {
tmp = m.blueprint.special;
} else {
tmp = undefined;
}
m.blueprint.special = Modifications.specials[specialName];
let specialTt = specialToolTip(translate, m.blueprint.grades[m.blueprint.grade], m.grp, m, specialName);
m.blueprint.special = tmp;
specials.push(<div style={{ cursor: 'pointer' }} className={classes} key={ specialName } onMouseOver={termtip.bind(null, specialTt)} onMouseOut={tooltip.bind(null, null)} onClick={ close }>{translate(Modifications.specials[specialName].name)}</div>);
} else {
specials.push(<div style={{ cursor: 'pointer' }} className={classes} key={ specialName } onClick={ close }>{translate(Modifications.specials[specialName].name)}</div>);
}
}
}
return specials;
@@ -136,8 +161,9 @@ export default class ModificationsMenu extends TranslatedComponent {
const blueprint = getBlueprint(fdname, m);
blueprint.grade = grade;
ship.setModuleBlueprint(m, blueprint);
setPercent(ship, m, 100);
this.setState({ blueprintMenuOpened: false });
this.setState({ blueprintMenuOpened: false, specialMenuOpened: true });
this.props.onChange();
}
@@ -168,11 +194,11 @@ export default class ModificationsMenu extends TranslatedComponent {
}
/**
* Provide a 'worst' roll within the information we have
* Provide a '50%' roll within the information we have
*/
_rollWorst() {
_rollFifty() {
const { m, ship } = this.props;
setWorst(ship, m);
setPercent(ship, m, 50);
this.props.onChange();
}
@@ -190,16 +216,16 @@ export default class ModificationsMenu extends TranslatedComponent {
*/
_rollBest() {
const { m, ship } = this.props;
setBest(ship, m);
setPercent(ship, m, 100);
this.props.onChange();
}
/**
* Provide an 'extreme' roll within the information we have
* Provide a 'worst' roll within the information we have
*/
_rollExtreme() {
_rollWorst() {
const { m, ship } = this.props;
setExtreme(ship, m);
setPercent(ship, m, 0);
this.props.onChange();
}
@@ -226,24 +252,28 @@ export default class ModificationsMenu extends TranslatedComponent {
const _toggleBlueprintsMenu = this._toggleBlueprintsMenu;
const _toggleSpecialsMenu = this._toggleSpecialsMenu;
const _rollBest = this._rollBest;
const _rollExtreme = this._rollExtreme;
const _rollFull = this._rollBest;
const _rollWorst = this._rollWorst;
const _rollFifty = this._rollFifty;
const _rollRandom = this._rollRandom;
const _reset = this._reset;
let blueprintLabel;
let haveBlueprint = false;
let blueprintTt;
let blueprintCv;
if (m.blueprint && m.blueprint.name) {
blueprintLabel = translate(m.blueprint.name) + ' ' + translate('grade') + ' ' + m.blueprint.grade;
haveBlueprint = true;
blueprintTt = blueprintTooltip(translate, m.blueprint.grades[m.blueprint.grade], Modifications.modules[m.grp].blueprints[m.blueprint.fdname].grades[m.blueprint.grade].engineers, m.grp);
blueprintCv = getPercent(m);
}
let specialLabel;
let specialTt;
if (m.blueprint && m.blueprint.special) {
specialLabel = m.blueprint.special.name;
specialTt = specialToolTip(translate, m.blueprint.grades[m.blueprint.grade], m.grp, m, m.blueprint.special.edname);
} else {
specialLabel = translate('PHRASE_SELECT_SPECIAL');
}
@@ -254,8 +284,8 @@ export default class ModificationsMenu extends TranslatedComponent {
const showSpecial = haveBlueprint && specials.length && !blueprintMenuOpened;
const showSpecialsMenu = specialMenuOpened;
const showRolls = haveBlueprint && !blueprintMenuOpened && !specialMenuOpened;
const showReset = !blueprintMenuOpened && !specialMenuOpened;
const showMods = !blueprintMenuOpened && !specialMenuOpened;
const showReset = !blueprintMenuOpened && !specialMenuOpened && haveBlueprint;
const showMods = !blueprintMenuOpened && !specialMenuOpened && haveBlueprint;
return (
<div
@@ -263,29 +293,28 @@ export default class ModificationsMenu extends TranslatedComponent {
onClick={(e) => e.stopPropagation() }
onContextMenu={stopCtxPropagation}
>
{ showBlueprintsMenu ? '' : haveBlueprint ?
<div className={ cn('section-menu', { selected: blueprintMenuOpened })} style={{ cursor: 'pointer' }} onMouseOver={termtip.bind(null, blueprintTt)} onMouseOut={tooltip.bind(null, null)} onClick={_toggleBlueprintsMenu}>{blueprintLabel}</div> :
<div className={ cn('section-menu', { selected: blueprintMenuOpened })} style={{ cursor: 'pointer' }} onClick={_toggleBlueprintsMenu}>{translate('PHRASE_SELECT_BLUEPRINT')}</div> }
{ showBlueprintsMenu | showSpecialsMenu ? '' : haveBlueprint ?
<div className={ cn('section-menu button-inline-menu', { selected: blueprintMenuOpened })} style={{ cursor: 'pointer' }} onMouseOver={termtip.bind(null, blueprintTt)} onMouseOut={tooltip.bind(null, null)} onClick={_toggleBlueprintsMenu}>{blueprintLabel}</div> :
<div className={ cn('section-menu button-inline-menu', { selected: blueprintMenuOpened })} style={{ cursor: 'pointer' }} onClick={_toggleBlueprintsMenu}>{translate('PHRASE_SELECT_BLUEPRINT')}</div> }
{ showBlueprintsMenu ? this._renderBlueprints(this.props, this.context) : null }
{ showSpecial ? <div className={ cn('section-menu', { selected: specialMenuOpened })} style={{ cursor: 'pointer' }} onClick={_toggleSpecialsMenu}>{specialLabel}</div> : null }
{ showSpecial & !showSpecialsMenu ? <div className={ cn('section-menu button-inline-menu', { selected: specialMenuOpened })} style={{ cursor: 'pointer' }} onMouseOver={specialTt ? termtip.bind(null, specialTt) : null} onMouseOut={specialTt ? tooltip.bind(null, null) : null} onClick={_toggleSpecialsMenu}>{specialLabel}</div> : null }
{ showSpecialsMenu ? specials : null }
{ showRolls || showReset ?
{ showReset ? <div className={'section-menu button-inline-menu warning'} style={{ cursor: 'pointer' }} onClick={_reset} onMouseOver={termtip.bind(null, 'PHRASE_BLUEPRINT_RESET')} onMouseOut={tooltip.bind(null, null)}> { translate('reset') } </div> : null }
{ showRolls ?
<table style={{ width: '100%', backgroundColor: 'transparent' }}>
<tbody>
{ showRolls ?
<tr>
<td> { translate('roll') }: </td>
<td style={{ cursor: 'pointer' }} onClick={_rollWorst} onMouseOver={termtip.bind(null, 'PHRASE_BLUEPRINT_WORST')} onMouseOut={tooltip.bind(null, null)}> { translate('worst') } </td>
<td style={{ cursor: 'pointer' }} onClick={_rollBest}onMouseOver={termtip.bind(null, 'PHRASE_BLUEPRINT_BEST')} onMouseOut={tooltip.bind(null, null)}> { translate('best') } </td>
<td style={{ cursor: 'pointer' }} onClick={_rollExtreme}onMouseOver={termtip.bind(null, 'PHRASE_BLUEPRINT_EXTREME')} onMouseOut={tooltip.bind(null, null)}> { translate('extreme') } </td>
<td style={{ cursor: 'pointer' }} onClick={_rollRandom} onMouseOver={termtip.bind(null, 'PHRASE_BLUEPRINT_RANDOM')} onMouseOut={tooltip.bind(null, null)}> { translate('random') } </td>
</tr> : null }
{ showReset ?
<tr>
<td colSpan={'5'} style={{ cursor: 'pointer' }} onClick={_reset}onMouseOver={termtip.bind(null, 'PHRASE_BLUEPRINT_RESET')} onMouseOut={tooltip.bind(null, null)}> { translate('reset') } </td>
<td className={ cn('section-menu button-inline-menu', {active: false})}> { translate('roll') }: </td>
<td className={ cn('section-menu button-inline-menu', { active: blueprintCv === 0 })} style={{ cursor: 'pointer' }} onClick={_rollWorst} onMouseOver={termtip.bind(null, 'PHRASE_BLUEPRINT_WORST')} onMouseOut={tooltip.bind(null, null)}> { translate('0%') } </td>
<td className={ cn('section-menu button-inline-menu', { active: blueprintCv === 50 })} style={{ cursor: 'pointer' }} onClick={_rollFifty} onMouseOver={termtip.bind(null, 'PHRASE_BLUEPRINT_FIFTY')} onMouseOut={tooltip.bind(null, null)}> { translate('50%') } </td>
<td className={ cn('section-menu button-inline-menu', { active: blueprintCv === 100 })} style={{ cursor: 'pointer' }} onClick={_rollFull} onMouseOver={termtip.bind(null, 'PHRASE_BLUEPRINT_BEST')} onMouseOut={tooltip.bind(null, null)}> { translate('100%') } </td>
<td className={ cn('section-menu button-inline-menu', { active: blueprintCv === null || blueprintCv % 50 != 0 })} style={{ cursor: 'pointer' }} onClick={_rollRandom} onMouseOver={termtip.bind(null, 'PHRASE_BLUEPRINT_RANDOM')} onMouseOut={tooltip.bind(null, null)}> { translate('random') } </td>
</tr> : null }
</tbody>
</table> : null }
{ showMods ? <hr /> : null }
{ showMods ?
<span onMouseOver={termtip.bind(null, 'HELP_MODIFICATIONS_MENU')} onMouseOut={tooltip.bind(null, null)} >
{ this._renderModifications(this.props) }

View File

@@ -53,6 +53,7 @@ export default class ShipSummaryTable extends TranslatedComponent {
<th rowSpan={2}>{translate('TTD')}</th>
{/* <th onMouseEnter={termtip.bind(null, 'heat per second')} onMouseLeave={hide} rowSpan={2}>{translate('HPS')}</th> */}
<th rowSpan={2}>{translate('cargo')}</th>
<th rowSpan={2}>{translate('pax')}</th>
<th rowSpan={2}>{translate('fuel')}</th>
<th colSpan={3}>{translate('mass')}</th>
<th onMouseEnter={termtip.bind(null, 'hull hardness', { cap: 0 })} onMouseLeave={hide} rowSpan={2}>{translate('hrd')}</th>
@@ -86,6 +87,7 @@ export default class ShipSummaryTable extends TranslatedComponent {
<td onMouseEnter={termtip.bind(null, 'TT_SUMMARY_TTD', { cap: 0 })} onMouseLeave={hide}>{timeToDrain === Infinity ? '∞' : time(timeToDrain)}</td>
{/* <td>{f1(ship.totalHps)}</td> */}
<td>{round(ship.cargoCapacity)}{u.T}</td>
<td>{ship.passengerCapacity}</td>
<td>{round(ship.fuelCapacity)}{u.T}</td>
<td onMouseEnter={termtip.bind(null, 'TT_SUMMARY_HULL_MASS', { cap: 0 })} onMouseLeave={hide}>{ship.hullMass}{u.T}</td>
<td onMouseEnter={termtip.bind(null, 'TT_SUMMARY_UNLADEN_MASS', { cap: 0 })} onMouseLeave={hide}>{int(ship.unladenMass)}{u.T}</td>

View File

@@ -48,7 +48,7 @@ export default class StandardSlot extends TranslatedComponent {
let m = slot.m;
let classRating = m.class + m.rating;
let menu;
let validMods = m == null ? [] : (Modifications.modules[m.grp].modifications || []);
let validMods = m == null || !Modifications.modules[m.grp] ? [] : (Modifications.modules[m.grp].modifications || []);
let showModuleResistances = Persist.showModuleResistances();
let mass = m.getMass() || m.cargo || m.fuel || 0;
@@ -56,6 +56,9 @@ export default class StandardSlot extends TranslatedComponent {
let modTT = translate('modified');
if (m && m.blueprint && m.blueprint.name) {
modTT = translate(m.blueprint.name) + ' ' + translate('grade') + ' ' + m.blueprint.grade;
if (m.blueprint.special && m.blueprint.special.id >= 0) {
modTT += ', ' + translate(m.blueprint.special.name);
}
modTT = (
<div>
<div>{modTT}</div>
@@ -96,7 +99,7 @@ export default class StandardSlot extends TranslatedComponent {
return (
<div className={cn('slot', { selected: this.props.selected })} onClick={this.props.onOpen} onContextMenu={stopCtxPropagation}>
<div className={cn('details-container', { warning: warning && warning(slot.m), disabled: m.grp !== 'bh' && !slot.enabled })}>
<div className={'sz'}>{slot.maxClass}</div>
<div className={'sz'}>{m.grp == 'bh' ? m.name.charAt(0) : slot.maxClass}</div>
<div>
<div className={'l'}>{classRating} {translate(m.name || m.grp)}{m.mods && Object.keys(m.mods).length > 0 ? <span className='r' onMouseOver={termtip.bind(null, modTT)} onMouseOut={tooltip.bind(null, null)}><Modified /></span> : null }</div>
<div className={'r'}>{formats.round(mass)}{units.T}</div>

View File

@@ -235,12 +235,10 @@ export default class StandardSlotSection extends SlotSection {
<ul>
<li className='lc' onClick={this._multiPurpose.bind(this, false, 0)}>{translate('Multi-purpose')}</li>
<li className='lc' onClick={this._multiPurpose.bind(this, true, 2)}>{translate('Combat')}</li>
<li className='lc' onClick={this._optimizeCargo.bind(this, false)}>{translate('Trader')}</li>
<li className='lc' onClick={this._optimizeCargo.bind(this, true)}>{translate('Shielded Trader')}</li>
<li className='lc' onClick={this._optimizeCargo.bind(this, true)}>{translate('Trader')}</li>
<li className='lc' onClick={this._optimizeExplorer.bind(this, false)}>{translate('Explorer')}</li>
<li className={cn('lc', { disabled: planetaryDisabled })} onClick={!planetaryDisabled && this._optimizeExplorer.bind(this, true)}>{translate('Planetary Explorer')}</li>
<li className='lc' onClick={this._optimizeMiner.bind(this, false)}>{translate('Miner')}</li>
<li className='lc' onClick={this._optimizeMiner.bind(this, true)}>{translate('Shielded Miner')}</li>
<li className='lc' onClick={this._optimizeMiner.bind(this, true)}>{translate('Miner')}</li>
<li className='lc' onClick={this._optimizeRacer.bind(this)}>{translate('Racer')}</li>
</ul>
</div>;

View File

@@ -6,6 +6,7 @@ import * as FR from './fr';
import * as IT from './it';
import * as RU from './ru';
import * as PL from './pl';
import * as PT from './pt';
import * as d3 from 'd3';
let fallbackTerms = EN.terms;
@@ -25,6 +26,7 @@ export function getLanguage(langCode) {
case 'it': lang = IT; break;
case 'ru': lang = RU; break;
case 'pl': lang = PL; break;
case 'pt': lang = PT; break;
default:
lang = EN;
}
@@ -88,5 +90,6 @@ export const Languages = {
es: 'Español',
fr: 'Français',
ru: 'ру́сский',
pl: 'polski'
pl: 'polski',
pt: 'português'
};

File diff suppressed because one or more lines are too long

16
src/app/i18n/pt.js Normal file
View File

@@ -0,0 +1,16 @@
export const formats = {
decimal: ',',
thousands: '.',
grouping: [3],
currency: ['', ' €'],
dateTime: '%A, %e de %B de %Y, %X',
date: '%d/%m/%Y',
time: '%H:%M:%S',
periods: ['AM', 'PM'],
days: ['domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes', 'sábado'],
shortDays: ['dom', 'lun', 'mar', 'mié', 'jue', 'vie', 'sáb'],
months: ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio', 'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre'],
shortMonths: ['ene', 'feb', 'mar', 'abr', 'may', 'jun', 'jul', 'ago', 'sep', 'oct', 'nov', 'dic']
};
export { default as terms } from './pt.json';

278
src/app/i18n/pt.json Normal file

File diff suppressed because one or more lines are too long

View File

@@ -41,6 +41,9 @@ export default class AboutPage extends Page {
<h3>Chat</h3>
<p>You can chat to us on our <a href='https://discord.gg/0uwCh6R62aPRjk9w' target='_blank'>EDCD Discord server</a>.</p>
<h3>Supporting Coriolis</h3>
<p>Coriolis is an open source project, and I work on it in my free time. I have set up a patreon at <a href='https://www.patreon.com/coriolis_elite'>patreon.com/coriolis_elite</a>, which will be used to keep Coriolis up to date and the servers running.</p>
</div>;
}
}

View File

@@ -73,13 +73,10 @@ export default class OutfittingPage extends Page {
let buildName = params.bn;
let data = Ships[shipId]; // Retrieve the basic ship properties, slots and defaults
let savedCode = Persist.getBuild(shipId, buildName);
if (!data) {
return { error: { message: 'Ship not found: ' + shipId } };
}
let ship = new Ship(shipId, data.properties, data.slots); // Create a new Ship instance
if (code) {
ship.buildFrom(code); // Populate modules from serialized 'code' URL param
} else {
@@ -556,10 +553,25 @@ export default class OutfittingPage extends Page {
const boostMarker = `${ship.canBoost(cargo, fuel)}`;
const shipSummaryMarker = `${ship.name}${_sStr}${_iStr}${_hStr}${_pStr}${_mStr}${ship.ladenMass}${cargo}${fuel}`;
const requirements = Ships[ship.id].requirements;
var requirementElements = [];
function renderRequirement(className, textKey, tooltipTextKey) {
requirementElements.push(<div key={textKey} className={className} onMouseEnter={termtip.bind(null, tooltipTextKey)} onMouseLeave={hide}>{translate(textKey)}</div>);
}
if (requirements) {
requirements.federationRank && renderRequirement('federation', 'federation rank ' + requirements.federationRank, 'federation rank required');
requirements.empireRank && renderRequirement('empire', 'empire rank ' + requirements.empireRank, 'empire rank required');
requirements.horizons && renderRequirement('horizons', 'horizons', 'horizons required');
requirements.horizonsEarlyAdoption && renderRequirement('horizons', 'horizons early adoption', 'horizons early adoption required');
}
return (
<div id='outfit' className={'page'} style={{ fontSize: (sizeRatio * 0.9) + 'em' }}>
<div id='overview'>
<h1>{ship.name}</h1>
<div id='requirements'>{requirementElements}</div>
<div id='build'>
<input value={newBuildName || ''} onChange={this._buildNameChange} placeholder={translate('Enter Name')} maxLength={50} />
<button onClick={canSave && this._saveBuild} disabled={!canSave} onMouseOver={termtip.bind(null, 'save')} onMouseOut={hide}>

View File

@@ -25,6 +25,25 @@ function countInt(slot) {
this.int[slot.maxClass - 1]++; // Subtract 1 since there is no Class 0 Internal compartment
this.intCount++;
this.maxCargo += crEligible ? ModuleUtils.findInternal('cr', slot.maxClass, 'E').cargo : 0;
// if no eligiblity, then assume pce
let passSlotType = null;
let passSlotRating = null;
if (!slot.eligible || slot.eligible.pce) {
passSlotType = 'pce';
passSlotRating = 'E';
} else if (slot.eligible.pci) {
passSlotType = 'pci';
passSlotRating = 'D';
} else if (slot.eligible.pcm) {
passSlotType = 'pcm';
passSlotRating = 'C';
} else if (slot.eligible.pcq) {
passSlotType = 'pcq';
passSlotRating = 'B';
}
let passengerBay = passSlotType ? ModuleUtils.findMaxInternal(passSlotType, slot.maxClass, passSlotRating) : null;
this.maxPassengers += passengerBay ? passengerBay.passengers : 0;
}
/**
@@ -39,6 +58,7 @@ function shipSummary(shipId, shipData) {
hpCount: 0,
intCount: 0,
maxCargo: 0,
maxPassengers: 0,
hp: [0, 0, 0, 0, 0], // Utility, Small, Medium, Large, Huge
int: [0, 0, 0, 0, 0, 0, 0, 0], // Sizes 1 - 8
standard: shipData.slots.standard,
@@ -139,15 +159,16 @@ export default class ShipyardPage extends Page {
* @param {Object} u Localized unit map
* @param {Function} fInt Localized integer formatter
* @param {Function} fRound Localized round formatter
* @param {Boolean} highlight Should this row be highlighted
* @return {React.Component} Table Row
*/
_shipRowElement(s, translate, u, fInt, fRound) {
_shipRowElement(s, translate, u, fInt, fRound, highlight) {
let noTouch = this.context.noTouch;
return <tr
key={s.id}
style={{ height: '1.5em' }}
className={cn({ highlighted: noTouch && this.state.shipId === s.id })}
className={cn({ highlighted: noTouch && this.state.shipId === s.id, alt: highlight })}
onMouseEnter={noTouch && this._highlightShip.bind(this, s.id)}
>
<td className='ri'>{s.manufacturer}</td>
@@ -166,12 +187,14 @@ export default class ShipyardPage extends Page {
<td className='ri'>{fInt(s.topBoost)}</td>
<td className='ri'>{fRound(s.maxJumpRange)}</td>
<td className='ri'>{fInt(s.maxCargo)}</td>
<td className='ri'>{fInt(s.maxPassengers)}</td>
<td className='cn'>{s.standard[0]}</td>
<td className='cn'>{s.standard[1]}</td>
<td className='cn'>{s.standard[2]}</td>
<td className='cn'>{s.standard[3]}</td>
<td className='cn'>{s.standard[4]}</td>
<td className='cn'>{s.standard[5]}</td>
<td className='cn'>{s.standard[6]}</td>
<td className={cn({ disabled: !s.hp[1] })}>{s.hp[1]}</td>
<td className={cn({ disabled: !s.hp[2] })}>{s.hp[2]}</td>
<td className={cn({ disabled: !s.hp[3] })}>{s.hp[3]}</td>
@@ -246,13 +269,26 @@ export default class ShipyardPage extends Page {
let shipRows = new Array(shipSummaries.length);
let detailRows = new Array(shipSummaries.length);
let lastShipSortValue = null;
let backgroundHighlight = false;
for (let s of shipSummaries) {
detailRows[i] = this._shipRowElement(s, translate, units, fInt, formats.f1);
let shipSortValue = s[shipPredicate];
if( shipPredicateIndex != undefined ) {
shipSortValue = shipSortValue[shipPredicateIndex];
}
if( shipSortValue != lastShipSortValue ) {
backgroundHighlight = !backgroundHighlight;
lastShipSortValue = shipSortValue;
}
detailRows[i] = this._shipRowElement(s, translate, units, fInt, formats.f1, backgroundHighlight);
shipRows[i] = (
<tr
key={i}
style={{ height: '1.5em' }}
className={cn({ highlighted: noTouch && this.state.shipId === s.id })}
className={cn({ highlighted: noTouch && this.state.shipId === s.id, alt: backgroundHighlight })}
onMouseEnter={noTouch && this._highlightShip.bind(this, s.id)}
>
<td className='le'><Link href={'/outfit/' + s.id}>{s.name}</Link></td>
@@ -293,8 +329,8 @@ export default class ShipyardPage extends Page {
<th rowSpan={3} className='sortable' onMouseEnter={termtip.bind(null, 'hardness')} onMouseLeave={hide} onClick={sortShips('hardness')}>{translate('hrd')}</th>
<th>&nbsp;</th>
<th colSpan={4}>{translate('base')}</th>
<th colSpan={4}>{translate('max')}</th>
<th className='lft' colSpan={6}></th>
<th colSpan={5}>{translate('max')}</th>
<th className='lft' colSpan={7}></th>
<th className='lft' colSpan={5}></th>
<th className='lft' colSpan={8}></th>
</tr>
@@ -310,29 +346,31 @@ export default class ShipyardPage extends Page {
<th className='sortable' onClick={sortShips('topBoost')}>{translate('boost')}</th>
<th className='sortable' onClick={sortShips('maxJumpRange')}>{translate('jump')}</th>
<th className='sortable' onClick={sortShips('maxCargo')}>{translate('cargo')}</th>
<th className='sortable' onClick={sortShips('maxPassengers')}>{translate('pax')}</th>
<th className='lft' colSpan={6}>{translate('core module classes')}</th>
<th className='lft' colSpan={7}>{translate('core module classes')}</th>
<th colSpan={5} className='sortable lft' onClick={sortShips('hpCount')}>{translate('hardpoints')}</th>
<th colSpan={8} className='sortable lft' onClick={sortShips('intCount')}>{translate('internal compartments')}</th>
</tr>
<tr>
<th className='sortable lft' onClick={sortShips('retailCost')}>{units.CR}</th>
<th className='sortable lft' onClick={sortShips('hullMass')}>{units.T}</th>
<th className='sortable lft' onClick={sortShips('speed')}>{units['m/s']}</th>
<th className='sortable' onClick={sortShips('boost')}>{units['m/s']}</th>
<th>&nbsp;</th>
<th className='sortable' onClick={sortShips('baseShieldStrength')}>{units.MJ}</th>
<th className='sortable lft' onClick={sortShips('topSpeed')}>{units['m/s']}</th>
<th className='sortable' onClick={sortShips('topBoost')}>{units['m/s']}</th>
<th className='sortable' onClick={sortShips('maxJumpRange')}>{units.LY}</th>
<th className='sortable' onClick={sortShips('maxCargo')}>{units.T}</th>
<th className='sortable lft' onClick={sortShips('retailCost')}>{units.CR}</th>
<th className='sortable lft' onClick={sortShips('hullMass')}>{units.T}</th>
<th className='sortable lft' onClick={sortShips('speed')}>{units['m/s']}</th>
<th className='sortable' onClick={sortShips('boost')}>{units['m/s']}</th>
<th>&nbsp;</th>
<th className='sortable' onClick={sortShips('baseShieldStrength')}>{units.MJ}</th>
<th className='sortable lft' onClick={sortShips('topSpeed')}>{units['m/s']}</th>
<th className='sortable' onClick={sortShips('topBoost')}>{units['m/s']}</th>
<th className='sortable' onClick={sortShips('maxJumpRange')}>{units.LY}</th>
<th className='sortable' onClick={sortShips('maxCargo')}>{units.T}</th>
<th>&nbsp;</th>
<th className='sortable lft' onMouseEnter={termtip.bind(null, 'power plant')} onMouseLeave={hide} onClick={sortShips('standard', 0)}>{'pp'}</th>
<th className='sortable' onMouseEnter={termtip.bind(null, 'thrusters')} onMouseLeave={hide} onClick={sortShips('standard', 1)}>{'th'}</th>
<th className='sortable' onMouseEnter={termtip.bind(null, 'frame shift drive')} onMouseLeave={hide} onClick={sortShips('standard', 2)}>{'fsd'}</th>
<th className='sortable' onMouseEnter={termtip.bind(null, 'life support')} onMouseLeave={hide} onClick={sortShips('standard', 3)}>{'ls'}</th>
<th className='sortable' onMouseEnter={termtip.bind(null, 'power distriubtor')} onMouseLeave={hide} onClick={sortShips('standard', 4)}>{'pd'}</th>
<th className='sortable' onMouseEnter={termtip.bind(null, 'sensors')} onMouseLeave={hide} onClick={sortShips('standard', 5)}>{'s'}</th>
<th className='sortable' onMouseEnter={termtip.bind(null, 'fuel tank')} onMouseLeave={hide} onClick={sortShips('standard', 6)}>{'ft'}</th>
<th className='sortable lft' onClick={sortShips('hp',1)}>{translate('S')}</th>
<th className='sortable' onClick={sortShips('hp', 2)}>{translate('M')}</th>
<th className='sortable' onClick={sortShips('hp', 3)}>{translate('L')}</th>
@@ -358,4 +396,4 @@ export default class ShipyardPage extends Page {
</div>
);
}
}
}

View File

@@ -9,12 +9,16 @@ export const StandardArray = [
'pd', // Power Distributor
's', // Sensors
'ft', // Fuel Tank
'gpp', // Guardian Hybrid Power Plant
'gpd' // Guardian Hybrid Power Distributor
];
// Map to lookup group labels/names for component grp, used for JSON Serialization
export const ModuleGroupToName = {
// Standard
pp: 'Power Plant',
gpp: 'Guardian Hybrid Power Plant',
gpd: 'Guardian Hybrid Power Distributor',
t: 'Thrusters',
fsd: 'Frame Shift Drive',
ls: 'Life Support',
@@ -58,19 +62,26 @@ export const ModuleGroupToName = {
cm: 'Countermeasure',
ec: 'Electronic Countermeasure',
fc: 'Fragment Cannon',
rfl: 'Remote Release Flak Launcher',
hs: 'Heat Sink Launcher',
ws: 'Frame Shift Wake Scanner',
kw: 'Kill Warrant Scanner',
nl: 'Mine Launcher',
ml: 'Mining Laser',
mr: 'Missile Rack',
axmr: 'AX Missile Rack',
pa: 'Plasma Accelerator',
po: 'Point Defence',
mc: 'Multi-cannon',
axmc: 'AX Multi-cannon',
pl: 'Pulse Laser',
rg: 'Rail Gun',
sb: 'Shield Booster',
tp: 'Torpedo Pylon'
tp: 'Torpedo Pylon',
sfn: 'Shutdown Field Neutraliser',
xs: 'Xeno Scanner',
gpc: 'Guardian Plasma Charger',
ggc: 'Guardian Gauss Cannon',
};
let GrpNameToCodeMap = {};

View File

@@ -64,7 +64,6 @@ export default class Module {
}
}
}
// Sanitise the resultant value to 4dp equivalent
return isNaN(result) ? result : Math.round(result);
}
@@ -79,6 +78,9 @@ export default class Module {
if (!this.mods) {
this.mods = {};
}
if (!this.origVals) {
this.origVals = {};
}
if (valueiswithspecial && this.blueprint && this.blueprint.special) {
// This module has a special effect, see if we need to alter the stored value
const modifierActions = Modifications.modifierActions[this.blueprint.special.edname];
@@ -117,7 +119,6 @@ export default class Module {
_getModifiedValue(name) {
const modification = Modifications.modifications[name];
let result = this[name];
if (!result) {
if (modification && modification.method === 'additive') {
// Additive modifications start at 0 rather than NULL
@@ -135,7 +136,7 @@ export default class Module {
if (modification.type === 'percentage') {
modValue = this.getModValue(name) / 10000;
} else if (modification.type === 'numeric') {
modValue = this.getModValue(name) / 100;
modValue = this.getModValue(name)/ 100;
} else {
modValue = this.getModValue(name);
}

View File

@@ -63,7 +63,6 @@ export function standard(type, id) {
if (!isNaN(type)) {
type = StandardArray[type];
}
let s = Modules.standard[type].find(e => e.id == id || (e.class == id.charAt(0) && e.rating == id.charAt(1)));
if (s) {
s = new Module({ template: s });
@@ -196,6 +195,29 @@ export function findInternal(groupName, clss, rating, name) {
return null;
}
/**
* Finds an internal module based on Class, Rating, Group and/or name.
* At least one of Group name or unique module name must be provided.
* will start searching at specified class and proceed lower until a
* module is found or 0 is hit
* Uses findInternal internally
*
* @param {String} groupName [Optional] Full name or abbreviated name for module group
* @param {integer} clss module Class
* @param {String} rating module Rating
* @param {String} name [Optional] Long/unique name for module -e.g. 'Advanced Discover Scanner'
* @return {Object} The module if found, null if not found
*/
export function findMaxInternal(groupName, clss, rating, name) {
let foundModule = null;
let currentClss = clss;
while (currentClss > 0 && foundModule == null) {
foundModule = findInternal(groupName, currentClss, rating, name);
currentClss = currentClss - 1;
}
return foundModule;
}
/**
* Finds an internal Module ID based on Class, Rating, Group and/or name.
* At least one ofGroup name or unique module name must be provided

View File

@@ -464,7 +464,17 @@ export default class Ship {
if (m.blueprint) {
m.blueprint.special = special;
}
this.recalculateDps().recalculateHps().recalculateEps();
this.updatePowerGenerated()
.updatePowerUsed()
.recalculateMass()
.updateJumpStats()
.recalculateShield()
.recalculateShieldCells()
.recalculateArmour()
.recalculateDps()
.recalculateEps()
.recalculateHps()
.updateMovement();
}
/**
@@ -490,7 +500,6 @@ export default class Ship {
// Value passed is invalid; reset it to 0
value = 0;
}
// Handle special cases
if (name === 'pgen') {
// Power generation
@@ -569,6 +578,7 @@ export default class Ship {
// Reset Cumulative stats
this.fuelCapacity = 0;
this.cargoCapacity = 0;
this.passengerCapacity = 0;
this.ladenMass = 0;
this.armour = this.baseArmour;
this.shield = this.baseShieldStrength;
@@ -616,7 +626,7 @@ export default class Ship {
standard[i].cat = 0;
standard[i].priority = priorities && priorities[i + 1] ? priorities[i + 1] * 1 : 0;
standard[i].type = 'SYS';
standard[i].m = null; // Resetting 'old' modul if there was one
standard[i].m = null; // Resetting 'old' module if there was one
standard[i].discountedCost = 0;
if (comps) {
let module = ModuleUtils.standard(i, comps.standard[i]);
@@ -770,7 +780,7 @@ export default class Ship {
// Alter as required due to changes in the (build) code from one version to the next
this.upgradeInternals(internal, 1 + this.standard.length + this.hardpoints.length, priorities, enabled, modifications, blueprints, version);
}
return this.buildWith(
{
bulkheads: code.charAt(0) * 1,
@@ -1188,6 +1198,7 @@ export default class Ship {
let unladenMass = this.hullMass;
let cargoCapacity = 0;
let fuelCapacity = 0;
let passengerCapacity = 0;
unladenMass += this.bulkheads.m.getMass();
@@ -1209,6 +1220,10 @@ export default class Ship {
fuelCapacity += slot.m.fuel;
} else if (slot.m.grp === 'cr') {
cargoCapacity += slot.m.cargo;
} else if (slot.m.grp.slice(0,2) === 'pc') {
if (slot.m.passengers) {
passengerCapacity += slot.m.passengers;
}
}
}
}
@@ -1224,6 +1239,7 @@ export default class Ship {
this.unladenMass = unladenMass;
this.cargoCapacity = cargoCapacity;
this.fuelCapacity = fuelCapacity;
this.passengerCapacity = passengerCapacity;
this.ladenMass = unladenMass + fuelCapacity + cargoCapacity;
return this;

View File

@@ -1,5 +1,5 @@
import * as ModuleUtils from './ModuleUtils';
import { canMount } from '../utils/SlotFunctions';
import * as ModuleUtils from './ModuleUtils'
import { canMount } from '../utils/SlotFunctions'
/**
* Standard / typical role for multi-purpose or combat (if shielded with better bulkheads)
@@ -7,20 +7,20 @@ import { canMount } from '../utils/SlotFunctions';
* @param {Boolean} shielded True if shield generator should be included
* @param {integer} bulkheadIndex Bulkhead to use see Constants.BulkheadNames
*/
export function multiPurpose(ship, shielded, bulkheadIndex) {
export function multiPurpose (ship, shielded, bulkheadIndex) {
ship.useStandard('A')
.use(ship.standard[3], ModuleUtils.standard(3, ship.standard[3].maxClass + 'D')) // D Life Support
.use(ship.standard[5], ModuleUtils.standard(5, ship.standard[5].maxClass + 'D')) // D Sensors
.useBulkhead(bulkheadIndex);
.use(ship.standard[3], ModuleUtils.standard(3, ship.standard[3].maxClass + 'D')) // D Life Support
.use(ship.standard[5], ModuleUtils.standard(5, ship.standard[5].maxClass + 'D')) // D Sensors
.useBulkhead(bulkheadIndex)
if (shielded) {
ship.internal.some(function(slot) {
ship.internal.some(function (slot) {
if (canMount(ship, slot, 'sg')) { // Assuming largest slot can hold an eligible shield
ship.use(slot, ModuleUtils.findInternal('sg', slot.maxClass, 'A'));
ship.setSlotEnabled(slot, true);
return true;
ship.use(slot, ModuleUtils.findInternal('sg', slot.maxClass, 'A'))
ship.setSlotEnabled(slot, true)
return true
}
});
})
}
}
@@ -30,40 +30,55 @@ export function multiPurpose(ship, shielded, bulkheadIndex) {
* @param {Boolean} shielded True if shield generator should be included
* @param {Object} standardOpts [Optional] Standard module optional overrides
*/
export function trader(ship, shielded, standardOpts) {
let usedSlots = [],
sg = ship.getAvailableModules().lightestShieldGenerator(ship.hullMass);
// Shield generator if required
if (shielded) {
const shieldOrder = [1, 2, 3, 4, 5, 6, 7, 8];
const shieldInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1)
.filter(a => (!a.eligible) || a.eligible.sg)
.filter(a => a.maxClass >= sg.class)
.sort((a,b) => shieldOrder.indexOf(a.maxClass) - shieldOrder.indexOf(b.maxClass));
for (let i = 0; i < shieldInternals.length; i++) {
if (canMount(ship, shieldInternals[i], 'sg')) {
ship.use(shieldInternals[i], sg);
usedSlots.push(shieldInternals[i]);
break;
export function trader (ship, shielded, standardOpts) {
let usedSlots = []
let bstCount = 2
let sg = ship.getAvailableModules().lightestShieldGenerator(ship.hullMass)
ship.useStandard('A')
.use(ship.standard[3], ModuleUtils.standard(3, ship.standard[3].maxClass + 'D')) // D Life Support
.use(ship.standard[1], ModuleUtils.standard(1, ship.standard[1].maxClass + 'D')) // D Life Support
.use(ship.standard[4], ModuleUtils.standard(4, ship.standard[4].maxClass + 'D')) // D Life Support
.use(ship.standard[5], ModuleUtils.standard(5, ship.standard[5].maxClass + 'D')) // D Sensors
const shieldOrder = [1, 2, 3, 4, 5, 6, 7, 8]
const shieldInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1)
.filter(a => (!a.eligible) || a.eligible.sg)
.filter(a => a.maxClass >= sg.class)
.sort((a, b) => shieldOrder.indexOf(a.maxClass) - shieldOrder.indexOf(b.maxClass))
shieldInternals.some(function (slot) {
if (canMount(ship, slot, 'sg')) { // Assuming largest slot can hold an eligible shield
const shield = ModuleUtils.findInternal('sg', slot.maxClass, 'A')
if (shield && shield.maxmass > ship.hullMass) {
console.log(shield)
ship.use(slot, shield)
ship.setSlotEnabled(slot, true)
usedSlots.push(slot)
return true
}
}
}
})
// Fill the empty internals with cargo racks
for (let i = ship.internal.length; i--;) {
let slot = ship.internal[i];
let slot = ship.internal[i]
if (usedSlots.indexOf(slot) == -1 && canMount(ship, slot, 'cr')) {
ship.use(slot, ModuleUtils.findInternal('cr', slot.maxClass, 'E'));
ship.use(slot, ModuleUtils.findInternal('cr', slot.maxClass, 'E'))
}
}
// Empty the hardpoints
for (let s of ship.hardpoints) {
ship.use(s, null);
ship.use(s, null)
}
ship.useLightestStandard(standardOpts);
for (let s of ship.hardpoints) {
if (s.maxClass == 0 && bstCount) { // Mount up to 2 boosters
ship.use(s, ModuleUtils.hardpoints('04'))
bstCount--
} else {
ship.use(s, null)
}
}
// ship.useLightestStandard(standardOpts);
}
/**
@@ -71,127 +86,127 @@ export function trader(ship, shielded, standardOpts) {
* @param {Ship} ship Ship instance
* @param {Boolean} planetary True if Planetary Vehicle Hangar (PVH) should be included
*/
export function explorer(ship, planetary) {
let standardOpts = { ppRating: 'A' },
heatSinkCount = 2, // Fit 2 heat sinks if possible
usedSlots = [],
sgSlot,
fuelScoopSlot,
sg = ship.getAvailableModules().lightestShieldGenerator(ship.hullMass);
export function explorer (ship, planetary) {
let standardOpts = {ppRating: 'A'},
heatSinkCount = 2, // Fit 2 heat sinks if possible
usedSlots = [],
sgSlot,
fuelScoopSlot,
sg = ship.getAvailableModules().lightestShieldGenerator(ship.hullMass)
if (!planetary) { // Non-planetary explorers don't really need to boost
standardOpts.pd = '1D';
standardOpts.pd = '1D'
}
// Cargo hatch can be disabled
ship.setSlotEnabled(ship.cargoHatch, false);
ship.setSlotEnabled(ship.cargoHatch, false)
// Advanced Discovery Scanner - class 1 or higher
const adsOrder = [1, 2, 3, 4, 5, 6, 7, 8];
const adsOrder = [1, 2, 3, 4, 5, 6, 7, 8]
const adsInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1)
.filter(a => (!a.eligible) || a.eligible.sc)
.sort((a,b) => adsOrder.indexOf(a.maxClass) - adsOrder.indexOf(b.maxClass));
.filter(a => (!a.eligible) || a.eligible.sc)
.sort((a, b) => adsOrder.indexOf(a.maxClass) - adsOrder.indexOf(b.maxClass))
for (let i = 0; i < adsInternals.length; i++) {
if (canMount(ship, adsInternals[i], 'sc')) {
ship.use(adsInternals[i], ModuleUtils.internal('2f'));
usedSlots.push(adsInternals[i]);
break;
ship.use(adsInternals[i], ModuleUtils.internal('2f'))
usedSlots.push(adsInternals[i])
break
}
}
if (planetary) {
// Planetary Vehicle Hangar - class 2 or higher
const pvhOrder = [2, 3, 4, 5, 6, 7, 8, 1];
const pvhOrder = [2, 3, 4, 5, 6, 7, 8, 1]
const pvhInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1)
.filter(a => (!a.eligible) || a.eligible.pv)
.sort((a,b) => pvhOrder.indexOf(a.maxClass) - pvhOrder.indexOf(b.maxClass));
.filter(a => (!a.eligible) || a.eligible.pv)
.sort((a, b) => pvhOrder.indexOf(a.maxClass) - pvhOrder.indexOf(b.maxClass))
for (let i = 0; i < pvhInternals.length; i++) {
if (canMount(ship, pvhInternals[i], 'pv')) {
// Planetary Vehical Hangar only has even classes
const pvhClass = pvhInternals[i].maxClass % 2 === 1 ? pvhInternals[i].maxClass - 1 : pvhInternals[i].maxClass;
ship.use(pvhInternals[i], ModuleUtils.findInternal('pv', pvhClass, 'G')); // G is lower mass
ship.setSlotEnabled(pvhInternals[i], false); // Disable power for Planetary Vehical Hangar
usedSlots.push(pvhInternals[i]);
break;
const pvhClass = pvhInternals[i].maxClass % 2 === 1 ? pvhInternals[i].maxClass - 1 : pvhInternals[i].maxClass
ship.use(pvhInternals[i], ModuleUtils.findInternal('pv', pvhClass, 'G')) // G is lower mass
ship.setSlotEnabled(pvhInternals[i], false) // Disable power for Planetary Vehical Hangar
usedSlots.push(pvhInternals[i])
break
}
}
}
// Shield generator
const shieldOrder = [1, 2, 3, 4, 5, 6, 7, 8];
const shieldOrder = [1, 2, 3, 4, 5, 6, 7, 8]
const shieldInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1)
.filter(a => (!a.eligible) || a.eligible.sg)
.filter(a => a.maxClass >= sg.class)
.sort((a,b) => shieldOrder.indexOf(a.maxClass) - shieldOrder.indexOf(b.maxClass));
.filter(a => (!a.eligible) || a.eligible.sg)
.filter(a => a.maxClass >= sg.class)
.sort((a, b) => shieldOrder.indexOf(a.maxClass) - shieldOrder.indexOf(b.maxClass))
for (let i = 0; i < shieldInternals.length; i++) {
if (canMount(ship, shieldInternals[i], 'sg')) {
ship.use(shieldInternals[i], sg);
usedSlots.push(shieldInternals[i]);
sgSlot = shieldInternals[i];
break;
ship.use(shieldInternals[i], sg)
usedSlots.push(shieldInternals[i])
sgSlot = shieldInternals[i]
break
}
}
// Detailed Surface Scanner
const dssOrder = [1, 2, 3, 4, 5, 6, 7, 8];
const dssOrder = [1, 2, 3, 4, 5, 6, 7, 8]
const dssInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1)
.filter(a => (!a.eligible) || a.eligible.sc)
.sort((a,b) => dssOrder.indexOf(a.maxClass) - dssOrder.indexOf(b.maxClass));
.filter(a => (!a.eligible) || a.eligible.sc)
.sort((a, b) => dssOrder.indexOf(a.maxClass) - dssOrder.indexOf(b.maxClass))
for (let i = 0; i < dssInternals.length; i++) {
if (canMount(ship, dssInternals[i], 'sc')) {
ship.use(dssInternals[i], ModuleUtils.internal('2i'));
usedSlots.push(dssInternals[i]);
break;
ship.use(dssInternals[i], ModuleUtils.internal('2i'))
usedSlots.push(dssInternals[i])
break
}
}
// Fuel scoop - best possible
const fuelScoopOrder = [8, 7, 6, 5, 4, 3, 2, 1];
const fuelScoopOrder = [8, 7, 6, 5, 4, 3, 2, 1]
const fuelScoopInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1)
.filter(a => (!a.eligible) || a.eligible.fs)
.sort((a,b) => fuelScoopOrder.indexOf(a.maxClass) - fuelScoopOrder.indexOf(b.maxClass));
.filter(a => (!a.eligible) || a.eligible.fs)
.sort((a, b) => fuelScoopOrder.indexOf(a.maxClass) - fuelScoopOrder.indexOf(b.maxClass))
for (let i = 0; i < fuelScoopInternals.length; i++) {
if (canMount(ship, fuelScoopInternals[i], 'fs')) {
ship.use(fuelScoopInternals[i], ModuleUtils.findInternal('fs', fuelScoopInternals[i].maxClass, 'A'));
usedSlots.push(fuelScoopInternals[i]);
fuelScoopSlot = fuelScoopInternals[i];
break;
ship.use(fuelScoopInternals[i], ModuleUtils.findInternal('fs', fuelScoopInternals[i].maxClass, 'A'))
usedSlots.push(fuelScoopInternals[i])
fuelScoopSlot = fuelScoopInternals[i]
break
}
}
// AFMUs - fill as they are 0-weight
const afmuOrder = [8, 7, 6, 5, 4, 3, 2, 1];
const afmuOrder = [8, 7, 6, 5, 4, 3, 2, 1]
const afmuInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1)
.filter(a => (!a.eligible) || a.eligible.pc)
.sort((a,b) => afmuOrder.indexOf(a.maxClass) - afmuOrder.indexOf(b.maxClass));
.filter(a => (!a.eligible) || a.eligible.pc)
.sort((a, b) => afmuOrder.indexOf(a.maxClass) - afmuOrder.indexOf(b.maxClass))
for (let i = 0; i < afmuInternals.length; i++) {
if (canMount(ship, afmuInternals[i], 'am')) {
ship.use(afmuInternals[i], ModuleUtils.findInternal('am', afmuInternals[i].maxClass, 'A'));
usedSlots.push(afmuInternals[i]);
ship.setSlotEnabled(afmuInternals[i], false); // Disable power for AFM Unit
ship.use(afmuInternals[i], ModuleUtils.findInternal('am', afmuInternals[i].maxClass, 'A'))
usedSlots.push(afmuInternals[i])
ship.setSlotEnabled(afmuInternals[i], false) // Disable power for AFM Unit
}
}
for (let s of ship.hardpoints) {
if (s.maxClass == 0 && heatSinkCount) { // Mount up to 2 heatsinks
ship.use(s, ModuleUtils.hardpoints('02'));
ship.setSlotEnabled(s, heatSinkCount == 2); // Only enable a single Heatsink
heatSinkCount--;
ship.use(s, ModuleUtils.hardpoints('02'))
ship.setSlotEnabled(s, heatSinkCount == 2) // Only enable a single Heatsink
heatSinkCount--
} else {
ship.use(s, null);
ship.use(s, null)
}
}
if (sgSlot && fuelScoopSlot) {
// The SG and Fuel scoop to not need to be powered at the same time
if (sgSlot.m.getPowerUsage() > fuelScoopSlot.m.getPowerUsage()) { // The Shield generator uses the most power
ship.setSlotEnabled(fuelScoopSlot, false);
ship.setSlotEnabled(fuelScoopSlot, false)
} else { // The Fuel scoop uses the most power
ship.setSlotEnabled(sgSlot, false);
ship.setSlotEnabled(sgSlot, false)
}
}
ship.useLightestStandard(standardOpts);
ship.useLightestStandard(standardOpts)
}
/**
@@ -199,187 +214,188 @@ export function explorer(ship, planetary) {
* @param {Ship} ship Ship instance
* @param {Boolean} shielded True if shield generator should be included
*/
export function miner(ship, shielded) {
let standardOpts = { ppRating: 'A' },
miningLaserCount = 2,
usedSlots = [],
sg = ship.getAvailableModules().lightestShieldGenerator(ship.hullMass);
export function miner (ship, shielded) {
shielded = true
let standardOpts = {ppRating: 'A'},
miningLaserCount = 2,
usedSlots = [],
sg = ship.getAvailableModules().lightestShieldGenerator(ship.hullMass)
// Cargo hatch should be enabled
ship.setSlotEnabled(ship.cargoHatch, true);
ship.setSlotEnabled(ship.cargoHatch, true)
// Largest possible refinery
const refineryOrder = [4, 5, 6, 7, 8, 3, 2, 1];
const refineryOrder = [4, 5, 6, 7, 8, 3, 2, 1]
const refineryInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1)
.filter(a => (!a.eligible) || a.eligible.rf)
.sort((a,b) => refineryOrder.indexOf(a.maxClass) - refineryOrder.indexOf(b.maxClass));
.filter(a => (!a.eligible) || a.eligible.rf)
.sort((a, b) => refineryOrder.indexOf(a.maxClass) - refineryOrder.indexOf(b.maxClass))
for (let i = 0; i < refineryInternals.length; i++) {
if (canMount(ship, refineryInternals[i], 'rf')) {
ship.use(refineryInternals[i], ModuleUtils.findInternal('rf', Math.min(refineryInternals[i].maxClass, 4), 'A'));
usedSlots.push(refineryInternals[i]);
break;
ship.use(refineryInternals[i], ModuleUtils.findInternal('rf', Math.min(refineryInternals[i].maxClass, 4), 'A'))
usedSlots.push(refineryInternals[i])
break
}
}
// Prospector limpet controller - 3A if possible
const prospectorOrder = [3, 4, 5, 6, 7, 8, 2, 1];
const prospectorOrder = [3, 4, 5, 6, 7, 8, 2, 1]
const prospectorInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1)
.filter(a => (!a.eligible) || a.eligible.pc)
.sort((a,b) => prospectorOrder.indexOf(a.maxClass) - prospectorOrder.indexOf(b.maxClass));
.filter(a => (!a.eligible) || a.eligible.pc)
.sort((a, b) => prospectorOrder.indexOf(a.maxClass) - prospectorOrder.indexOf(b.maxClass))
for (let i = 0; i < prospectorInternals.length; i++) {
if (canMount(ship, prospectorInternals[i], 'pc')) {
// Prospector only has odd classes
const prospectorClass = prospectorInternals[i].maxClass % 2 === 0 ? prospectorInternals[i].maxClass - 1 : prospectorInternals[i].maxClass;
ship.use(prospectorInternals[i], ModuleUtils.findInternal('pc', prospectorClass, 'A'));
usedSlots.push(prospectorInternals[i]);
break;
const prospectorClass = prospectorInternals[i].maxClass % 2 === 0 ? prospectorInternals[i].maxClass - 1 : prospectorInternals[i].maxClass
ship.use(prospectorInternals[i], ModuleUtils.findInternal('pc', prospectorClass, 'A'))
usedSlots.push(prospectorInternals[i])
break
}
}
// Shield generator if required
if (shielded) {
const shieldOrder = [1, 2, 3, 4, 5, 6, 7, 8];
const shieldOrder = [1, 2, 3, 4, 5, 6, 7, 8]
const shieldInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1)
.filter(a => (!a.eligible) || a.eligible.sg)
.filter(a => a.maxClass >= sg.class)
.sort((a,b) => shieldOrder.indexOf(a.maxClass) - shieldOrder.indexOf(b.maxClass));
.filter(a => (!a.eligible) || a.eligible.sg)
.filter(a => a.maxClass >= sg.class)
.sort((a, b) => shieldOrder.indexOf(a.maxClass) - shieldOrder.indexOf(b.maxClass))
for (let i = 0; i < shieldInternals.length; i++) {
if (canMount(ship, shieldInternals[i], 'sg')) {
ship.use(shieldInternals[i], sg);
usedSlots.push(shieldInternals[i]);
break;
ship.use(shieldInternals[i], sg)
usedSlots.push(shieldInternals[i])
break
}
}
}
// Dual mining lasers of highest possible class; remove anything else
const miningLaserOrder = [2, 3, 4, 1, 0];
const miningLaserHardpoints = ship.hardpoints.concat().sort(function(a,b) {
return miningLaserOrder.indexOf(a.maxClass) - miningLaserOrder.indexOf(b.maxClass);
});
const miningLaserOrder = [2, 3, 4, 1, 0]
const miningLaserHardpoints = ship.hardpoints.concat().sort(function (a, b) {
return miningLaserOrder.indexOf(a.maxClass) - miningLaserOrder.indexOf(b.maxClass)
})
for (let s of miningLaserHardpoints) {
if (s.maxClass >= 1 && miningLaserCount) {
ship.use(s, ModuleUtils.hardpoints(s.maxClass >= 2 ? '2m' : '2l'));
miningLaserCount--;
ship.use(s, ModuleUtils.hardpoints(s.maxClass >= 2 ? '2m' : '2l'))
miningLaserCount--
} else {
ship.use(s, null);
ship.use(s, null)
}
}
// Number of collector limpets required to be active is a function of the size of the ship and the power of the lasers
const miningLaserDps = ship.hardpoints.filter(h => h.m != null)
.reduce(function(a, b) {
return a + b.m.getDps();
}, 0);
.reduce(function (a, b) {
return a + b.m.getDps()
}, 0)
// Find out how many internal slots we have, and their potential cargo size
const potentialCargo = ship.internal.filter(a => usedSlots.indexOf(a) == -1)
.filter(a => (!a.eligible) || a.eligible.cr)
.map(b => Math.pow(2, b.maxClass));
.filter(a => (!a.eligible) || a.eligible.cr)
.map(b => Math.pow(2, b.maxClass))
// One collector for each 1.25 DPS, multiply by 1.25 for medium ships and 1.5 for large ships as they have further to travel
// 0 if we only have 1 cargo slot, otherwise minium of 1 and maximum of 6 (excluding size modifier)
const sizeModifier = ship.class == 2 ? 1.2 : ship.class == 3 ? 1.5 : 1;
let collectorLimpetsRequired = potentialCargo.length == 1 ? 0 : Math.ceil(sizeModifier * Math.min(6, Math.floor(miningLaserDps / 1.25)));
const sizeModifier = ship.class == 2 ? 1.2 : ship.class == 3 ? 1.5 : 1
let collectorLimpetsRequired = potentialCargo.length == 1 ? 0 : Math.ceil(sizeModifier * Math.min(6, Math.floor(miningLaserDps / 1.25)))
if (collectorLimpetsRequired > 0) {
const collectorOrder = [1, 2, 3, 4, 5, 6, 7, 8];
const collectorOrder = [1, 2, 3, 4, 5, 6, 7, 8]
const collectorInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1)
.filter(a => (!a.eligible) || a.eligible.cc)
.sort((a,b) => collectorOrder.indexOf(a.maxClass) - collectorOrder.indexOf(b.maxClass));
.filter(a => (!a.eligible) || a.eligible.cc)
.sort((a, b) => collectorOrder.indexOf(a.maxClass) - collectorOrder.indexOf(b.maxClass))
// Always keep at least 2 slots free for cargo racks (1 for shielded)
for (let i = 0; i < collectorInternals.length - (shielded ? 1 : 2) && collectorLimpetsRequired > 0; i++) {
if (canMount(ship, collectorInternals[i], 'cc')) {
// Collector only has odd classes
const collectorClass = collectorInternals[i].maxClass % 2 === 0 ? collectorInternals[i].maxClass - 1 : collectorInternals[i].maxClass;
ship.use(collectorInternals[i], ModuleUtils.findInternal('cc', collectorClass, 'D'));
usedSlots.push(collectorInternals[i]);
collectorLimpetsRequired -= collectorInternals[i].m.maximum;
const collectorClass = collectorInternals[i].maxClass % 2 === 0 ? collectorInternals[i].maxClass - 1 : collectorInternals[i].maxClass
ship.use(collectorInternals[i], ModuleUtils.findInternal('cc', collectorClass, 'D'))
usedSlots.push(collectorInternals[i])
collectorLimpetsRequired -= collectorInternals[i].m.maximum
}
}
}
// Power distributor to power the mining lasers indefinitely
const wepRateRequired = ship.hardpoints.filter(h => h.m != null)
.reduce(function(a, b) {
return a + b.m.getEps();
}, 0);
standardOpts.pd = ship.getAvailableModules().matchingPowerDist({ weprate: wepRateRequired }).id;
.reduce(function (a, b) {
return a + b.m.getEps()
}, 0)
standardOpts.pd = ship.getAvailableModules().matchingPowerDist({weprate: wepRateRequired}).id
// Fill the empty internals with cargo racks
for (let i = ship.internal.length; i--;) {
let slot = ship.internal[i];
let slot = ship.internal[i]
if (usedSlots.indexOf(slot) == -1 && canMount(ship, slot, 'cr')) {
ship.use(slot, ModuleUtils.findInternal('cr', slot.maxClass, 'E'));
ship.use(slot, ModuleUtils.findInternal('cr', slot.maxClass, 'E'))
}
}
ship.useLightestStandard(standardOpts);
ship.useLightestStandard(standardOpts)
}
/**
* Racer Role
* @param {Ship} ship Ship instance
*/
export function racer(ship) {
export function racer (ship) {
let standardOpts = {},
usedSlots = [],
sgSlot,
sg = ship.getAvailableModules().lightestShieldGenerator(ship.hullMass);
usedSlots = [],
sgSlot,
sg = ship.getAvailableModules().lightestShieldGenerator(ship.hullMass)
// Cargo hatch can be disabled
ship.setSlotEnabled(ship.cargoHatch, false);
ship.setSlotEnabled(ship.cargoHatch, false)
// Shield generator
const shieldOrder = [1, 2, 3, 4, 5, 6, 7, 8];
const shieldOrder = [1, 2, 3, 4, 5, 6, 7, 8]
const shieldInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1)
.filter(a => (!a.eligible) || a.eligible.sg)
.filter(a => a.maxClass >= sg.class)
.sort((a,b) => shieldOrder.indexOf(a.maxClass) - shieldOrder.indexOf(b.maxClass));
.filter(a => (!a.eligible) || a.eligible.sg)
.filter(a => a.maxClass >= sg.class)
.sort((a, b) => shieldOrder.indexOf(a.maxClass) - shieldOrder.indexOf(b.maxClass))
for (let i = 0; i < shieldInternals.length; i++) {
if (canMount(ship, shieldInternals[i], 'sg')) {
ship.use(shieldInternals[i], sg);
usedSlots.push(shieldInternals[i]);
sgSlot = shieldInternals[i];
break;
ship.use(shieldInternals[i], sg)
usedSlots.push(shieldInternals[i])
sgSlot = shieldInternals[i]
break
}
}
// Empty the hardpoints
for (let s of ship.hardpoints) {
ship.use(s, null);
ship.use(s, null)
}
// Empty the internals
for (let i = ship.internal.length; i--;) {
let slot = ship.internal[i];
let slot = ship.internal[i]
if (usedSlots.indexOf(slot) == -1) {
ship.use(slot, null);
ship.use(slot, null)
}
}
// Best thrusters
if (ship.standard[1].maxClass === 3) {
standardOpts.th = 'tz';
standardOpts.th = 'tz'
} else if (ship.standard[1].maxClass === 2) {
standardOpts.th = 'u0';
standardOpts.th = 'u0'
} else {
standardOpts.th = ship.standard[1].maxClass + 'A';
standardOpts.th = ship.standard[1].maxClass + 'A'
}
// Best power distributor for more boosting
standardOpts.pd = ship.standard[4].maxClass + 'A';
standardOpts.pd = ship.standard[4].maxClass + 'A'
// Smallest possible FSD drive
standardOpts.fsd = '2D';
standardOpts.fsd = '2D'
// Minimal fuel tank
standardOpts.ft = '1C';
standardOpts.ft = '1C'
// Disable nearly everything
standardOpts.fsdDisabled = true;
standardOpts.sDisabled = true;
standardOpts.pdDisabled = true;
standardOpts.lsDisabled = true;
standardOpts.fsdDisabled = true
standardOpts.sDisabled = true
standardOpts.pdDisabled = true
standardOpts.lsDisabled = true
ship.useLightestStandard(standardOpts);
ship.useLightestStandard(standardOpts)
// Apply engineering to each module
// ship.standard[1].m.blueprint = getBlueprint('Engine_Dirty', ship.standard[0]);

View File

@@ -1,6 +1,67 @@
import React from 'react';
import { Modifications } from 'coriolis-data/dist';
/**
* Generate a tooltip with details of a blueprint's specials
* @param {Object} translate The translate object
* @param {Object} blueprint The blueprint at the required grade
* @param {string} grp The group of the module
* @param {Object} m The module to compare with
* @param specialName
* @returns {Object} The react components
*/
export function specialToolTip(translate, blueprint, grp, m, specialName) {
const effects = [];
if (!blueprint || !blueprint.features) {
return undefined;
}
if (m) {
// We also add in any benefits from specials that aren't covered above
if (m.blueprint) {
for (const feature in Modifications.modifierActions[specialName]) {
// if (!blueprint.features[feature] && !m.mods.feature) {
const featureDef = Modifications.modifications[feature];
if (featureDef && !featureDef.hidden) {
let symbol = '';
if (feature === 'jitter') {
symbol = '°';
} else if (featureDef.type === 'percentage') {
symbol = '%';
}
let current = m.getModValue(feature) - m.getModValue(feature, true);
if (featureDef.type === 'percentage') {
current = Math.round(current / 10) / 10;
} else if (featureDef.type === 'numeric') {
current /= 100;
}
const currentIsBeneficial = isValueBeneficial(feature, current);
effects.push(
<tr key={feature + '_specialTT'}>
<td style={{textAlign: 'left'}}>{translate(feature, grp)}</td>
<td>&nbsp;</td>
<td className={current === 0 ? '' : currentIsBeneficial ? 'secondary' : 'warning'}
style={{textAlign: 'right'}}>{current}{symbol}</td>
<td>&nbsp;</td>
</tr>
);
}
}
}
}
return (
<div>
<table width='100%'>
<tbody>
{effects}
</tbody>
</table>
</div>
);
}
/**
* Generate a tooltip with details of a blueprint's effects
* @param {Object} translate The translate object
@@ -12,6 +73,9 @@ import { Modifications } from 'coriolis-data/dist';
*/
export function blueprintTooltip(translate, blueprint, engineers, grp, m) {
const effects = [];
if (!blueprint || !blueprint.features) {
return undefined;
}
for (const feature in blueprint.features) {
const featureIsBeneficial = isBeneficial(feature, blueprint.features[feature]);
const featureDef = Modifications.modifications[feature];
@@ -225,27 +289,13 @@ export function isValueBeneficial(feature, value) {
*/
export function getBlueprint(name, module) {
// Start with a copy of the blueprint
const blueprint = JSON.parse(JSON.stringify(Modifications.blueprints[name]));
const findMod = val => Object.keys(Modifications.blueprints).find(elem => elem.toString().toLowerCase().search(val.toString().toLowerCase().replace(/(OutfittingFieldType_|persecond)/igm, '')) >= 0)
const found = Modifications.blueprints[findMod(name)];
if (!found || !found.fdname) {
return {};
}
const blueprint = JSON.parse(JSON.stringify(found));
if (module) {
if (module.grp === 'bh' || module.grp === 'hr' || module.grp === 'sg' || module.grp === 'psg' || module.grp === 'bsg') {
// Bulkheads, hull reinforcements and shield generators need to have their resistances altered by the base values
for (const grade in blueprint.grades) {
for (const feature in blueprint.grades[grade].features) {
if (feature === 'explres') {
blueprint.grades[grade].features[feature][0] *= (1 - module.explres);
blueprint.grades[grade].features[feature][1] *= (1 - module.explres);
}
if (feature === 'kinres') {
blueprint.grades[grade].features[feature][0] *= (1 - module.kinres);
blueprint.grades[grade].features[feature][1] *= (1 - module.kinres);
}
if (feature === 'thermres') {
blueprint.grades[grade].features[feature][0] *= (1 - module.thermres);
blueprint.grades[grade].features[feature][1] *= (1 - module.thermres);
}
}
}
}
if (module.grp === 'sb') {
// Shield boosters are treated internally as straight modifiers, so rather than (for example)
// being a 4% boost they are a 104% multiplier. We need to fix the values here so that they look
@@ -264,56 +314,31 @@ export function getBlueprint(name, module) {
}
/**
* Provide 'worst' primary modifications
* Provide 'percent' primary modifications
* @param {Object} ship The ship for which to perform the modifications
* @param {Object} m The module for which to perform the modifications
* @param {Number} percent The percent to set values to of full.
*/
export function setWorst(ship, m) {
ship.clearModifications(m);
const features = m.blueprint.grades[m.blueprint.grade].features;
for (const featureName in features) {
const value = features[featureName][0];
_setValue(ship, m, featureName, value);
}
}
/**
* Provide 'best' primary modifications
* @param {Object} ship The ship for which to perform the modifications
* @param {Object} m The module for which to perform the modifications
*/
export function setBest(ship, m) {
ship.clearModifications(m);
const features = m.blueprint.grades[m.blueprint.grade].features;
for (const featureName in features) {
const value = features[featureName][1];
_setValue(ship, m, featureName, value);
}
}
/**
* Provide 'extreme' primary modifications
* @param {Object} ship The ship for which to perform the modifications
* @param {Object} m The module for which to perform the modifications
*/
export function setExtreme(ship, m) {
export function setPercent(ship, m, percent) {
ship.clearModifications(m);
// Pick given value as multiplier
const mult = percent / 100;
const features = m.blueprint.grades[m.blueprint.grade].features;
for (const featureName in features) {
let value;
if (Modifications.modifications[featureName].higherbetter) {
// Higher is better, but is this making it better or worse?
if (features[featureName][0] < 0 || (features[featureName][0] === 0 && features[featureName][1] < 0)) {
value = features[featureName][0];
value = features[featureName][1] + ((features[featureName][0] - features[featureName][1]) * mult);
} else {
value = features[featureName][1];
value = features[featureName][0] + ((features[featureName][1] - features[featureName][0]) * mult);
}
} else {
// Higher is worse, but is this making it better or worse?
if (features[featureName][0] < 0 || (features[featureName][0] === 0 && features[featureName][1] < 0)) {
value = features[featureName][1];
value = features[featureName][0] + ((features[featureName][1] - features[featureName][0]) * mult);
} else {
value = features[featureName][0];
value = features[featureName][1] + ((features[featureName][0] - features[featureName][1]) * mult);
}
}
@@ -327,30 +352,8 @@ export function setExtreme(ship, m) {
* @param {Object} m The module for which to perform the modifications
*/
export function setRandom(ship, m) {
ship.clearModifications(m);
// Pick a single value for our randomness
const mult = Math.random();
const features = m.blueprint.grades[m.blueprint.grade].features;
for (const featureName in features) {
let value;
if (Modifications.modifications[featureName].higherbetter) {
// Higher is better, but is this making it better or worse?
if (features[featureName][0] < 0 || (features[featureName][0] === 0 && features[featureName][1] < 0)) {
value = features[featureName][1] + ((features[featureName][0] - features[featureName][1]) * mult);
} else {
value = features[featureName][0] + ((features[featureName][1] - features[featureName][0]) * mult);
}
} else {
// Higher is worse, but is this making it better or worse?
if (features[featureName][0] < 0 || (features[featureName][0] === 0 && features[featureName][1] < 0)) {
value = features[featureName][0] + ((features[featureName][1] - features[featureName][0]) * mult);
} else {
value = features[featureName][1] + ((features[featureName][0] - features[featureName][1]) * mult);
}
}
_setValue(ship, m, featureName, value);
}
setPercent(ship, m, Math.random() * 100);
}
/**
@@ -369,3 +372,60 @@ function _setValue(ship, m, featureName, value) {
ship.setModification(m, featureName, value);
}
}
/**
* Provide 'percent' primary query
* @param {Object} m The module for which to perform the query
* @returns {Number} percent The percentage indicator of current applied values.
*/
export function getPercent(m) {
let result = null;
const features = m.blueprint.grades[m.blueprint.grade].features;
for (const featureName in features) {
if (features[featureName][0] === features[featureName][1]) {
continue;
}
let value = _getValue(m, featureName);
let mult;
if (Modifications.modifications[featureName].higherbetter) {
// Higher is better, but is this making it better or worse?
if (features[featureName][0] < 0 || (features[featureName][0] === 0 && features[featureName][1] < 0)) {
mult = Math.round((value - features[featureName][1]) / (features[featureName][0] - features[featureName][1]) * 100);
} else {
mult = Math.round((value - features[featureName][0]) / (features[featureName][1] - features[featureName][0]) * 100);
}
} else {
// Higher is worse, but is this making it better or worse?
if (features[featureName][0] < 0 || (features[featureName][0] === 0 && features[featureName][1] < 0)) {
mult = Math.round((value - features[featureName][0]) / (features[featureName][1] - features[featureName][0]) * 100);
} else {
mult = Math.round((value - features[featureName][1]) / (features[featureName][0] - features[featureName][1]) * 100);
}
}
if (result && result != mult) {
return null;
} else if (result != mult) {
result = mult;
}
}
return result;
}
/**
* Query a feature value
* @param {Object} m The module for which to perform the query
* @param {string} featureName The feature being queried
*/
function _getValue(m, featureName) {
if (Modifications.modifications[featureName].type == 'percentage') {
return m.getModValue(featureName, true) / 10000;
} else if (Modifications.modifications[featureName].type == 'numeric') {
return m.getModValue(featureName, true) / 100;
} else {
return m.getModValue(featureName, true);
}
}

View File

@@ -35,13 +35,15 @@ const SHIP_FD_NAME_TO_CORIOLIS_NAME = {
'Type6': 'type_6_transporter',
'Type7': 'type_7_transport',
'Type9': 'type_9_heavy',
'Type9_Military': 'type_10_defender',
'TypeX': 'alliance_chieftain',
'Viper': 'viper',
'Viper_MkIV': 'viper_mk_iv',
'Vulture': 'vulture'
};
// Mapping from hardpoint class to name in companion API
const HARDPOINT_NUM_TO_CLASS = {
export const HARDPOINT_NUM_TO_CLASS = {
0: 'Tiny',
1: 'Small',
2: 'Medium',
@@ -104,7 +106,7 @@ function _moduleFromEdId(edId) {
* @return {string} the Coriolis model of the ship
*/
function _shipModelFromEDName(edName) {
return SHIP_FD_NAME_TO_CORIOLIS_NAME[edName];
return SHIP_FD_NAME_TO_CORIOLIS_NAME[Object.keys(SHIP_FD_NAME_TO_CORIOLIS_NAME).find(elem => elem.toLowerCase() === edName.toLowerCase())];
}
/**
@@ -113,7 +115,7 @@ function _shipModelFromEDName(edName) {
* @return {string} the Coriolis model of the ship
*/
export function shipModelFromJson(json) {
return _shipModelFromEDName(json.name);
return _shipModelFromEDName(json.name || json.Ship);
}
/**
@@ -141,30 +143,34 @@ export function shipFromJson(json) {
ship.cargoHatch.enabled = false;
ship.cargoHatch.priority = 4;
}
let rootModule;
// Add the bulkheads
const armourJson = json.modules.Armour.module;
if (armourJson.name.endsWith('_Armour_Grade1')) {
if (armourJson.name.toLowerCase().endsWith('_armour_grade1')) {
ship.useBulkhead(0, true);
} else if (armourJson.name.endsWith('_Armour_Grade2')) {
} else if (armourJson.name.toLowerCase().endsWith('_armour_grade2')) {
ship.useBulkhead(1, true);
} else if (armourJson.name.endsWith('_Armour_Grade3')) {
} else if (armourJson.name.toLowerCase().endsWith('_armour_grade3')) {
ship.useBulkhead(2, true);
} else if (armourJson.name.endsWith('_Armour_Mirrored')) {
} else if (armourJson.name.toLowerCase().endsWith('_armour_mirrored')) {
ship.useBulkhead(3, true);
} else if (armourJson.name.endsWith('_Armour_Reactive')) {
} else if (armourJson.name.toLowerCase().endsWith('_armour_reactive')) {
ship.useBulkhead(4, true);
} else {
throw 'Unknown bulkheads "' + armourJson.name + '"';
}
ship.bulkheads.enabled = true;
if (armourJson.modifiers) _addModifications(ship.bulkheads.m, armourJson.modifiers, armourJson.recipeName, armourJson.recipeLevel);
rootModule = json.modules.Armour;
if (rootModule.WorkInProgress_modifications) _addModifications(ship.bulkheads.m, rootModule.WorkInProgress_modifications, rootModule.engineer.recipeName, rootModule.engineer.recipeLevel);
// Add the standard modules
// Power plant
const powerplantJson = json.modules.PowerPlant.module;
const powerplant = _moduleFromEdId(powerplantJson.id);
if (powerplantJson.modifiers) _addModifications(powerplant, powerplantJson.modifiers, powerplantJson.recipeName, powerplantJson.recipeLevel);
rootModule = json.modules.PowerPlant;
if (rootModule.WorkInProgress_modifications) _addModifications(powerplant, rootModule.WorkInProgress_modifications, rootModule.engineer.recipeName, rootModule.engineer.recipeLevel);
ship.use(ship.standard[0], powerplant, true);
ship.standard[0].enabled = powerplantJson.on === true;
ship.standard[0].priority = powerplantJson.priority;
@@ -172,7 +178,8 @@ export function shipFromJson(json) {
// Thrusters
const thrustersJson = json.modules.MainEngines.module;
const thrusters = _moduleFromEdId(thrustersJson.id);
if (thrustersJson.modifiers) _addModifications(thrusters, thrustersJson.modifiers, thrustersJson.recipeName, thrustersJson.recipeLevel);
rootModule = json.modules.MainEngines;
if (rootModule.WorkInProgress_modifications) _addModifications(thrusters, rootModule.WorkInProgress_modifications, rootModule.engineer.recipeName, rootModule.engineer.recipeLevel);
ship.use(ship.standard[1], thrusters, true);
ship.standard[1].enabled = thrustersJson.on === true;
ship.standard[1].priority = thrustersJson.priority;
@@ -180,7 +187,8 @@ export function shipFromJson(json) {
// FSD
const frameshiftdriveJson = json.modules.FrameShiftDrive.module;
const frameshiftdrive = _moduleFromEdId(frameshiftdriveJson.id);
if (frameshiftdriveJson.modifiers) _addModifications(frameshiftdrive, frameshiftdriveJson.modifiers, frameshiftdriveJson.recipeName, frameshiftdriveJson.recipeLevel);
rootModule = json.modules.FrameShiftDrive;
if (rootModule.WorkInProgress_modifications) _addModifications(frameshiftdrive, rootModule.WorkInProgress_modifications, rootModule.engineer.recipeName, rootModule.engineer.recipeLevel);
ship.use(ship.standard[2], frameshiftdrive, true);
ship.standard[2].enabled = frameshiftdriveJson.on === true;
ship.standard[2].priority = frameshiftdriveJson.priority;
@@ -188,7 +196,8 @@ export function shipFromJson(json) {
// Life support
const lifesupportJson = json.modules.LifeSupport.module;
const lifesupport = _moduleFromEdId(lifesupportJson.id);
if (lifesupportJson.modifiers)_addModifications(lifesupport, lifesupportJson.modifiers, lifesupportJson.recipeName, lifesupportJson.recipeLevel);
rootModule = json.modules.LifeSupport;
if (rootModule.WorkInProgress_modifications) _addModifications(lifesupport, rootModule.WorkInProgress_modifications, rootModule.engineer.recipeName, rootModule.engineer.recipeLevel);
ship.use(ship.standard[3], lifesupport, true);
ship.standard[3].enabled = lifesupportJson.on === true;
ship.standard[3].priority = lifesupportJson.priority;
@@ -196,7 +205,8 @@ export function shipFromJson(json) {
// Power distributor
const powerdistributorJson = json.modules.PowerDistributor.module;
const powerdistributor = _moduleFromEdId(powerdistributorJson.id);
if (powerdistributorJson.modifiers) _addModifications(powerdistributor, powerdistributorJson.modifiers, powerdistributorJson.recipeName, powerdistributorJson.recipeLevel);
rootModule = json.modules.PowerDistributor;
if (rootModule.WorkInProgress_modifications) _addModifications(powerdistributor, rootModule.WorkInProgress_modifications, rootModule.engineer.recipeName, rootModule.engineer.recipeLevel);
ship.use(ship.standard[4], powerdistributor, true);
ship.standard[4].enabled = powerdistributorJson.on === true;
ship.standard[4].priority = powerdistributorJson.priority;
@@ -204,7 +214,8 @@ export function shipFromJson(json) {
// Sensors
const sensorsJson = json.modules.Radar.module;
const sensors = _moduleFromEdId(sensorsJson.id);
if (sensorsJson.modifiers) _addModifications(sensors, sensorsJson.modifiers, sensorsJson.recipeName, sensorsJson.recipeLevel);
rootModule = json.modules.Radar;
if (rootModule.WorkInProgress_modifications) _addModifications(sensors, rootModule.WorkInProgress_modifications, rootModule.engineer.recipeName, rootModule.engineer.recipeLevel);
ship.use(ship.standard[5], sensors, true);
ship.standard[5].enabled = sensorsJson.on === true;
ship.standard[5].priority = sensorsJson.priority;
@@ -240,7 +251,8 @@ export function shipFromJson(json) {
} else {
const hardpointJson = hardpointSlot.module;
const hardpoint = _moduleFromEdId(hardpointJson.id);
if (hardpointJson.modifiers) _addModifications(hardpoint, hardpointJson.modifiers, hardpointJson.recipeName, hardpointJson.recipeLevel);
rootModule = hardpointSlot;
if (rootModule.WorkInProgress_modifications) _addModifications(hardpoint, rootModule.WorkInProgress_modifications, rootModule.engineer.recipeName, rootModule.engineer.recipeLevel, rootModule.specialModifications);
ship.use(ship.hardpoints[hardpointArrayNum], hardpoint, true);
ship.hardpoints[hardpointArrayNum].enabled = hardpointJson.on === true;
ship.hardpoints[hardpointArrayNum].priority = hardpointJson.priority;
@@ -282,7 +294,8 @@ export function shipFromJson(json) {
} else {
const internalJson = internalSlot.module;
const internal = _moduleFromEdId(internalJson.id);
if (internalJson.modifiers) _addModifications(internal, internalJson.modifiers, internalJson.recipeName, internalJson.recipeLevel);
rootModule = internalSlot;
if (rootModule.WorkInProgress_modifications) _addModifications(internal, rootModule.WorkInProgress_modifications, rootModule.engineer.recipeName, rootModule.engineer.recipeLevel);
ship.use(ship.internal[i], internal, true);
ship.internal[i].enabled = internalJson.on === true;
ship.internal[i].priority = internalJson.priority;
@@ -299,35 +312,48 @@ export function shipFromJson(json) {
* @param {Object} modifiers the modifiers
* @param {Object} blueprint the blueprint of the modification
* @param {Object} grade the grade of the modification
* @param {Object} specialModifications special modification
*/
function _addModifications(module, modifiers, blueprint, grade) {
if (!modifiers || !modifiers.modifiers) return;
function _addModifications(module, modifiers, blueprint, grade, specialModifications) {
if (!modifiers) return;
let special;
for (const i in modifiers.modifiers) {
if (specialModifications) {
special = Modifications.specials[Object.keys(specialModifications)[0]]
}
for (const i in modifiers) {
// Some special modifications
if (modifiers.modifiers[i].name === 'mod_weapon_clip_size_override') {
if (modifiers[i].name === 'mod_weapon_clip_size_override') {
// This is a numeric addition to the clip size, but we need to work it out in terms of being a percentage so
// that it works the same as other modifications
const origClip = module.clip || 1;
module.setModValue('clip', ((modifiers.modifiers[i].value - origClip) / origClip) * 10000);
} else if (modifiers.modifiers[i].name === 'mod_weapon_burst_size') {
module.setModValue('clip', ((modifiers[i].value - origClip) / origClip) * 10000);
} else if (modifiers[i].name === 'mod_weapon_burst_size') {
// This is an absolute number that acts as an override
module.setModValue('burst', modifiers.modifiers[i].value * 100);
} else if (modifiers.modifiers[i].name === 'mod_weapon_burst_rof') {
module.setModValue('burst', modifiers[i].value * 100);
} else if (modifiers[i].name === 'mod_weapon_burst_rof') {
// This is an absolute number that acts as an override
module.setModValue('burstrof', modifiers.modifiers[i].value * 100);
} else if (modifiers.modifiers[i].name === 'mod_weapon_falloffrange_from_range') {
module.setModValue('burstrof', modifiers[i].value * 100);
} else if (modifiers[i].name === 'mod_weapon_falloffrange_from_range') {
// Obtain the falloff value directly from the range
module.setModValue('fallofffromrange', 1);
} else if (modifiers.modifiers[i].name && modifiers.modifiers[i].name.startsWith('special_')) {
} else if (modifiers[i].name && modifiers[i].name.startsWith('special_')) {
// We don't add special effects directly, but keep a note of them so they can be added when fetching values
special = Modifications.specials[modifiers.modifiers[i].name];
special = Modifications.specials[modifiers[i].name];
} else {
// Look up the modifiers to find what we need to do
const modifierActions = Modifications.modifierActions[modifiers.modifiers[i].name];
const value = modifiers.modifiers[i].value;
const modifierActions = Modifications.modifierActions[i];
let value;
if (i === 'OutfittingFieldType_DefenceModifierShieldMultiplier') {
value = modifiers[i].value - 1;
} else if (i === 'OutfittingFieldType_DefenceModifierHealthMultiplier' && blueprint.startsWith('Armour_')) {
value = (modifiers[i].value - module.hullboost) / module.hullboost;
} else if (i === 'OutfittingFieldType_DefenceModifierHealthMultiplier') {
value = modifiers[i].value / module.hullboost;
} else if (i === 'OutfittingFieldType_RateOfFire') {
value = (1 / Math.abs(modifiers[i].value));
} else {
value = modifiers[i].value - 1;
}
// Carry out the required changes
for (const action in modifierActions) {
if (isNaN(modifierActions[action])) {
@@ -354,7 +380,7 @@ function _addModifications(module, modifiers, blueprint, grade) {
module.blueprint.special = special;
}
}
// Need to fix up a few items
// Shield boosters are treated internally as straight modifiers, so rather than (for example)
@@ -377,7 +403,7 @@ function _addModifications(module, modifiers, blueprint, grade) {
module.setModValue('thermres', ((module.getModValue('thermres') / 10000) * -1) * 10000);
}
}
// Shield generator resistance is actually a damage modifier, so needs to be inverted.
// In addition, the modification is based off the inherent resistance of the module
if (ModuleUtils.isShieldGenerator(module.grp)) {
@@ -405,7 +431,7 @@ function _addModifications(module, modifiers, blueprint, grade) {
module.setModValue('thermres', ((1 - (1 - module.thermres) * (1 + module.getModValue('thermres') / 10000)) - module.thermres) * 10000);
}
}
// Bulkhead resistance is actually a damage modifier, so needs to be inverted.
// In addition, the modification is based off the inherent resistance of the module
if (module.grp == 'bh') {
@@ -423,7 +449,7 @@ function _addModifications(module, modifiers, blueprint, grade) {
// Bulkhead boost is based off the inherent boost of the module
if (module.grp == 'bh') {
const alteredBoost = (1 + module.hullboost) * (1 + module.getModValue('hullboost') / 10000) - 1;
module.setModValue('hullboost', (alteredBoost / module.hullboost - 1) * 10000);
module.setModValue('hullboost', (alteredBoost / module.hullboost - 1) * 1000);
}
// Jitter is an absolute number, so we need to divide it by 100
@@ -431,11 +457,6 @@ function _addModifications(module, modifiers, blueprint, grade) {
module.setModValue('jitter', module.getModValue('jitter') / 100);
}
// FD uses interval between bursts internally, so we need to translate this to a real rate of fire
if (module.getModValue('rof')) {
module.setModValue('rof', ((1 / (1 + module.getModValue('rof') / 10000)) - 1) * 10000);
}
// Clip size is rounded up so that the result is a whole number
if (module.getModValue('clip')) {
const individual = 1 / (module.clip || 1);

View File

@@ -0,0 +1,292 @@
import Ship from '../shipyard/Ship'
import { HARDPOINT_NUM_TO_CLASS, shipModelFromJson } from './CompanionApiUtils'
import { Ships } from 'coriolis-data/dist'
import Module from '../shipyard/Module'
import { Modules } from 'coriolis-data/dist'
import { Modifications } from 'coriolis-data/dist'
import { getBlueprint } from './BlueprintFunctions'
/**
* Obtain a module given its FD Name
* @param {string} fdname the FD Name of the module
* @return {Module} the module
*/
function _moduleFromFdName (fdname) {
if (!fdname) return null
fdname = fdname.toLowerCase()
// Check standard modules
for (const grp in Modules.standard) {
if (Modules.standard.hasOwnProperty(grp)) {
for (const i in Modules.standard[grp]) {
if (Modules.standard[grp][i].symbol && Modules.standard[grp][i].symbol.toLowerCase() === fdname) {
// Found it
return new Module({template: Modules.standard[grp][i]})
}
}
}
}
// Check hardpoint modules
for (const grp in Modules.hardpoints) {
if (Modules.hardpoints.hasOwnProperty(grp)) {
for (const i in Modules.hardpoints[grp]) {
if (Modules.hardpoints[grp][i].symbol && Modules.hardpoints[grp][i].symbol.toLowerCase() === fdname) {
// Found it
return new Module({template: Modules.hardpoints[grp][i]})
}
}
}
}
// Check internal modules
for (const grp in Modules.internal) {
if (Modules.internal.hasOwnProperty(grp)) {
for (const i in Modules.internal[grp]) {
if (Modules.internal[grp][i].symbol && Modules.internal[grp][i].symbol.toLowerCase() === fdname) {
// Found it
return new Module({template: Modules.internal[grp][i]})
}
}
}
}
// Not found
return null
}
/**
* Build a ship from the journal Loadout event JSON
* @param {object} json the Loadout event JSON
* @return {Ship} the built ship
*/
export function shipFromLoadoutJSON (json) {
// Start off building a basic ship
const shipModel = shipModelFromJson(json)
if (!shipModel) {
throw 'No such ship found: "' + json.Ship + '"'
}
const shipTemplate = Ships[shipModel]
let ship = new Ship(shipModel, shipTemplate.properties, shipTemplate.slots)
ship.buildWith(null)
// Initial Ship building, don't do engineering yet.
let opts = [];
for (const module of json.Modules) {
switch (module.Slot.toLowerCase()) {
// Cargo Hatch.
case 'cargohatch':
ship.cargoHatch.enabled = module.On
ship.cargoHatch.priority = module.Priority
break
// Add the bulkheads
case 'armour':
if (module.Item.toLowerCase().endsWith('_armour_grade1')) {
ship.useBulkhead(0, true)
} else if (module.Item.toLowerCase().endsWith('_armour_grade2')) {
ship.useBulkhead(1, true)
} else if (module.Item.toLowerCase().endsWith('_armour_grade3')) {
ship.useBulkhead(2, true)
} else if (module.Item.toLowerCase().endsWith('_armour_mirrored')) {
ship.useBulkhead(3, true)
} else if (module.Item.toLowerCase().endsWith('_armour_reactive')) {
ship.useBulkhead(4, true)
} else {
throw 'Unknown bulkheads "' + module.Item + '"'
}
ship.bulkheads.enabled = true
if (module.Engineering) _addModifications(ship.bulkheads.m, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level)
break
case 'powerplant':
const powerplant = _moduleFromFdName(module.Item)
ship.use(ship.standard[0], powerplant, true)
ship.standard[0].enabled = module.On
ship.standard[0].priority = module.Priority
if (module.Engineering) _addModifications(powerplant, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level)
break
case 'mainengines':
const thrusters = _moduleFromFdName(module.Item)
ship.use(ship.standard[1], thrusters, true)
ship.standard[1].enabled = module.On
ship.standard[1].priority = module.Priority
if (module.Engineering) _addModifications(thrusters, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level)
break
case 'frameshiftdrive':
const frameshiftdrive = _moduleFromFdName(module.Item)
ship.use(ship.standard[2], frameshiftdrive, true)
ship.standard[2].enabled = module.On
ship.standard[2].priority = module.Priority
if (module.Engineering) _addModifications(frameshiftdrive, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level)
break
case 'lifesupport':
const lifesupport = _moduleFromFdName(module.Item)
ship.use(ship.standard[3], lifesupport, true)
ship.standard[3].enabled = module.On === true
ship.standard[3].priority = module.Priority
if (module.Engineering) _addModifications(lifesupport, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level)
break
case 'powerdistributor':
const powerdistributor = _moduleFromFdName(module.Item)
ship.use(ship.standard[4], powerdistributor, true)
ship.standard[4].enabled = module.On
ship.standard[4].priority = module.Priority
if (module.Engineering) _addModifications(powerdistributor, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level)
break
case 'radar':
const sensors = _moduleFromFdName(module.Item)
ship.use(ship.standard[5], sensors, true)
ship.standard[5].enabled = module.On
ship.standard[5].priority = module.Priority
if (module.Engineering) _addModifications(sensors, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level)
break
case 'fueltank':
const fueltank = _moduleFromFdName(module.Item)
ship.use(ship.standard[6], fueltank, true)
ship.standard[6].enabled = true
ship.standard[6].priority = 0
break
default:
}
for (const module of json.Modules) {
if (module.Slot.toLowerCase().search(/hardpoint/) !== -1) {
// Add hardpoints
let hardpoint;
let hardpointClassNum = -1
let hardpointSlotNum = -1
let hardpointArrayNum = 0
for (let i in shipTemplate.slots.hardpoints) {
if (shipTemplate.slots.hardpoints[i] === hardpointClassNum) {
// Another slot of the same class
hardpointSlotNum++
} else {
// The first slot of a new class
hardpointClassNum = shipTemplate.slots.hardpoints[i]
hardpointSlotNum = 1
}
// Now that we know what we're looking for, find it
const hardpointName = HARDPOINT_NUM_TO_CLASS[hardpointClassNum] + 'Hardpoint' + hardpointSlotNum
const hardpointSlot = json.Modules.find(elem => elem.Slot.toLowerCase() === hardpointName.toLowerCase())
if (!hardpointSlot) {
// This can happen with old imports that don't contain new hardpoints
} else if (!hardpointSlot) {
// No module
} else {
hardpoint = _moduleFromFdName(hardpointSlot.Item)
ship.use(ship.hardpoints[hardpointArrayNum], hardpoint, true)
ship.hardpoints[hardpointArrayNum].enabled = hardpointSlot.On
ship.hardpoints[hardpointArrayNum].priority = hardpointSlot.Priority
opts.push({coriolisMod: hardpoint, json: hardpointSlot});
}
hardpointArrayNum++
}
}
if (module.Slot.toLowerCase().search(/slot\d/) !== -1) {
let internalSlotNum = 1
let militarySlotNum = 1
for (let i in shipTemplate.slots.internal) {
const isMilitary = isNaN(shipTemplate.slots.internal[i]) ? shipTemplate.slots.internal[i].name = 'military' : false
// The internal slot might be a standard or a military slot. Military slots have a different naming system
let internalSlot = null
if (isMilitary) {
const internalName = 'Military0' + militarySlotNum
internalSlot = json.Modules.find(elem => elem.Slot.toLowerCase() === internalName.toLowerCase())
militarySlotNum++
} else {
// Slot numbers are not contiguous so handle skips.
while (internalSlot === null && internalSlotNum < 99) {
// Slot sizes have no relationship to the actual size, either, so check all possibilities
for (let slotsize = 0; slotsize < 9; slotsize++) {
const internalName = 'Slot' + (internalSlotNum <= 9 ? '0' : '') + internalSlotNum + '_Size' + slotsize
if (json.Modules.find(elem => elem.Slot.toLowerCase() === internalName.toLowerCase())) {
internalSlot = json.Modules.find(elem => elem.Slot.toLowerCase() === internalName.toLowerCase());
break
}
}
internalSlotNum++
}
}
if (!internalSlot) {
// This can happen with old imports that don't contain new slots
} else if (!internalSlot) {
// No module
} else {
const internalJson = internalSlot
const internal = _moduleFromFdName(internalJson.Item)
ship.use(ship.internal[i], internal, true)
ship.internal[i].enabled = internalJson.On === true
ship.internal[i].priority = internalJson.Priority
opts.push({coriolisMod: internal, json: internalSlot});
}
}
}
}
}
for (const i of opts) {
if (i.json.Engineering) _addModifications(i.coriolisMod, i.json.Engineering.Modifiers, i.json.Engineering.BlueprintName, i.json.Engineering.Level, i.json.Engineering.ExperimentalEffect)
}
// We don't have any information on it so guess it's priority 5 and disabled
if (!ship.cargoHatch) {
ship.cargoHatch.enabled = false
ship.cargoHatch.priority = 4
}
console.log(ship)
// Now update the ship's codes before returning it
return ship.updatePowerPrioritesString().updatePowerEnabledString().updateModificationsString()
}
/**
* Add the modifications for a module
* @param {Module} module the module
* @param {Object} modifiers the modifiers
* @param {Object} blueprint the blueprint of the modification
* @param {Object} grade the grade of the modification
* @param {Object} specialModifications special modification
*/
function _addModifications (module, modifiers, blueprint, grade, specialModifications) {
if (!modifiers) return
let special
if (specialModifications) {
special = Modifications.specials[specialModifications]
}
for (const i in modifiers) {
// Some special modifications
// Look up the modifiers to find what we need to do
const findMod = val => Object.keys(Modifications.modifierActions).find(elem => elem.toString().toLowerCase().search(val.toString().toLowerCase().replace(/(OutfittingFieldType_|persecond)/igm, '')) >= 0)
const modifierActions = Modifications.modifierActions[findMod(modifiers[i].Label)]
//TODO: Figure out how to scale this value.
if (!!modifiers[i].LessIsGood) {
}
let value = (modifiers[i].Value / modifiers[i].OriginalValue * 100 - 100) * 100;
if (value === Infinity) {
value = modifiers[i].Value * 100;
}
if (modifiers[i].Label.search('Resistance') >= 0) {
value = (modifiers[i].Value * 100) - (modifiers[i].OriginalValue * 100)
}
// Carry out the required changes
for (const action in modifierActions) {
if (isNaN(modifierActions[action])) {
module.setModValue(action, modifierActions[action])
} else {
module.setModValue(action, value)
}
}
}
// Add the blueprint definition, grade and special
if (blueprint) {
module.blueprint = getBlueprint(blueprint, module)
if (grade) {
module.blueprint.grade = Number(grade)
}
if (special) {
module.blueprint.special = special
}
}
}

View File

@@ -220,7 +220,7 @@ export function diffDetails(language, m, mm) {
let mCost = m.cost || 0;
let mmCost = mm ? mm.cost : 0;
if (mCost != mmCost) propDiffs.push(<div key='cost'>{translate('cost')}: <span className={diffClass(mCost, mmCost, true) }>{mCost ? Math.round(mCost * (1 - Persist.getModuleDiscount())) : 0}{units.CR}</span></div>);
if (mCost != mmCost) propDiffs.push(<div key='cost'>{translate('cost')}: <span className={diffClass(mCost, mmCost, true) }>{formats.int(mCost ? Math.round(mCost * (1 - Persist.getModuleDiscount())) : 0)}{units.CR}</span></div>);
let mMass = m.mass || 0;
let mmMass = mm ? mm.getMass() : 0;

6
src/images/Empire.svg Normal file
View File

@@ -0,0 +1,6 @@
<svg width="1718.2px" height="999.8px" viewBox="0 0 1718.2 999.8" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs/>
<g>
<path stroke="none" fill="#FF8C0D" d="M1717.55 -0.05 L1717.65 -0.25 1718.2 -0.1 1718.6 0.35 1719.2 1.55 1719.3 2.25 1718.95 2.85 1709.75 11.35 1010.8 687.7 1008.05 690.5 1005.45 693.4 1003 696.35 1000.75 699.45 998.65 702.65 996.7 705.95 994.9 709.4 993.25 713.05 934.9 850.7 876.4 988.25 871.55 998.95 871.3 999.3 870.9 999.5 870.6 999.55 870 999.4 869.5 999.05 868.3 997.95 867.35 996.7 866.6 995.25 864.7 989.85 762.3 730.55 754.8 711.85 751.1 702.45 746.6 690.65 745.5 688.4 744.25 686.3 742.9 684.35 741.4 682.45 739.75 680.6 737.95 678.85 736 677.15 8.1 61.2 5.75 59.15 3.65 57.1 1.6 54.6 1.1 53.7 1.1 53.25 1.25 52.9 1.5 52.65 1.8 52.45 2.15 52.4 2.55 52.5 9.75 55.7 713.05 398.5 780.95 431.7 848.75 464.95 851.7 466.25 854.4 467.15 856.95 467.6 859.45 467.65 861.9 467.25 864.4 466.45 866.95 465.2 869.6 463.5 1416.95 79.15 1419.7 77.35 1422.45 75.7 1425.25 74.2 1428.1 72.85 1431 71.6 1434 70.5 1437.05 69.55 1440.2 68.7 1574.85 35.15 1709.5 1.5 1713.75 0.6 1717.55 -0.05 M903.9 129.8 L904 129.65 930.9 129.75 934.3 129.85 937.55 130.15 940.65 130.65 943.6 131.35 946.4 132.2 949.2 133.3 951.95 134.6 954.55 136.05 957 137.7 959.35 139.5 961.6 141.5 963.75 143.65 965.8 145.95 967.75 148.4 969.6 151 971.35 153.8 974.25 159 976.8 164.3 979.05 169.7 981 175.2 982.7 180.8 984.2 186.45 985.55 192.15 986.75 197.9 987.85 203.75 988.8 209.65 990.4 221.45 991.6 233.25 992.55 245.1 995 280.65 996 292.5 996.2 295.1 996.25 297.55 996.15 299.85 995.9 302 995.5 304.1 994.95 306.1 994.25 308 993.45 309.7 992.4 311.5 991.25 313.15 989.95 314.75 988.45 316.3 986.8 317.8 985 319.25 980.85 322.15 946.35 344.45 912.05 367.15 843.7 413.05 841.45 414.45 839.25 415.55 836.9 416.35 834.85 416.75 832.6 416.85 830.15 416.5 827.75 415.8 825.25 414.7 812.45 408.55 799.4 402.55 773.35 390.75 773 390.5 772.8 390.15 772.75 389.75 772.85 389.35 794.5 343.45 801.35 328.15 811 305.8 820.45 283.4 839 238.45 841 233 842.7 227.35 844.1 221.65 845.25 215.95 845.7 213.05 845.8 210.65 845.55 208.55 845.3 207.75 844.9 206.9 843.85 205.55 842.3 204.4 840.2 203.4 837.55 202.55 830.2 200.55 822.85 198.85 819.15 198.15 815.5 197.6 811.85 197.2 808.2 196.95 804.55 196.9 800.9 197.05 797.25 197.4 793.6 198 789.9 198.9 786.25 200.05 782.6 201.55 778.55 203.5 777 203.65 776.65 203.6 776.1 203.15 775.95 202.8 775.5 200.55 775.25 197.65 775.3 194.75 775.65 191.9 776.25 189.05 777.05 186.3 778 183.6 779.05 180.9 780.5 177.65 782.1 174.5 783.8 171.5 785.65 168.6 787.6 165.85 789.7 163.2 791.9 160.7 794.25 158.3 796.7 156 799.3 153.85 802 151.8 804.8 149.9 807.7 148.1 810.75 146.4 813.9 144.85 817.15 143.4 824.4 140.6 831.75 138.2 839.15 136.15 846.65 134.45 854.2 133.05 861.8 131.95 869.45 131.1 877.1 130.5 883.8 130.15 890.5 129.95 903.9 129.8"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 30 KiB

View File

@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="631.072px" height="713.591px" viewBox="0 0 631.072 713.591" enable-background="new 0 0 631.072 713.591"
xml:space="preserve">
<g id="Layer_2">
<g>
<rect x="460.344" y="668.509" transform="matrix(0.7399 0.6727 -0.6727 0.7399 586.8318 -155.8918)" fill="#FF8C0D" width="69.376" height="24.999"/>
</g>
<g>
<rect x="499.816" y="630.511" transform="matrix(0.8742 0.4856 -0.4856 0.8742 379.9255 -180.1477)" fill="#FF8C0D" width="75.501" height="24.999"/>
</g>
<g>
<rect x="537.078" y="590.363" transform="matrix(0.9477 0.319 -0.319 0.9477 222.2531 -151.1744)" fill="#FF8C0D" width="71.047" height="25"/>
</g>
<g>
<rect x="561.364" y="544.916" transform="matrix(0.9741 0.2263 -0.2263 0.9741 141.5892 -120.2454)" fill="#FF8C0D" width="67.758" height="25"/>
</g>
<g>
<rect x="113.454" y="633.977" transform="matrix(0.6727 0.7399 -0.7399 0.6727 536.0002 125.674)" fill="#FF8C0D" width="24.999" height="69.375"/>
</g>
<g>
<rect x="72.787" y="594.581" transform="matrix(0.4857 0.8741 -0.8741 0.4857 596.6155 250.6765)" fill="#FF8C0D" width="25" height="75.501"/>
</g>
<g>
<rect x="43.454" y="554.475" transform="matrix(0.319 0.9477 -0.9477 0.319 597.2715 348.7429)" fill="#FF8C0D" width="25" height="71.046"/>
</g>
<g>
<rect x="23.329" y="507.12" transform="matrix(0.2263 0.9741 -0.9741 0.2263 554.6862 383.6775)" fill="#FF8C0D" width="25" height="67.758"/>
</g>
<path fill="#FF8C0D" d="M556.439,425.748c-13.466-24.188-32.583-45.79-56.821-64.205c-30.562-23.22-67.327-39.855-107.331-48.986
v25.737c93.31,23.32,160.681,90.053,160.681,168.752c0,98.096-104.668,177.619-233.785,177.619
c-129.115,0-233.784-79.523-233.784-177.619c0-75.918,62.696-140.699,150.889-166.118v-25.964
c-36.209,9.508-69.489,25.266-97.539,46.578c-24.238,18.415-43.355,40.017-56.821,64.205
c-14.286,25.66-21.529,53.014-21.529,81.299c0,28.284,7.243,55.637,21.529,81.298c13.465,24.188,32.583,45.789,56.821,64.204
c48.479,36.832,112.559,57.117,180.435,57.117c67.876,0,131.956-20.285,180.436-57.117c24.238-18.415,43.355-40.017,56.821-64.204
c14.285-25.661,21.528-53.014,21.528-81.298C577.968,478.761,570.725,451.408,556.439,425.748z"/>
<path fill="#FF8C0D" d="M473.97,427.082c-8.958-16.091-21.621-30.42-37.64-42.591c-13.129-9.975-27.996-18.079-44.043-24.152
v27.053c42.591,19.056,71.178,54.248,71.178,94.519c0,60.541-64.597,109.619-144.282,109.619
c-79.684,0-144.281-49.078-144.281-109.619c0-37.101,24.263-69.892,61.386-89.727v-27.819c-12.323,5.48-23.835,12.212-34.25,20.125
c-16.019,12.171-28.683,26.5-37.64,42.591c-9.618,17.276-14.495,35.724-14.495,54.829c0,19.104,4.877,37.552,14.495,54.829
c8.958,16.091,21.622,30.42,37.64,42.59c31.574,23.989,73.178,37.2,117.146,37.2c43.969,0,85.572-13.211,117.147-37.2
c16.019-12.17,28.682-26.499,37.64-42.59c9.618-17.277,14.495-35.725,14.495-54.829
C488.465,462.805,483.588,444.358,473.97,427.082z"/>
</g>
<g id="Layer_3">
<path fill="#FF8C0D" d="M253.551,232.333c-0.157-0.981-0.264-1.978-0.264-3c0-10.844,9.173-19.667,20.448-19.667
s20.448,8.822,20.448,19.667c0,1.022-0.106,2.019-0.264,3h25.15c0.067-0.993,0.113-1.991,0.113-3
c0-24.668-20.348-44.667-45.448-44.667s-45.448,19.998-45.448,44.667c0,1.009,0.046,2.007,0.113,3H253.551z"/>
<path fill="#FF8C0D" d="M302.831,48c-0.136-0.669-0.21-1.337-0.21-2c0-9.913,15.539-21,36.333-21s36.333,11.087,36.333,21
c0,0.663-0.074,1.331-0.21,2h25.143c0.038-0.664,0.067-1.329,0.067-2c0-25.405-27.46-46-61.333-46
c-33.874,0-61.333,20.595-61.333,46c0,0.671,0.03,1.336,0.067,2H302.831z"/>
<ellipse fill="#FF8C0D" cx="338.954" cy="68.499" rx="36.333" ry="6.75"/>
<path fill="#FF8C0D" d="M375.287,46c0,2.208-16.267,3.999-36.333,3.999S302.621,48.208,302.621,46h-25v158.499h25v-136h72.667
V473.51c-4.165,3.092-16.463,8.535-36.333,8.535c-7.763,0-14.353-0.836-19.771-2.033l-10.749,23.051
c8.99,2.529,19.405,3.982,30.52,3.982c33.873,0,61.333-13.432,61.333-30V46H375.287z"/>
<ellipse fill="#FF8C0D" cx="273.735" cy="253.132" rx="20.448" ry="3.916"/>
<path fill="#FF8C0D" d="M294.184,229.333c0,1.151-9.155,2.084-20.448,2.084s-20.448-0.933-20.448-2.084h-25v257.666h0.128
c1.667,14.529,21.313,26,45.32,26s43.653-11.471,45.32-26h0.128V229.333H294.184z M294.184,254.333v228.201
c-2.473,2.008-9.464,5.465-20.448,5.465s-17.975-3.456-20.448-5.465V253.132h40.896V254.333z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

@@ -55,10 +55,12 @@
<!-- End Piwik Code -->
<!-- Bugsnag -->
<script
src="//d2wy8f7a9ursnm.cloudfront.net/bugsnag-3.min.js"
data-apikey="2382691c622937f28f8fa82a1bfd797a"></script>
<script src="//d2wy8f7a9ursnm.cloudfront.net/v4/bugsnag.min.js"></script>
<script src="//d2wy8f7a9ursnm.cloudfront.net/bugsnag-plugins/v1/bugsnag-react.min.js"></script>
<script>
window.bugsnagClient = bugsnag('ba9fae819372850fb660755341fa6ef5', {appVersion: window.CORIOLIS_VERSION || undefined})
window.Bugsnag = window.bugsnagClient
</script>
</head>
<body style="background-color:#000;">
<section id="coriolis"></section>

View File

@@ -31,6 +31,50 @@ button {
}
}
.button-inline-menu {
white-space: nowrap;
line-height: 1.5em;
text-align: center;
margin: 0.5em 0;
padding-left: 5px;
border-top: 1px solid @primary-disabled;
border-bottom: 1px solid @primary-disabled;
overflow: hidden;
text-overflow: ellipsis;
background: @primary-bg;
&.warning {
border-color: @warning-disabled;
color: @warning-disabled;
stroke: @warning-disabled;
.no-touch &:hover {
border-color: @warning;
color: @warning;
stroke: @warning;
}
}
&.disabled, &.disabled:hover {
cursor: not-allowed;
border-color: @disabled;
color: @disabled;
stroke: @disabled;
}
&.active {
border-color: @secondary;
color: @secondary;
stroke: @secondary;
}
&:hover {
border-color: @primary;
color: @primary;
stroke: @primary;
}
}
.button-lbl {
margin-left: 0.5em;

View File

@@ -18,6 +18,7 @@
@bg: rgba(30,30,30,1);
@bgBlack: #000;
@primary-bg: fadeout(darken(@primary, 47%), 15%);
@alt-primary-bg: fadeout(darken(@primary, 42%), 15%); // Lighter brown background
@secondary-bg: fadeout(darken(@secondary, @bgDarken), @bgTransparency); // Brown background
@warning-bg: fadeout(darken(@warning, @bgDarken), @bgTransparency); // Dark Red

View File

@@ -54,6 +54,7 @@ textarea {
width:100%;
min-height: 10em;
resize: vertical;
user-select: auto;
margin:2em 0;
}
}

View File

@@ -21,13 +21,47 @@
#overview {
h1 {
margin: 0;
margin: 0 1em 0.2em 0;
float: left;
}
overflow: hidden;
margin: 0.5em;
}
#requirements {
margin: 0;
float: left;
text-align: left;
div {
display: inline-block;
margin: 0 1em 0.5em 0;
height: 1.6em;
line-height: 1.6em;
text-align: left;
vertical-align: middle;
cursor: default;
background-repeat: no-repeat;
background-position: left center;
background-size: contain;
}
.federation {
background-image: url('../images/Federation.svg');
padding-left: 1.985em + 0.5em;
}
.empire {
background-image: url('../images/Empire.svg');
padding-left: 2.750em + 0.5em;
}
.horizons {
background-image: url('../images/surface_port_pm.svg');
padding-left: 1.415em + 0.5em;
}
}
#summary {
overflow-x: auto;
-webkit-overflow-scrolling: touch;

View File

@@ -54,6 +54,10 @@ tbody tr {
.no-touch &.highlight:hover, .no-touch &.highlighted {
background-color: @warning-bg;
}
&.alt {
background-color: @alt-primary-bg;
}
}
td {

View File

@@ -1,28 +1,30 @@
var path = require('path');
var exec = require('child_process').exec;
var webpack = require('webpack');
var pkgJson = require('./package');
var HtmlWebpackPlugin = require("html-webpack-plugin");
var ExtractTextPlugin = require("extract-text-webpack-plugin");
const path = require('path')
const exec = require('child_process').exec
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const WebpackNotifierPlugin = require('webpack-notifier')
const pkgJson = require('./package')
function CopyDirPlugin(source, destination) {
this.source = source;
this.destination = destination;
this.source = source
this.destination = destination
}
CopyDirPlugin.prototype.apply = function (compiler) {
compiler.plugin('done', () => {
console.log(compiler.outputPath, this.destination)
exec('cp -r ' + this.source + ' ' + path.join(compiler.outputPath, this.destination))
})
}
CopyDirPlugin.prototype.apply = function(compiler) {
compiler.plugin('done', function() {
console.log(compiler.outputPath, this.destination);
exec('cp -r ' + this.source + ' ' + path.join(compiler.outputPath, this.destination));
}.bind(this));
};
module.exports = {
devtool: 'eval',
devtool: 'source-map',
devServer: {
headers: { "Access-Control-Allow-Origin": "*" }
headers: {'Access-Control-Allow-Origin': '*'}
},
entry: {
app: [ 'webpack-dev-server/client?http://0.0.0.0:3300', 'webpack/hot/only-dev-server', path.join(__dirname, "src/app/index.js") ],
app: ['webpack-dev-server/client?http://0.0.0.0:3300', 'webpack/hot/only-dev-server', path.join(__dirname, 'src/app/index.js')],
lib: ['d3', 'react', 'react-dom', 'classnames', 'fbemitter', 'lz-string']
},
resolve: {
@@ -37,33 +39,34 @@ module.exports = {
plugins: [
new CopyDirPlugin(path.join(__dirname, 'src/.htaccess'), ''),
new webpack.optimize.CommonsChunkPlugin({
name: 'lib',
filename: 'lib.js'
name: 'lib',
filename: 'lib.js'
}),
new HtmlWebpackPlugin({
inject: false,
template: path.join(__dirname, "src/index.ejs"),
version: pkgJson.version,
gapiKey: process.env.CORIOLIS_GAPI_KEY || '',
inject: false,
template: path.join(__dirname, 'src/index.ejs'),
version: pkgJson.version,
gapiKey: process.env.CORIOLIS_GAPI_KEY || ''
}),
new ExtractTextPlugin({
filename: 'app.css',
disable: false,
allChunks: true
filename: 'app.css',
disable: false,
allChunks: true
}),
new WebpackNotifierPlugin({alwaysNotify: true}),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin()
],
module: {
rules: [
{ test: /\.css$/, loader: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader'}) },
{ test: /\.less$/, loader: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader!less-loader'}) },
{ test: /\.(js|jsx)$/, loaders: [ 'babel-loader' ], include: path.join(__dirname, 'src') },
{ test: /\.woff(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=application/font-woff' },
{ test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=application/font-woff' },
{ test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=application/octet-stream' },
{ test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: 'file-loader' },
{ test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=image/svg+xml' }
{test: /\.css$/, loader: ExtractTextPlugin.extract({fallback: 'style-loader', use: 'css-loader'})},
{test: /\.less$/, loader: ExtractTextPlugin.extract({fallback: 'style-loader', use: 'css-loader!less-loader'})},
{test: /\.(js|jsx)$/, loaders: ['babel-loader'], include: path.join(__dirname, 'src')},
{test: /\.woff(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=application/font-woff'},
{test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=application/font-woff'},
{test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=application/octet-stream'},
{test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: 'file-loader'},
{test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=image/svg+xml'}
]
}
};
}

View File

@@ -1,24 +1,27 @@
var path = require('path');
var exec = require('child_process').exec;
var webpack = require('webpack');
var pkgJson = require('./package');
var HtmlWebpackPlugin = require("html-webpack-plugin");
var ExtractTextPlugin = require("extract-text-webpack-plugin");
var AppCachePlugin = require('appcache-webpack-plugin');
const path = require('path')
const exec = require('child_process').exec
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const AppCachePlugin = require('appcache-webpack-plugin')
const {BugsnagSourceMapUploaderPlugin} = require('webpack-bugsnag-plugins')
const pkgJson = require('./package')
function CopyDirPlugin(source, destination) {
this.source = source;
this.destination = destination;
function CopyDirPlugin (source, destination) {
this.source = source
this.destination = destination
}
CopyDirPlugin.prototype.apply = function (compiler) {
compiler.plugin('done', () => {
console.log(compiler.outputPath, this.destination)
exec('cp -r ' + this.source + ' ' + path.join(compiler.outputPath, this.destination))
})
}
CopyDirPlugin.prototype.apply = function(compiler) {
compiler.plugin('done', function() {
console.log(compiler.outputPath, this.destination);
exec('cp -r ' + this.source + ' ' + path.join(compiler.outputPath, this.destination));
}.bind(this));
};
module.exports = {
cache: true,
devtool: 'source-map',
entry: {
app: ['babel-polyfill', path.resolve(__dirname, 'src/app/index')],
lib: ['d3', 'react', 'react-dom', 'classnames', 'fbemitter', 'lz-string']
@@ -34,34 +37,39 @@ module.exports = {
},
plugins: [
new webpack.optimize.UglifyJsPlugin({
'screw-ie8': true
'screw-ie8': true,
sourceMap: true
}),
//new webpack.optimize.CommonsChunkPlugin({
// name: 'lib',
// filename: 'lib.[chunkhash:6].js'
//}),
new HtmlWebpackPlugin({
inject: false,
appCache: 'coriolis.appcache',
minify: {
collapseBooleanAttributes: true,
collapseWhitespace: true,
removeAttributeQuotes: true,
removeComments: true,
removeEmptyAttributes: true,
removeRedundantAttributes: true,
removeScriptTypeAttributes: true,
removeStyleLinkTypeAttributes: true
},
template: path.join(__dirname, "src/index.ejs"),
uaTracking: process.env.CORIOLIS_UA_TRACKING || '',
gapiKey: process.env.CORIOLIS_GAPI_KEY || '',
version: pkgJson.version
inject: false,
appCache: 'coriolis.appcache',
minify: {
collapseBooleanAttributes: true,
collapseWhitespace: true,
removeAttributeQuotes: true,
removeComments: true,
removeEmptyAttributes: true,
removeRedundantAttributes: true,
removeScriptTypeAttributes: true,
removeStyleLinkTypeAttributes: true
},
template: path.join(__dirname, 'src/index.ejs'),
uaTracking: process.env.CORIOLIS_UA_TRACKING || '',
gapiKey: process.env.CORIOLIS_GAPI_KEY || '',
version: pkgJson.version
}),
new ExtractTextPlugin({
filename: '[contenthash:6].css',
disable: false,
allChunks: true
filename: '[contenthash:6].css',
disable: false,
allChunks: true
}),
new BugsnagSourceMapUploaderPlugin({
apiKey: 'ba9fae819372850fb660755341fa6ef5',
appVersion: pkgJson.version
}),
new CopyDirPlugin(path.join(__dirname, 'src/schemas'), 'schemas'),
new CopyDirPlugin(path.join(__dirname, 'src/images/logo/*'), ''),
@@ -75,14 +83,14 @@ module.exports = {
],
module: {
rules: [
{ test: /\.css$/, loader: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader'}) },
{ test: /\.less$/, loader: ExtractTextPlugin.extract({ fallback: 'style-loader',use: 'css-loader!less-loader'}) },
{ test: /\.(js|jsx)$/, loader: 'babel-loader?cacheDirectory=true', include: path.join(__dirname, 'src') },
{ test: /\.woff(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=application/font-woff' },
{ test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=application/font-woff' },
{ test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=application/octet-stream' },
{ test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: 'file-loader' },
{ test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=image/svg+xml' }
{test: /\.css$/, loader: ExtractTextPlugin.extract({fallback: 'style-loader', use: 'css-loader'})},
{test: /\.less$/, loader: ExtractTextPlugin.extract({fallback: 'style-loader', use: 'css-loader!less-loader'})},
{test: /\.(js|jsx)$/, loader: 'babel-loader?cacheDirectory=true', include: path.join(__dirname, 'src')},
{test: /\.woff(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=application/font-woff'},
{test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=application/font-woff'},
{test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=application/octet-stream'},
{test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: 'file-loader'},
{test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=image/svg+xml'}
]
}
};
}