diff --git a/.esdoc.json b/.esdoc.json
new file mode 100644
index 00000000..4d236594
--- /dev/null
+++ b/.esdoc.json
@@ -0,0 +1,103 @@
+{
+ "source": "./src/app",
+ "includes": ["\\.js$", "\\.jsx$"],
+ "destination": "./docs",
+ "index": "./README.md",
+ "plugins": [
+ {
+ "name": "esdoc-standard-plugin",
+ "option": {
+ "lint": {
+ "enable": false
+ },
+ "coverage": {
+ "enable": false
+ },
+ "accessor": {
+ "access": [
+ "public",
+ "protected",
+ "private"
+ ],
+ "autoPrivate": true
+ },
+ "undocumentIdentifier": {
+ "enable": true
+ },
+ "unexportedIdentifier": {
+ "enable": false
+ },
+ "typeInference": {
+ "enable": true
+ },
+ "brand": {
+ "logo": "./src/images/logo/192x192.png",
+ "title": "Coriolis",
+ "description": "Coriolis Shipyard for Elite Dangerous",
+ "repository": "https://github.com/EDCD/coriolis",
+ "site": "https://coriolis.edcd.io",
+ "author": "https://github.com/edcd",
+ "image": "./src/images/logo/192x192.png"
+ }
+ }
+ },
+ {
+ "name": "esdoc-ecmascript-proposal-plugin",
+ "option": {
+ "all": true
+ }
+ },
+ {
+ "name": "esdoc-react-plugin"
+ },
+ {
+ "name": "esdoc-standard-plugin",
+ "option": {
+ "lint": {
+ "enable": false
+ },
+ "coverage": {
+ "enable": false
+ },
+ "accessor": {
+ "access": [
+ "public",
+ "protected",
+ "private"
+ ],
+ "autoPrivate": true
+ },
+ "undocumentIdentifier": {
+ "enable": true
+ },
+ "unexportedIdentifier": {
+ "enable": false
+ },
+ "typeInference": {
+ "enable": true
+ },
+ "brand": {
+ "logo": "./src/images/logo/192x192.png",
+ "title": "Coriolis",
+ "description": "Coriolis Shipyard for Elite Dangerous",
+ "repository": "https://github.com/EDCD/coriolis",
+ "site": "https://coriolis.edcd.io",
+ "author": "https://github.com/edcd",
+ "image": "./src/images/logo/192x192.png"
+ }
+ }
+ },
+ {
+ "name": "esdoc-jsx-plugin",
+ "option": {
+ "enable": true
+ }
+ },
+ {
+ "name": "esdoc-publish-html-plugin",
+ "option": {
+ "template": "./node_modules/esdoc-custom-theme/template"
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.eslintrc b/.eslintrc
index 8e0f6cd1..d1c8bd1a 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -9,7 +9,8 @@
},
"env": {
"browser": true,
- "node": true
+ "node": true,
+ "es6": true
},
"plugins": [
"react"
diff --git a/.gitignore b/.gitignore
index 13cf3ae0..76f6c3f1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,5 @@ nginx.pid
env
*.swp
.project
+.vscode/
+docs/
\ No newline at end of file
diff --git a/README.md b/README.md
index f5a2dfb1..fd7ba711 100755
--- a/README.md
+++ b/README.md
@@ -23,6 +23,7 @@ Chat to us on [Discord](https://discord.gg/0uwCh6R62aPRjk9w)!
See the [Developer's Guide](https://github.com/EDCD/coriolis/wiki/Developing-for-Coriolis) in the wiki.
+Also see [the documentation site.](https://coriolis.willb.info/)
### Ship and Module Database
diff --git a/package-lock.json b/package-lock.json
index 7ee2b683..13b10ba3 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -136,6 +136,12 @@
}
}
},
+ "@types/node": {
+ "version": "10.5.1",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-10.5.1.tgz",
+ "integrity": "sha512-AFLl1IALIuyt6oK4AYZsgWVJ/5rnyzQWud7IebaZWWV3YmgtPZkQmYio9R5Ze/2pdd7XfqF5bP+hWS11mAKoOQ==",
+ "dev": true
+ },
"abab": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/abab/-/abab-1.0.4.tgz",
@@ -2189,6 +2195,54 @@
"supports-color": "^2.0.0"
}
},
+ "cheerio": {
+ "version": "1.0.0-rc.2",
+ "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.2.tgz",
+ "integrity": "sha1-S59TqBsn5NXawxwP/Qz6A8xoMNs=",
+ "dev": true,
+ "requires": {
+ "css-select": "~1.2.0",
+ "dom-serializer": "~0.1.0",
+ "entities": "~1.1.1",
+ "htmlparser2": "^3.9.1",
+ "lodash": "^4.15.0",
+ "parse5": "^3.0.1"
+ },
+ "dependencies": {
+ "domhandler": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz",
+ "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==",
+ "dev": true,
+ "requires": {
+ "domelementtype": "1"
+ }
+ },
+ "htmlparser2": {
+ "version": "3.9.2",
+ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz",
+ "integrity": "sha1-G9+HrMoPP55T+k/M6w9LTLsAszg=",
+ "dev": true,
+ "requires": {
+ "domelementtype": "^1.3.0",
+ "domhandler": "^2.3.0",
+ "domutils": "^1.5.1",
+ "entities": "^1.1.1",
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "parse5": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz",
+ "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==",
+ "dev": true,
+ "requires": {
+ "@types/node": "*"
+ }
+ }
+ }
+ },
"chokidar": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz",
@@ -2333,6 +2387,12 @@
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
"dev": true
},
+ "codemirror": {
+ "version": "5.39.0",
+ "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.39.0.tgz",
+ "integrity": "sha512-vpJRray/0ZCt9FiS7UcVr1JAm6OBdUt6TA/94Q7MScr8TnutVdQWh/WPr0migzaBPQmYvY7I9UZNvbsaLESIuQ==",
+ "dev": true
+ },
"color": {
"version": "0.11.4",
"resolved": "https://registry.npmjs.org/color/-/color-0.11.4.tgz",
@@ -2353,6 +2413,12 @@
"color-name": "^1.1.1"
}
},
+ "color-logger": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/color-logger/-/color-logger-0.0.6.tgz",
+ "integrity": "sha1-5WJF7ymCJlcRDHy3WpzXhstp7Rs=",
+ "dev": true
+ },
"color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
@@ -4760,6 +4826,413 @@
"estraverse": "^4.1.1"
}
},
+ "esdoc": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/esdoc/-/esdoc-1.1.0.tgz",
+ "integrity": "sha512-vsUcp52XJkOWg9m1vDYplGZN2iDzvmjDL5M/Mp8qkoDG3p2s0yIQCIjKR5wfPBaM3eV14a6zhQNYiNTCVzPnxA==",
+ "dev": true,
+ "requires": {
+ "babel-generator": "6.26.1",
+ "babel-traverse": "6.26.0",
+ "babylon": "6.18.0",
+ "cheerio": "1.0.0-rc.2",
+ "color-logger": "0.0.6",
+ "escape-html": "1.0.3",
+ "fs-extra": "5.0.0",
+ "ice-cap": "0.0.4",
+ "marked": "0.3.19",
+ "minimist": "1.2.0",
+ "taffydb": "2.7.3"
+ },
+ "dependencies": {
+ "babel-generator": {
+ "version": "6.26.1",
+ "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz",
+ "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==",
+ "dev": true,
+ "requires": {
+ "babel-messages": "^6.23.0",
+ "babel-runtime": "^6.26.0",
+ "babel-types": "^6.26.0",
+ "detect-indent": "^4.0.0",
+ "jsesc": "^1.3.0",
+ "lodash": "^4.17.4",
+ "source-map": "^0.5.7",
+ "trim-right": "^1.0.1"
+ }
+ },
+ "minimist": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+ "dev": true
+ }
+ }
+ },
+ "esdoc-accessor-plugin": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/esdoc-accessor-plugin/-/esdoc-accessor-plugin-1.0.0.tgz",
+ "integrity": "sha1-eRukhy5sQDUVznSbE0jW8Ck62es=",
+ "dev": true
+ },
+ "esdoc-brand-plugin": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/esdoc-brand-plugin/-/esdoc-brand-plugin-1.0.1.tgz",
+ "integrity": "sha512-Yv9j3M7qk5PSLmSeD6MbPsfIsEf8K43EdH8qZpE/GZwnJCRVmDPrZJ1cLDj/fPu6P35YqgcEaJK4E2NL/CKA7g==",
+ "dev": true,
+ "requires": {
+ "cheerio": "0.22.0"
+ },
+ "dependencies": {
+ "cheerio": {
+ "version": "0.22.0",
+ "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz",
+ "integrity": "sha1-qbqoYKP5tZWmuBsahocxIe06Jp4=",
+ "dev": true,
+ "requires": {
+ "css-select": "~1.2.0",
+ "dom-serializer": "~0.1.0",
+ "entities": "~1.1.1",
+ "htmlparser2": "^3.9.1",
+ "lodash.assignin": "^4.0.9",
+ "lodash.bind": "^4.1.4",
+ "lodash.defaults": "^4.0.1",
+ "lodash.filter": "^4.4.0",
+ "lodash.flatten": "^4.2.0",
+ "lodash.foreach": "^4.3.0",
+ "lodash.map": "^4.4.0",
+ "lodash.merge": "^4.4.0",
+ "lodash.pick": "^4.2.1",
+ "lodash.reduce": "^4.4.0",
+ "lodash.reject": "^4.4.0",
+ "lodash.some": "^4.4.0"
+ }
+ },
+ "domhandler": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz",
+ "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==",
+ "dev": true,
+ "requires": {
+ "domelementtype": "1"
+ }
+ },
+ "htmlparser2": {
+ "version": "3.9.2",
+ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz",
+ "integrity": "sha1-G9+HrMoPP55T+k/M6w9LTLsAszg=",
+ "dev": true,
+ "requires": {
+ "domelementtype": "^1.3.0",
+ "domhandler": "^2.3.0",
+ "domutils": "^1.5.1",
+ "entities": "^1.1.1",
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.0.2"
+ }
+ }
+ }
+ },
+ "esdoc-coverage-plugin": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/esdoc-coverage-plugin/-/esdoc-coverage-plugin-1.1.0.tgz",
+ "integrity": "sha1-OGmGnNf4eJH5cmJXh2laKZrs5Fw=",
+ "dev": true
+ },
+ "esdoc-custom-theme": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/esdoc-custom-theme/-/esdoc-custom-theme-1.4.2.tgz",
+ "integrity": "sha512-vlK7upah872gYdO6qIEDgWO2LPmq2iH2995L2YjNu2ULyR75KsFslgWjTJmqn/bHHrFiJsWKuB4NK2lIwwPDKw==",
+ "dev": true,
+ "requires": {
+ "codemirror": "^5.34.0"
+ }
+ },
+ "esdoc-ecmascript-proposal-plugin": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/esdoc-ecmascript-proposal-plugin/-/esdoc-ecmascript-proposal-plugin-1.0.0.tgz",
+ "integrity": "sha1-OQ3FZWuoooMOOdujVw15E43y/9k=",
+ "dev": true
+ },
+ "esdoc-external-ecmascript-plugin": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/esdoc-external-ecmascript-plugin/-/esdoc-external-ecmascript-plugin-1.0.0.tgz",
+ "integrity": "sha1-ePVl1KDFGFrGMVJhTc4f4ahmiNs=",
+ "dev": true,
+ "requires": {
+ "fs-extra": "1.0.0"
+ },
+ "dependencies": {
+ "fs-extra": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz",
+ "integrity": "sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "jsonfile": "^2.1.0",
+ "klaw": "^1.0.0"
+ }
+ },
+ "jsonfile": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
+ "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.6"
+ }
+ }
+ }
+ },
+ "esdoc-integrate-manual-plugin": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/esdoc-integrate-manual-plugin/-/esdoc-integrate-manual-plugin-1.0.0.tgz",
+ "integrity": "sha1-GFSmqhwIEDXXyMUeO91PtlqkcRw=",
+ "dev": true
+ },
+ "esdoc-integrate-test-plugin": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/esdoc-integrate-test-plugin/-/esdoc-integrate-test-plugin-1.0.0.tgz",
+ "integrity": "sha1-4tDQAJD38MNeXS8sAzMnp55T5Ak=",
+ "dev": true
+ },
+ "esdoc-jsx-plugin": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/esdoc-jsx-plugin/-/esdoc-jsx-plugin-1.0.0.tgz",
+ "integrity": "sha1-k37119LeWhfdIP90ZL5CWaeGQdE=",
+ "dev": true
+ },
+ "esdoc-lint-plugin": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/esdoc-lint-plugin/-/esdoc-lint-plugin-1.0.2.tgz",
+ "integrity": "sha512-24AYqD2WbZI9We02I7/6dzAa7yUliRTFUaJCZAcYJMQicJT5gUrNFVaI8XmWEN/mhF3szIn1uZBNWeLul4CmNw==",
+ "dev": true
+ },
+ "esdoc-publish-html-plugin": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/esdoc-publish-html-plugin/-/esdoc-publish-html-plugin-1.1.2.tgz",
+ "integrity": "sha512-hG1fZmTcEp3P/Hv/qKiMdG1qSp8MjnVZMMkxL5P5ry7I2sX0HQ4P9lt2lms+90Lt0r340HHhSuVx107UL7dphg==",
+ "dev": true,
+ "requires": {
+ "babel-generator": "6.11.4",
+ "cheerio": "0.22.0",
+ "escape-html": "1.0.3",
+ "fs-extra": "1.0.0",
+ "ice-cap": "0.0.4",
+ "marked": "0.3.19",
+ "taffydb": "2.7.2"
+ },
+ "dependencies": {
+ "babel-generator": {
+ "version": "6.11.4",
+ "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.11.4.tgz",
+ "integrity": "sha1-FPaTOrsgxiZm0n47e59bncBxKpo=",
+ "dev": true,
+ "requires": {
+ "babel-messages": "^6.8.0",
+ "babel-runtime": "^6.9.0",
+ "babel-types": "^6.10.2",
+ "detect-indent": "^3.0.1",
+ "lodash": "^4.2.0",
+ "source-map": "^0.5.0"
+ }
+ },
+ "cheerio": {
+ "version": "0.22.0",
+ "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz",
+ "integrity": "sha1-qbqoYKP5tZWmuBsahocxIe06Jp4=",
+ "dev": true,
+ "requires": {
+ "css-select": "~1.2.0",
+ "dom-serializer": "~0.1.0",
+ "entities": "~1.1.1",
+ "htmlparser2": "^3.9.1",
+ "lodash.assignin": "^4.0.9",
+ "lodash.bind": "^4.1.4",
+ "lodash.defaults": "^4.0.1",
+ "lodash.filter": "^4.4.0",
+ "lodash.flatten": "^4.2.0",
+ "lodash.foreach": "^4.3.0",
+ "lodash.map": "^4.4.0",
+ "lodash.merge": "^4.4.0",
+ "lodash.pick": "^4.2.1",
+ "lodash.reduce": "^4.4.0",
+ "lodash.reject": "^4.4.0",
+ "lodash.some": "^4.4.0"
+ }
+ },
+ "detect-indent": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-3.0.1.tgz",
+ "integrity": "sha1-ncXl3bzu+DJXZLlFGwK8bVQIT3U=",
+ "dev": true,
+ "requires": {
+ "get-stdin": "^4.0.1",
+ "minimist": "^1.1.0",
+ "repeating": "^1.1.0"
+ }
+ },
+ "domhandler": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz",
+ "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==",
+ "dev": true,
+ "requires": {
+ "domelementtype": "1"
+ }
+ },
+ "fs-extra": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz",
+ "integrity": "sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "jsonfile": "^2.1.0",
+ "klaw": "^1.0.0"
+ }
+ },
+ "htmlparser2": {
+ "version": "3.9.2",
+ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz",
+ "integrity": "sha1-G9+HrMoPP55T+k/M6w9LTLsAszg=",
+ "dev": true,
+ "requires": {
+ "domelementtype": "^1.3.0",
+ "domhandler": "^2.3.0",
+ "domutils": "^1.5.1",
+ "entities": "^1.1.1",
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "jsonfile": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
+ "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "minimist": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+ "dev": true
+ },
+ "repeating": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/repeating/-/repeating-1.1.3.tgz",
+ "integrity": "sha1-PUEUIYh3U3SU+X93+Xhfq4EPpKw=",
+ "dev": true,
+ "requires": {
+ "is-finite": "^1.0.0"
+ }
+ },
+ "taffydb": {
+ "version": "2.7.2",
+ "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.7.2.tgz",
+ "integrity": "sha1-e/gQalwaSCUbPjvAoOFzJIn9Dcg=",
+ "dev": true
+ }
+ }
+ },
+ "esdoc-react-plugin": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/esdoc-react-plugin/-/esdoc-react-plugin-1.0.1.tgz",
+ "integrity": "sha1-IUoSFdDmFln1Gi2Z7+SONAw/pvQ=",
+ "dev": true,
+ "requires": {
+ "cheerio": "1.0.0-rc.1"
+ },
+ "dependencies": {
+ "cheerio": {
+ "version": "1.0.0-rc.1",
+ "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.1.tgz",
+ "integrity": "sha1-KvNzOeq3E+9rcs3pjO+mcrh2Qf4=",
+ "dev": true,
+ "requires": {
+ "css-select": "~1.2.0",
+ "dom-serializer": "~0.1.0",
+ "entities": "~1.1.1",
+ "htmlparser2": "^3.9.1",
+ "lodash": "^4.15.0",
+ "parse5": "^3.0.1"
+ }
+ },
+ "domhandler": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz",
+ "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==",
+ "dev": true,
+ "requires": {
+ "domelementtype": "1"
+ }
+ },
+ "htmlparser2": {
+ "version": "3.9.2",
+ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz",
+ "integrity": "sha1-G9+HrMoPP55T+k/M6w9LTLsAszg=",
+ "dev": true,
+ "requires": {
+ "domelementtype": "^1.3.0",
+ "domhandler": "^2.3.0",
+ "domutils": "^1.5.1",
+ "entities": "^1.1.1",
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "parse5": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz",
+ "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==",
+ "dev": true,
+ "requires": {
+ "@types/node": "*"
+ }
+ }
+ }
+ },
+ "esdoc-standard-plugin": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/esdoc-standard-plugin/-/esdoc-standard-plugin-1.0.0.tgz",
+ "integrity": "sha1-ZhIBysfvhokkkCRG/awVJyU8XU0=",
+ "dev": true,
+ "requires": {
+ "esdoc-accessor-plugin": "^1.0.0",
+ "esdoc-brand-plugin": "^1.0.0",
+ "esdoc-coverage-plugin": "^1.0.0",
+ "esdoc-external-ecmascript-plugin": "^1.0.0",
+ "esdoc-integrate-manual-plugin": "^1.0.0",
+ "esdoc-integrate-test-plugin": "^1.0.0",
+ "esdoc-lint-plugin": "^1.0.0",
+ "esdoc-publish-html-plugin": "^1.0.0",
+ "esdoc-type-inference-plugin": "^1.0.0",
+ "esdoc-undocumented-identifier-plugin": "^1.0.0",
+ "esdoc-unexported-identifier-plugin": "^1.0.0"
+ }
+ },
+ "esdoc-type-inference-plugin": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/esdoc-type-inference-plugin/-/esdoc-type-inference-plugin-1.0.2.tgz",
+ "integrity": "sha512-tMIcEHNe1uhUGA7lT1UTWc9hs2dzthnTgmqXpmeUhurk7fL2tinvoH+IVvG/sLROzwOGZQS9zW/F9KWnpMzLIQ==",
+ "dev": true
+ },
+ "esdoc-undocumented-identifier-plugin": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/esdoc-undocumented-identifier-plugin/-/esdoc-undocumented-identifier-plugin-1.0.0.tgz",
+ "integrity": "sha1-guBdNxwy0ShxFA8dXIHsmf2cwsg=",
+ "dev": true
+ },
+ "esdoc-unexported-identifier-plugin": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/esdoc-unexported-identifier-plugin/-/esdoc-unexported-identifier-plugin-1.0.0.tgz",
+ "integrity": "sha1-H5h0xqfCvr+a05fDzrdcnGnaurE=",
+ "dev": true
+ },
"eslint": {
"version": "3.19.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-3.19.0.tgz",
@@ -5370,6 +5843,17 @@
"integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=",
"dev": true
},
+ "fs-extra": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz",
+ "integrity": "sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "jsonfile": "^4.0.0",
+ "universalify": "^0.1.0"
+ }
+ },
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
@@ -5519,6 +6003,7 @@
"version": "1.0.5",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"delayed-stream": "~1.0.0"
}
@@ -5581,7 +6066,8 @@
"delayed-stream": {
"version": "1.0.0",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"delegates": {
"version": "1.0.0",
@@ -5869,12 +6355,14 @@
"mime-db": {
"version": "1.27.0",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"mime-types": {
"version": "2.1.15",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"mime-db": "~1.27.0"
}
@@ -5950,7 +6438,8 @@
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"oauth-sign": {
"version": "0.8.2",
@@ -6788,6 +7277,139 @@
"integrity": "sha1-P5E2XKvmC3ftDruiS0VOPgnZWoI=",
"dev": true
},
+ "ice-cap": {
+ "version": "0.0.4",
+ "resolved": "https://registry.npmjs.org/ice-cap/-/ice-cap-0.0.4.tgz",
+ "integrity": "sha1-im0xq0ysjUtW3k+pRt8zUlYbbhg=",
+ "dev": true,
+ "requires": {
+ "cheerio": "0.20.0",
+ "color-logger": "0.0.3"
+ },
+ "dependencies": {
+ "acorn": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-2.7.0.tgz",
+ "integrity": "sha1-q259nYhqrKiwhbwzEreaGYQz8Oc=",
+ "dev": true
+ },
+ "acorn-globals": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-1.0.9.tgz",
+ "integrity": "sha1-VbtemGkVB7dFedBRNBMhfDgMVM8=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "acorn": "^2.1.0"
+ }
+ },
+ "cheerio": {
+ "version": "0.20.0",
+ "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.20.0.tgz",
+ "integrity": "sha1-XHEPK6uVZTJyhCugHG6mGzVF7DU=",
+ "dev": true,
+ "requires": {
+ "css-select": "~1.2.0",
+ "dom-serializer": "~0.1.0",
+ "entities": "~1.1.1",
+ "htmlparser2": "~3.8.1",
+ "jsdom": "^7.0.2",
+ "lodash": "^4.1.0"
+ }
+ },
+ "color-logger": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/color-logger/-/color-logger-0.0.3.tgz",
+ "integrity": "sha1-2bIt0dlz4Waxi/MT+fSBu6TfIBg=",
+ "dev": true
+ },
+ "domhandler": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz",
+ "integrity": "sha1-LeWaCCLVAn+r/28DLCsloqir5zg=",
+ "dev": true,
+ "requires": {
+ "domelementtype": "1"
+ }
+ },
+ "htmlparser2": {
+ "version": "3.8.3",
+ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz",
+ "integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=",
+ "dev": true,
+ "requires": {
+ "domelementtype": "1",
+ "domhandler": "2.3",
+ "domutils": "1.5",
+ "entities": "1.0",
+ "readable-stream": "1.1"
+ },
+ "dependencies": {
+ "entities": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz",
+ "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=",
+ "dev": true
+ }
+ }
+ },
+ "isarray": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+ "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
+ "dev": true
+ },
+ "jsdom": {
+ "version": "7.2.2",
+ "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-7.2.2.tgz",
+ "integrity": "sha1-QLQCdwwr2iNGkJa+6Rq2deOx/G4=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "abab": "^1.0.0",
+ "acorn": "^2.4.0",
+ "acorn-globals": "^1.0.4",
+ "cssom": ">= 0.3.0 < 0.4.0",
+ "cssstyle": ">= 0.2.29 < 0.3.0",
+ "escodegen": "^1.6.1",
+ "nwmatcher": ">= 1.3.7 < 2.0.0",
+ "parse5": "^1.5.1",
+ "request": "^2.55.0",
+ "sax": "^1.1.4",
+ "symbol-tree": ">= 3.1.0 < 4.0.0",
+ "tough-cookie": "^2.2.0",
+ "webidl-conversions": "^2.0.0",
+ "whatwg-url-compat": "~0.6.5",
+ "xml-name-validator": ">= 2.0.1 < 3.0.0"
+ }
+ },
+ "readable-stream": {
+ "version": "1.1.14",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
+ "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
+ "dev": true,
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.1",
+ "isarray": "0.0.1",
+ "string_decoder": "~0.10.x"
+ }
+ },
+ "string_decoder": {
+ "version": "0.10.31",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+ "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
+ "dev": true
+ },
+ "webidl-conversions": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-2.0.1.tgz",
+ "integrity": "sha1-O/glj30xjHRDw28uFpQCoaZwNQY=",
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
"iconv-lite": {
"version": "0.4.19",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz",
@@ -8503,6 +9125,15 @@
"integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=",
"dev": true
},
+ "jsonfile": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
+ "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
"jsonify": {
"version": "0.0.0",
"resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
@@ -8548,6 +9179,15 @@
"is-buffer": "^1.1.5"
}
},
+ "klaw": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz",
+ "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.9"
+ }
+ },
"lazy-cache": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz",
@@ -8876,18 +9516,90 @@
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
"integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4="
},
+ "lodash.assignin": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/lodash.assignin/-/lodash.assignin-4.2.0.tgz",
+ "integrity": "sha1-uo31+4QesKPoBEIysOJjqNxqKKI=",
+ "dev": true
+ },
+ "lodash.bind": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/lodash.bind/-/lodash.bind-4.2.1.tgz",
+ "integrity": "sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU=",
+ "dev": true
+ },
"lodash.camelcase": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
"integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=",
"dev": true
},
+ "lodash.defaults": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
+ "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=",
+ "dev": true
+ },
+ "lodash.filter": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz",
+ "integrity": "sha1-ZosdSYFgOuHMWm+nYBQ+SAtMSs4=",
+ "dev": true
+ },
+ "lodash.flatten": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
+ "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=",
+ "dev": true
+ },
+ "lodash.foreach": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz",
+ "integrity": "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM=",
+ "dev": true
+ },
+ "lodash.map": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz",
+ "integrity": "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM=",
+ "dev": true
+ },
"lodash.memoize": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
"integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=",
"dev": true
},
+ "lodash.merge": {
+ "version": "4.6.1",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.1.tgz",
+ "integrity": "sha512-AOYza4+Hf5z1/0Hztxpm2/xiPZgi/cjMqdnKTUWTBSKchJlxXXuUSxCCl8rJlf4g6yww/j6mA8nC8Hw/EZWxKQ==",
+ "dev": true
+ },
+ "lodash.pick": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz",
+ "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=",
+ "dev": true
+ },
+ "lodash.reduce": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz",
+ "integrity": "sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs=",
+ "dev": true
+ },
+ "lodash.reject": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/lodash.reject/-/lodash.reject-4.6.0.tgz",
+ "integrity": "sha1-gNZJLcFHCGS79YNTO2UfQqn1JBU=",
+ "dev": true
+ },
+ "lodash.some": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz",
+ "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=",
+ "dev": true
+ },
"lodash.uniq": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
@@ -9002,6 +9714,12 @@
"integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=",
"dev": true
},
+ "marked": {
+ "version": "0.3.19",
+ "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.19.tgz",
+ "integrity": "sha512-ea2eGWOqNxPcXv8dyERdSr/6FmzvWwzjMxpfGB/sbMccXoct+xY+YukPD+QTUZwyvK7BZwcr4m21WBOW41pAkg==",
+ "dev": true
+ },
"math-expression-evaluator": {
"version": "1.2.17",
"resolved": "https://registry.npmjs.org/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz",
@@ -11975,6 +12693,12 @@
}
}
},
+ "taffydb": {
+ "version": "2.7.3",
+ "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.7.3.tgz",
+ "integrity": "sha1-KtNxaWKUmPylvIQkMJbTzeDsOjQ=",
+ "dev": true
+ },
"tapable": {
"version": "0.2.8",
"resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.8.tgz",
@@ -12205,6 +12929,12 @@
"integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=",
"dev": true
},
+ "universalify": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
+ "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
+ "dev": true
+ },
"unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
@@ -12687,6 +13417,16 @@
}
}
},
+ "whatwg-url-compat": {
+ "version": "0.6.5",
+ "resolved": "https://registry.npmjs.org/whatwg-url-compat/-/whatwg-url-compat-0.6.5.tgz",
+ "integrity": "sha1-AImBEa9om7CXVBzVpFymyHmERb8=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "tr46": "~0.0.1"
+ }
+ },
"whet.extend": {
"version": "0.9.9",
"resolved": "https://registry.npmjs.org/whet.extend/-/whet.extend-0.9.9.tgz",
diff --git a/package.json b/package.json
index 702b0a89..a8ef3274 100644
--- a/package.json
+++ b/package.json
@@ -16,6 +16,7 @@
"clean": "rimraf build",
"start": "node devServer.js",
"lint": "eslint --ext .js,.jsx src",
+ "preinstall": "ls ../coriolis-data || git clone https://github.com/edcd/coriolis-data.git ../coriolis-data && (cd ../coriolis-data && npm i)",
"test": "jest",
"prod-serve": "nginx -p $(pwd) -c nginx.conf",
"prod-stop": "kill -QUIT $(cat nginx.pid)",
@@ -93,7 +94,14 @@
"webpack": "^2.4.1",
"webpack-dev-server": "^2.4.4",
"webpack-notifier": "^1.6.0",
- "webpack-bugsnag-plugins": "^1.1.1"
+ "webpack-bugsnag-plugins": "^1.1.1",
+ "esdoc": "^1.1.0",
+ "esdoc-ecmascript-proposal-plugin": "^1.0.0",
+ "esdoc-jsx-plugin": "^1.0.0",
+ "esdoc-react-plugin": "^1.0.1",
+ "esdoc-standard-plugin": "^1.0.0",
+ "esdoc-publish-html-plugin": "^1.1.2",
+ "esdoc-custom-theme": "^1.4.2"
},
"dependencies": {
"babel-polyfill": "*",
diff --git a/src/app/components/AvailableModulesMenu.jsx b/src/app/components/AvailableModulesMenu.jsx
index 2fc495d8..251c0712 100644
--- a/src/app/components/AvailableModulesMenu.jsx
+++ b/src/app/components/AvailableModulesMenu.jsx
@@ -61,7 +61,9 @@ const GRPCAT = {
// Standard
'gpp': 'guardian',
'gpc': 'guardian',
- 'ggc': 'guardian'
+ 'gsrp': 'guardian',
+ 'ggc': 'guardian',
+ 'gfsb': 'guardian'
};
// Order here is the order in which items will be shown in the modules menu
const CATEGORIES = {
@@ -90,7 +92,7 @@ const CATEGORIES = {
'experimental': ['axmc', 'axmr', 'rfl', 'xs', 'sfn', 'rcpl'],
// Guardian
- 'guardian': ['gpp', 'gpd', 'gpc', 'ggc']
+ 'guardian': ['gpp', 'gpd', 'gpc', 'ggc', 'gsrp', 'gfsb']
};
/**
diff --git a/src/app/components/Defence.jsx b/src/app/components/Defence.jsx
index 35fea165..576b65f6 100644
--- a/src/app/components/Defence.jsx
+++ b/src/app/components/Defence.jsx
@@ -76,6 +76,7 @@ export default class Defence extends TranslatedComponent {
shieldSourcesData.push({ value: Math.round(shield.generator), label: translate('generator') });
shieldSourcesData.push({ value: Math.round(shield.boosters), label: translate('boosters') });
shieldSourcesData.push({ value: Math.round(shield.cells), label: translate('cells') });
+ shieldSourcesData.push({ value: Math.round(shield.addition), label: translate('shield addition') });
if (shield.generator > 0) {
shieldSourcesTt.push(
{translate('generator') + ' ' + formats.int(shield.generator)}{units.MJ}
);
diff --git a/src/app/components/FSDProfile.jsx b/src/app/components/FSDProfile.jsx
index 4a4f2094..bd12fc10 100644
--- a/src/app/components/FSDProfile.jsx
+++ b/src/app/components/FSDProfile.jsx
@@ -57,7 +57,7 @@ export default class FSDProfile extends TranslatedComponent {
*/
_calcMaxRange(ship, fuel, mass) {
// Obtain the maximum range
- return Calc.jumpRange(mass, ship.standard[2].m, Math.min(fuel, ship.standard[2].m.getMaxFuelPerJump()));
+ return Calc.jumpRange(mass, ship.standard[2].m, Math.min(fuel, ship.standard[2].m.getMaxFuelPerJump()), ship);
}
/**
@@ -77,7 +77,7 @@ export default class FSDProfile extends TranslatedComponent {
const maxMass = thrusters.getMaxMass();
const mass = ship.unladenMass + fuel + cargo;
const minRange = 0;
- const maxRange = Calc.jumpRange(minMass + fsd.getMaxFuelPerJump(), fsd, fsd.getMaxFuelPerJump());
+ const maxRange = Calc.jumpRange(minMass + fsd.getMaxFuelPerJump(), fsd, fsd.getMaxFuelPerJump(), ship);
// Add a mark at our current mass
const mark = Math.min(mass, maxMass);
diff --git a/src/app/components/InternalSlot.jsx b/src/app/components/InternalSlot.jsx
index 2bf0feb8..38f1011f 100644
--- a/src/app/components/InternalSlot.jsx
+++ b/src/app/components/InternalSlot.jsx
@@ -63,6 +63,9 @@ export default class InternalSlot extends Slot {
{ m.getSpinup() ? {translate('spinup')}: {formats.f1(m.getSpinup())}{u.s}
: null }
{ m.getDuration() ? {translate('duration')}: {formats.f1(m.getDuration())}{u.s}
: null }
{ m.grp === 'scb' ? {translate('cells')}: {formats.int(m.getAmmo() + 1)}
: null }
+ { m.grp === 'gsrp' ? {translate('shield addition')}: {formats.f1(m.getShieldAddition())}{u.MJ}
: null }
+ { m.grp === 'gfsb' ? {translate('jump addition')}: {formats.f1(m.getJumpBoost())}{u.LY}
: null }
+ { m.grp === 'gs' ? {translate('shield addition')}: {formats.f1(m.getShieldAddition())}{u.MJ}
: null }
{ m.getShieldReinforcement() ? {translate('shieldreinforcement')}: {formats.f1(m.getDuration() * m.getShieldReinforcement())}{u.MJ}
: null }
{ m.getShieldReinforcement() ? {translate('total')}: {formats.int((m.getAmmo() + 1) * (m.getDuration() * m.getShieldReinforcement()))}{u.MJ}
: null }
{ m.repair ? {translate('repair')}: {m.repair}
: null }
diff --git a/src/app/components/JumpRange.jsx b/src/app/components/JumpRange.jsx
index 2b8f5196..ceba5bc2 100644
--- a/src/app/components/JumpRange.jsx
+++ b/src/app/components/JumpRange.jsx
@@ -61,7 +61,7 @@ export default class JumpRange extends TranslatedComponent {
const fuel = this.state.fuelLevel * ship.fuelCapacity;
// Obtain the jump range
- return Calc.jumpRange(ship.unladenMass + fuel + cargo, fsd, fuel);
+ return Calc.jumpRange(ship.unladenMass + fuel + cargo, fsd, fuel, ship);
}
/**
diff --git a/src/app/components/ModalShoppingList.jsx b/src/app/components/ModalShoppingList.jsx
index e8d5efa3..047e69bb 100644
--- a/src/app/components/ModalShoppingList.jsx
+++ b/src/app/components/ModalShoppingList.jsx
@@ -23,7 +23,8 @@ export default class ModalShoppingList extends TranslatedComponent {
matsList: '',
mats: {},
failed: false,
- cmdrName: Persist.getCmdr(),
+ cmdrName: Persist.getCmdr().selected,
+ cmdrs: Persist.getCmdr().cmdrs,
matsPerGrade: Persist.getRolls(),
blueprints: []
};
@@ -34,11 +35,14 @@ export default class ModalShoppingList extends TranslatedComponent {
*/
componentDidMount() {
this.renderMats();
- this.registerBPs();
+ if (this.checkBrowserIsCompatible()) {
+ this.getCommanders();
+ this.registerBPs();
+ }
}
/**
- * Convert mats object to string
+ * Find all blueprints needed to make a build.
*/
registerBPs() {
const ship = this.props.ship;
@@ -51,34 +55,81 @@ export default class ModalShoppingList extends TranslatedComponent {
if (!module.m.blueprint.grade || !module.m.blueprint.grades) {
continue;
}
+ if (module.m.blueprint.special) {
+ console.log(module.m.blueprint.special);
+ blueprints.push({ uuid: module.m.blueprint.special.uuid, number: 1 });
+ }
for (const g in module.m.blueprint.grades) {
+ if (!module.m.blueprint.grades.hasOwnProperty(g)) {
+ continue;
+ }
if (g > module.m.blueprint.grade) {
continue;
}
- blueprints.push({ blueprint: module.m.blueprint.grades[g], number: this.state.matsPerGrade[g] });
+ blueprints.push({ uuid: module.m.blueprint.grades[g].uuid, number: this.state.matsPerGrade[g] });
}
}
}
this.setState({ blueprints });
}
+ /**
+ * Check browser isn't firefox.
+ * @return {boolean} true if compatible, false if not.
+ */
+ checkBrowserIsCompatible() {
+ // Firefox 1.0+
+ return typeof InstallTrigger === 'undefined';
+ }
+
+ /**
+ * Get a list of commanders from EDEngineer.
+ */
+ getCommanders() {
+ request
+ .get('http://localhost:44405/commanders')
+ .end((err, res) => {
+ if (err) {
+ console.log(err);
+ return this.setState({ failed: true });
+ }
+ const cmdrs = JSON.parse(res.text);
+ if (!this.state.cmdrName) {
+ this.setState({ cmdrName: cmdrs[0] });
+ }
+ this.setState({ cmdrs }, () => {
+ Persist.setCmdr({ selected: this.state.cmdrName, cmdrs });
+ });
+ });
+ }
+
/**
* Send all blueprints to ED Engineer
- * @param {SyntheticEvent} event React event
+ * @param {Event} event React event
*/
sendToEDEng(event) {
event.preventDefault();
- event.target.disabled = true;
- event.target.innerText = 'Sending...';
+ const target = event.target;
+ target.disabled = this.state.blueprints.length > 0;
+ if (this.state.blueprints.length === 0) {
+ target.innerText = 'No modded components.';
+ target.disabled = true;
+ setTimeout(() => {
+ target.innerText = 'Send to EDEngineer';
+ target.disabled = false;
+ }, 3000);
+ } else {
+ target.innerText = 'Sending...';
+ }
let countSent = 0;
let countTotal = this.state.blueprints.length;
- const target = event.target;
+
for (const i of this.state.blueprints) {
request
.patch(`http://localhost:44405/${this.state.cmdrName}/shopping-list`)
- .field('uuid', i.blueprint.uuid)
+ .field('uuid', i.uuid)
.field('size', i.number)
- .end((err, res) => {
+ .end(err => {
if (err) {
console.log(err);
if (err.message !== 'Bad Request') {
@@ -109,10 +160,16 @@ export default class ModalShoppingList extends TranslatedComponent {
continue;
}
for (const g in module.m.blueprint.grades) {
+ if (!module.m.blueprint.grades.hasOwnProperty(g)) {
+ continue;
+ }
if (g > module.m.blueprint.grade) {
continue;
}
for (const i in module.m.blueprint.grades[g].components) {
+ if (!module.m.blueprint.grades[g].components.hasOwnProperty(i)) {
+ continue;
+ }
if (mats[i]) {
mats[i] += module.m.blueprint.grades[g].components[i] * this.state.matsPerGrade[g];
} else {
@@ -156,8 +213,9 @@ export default class ModalShoppingList extends TranslatedComponent {
*/
cmdrChangeHandler(e) {
let cmdrName = e.target.value;
- this.setState({ cmdrName });
- Persist.setCmdr(cmdrName);
+ this.setState({ cmdrName }, () => {
+ Persist.setCmdr({ selected: this.state.cmdrName, cmdrs: this.state.cmdrs });
+ });
}
/**
@@ -167,6 +225,7 @@ export default class ModalShoppingList extends TranslatedComponent {
render() {
let translate = this.context.language.translate;
this.changeHandler = this.changeHandler.bind(this);
+ const compatible = this.checkBrowserIsCompatible();
this.cmdrChangeHandler = this.cmdrChangeHandler.bind(this);
this.sendToEDEng = this.sendToEDEng.bind(this);
return e.stopPropagation() }>
@@ -188,12 +247,15 @@ export default class ModalShoppingList extends TranslatedComponent {
-
+
-
+
-
Failed to send to EDEngineer (Launch EDEngineer and make sure the API is started then refresh the page.)
-
+
Failed to send to EDEngineer (Launch EDEngineer and make sure the API is started then refresh the page.)
+
Sending to EDEngineer is not compatible with Firefox's security settings. Please try again with Chrome.
+
;
}
diff --git a/src/app/components/ShipSummaryTable.jsx b/src/app/components/ShipSummaryTable.jsx
index 600fc5d0..450c760e 100644
--- a/src/app/components/ShipSummaryTable.jsx
+++ b/src/app/components/ShipSummaryTable.jsx
@@ -99,11 +99,11 @@ export default class ShipSummaryTable extends TranslatedComponent {
| { canThrust ? {int(ship.calcSpeed(4, ship.fuelCapacity, 0, false))}{u['m/s']} : 0 } |
{ canBoost ? {int(ship.calcSpeed(4, ship.fuelCapacity, 0, true))}{u['m/s']} : 0 } |
- {f2(Calc.jumpRange(ship.unladenMass + ship.standard[2].m.getMaxFuelPerJump(), ship.standard[2].m, ship.standard[2].m.getMaxFuelPerJump()))}{u.LY} |
- {f2(Calc.jumpRange(ship.unladenMass + ship.fuelCapacity, ship.standard[2].m, ship.fuelCapacity))}{u.LY} |
- {f2(Calc.jumpRange(ship.unladenMass + ship.fuelCapacity + ship.cargoCapacity, ship.standard[2].m, ship.fuelCapacity))}{u.LY} |
- {f2(Calc.totalJumpRange(ship.unladenMass + ship.fuelCapacity, ship.standard[2].m, ship.fuelCapacity))}{u.LY} |
- {f2(Calc.totalJumpRange(ship.unladenMass + ship.fuelCapacity + ship.cargoCapacity, ship.standard[2].m, ship.fuelCapacity))}{u.LY} |
+ {f2(Calc.jumpRange(ship.unladenMass + ship.standard[2].m.getMaxFuelPerJump(), ship.standard[2].m, ship.standard[2].m.getMaxFuelPerJump(), ship))}{u.LY} |
+ {f2(Calc.jumpRange(ship.unladenMass + ship.fuelCapacity, ship.standard[2].m, ship.fuelCapacity, ship))}{u.LY} |
+ {f2(Calc.jumpRange(ship.unladenMass + ship.fuelCapacity + ship.cargoCapacity, ship.standard[2].m, ship.fuelCapacity, ship))}{u.LY} |
+ {f2(Calc.totalJumpRange(ship.unladenMass + ship.fuelCapacity, ship.standard[2].m, ship.fuelCapacity, ship))}{u.LY} |
+ {f2(Calc.totalJumpRange(ship.unladenMass + ship.fuelCapacity + ship.cargoCapacity, ship.standard[2].m, ship.fuelCapacity, ship))}{u.LY} |
{int(ship.shield)}{u.MJ} |
{int(ship.armour)} |
{f1(ship.totalDps)} |
@@ -142,13 +142,13 @@ export default class ShipSummaryTable extends TranslatedComponent {
| {translate(shieldGenerator && shieldGenerator.m.grp || 'No Shield')} |
- {int(ship.shieldExplRes * 100) + '%'} |
- {int(ship.shieldKinRes * 100) + '%'} |
- {int(ship.shieldThermRes * 100) + '%'} |
- {int(sgMetrics && sgMetrics.generator ? sgMetrics.total / sgMetrics.absolute.total : 0)} |
- {int(sgMetrics && sgMetrics.generator ? sgMetrics.total / sgMetrics.explosive.total : 0)} |
- {int(sgMetrics && sgMetrics.generator ? sgMetrics.total / sgMetrics.kinetic.total : 0)} |
- {int(sgMetrics && sgMetrics.generator ? sgMetrics.total / sgMetrics.thermal.total : 0)} |
+ {formats.pct1(ship.shieldExplRes)} |
+ {formats.pct1(ship.shieldKinRes)} |
+ {formats.pct1(ship.shieldThermRes)} |
+ {int(ship && ship.shield > 0 ? ship.shield : 0)}{u.MJ} |
+ {int(ship && ship.shield > 0 ? ship.shield * ((1 / (1 - (ship.shieldExplRes)))) : 0)}{u.MJ} |
+ {int(ship && ship.shield > 0 ? ship.shield * ((1 / (1 - (ship.shieldKinRes)))) : 0)}{u.MJ} |
+ {int(ship && ship.shield > 0 ? ship.shield * ((1 / (1 - (ship.shieldThermRes)))) : 0)}{u.MJ} |
{sgMetrics && sgMetrics.recover ? formats.time(sgMetrics.recover) : 0} |
{sgMetrics && sgMetrics.recharge ? formats.time(sgMetrics.recharge) : 0} |
@@ -173,13 +173,13 @@ export default class ShipSummaryTable extends TranslatedComponent {
| {translate(ship && ship.bulkheads && ship.bulkheads.m && ship.bulkheads.m.name || 'No Armour')} |
- {int(ship.hullExplRes * 100) + '%'} |
- {int(ship.hullKinRes * 100) + '%'} |
- {int(ship.hullThermRes * 100) + '%'} |
- {int(armourMetrics.total / armourMetrics.absolute.total)} |
- {int(armourMetrics.total / armourMetrics.explosive.total)} |
- {int(armourMetrics.total / armourMetrics.kinetic.total)} |
- {int(armourMetrics.total / armourMetrics.thermal.total)} |
+ {formats.pct1(ship.hullExplRes)} |
+ {formats.pct1(ship.hullKinRes)} |
+ {formats.pct1(ship.hullThermRes)} |
+ {int(ship.armour)} |
+ {int(ship.armour * ((1 / (1 - (ship.hullExplRes)))))} |
+ {int(ship.armour * ((1 / (1 - (ship.hullKinRes)))))} |
+ {int(ship.armour * ((1 / (1 - (ship.hullThermRes)))))} |
{int(armourMetrics.modulearmour)} |
{int(armourMetrics.moduleprotection * 100) + '%'} |
diff --git a/src/app/i18n/en.json b/src/app/i18n/en.json
index ff504e94..9bc1866f 100644
--- a/src/app/i18n/en.json
+++ b/src/app/i18n/en.json
@@ -124,6 +124,8 @@
"gpd": "Guardian Hybrid Power Distributor",
"gpc": "Guardian Plasma Charger",
"ggc": "Guardian Gauss Cannon",
+ "gsrp": "Guardian Shield Reinforcement Package",
+ "gfsb": "Guardian Frame Shift Drive Booster",
"psg": "Prismatic Shield Generator",
"pv": "Planetary Vehicle Hangar",
"rf": "Refinery",
@@ -257,6 +259,8 @@
"generator": "Generator",
"boosters": "Boosters",
"cells": "Cells",
+ "shield addition": "Shield Addition",
+ "jump addition": "Jump Addition",
"bulkheads": "Bulkheads",
"reinforcement": "Reinforcement",
"power and costs": "power and costs",
diff --git a/src/app/shipyard/Calculations.js b/src/app/shipyard/Calculations.js
index e6058073..84c84647 100644
--- a/src/app/shipyard/Calculations.js
+++ b/src/app/shipyard/Calculations.js
@@ -7,11 +7,20 @@ import Module from './Module';
* @param {object} fsd The FDS object/component with maxfuel, fuelmul, fuelpower, optmass
* @param {number} fuel Optional - The fuel consumed during the jump
* @return {number} Distance in Light Years
+ * @param {object} ship Ship instance
*/
-export function jumpRange(mass, fsd, fuel) {
+export function jumpRange(mass, fsd, fuel, ship) {
const fsdMaxFuelPerJump = fsd instanceof Module ? fsd.getMaxFuelPerJump() : fsd.maxfuel;
const fsdOptimalMass = fsd instanceof Module ? fsd.getOptMass() : fsd.optmass;
- return Math.pow(Math.min(fuel === undefined ? fsdMaxFuelPerJump : fuel, fsdMaxFuelPerJump) / fsd.fuelmul, 1 / fsd.fuelpower) * fsdOptimalMass / mass;
+ let jumpAddition = 0;
+ if (ship) {
+ for (const module of ship.internal) {
+ if (module && module.m && module.m.grp === 'gfsb') {
+ jumpAddition += module.m.getJumpBoost();
+ }
+ }
+ }
+ return (Math.pow(Math.min(fuel === undefined ? fsdMaxFuelPerJump : fuel, fsdMaxFuelPerJump) / fsd.fuelmul, 1 / fsd.fuelpower) * fsdOptimalMass / mass) + jumpAddition;
}
/**
@@ -21,8 +30,9 @@ export function jumpRange(mass, fsd, fuel) {
* @param {object} fsd The FDS object/component with maxfuel, fuelmul, fuelpower, optmass
* @param {number} fuel The total fuel available
* @return {number} Distance in Light Years
+ * @param {object} ship Ship instance
*/
-export function totalJumpRange(mass, fsd, fuel) {
+export function totalJumpRange(mass, fsd, fuel, ship) {
const fsdMaxFuelPerJump = fsd instanceof Module ? fsd.getMaxFuelPerJump() : fsd.maxfuel;
const fsdOptimalMass = fsd instanceof Module ? fsd.getOptMass() : fsd.optmass;
@@ -30,7 +40,7 @@ export function totalJumpRange(mass, fsd, fuel) {
let totalRange = 0;
while (fuelRemaining > 0) {
const fuelForThisJump = Math.min(fuelRemaining, fsdMaxFuelPerJump);
- totalRange += this.jumpRange(mass, fsd, fuelForThisJump);
+ totalRange += this.jumpRange(mass, fsd, fuelForThisJump, ship);
// Mass is reduced
mass -= fuelForThisJump;
fuelRemaining -= fuelForThisJump;
@@ -60,7 +70,7 @@ export function shieldStrength(mass, baseShield, sg, multiplier) {
let ynorm = Math.pow(xnorm, exponent);
let mul = minMul + ynorm * (maxMul - minMul);
- return baseShield * mul * multiplier;
+ return (baseShield * mul * multiplier);
}
/**
@@ -86,6 +96,16 @@ export function speed(mass, baseSpeed, thrusters, engpip) {
return results;
}
+/**
+ * Calculate pip multiplier for speed.
+ * @param {number} baseSpeed The base speed of ship in data
+ * @param {number} topSpeed The top speed of ship in data
+ * @return {number} The multiplier that pips affect speed.
+ */
+export function calcPipSpeed(baseSpeed, topSpeed) {
+ return (topSpeed - baseSpeed) / (4 * topSpeed);
+}
+
/**
* Calculate pitch of a ship based on mass and thrusters
* @param {number} mass the mass of the ship
@@ -201,7 +221,7 @@ function calcValue(minMass, optMass, maxMass, minMul, optMul, maxMul, mass, base
* Calculate speed for a given setup
* @param {number} mass the mass of the ship
* @param {number} baseSpeed the base speed of the ship
- * @param {ojbect} thrusters the thrusters of the ship
+ * @param {object} thrusters the thrusters of the ship
* @param {number} engpip the multiplier per pip to engines
* @param {number} eng the pips to engines
* @param {number} boostFactor the boost factor for ths ship
@@ -320,41 +340,81 @@ export function shieldMetrics(ship, sys) {
const maxSysResistance = this.sysResistance(4);
let shield = {};
+ const dimReturnLine = (res) => 1 - (1 - res) * 0.7;
const shieldGeneratorSlot = ship.findInternalByGroup('sg');
if (shieldGeneratorSlot && shieldGeneratorSlot.enabled && shieldGeneratorSlot.m) {
const shieldGenerator = shieldGeneratorSlot.m;
-
+ let res = {
+ kin: shieldGenerator.kinres,
+ therm: shieldGenerator.thermres,
+ expl: shieldGenerator.explres
+ };
// Boosters
let boost = 1;
let boosterExplDmg = 1;
let boosterKinDmg = 1;
let boosterThermDmg = 1;
+ // const explDim = dimReturnLine(shieldGenerator.explres);
+ // const thermDim = dimReturnLine(shieldGenerator.thermres);
+ // const kinDim = dimReturnLine(shieldGenerator.kinres);
for (let slot of ship.hardpoints) {
if (slot.enabled && slot.m && slot.m.grp == 'sb') {
boost += slot.m.getShieldBoost();
+ res.expl += slot.m.getExplosiveResistance();
+ res.kin += slot.m.getKineticResistance();
+ res.therm += slot.m.getThermalResistance();
boosterExplDmg = boosterExplDmg * (1 - slot.m.getExplosiveResistance());
boosterKinDmg = boosterKinDmg * (1 - slot.m.getKineticResistance());
boosterThermDmg = boosterThermDmg * (1 - slot.m.getThermalResistance());
}
- }
+ if (slot.m && slot.m.grp == 'gsrp') {
+ }
+ }
// Calculate diminishing returns for boosters
// Diminishing returns not currently in-game
// boost = Math.min(boost, (1 - Math.pow(Math.E, -0.7 * boost)) * 2.5);
+
// Remove base shield generator strength
boost -= 1;
- // Apply diminishing returns
- boosterExplDmg = boosterExplDmg > 0.7 ? boosterExplDmg : 0.7 - (0.7 - boosterExplDmg) / 2;
- boosterKinDmg = boosterKinDmg > 0.7 ? boosterKinDmg : 0.7 - (0.7 - boosterKinDmg) / 2;
- boosterThermDmg = boosterThermDmg > 0.7 ? boosterThermDmg : 0.7 - (0.7 - boosterThermDmg) / 2;
- const generatorStrength = this.shieldStrength(ship.hullMass, ship.baseShieldStrength, shieldGenerator, 1);
+ // if (res.expl > explDim) {
+ // const overage = (res.expl - explDim) * 0.5;
+ // res.expl = explDim + overage;
+ // boosterExplDmg = explDim + overage;
+ // }
+ //
+ // if (res.therm > thermDim) {
+ // const overage = (res.therm - thermDim) * 0.5;
+ // res.therm = thermDim + overage;
+ // boosterThermDmg = thermDim + overage;
+ // }
+ //
+ // if (res.kin > kinDim) {
+ // const overage = (res.kin - kinDim) * 0.5;
+ // res.kin = kinDim + overage;
+ // boosterKinDmg = kinDim + overage;
+ // }
+ // Apply diminishing returns
+ // boosterExplDmg = boosterExplDmg > 0.7 ? boosterExplDmg : 0.7 - (0.7 - boosterExplDmg) / 2;
+ // boosterKinDmg = boosterKinDmg > 0.7 ? boosterKinDmg : 0.7 - (0.7 - boosterKinDmg) / 2;
+ // boosterThermDmg = boosterThermDmg > 0.7 ? boosterThermDmg : 0.7 - (0.7 - boosterThermDmg) / 2;
+ // res.therm = res.therm > 0.7 ? res.therm : 0.7 - (0.7 - res.therm) / 2;
+ let shieldAddition = 0;
+ if (ship) {
+ for (const module of ship.internal) {
+ if (module && module.m && module.m.grp === 'gsrp') {
+ shieldAddition += module.m.getShieldAddition();
+ }
+ }
+ }
+ let generatorStrength = this.shieldStrength(ship.hullMass, ship.baseShieldStrength, shieldGenerator, 1);
const boostersStrength = generatorStrength * boost;
// Recover time is the time taken to go from 0 to 50%. It includes a 16-second wait before shields start to recover
- const shieldToRecover = (generatorStrength + boostersStrength) / 2;
+ const shieldToRecover = (generatorStrength + boostersStrength + shieldAddition) / 2;
const powerDistributor = ship.standard[4].m;
const sysRechargeRate = this.sysRechargeRate(powerDistributor, sys);
@@ -373,7 +433,7 @@ export function shieldMetrics(ship, sys) {
const remainingShieldToRecover = shieldToRecover - capacitorLifetime * shieldGenerator.getBrokenRegenerationRate();
if (sys === 0) {
// No system pips so will never recover shields
- recover = Math.Inf;
+ recover = Math.Infinity;
} else {
// Recover remaining shields at the rate of the power distributor's recharge
recover += remainingShieldToRecover / (sysRechargeRate / 0.6);
@@ -381,7 +441,7 @@ export function shieldMetrics(ship, sys) {
}
// Recharge time is the time taken to go from 50% to 100%
- const shieldToRecharge = (generatorStrength + boostersStrength) / 2;
+ const shieldToRecharge = (generatorStrength + boostersStrength + shieldAddition) / 2;
// Our initial regeneration comes from the SYS capacitor store, which is replenished as it goes
// 0.6 is a magic number from FD: each 0.6 MW of energy from the power distributor recharges 1 MJ/s of regeneration
@@ -408,8 +468,9 @@ export function shieldMetrics(ship, sys) {
shield = {
generator: generatorStrength,
boosters: boostersStrength,
+ addition: shieldAddition,
cells: ship.shieldCells,
- total: generatorStrength + boostersStrength + ship.shieldCells,
+ total: generatorStrength + boostersStrength + ship.shieldCells + shieldAddition,
recover,
recharge,
};
@@ -429,7 +490,8 @@ export function shieldMetrics(ship, sys) {
boosters: boosterExplDmg,
sys: (1 - sysResistance),
total: (1 - shieldGenerator.getExplosiveResistance()) * boosterExplDmg * (1 - sysResistance),
- max: (1 - shieldGenerator.getExplosiveResistance()) * boosterExplDmg * (1 - maxSysResistance)
+ max: (1 - shieldGenerator.getExplosiveResistance()) * boosterExplDmg * (1 - maxSysResistance),
+ res: 1 - boosterExplDmg
};
shield.kinetic = {
@@ -437,7 +499,8 @@ export function shieldMetrics(ship, sys) {
boosters: boosterKinDmg,
sys: (1 - sysResistance),
total: (1 - shieldGenerator.getKineticResistance()) * boosterKinDmg * (1 - sysResistance),
- max: (1 - shieldGenerator.getKineticResistance()) * boosterKinDmg * (1 - maxSysResistance)
+ max: (1 - shieldGenerator.getKineticResistance()) * boosterKinDmg * (1 - maxSysResistance),
+ res: 1 - boosterKinDmg
};
shield.thermal = {
@@ -445,10 +508,10 @@ export function shieldMetrics(ship, sys) {
boosters: boosterThermDmg,
sys: (1 - sysResistance),
total: (1 - shieldGenerator.getThermalResistance()) * boosterThermDmg * (1 - sysResistance),
- max: (1 - shieldGenerator.getThermalResistance()) * boosterThermDmg * (1 - maxSysResistance)
+ max: (1 - shieldGenerator.getThermalResistance()) * boosterThermDmg * (1 - maxSysResistance),
+ res: 1 - boosterThermDmg
};
}
-
return shield;
}
@@ -477,19 +540,27 @@ export function armourMetrics(ship) {
let moduleArmour = 0;
let moduleProtection = 1;
-
+ const bulkheads = ship.bulkheads.m;
let hullExplDmg = 1;
let hullKinDmg = 1;
let hullThermDmg = 1;
-
+ // const dimReturnLine = (res) => 1 - (1 - res) * 0.7;
+ let res = {
+ kin: 0,
+ therm: 0,
+ expl: 0
+ };
// Armour from HRPs and module armour from MRPs
for (let slot of ship.internal) {
if (slot.m && slot.m.grp == 'hr') {
armourReinforcement += slot.m.getHullReinforcement();
// Hull boost for HRPs is applied against the ship's base armour
armourReinforcement += ship.baseArmour * slot.m.getModValue('hullboost') / 10000;
-
+ res.expl += slot.m.getExplosiveResistance();
+ res.kin += slot.m.getKineticResistance();
+ res.therm += slot.m.getThermalResistance();
hullExplDmg = hullExplDmg * (1 - slot.m.getExplosiveResistance());
+
hullKinDmg = hullKinDmg * (1 - slot.m.getKineticResistance());
hullThermDmg = hullThermDmg * (1 - slot.m.getThermalResistance());
}
@@ -500,10 +571,31 @@ export function armourMetrics(ship) {
}
moduleProtection = 1 - moduleProtection;
+ // const explDim = dimReturnLine(bulkheads.explres);
+ // const thermDim = dimReturnLine(bulkheads.thermres);
+ // const kinDim = dimReturnLine(bulkheads.kinres);
+ // if (res.expl > explDim) {
+ // const overage = (res.expl - explDim) * 0.5;
+ // res.expl = explDim + overage;
+ // hullExplDmg = explDim + overage;
+ // }
+ //
+ // if (res.therm > thermDim) {
+ // const overage = (res.therm - thermDim) * 0.5;
+ // res.therm = thermDim + overage;
+ // hullThermDmg = thermDim + overage;
+ // }
+ //
+ // if (res.kin > kinDim) {
+ // const overage = (res.kin - kinDim) * 0.5;
+ // res.kin = kinDim + overage;
+ // hullKinDmg = kinDim + overage;
+ // }
+
// Apply diminishing returns
- hullExplDmg = hullExplDmg > 0.7 ? hullExplDmg : 0.7 - (0.7 - hullExplDmg) / 2;
- hullKinDmg = hullKinDmg > 0.7 ? hullKinDmg : 0.7 - (0.7 - hullKinDmg) / 2;
- hullThermDmg = hullThermDmg > 0.7 ? hullThermDmg : 0.7 - (0.7 - hullThermDmg) / 2;
+ // hullExplDmg = hullExplDmg > 0.7 ? hullExplDmg : 0.7 - (0.7 - hullExplDmg) / 2;
+ // hullKinDmg = hullKinDmg > 0.7 ? hullKinDmg : 0.7 - (0.7 - hullKinDmg) / 2;
+ // hullThermDmg = hullThermDmg > 0.7 ? hullThermDmg : 0.7 - (0.7 - hullThermDmg) / 2;
const armour = {
bulkheads: armourBulkheads,
@@ -524,21 +616,23 @@ export function armourMetrics(ship) {
armour.explosive = {
bulkheads: 1 - ship.bulkheads.m.getExplosiveResistance(),
reinforcement: hullExplDmg,
- total: (1 - ship.bulkheads.m.getExplosiveResistance()) * hullExplDmg
+ total: (1 - ship.bulkheads.m.getExplosiveResistance()) * hullExplDmg,
+ res: 1 - hullExplDmg
};
armour.kinetic = {
bulkheads: 1 - ship.bulkheads.m.getKineticResistance(),
reinforcement: hullKinDmg,
- total: (1 - ship.bulkheads.m.getKineticResistance()) * hullKinDmg
+ total: (1 - ship.bulkheads.m.getKineticResistance()) * hullKinDmg,
+ res: 1 - hullKinDmg
};
armour.thermal = {
bulkheads: 1 - ship.bulkheads.m.getThermalResistance(),
reinforcement: hullThermDmg,
- total: (1 - ship.bulkheads.m.getThermalResistance()) * hullThermDmg
+ total: (1 - ship.bulkheads.m.getThermalResistance()) * hullThermDmg,
+ res: 1 - hullThermDmg
};
-
return armour;
}
diff --git a/src/app/shipyard/Constants.js b/src/app/shipyard/Constants.js
index 70569e65..ce3788bb 100755
--- a/src/app/shipyard/Constants.js
+++ b/src/app/shipyard/Constants.js
@@ -52,6 +52,8 @@ export const ModuleGroupToName = {
pcq: 'Luxury Passenger Cabin',
cc: 'Collector Limpet Controller',
ss: 'Surface Scanner',
+ gsrp: 'Guardian Shield Reinforcement Packages',
+ gfsb: 'Guardian Frame Shift Drive Booster',
// Hard Points
bl: 'Beam Laser',
diff --git a/src/app/shipyard/Module.js b/src/app/shipyard/Module.js
index 193f37d2..888d8e27 100755
--- a/src/app/shipyard/Module.js
+++ b/src/app/shipyard/Module.js
@@ -649,6 +649,22 @@ export default class Module {
return this._getModifiedValue('shieldreinforcement');
}
+ /**
+ * Get the shield addition for this module, taking in to account modifications
+ * @return {Number} the shield addition for this module
+ */
+ getShieldAddition() {
+ return this._getModifiedValue('shieldaddition');
+ }
+
+ /**
+ * Get the jump range boost for this module, taking in to account modifications
+ * @return {Number} the jump range boost for this module
+ */
+ getJumpBoost() {
+ return this._getModifiedValue('jumpboost');
+ }
+
/**
* Get the piercing for this module, taking in to account modifications
* @return {Number} the piercing for this module
diff --git a/src/app/shipyard/Ship.js b/src/app/shipyard/Ship.js
index 3e81877e..a7be5860 100755
--- a/src/app/shipyard/Ship.js
+++ b/src/app/shipyard/Ship.js
@@ -9,7 +9,7 @@ import isEqual from 'lodash/lang';
import { Ships, Modifications } from 'coriolis-data/dist';
const zlib = require('zlib');
-const UNIQUE_MODULES = ['psg', 'sg', 'bsg', 'rf', 'fs', 'fh'];
+const UNIQUE_MODULES = ['psg', 'sg', 'bsg', 'rf', 'fs', 'fh', 'gfsb'];
// Constants for modifications struct
const SLOT_ID_DONE = -1;
@@ -151,7 +151,7 @@ export default class Ship {
* @return {Number} Jump range in Light Years
*/
calcLadenRange(massDelta, fuel, fsd) {
- return Calc.jumpRange(this.ladenMass + (massDelta || 0), fsd || this.standard[2].m, fuel);
+ return Calc.jumpRange(this.ladenMass + (massDelta || 0), fsd || this.standard[2].m, fuel, this);
}
/**
@@ -164,7 +164,7 @@ export default class Ship {
calcUnladenRange(massDelta, fuel, fsd) {
fsd = fsd || this.standard[2].m;
let fsdMaxFuelPerJump = fsd instanceof Module ? fsd.getMaxFuelPerJump() : fsd.maxfuel;
- return Calc.jumpRange(this.unladenMass + (massDelta || 0) + Math.min(fsdMaxFuelPerJump, fuel || this.fuelCapacity), fsd || this.standard[2].m, fuel);
+ return Calc.jumpRange(this.unladenMass + (massDelta || 0) + Math.min(fsdMaxFuelPerJump, fuel || this.fuelCapacity), fsd || this.standard[2].m, fuel, this);
}
/**
@@ -239,7 +239,6 @@ export default class Ship {
}
sg = sgSlot.m;
}
-
// TODO Not accurate if the ship has modified shield boosters
return Calc.shieldStrength(this.hullMass, this.baseShieldStrength, sg, 1 + (multiplierDelta || 0));
}
@@ -943,7 +942,7 @@ export default class Ship {
let armourChange = (slot === this.bulkheads) || (n && n.grp === 'hr') || (old && old.grp === 'hr') || (n && n.grp === 'mrp') || (old && old.grp === 'mrp');
- let shieldChange = (n && n.grp === 'bsg') || (old && old.grp === 'bsg') || (n && n.grp === 'psg') || (old && old.grp === 'psg') || (n && n.grp === 'sg') || (old && old.grp === 'sg') || (n && n.grp === 'sb') || (old && old.grp === 'sb');
+ let shieldChange = (n && n.grp === 'bsg') || (old && old.grp === 'bsg') || (n && n.grp === 'psg') || (old && old.grp === 'psg') || (n && n.grp === 'sg') || (old && old.grp === 'sg') || (n && n.grp === 'sb') || (old && old.grp === 'sb') || (old && old.grp === 'gsrp') || (n && n.grp === 'gsrp');
let shieldCellsChange = (n && n.grp === 'scb') || (old && old.grp === 'scb');
@@ -1277,7 +1276,7 @@ export default class Ship {
// Obtain shield metrics with 0 pips to sys (parts affected by SYS aren't used here)
const metrics = Calc.shieldMetrics(this, 0);
- this.shield = metrics.generator ? metrics.generator + metrics.boosters : 0;
+ this.shield = metrics.generator ? metrics.generator + metrics.boosters + metrics.addition : 0;
this.shieldExplRes = this.shield > 0 ? 1 - metrics.explosive.total : null;
this.shieldKinRes = this.shield > 0 ? 1 - metrics.kinetic.total : null;
this.shieldThermRes = this.shield > 0 ? 1 - metrics.thermal.total : null;
@@ -1360,10 +1359,10 @@ export default class Ship {
let fsd = this.standard[2].m; // Frame Shift Drive;
let { unladenMass, fuelCapacity } = this;
this.unladenRange = this.calcUnladenRange(); // Includes fuel weight for jump
- this.fullTankRange = Calc.jumpRange(unladenMass + fuelCapacity, fsd); // Full Tank
+ this.fullTankRange = Calc.jumpRange(unladenMass + fuelCapacity, fsd, this); // Full Tank
this.ladenRange = this.calcLadenRange(); // Includes full tank and caro
- this.unladenFastestRange = Calc.totalJumpRange(unladenMass + this.fuelCapacity, fsd, fuelCapacity);
- this.ladenFastestRange = Calc.totalJumpRange(unladenMass + this.fuelCapacity + this.cargoCapacity, fsd, fuelCapacity);
+ this.unladenFastestRange = Calc.totalJumpRange(unladenMass + this.fuelCapacity, fsd, fuelCapacity, this);
+ this.ladenFastestRange = Calc.totalJumpRange(unladenMass + this.fuelCapacity + this.cargoCapacity, fsd, fuelCapacity, this);
this.maxJumpCount = Math.ceil(fuelCapacity / fsd.getMaxFuelPerJump());
return this;
}
diff --git a/src/app/stores/Persist.js b/src/app/stores/Persist.js
index dc162909..2d00628e 100644
--- a/src/app/stores/Persist.js
+++ b/src/app/stores/Persist.js
@@ -87,7 +87,7 @@ export class Persist extends EventEmitter {
let moduleResistances = _get(LS_KEY_MODULE_RESISTANCES);
let matsPerGrade = _get(LS_KEY_ROLLS);
- let cmdrName = _getString(LS_KEY_CMDR_NAME);
+ let cmdrName = _get(LS_KEY_CMDR_NAME);
let tips = _get(LS_KEY_TOOLTIPS);
let insurance = _getString(LS_KEY_INSURANCE);
let shipDiscount = _get(LS_KEY_SHIP_DISCOUNT);
@@ -113,7 +113,7 @@ export class Persist extends EventEmitter {
4: 4,
5: 10
};
- this.cmdrName = cmdrName || '';
+ this.cmdrName = cmdrName || { selected: '', cmdrs: [] };
this.tooltipsEnabled = tips === null ? true : tips;
this.moduleResistancesEnabled = moduleResistances === null ? true : moduleResistances;
@@ -509,7 +509,7 @@ export class Persist extends EventEmitter {
/**
* Persist cmdr name
- * @param {string} cmdrName Commander name for EDEngineer
+ * @param {Object} cmdrName Commander name for EDEngineer
*/
setCmdr(cmdrName) {
this.cmdrName = cmdrName;
diff --git a/src/app/utils/CompanionApiUtils.js b/src/app/utils/CompanionApiUtils.js
index 1755bb27..325f32b9 100644
--- a/src/app/utils/CompanionApiUtils.js
+++ b/src/app/utils/CompanionApiUtils.js
@@ -29,6 +29,7 @@ const SHIP_FD_NAME_TO_CORIOLIS_NAME = {
'FerDeLance': 'fer_de_lance',
'Hauler': 'hauler',
'Independant_Trader': 'keelback',
+ 'Krait_MkII': 'krait_mkii',
'Orca': 'orca',
'Python': 'python',
'SideWinder': 'sidewinder',
@@ -37,6 +38,7 @@ const SHIP_FD_NAME_TO_CORIOLIS_NAME = {
'Type9': 'type_9_heavy',
'Type9_Military': 'type_10_defender',
'TypeX': 'alliance_chieftain',
+ 'TypeX_3': 'alliance_challenger',
'Viper': 'viper',
'Viper_MkIV': 'viper_mk_iv',
'Vulture': 'vulture'
diff --git a/src/app/utils/JournalUtils.js b/src/app/utils/JournalUtils.js
index cbfd7e45..e9094544 100644
--- a/src/app/utils/JournalUtils.js
+++ b/src/app/utils/JournalUtils.js
@@ -70,7 +70,7 @@ export function shipFromLoadoutJSON(json) {
let ship = new Ship(shipModel, shipTemplate.properties, shipTemplate.slots);
ship.buildWith(null);
// Initial Ship building, don't do engineering yet.
- let opts = [];
+ let modsToAdd = [];
for (const module of json.Modules) {
switch (module.Slot.toLowerCase()) {
@@ -176,7 +176,7 @@ export function shipFromLoadoutJSON(json) {
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 });
+ modsToAdd.push({ coriolisMod: hardpoint, json: hardpointSlot });
}
hardpointArrayNum++;
}
@@ -185,6 +185,9 @@ export function shipFromLoadoutJSON(json) {
let internalSlotNum = 1;
let militarySlotNum = 1;
for (let i in shipTemplate.slots.internal) {
+ if (!shipTemplate.slots.internal.hasOwnProperty(i)) {
+ continue;
+ }
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
@@ -198,7 +201,7 @@ export function shipFromLoadoutJSON(json) {
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;
+ const internalName = 'Slot' + (internalSlotNum <= 9 ? '0' : '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;
@@ -210,23 +213,23 @@ export function shipFromLoadoutJSON(json) {
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 });
+ modsToAdd.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);
+ for (const i of modsToAdd) {
+ 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) {
diff --git a/src/less/select.less b/src/less/select.less
index 81b80a1a..012baa18 100755
--- a/src/less/select.less
+++ b/src/less/select.less
@@ -22,6 +22,11 @@ select {
}
}
+.cmdr-select {
+ border: 1px solid @primary;
+ padding: 0.5em 0.5em;
+}
+
.select {
color: @primary-disabled;
position: absolute;