mirror of
https://github.com/EDCD/coriolis.git
synced 2025-12-09 22:55:35 +00:00
Compare commits
20 Commits
0c3de95025
...
dw2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9abb4f6d05 | ||
|
|
38038fcc32 | ||
|
|
9fa740f54e | ||
|
|
d37d69c3a7 | ||
|
|
78d8779641 | ||
|
|
352023f0fb | ||
|
|
3ea194d43e | ||
|
|
c6269192f0 | ||
|
|
841e6c3348 | ||
|
|
0febc581d1 | ||
|
|
dc6e398526 | ||
|
|
cb24c1fc69 | ||
|
|
90ad9de831 | ||
|
|
9360b1d574 | ||
|
|
08d2573d1f | ||
|
|
427b9af7de | ||
|
|
318d06d9f9 | ||
|
|
1f3c3726f2 | ||
|
|
71beda3a6c | ||
|
|
1d6644b531 |
77
.dockerignore
Normal file
77
.dockerignore
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
node_modules
|
||||||
|
npm-debug.log
|
||||||
|
### Node template
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
pids
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
*.pid.lock
|
||||||
|
|
||||||
|
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||||
|
lib-cov
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
coverage
|
||||||
|
|
||||||
|
# nyc test coverage
|
||||||
|
.nyc_output
|
||||||
|
|
||||||
|
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||||
|
.grunt
|
||||||
|
|
||||||
|
# Bower dependency directory (https://bower.io/)
|
||||||
|
bower_components
|
||||||
|
|
||||||
|
# node-waf configuration
|
||||||
|
.lock-wscript
|
||||||
|
|
||||||
|
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||||
|
build/Release
|
||||||
|
|
||||||
|
# Dependency directories
|
||||||
|
node_modules/
|
||||||
|
jspm_packages/
|
||||||
|
|
||||||
|
# TypeScript v1 declaration files
|
||||||
|
typings/
|
||||||
|
|
||||||
|
# Optional npm cache directory
|
||||||
|
.npm
|
||||||
|
|
||||||
|
# Optional eslint cache
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
|
# Optional REPL history
|
||||||
|
.node_repl_history
|
||||||
|
|
||||||
|
# Output of 'npm pack'
|
||||||
|
*.tgz
|
||||||
|
|
||||||
|
# Yarn Integrity file
|
||||||
|
.yarn-integrity
|
||||||
|
|
||||||
|
# dotenv environment variables file
|
||||||
|
.env
|
||||||
|
|
||||||
|
# parcel-bundler cache (https://parceljs.org/)
|
||||||
|
.cache
|
||||||
|
|
||||||
|
# next.js build output
|
||||||
|
.next
|
||||||
|
|
||||||
|
# nuxt.js build output
|
||||||
|
.nuxt
|
||||||
|
|
||||||
|
# vuepress build output
|
||||||
|
.vuepress/dist
|
||||||
|
|
||||||
|
# Serverless directories
|
||||||
|
.serverless
|
||||||
|
|
||||||
34
Dockerfile
Normal file
34
Dockerfile
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
### STAGE 1: Build ###
|
||||||
|
FROM node:9.11.1-alpine as builder
|
||||||
|
ARG branch=develop
|
||||||
|
ENV BRANCH=$branch
|
||||||
|
WORKDIR /src/app
|
||||||
|
RUN mkdir -p /src/app/coriolis
|
||||||
|
RUN mkdir -p /src/app/coriolis-data
|
||||||
|
|
||||||
|
RUN apk add --update git
|
||||||
|
|
||||||
|
COPY . /src/app/coriolis
|
||||||
|
|
||||||
|
RUN npm i -g npm
|
||||||
|
|
||||||
|
# Set up coriolis-data
|
||||||
|
WORKDIR /src/app/coriolis-data
|
||||||
|
RUN git clone https://github.com/EDCD/coriolis-data.git .
|
||||||
|
RUN git checkout ${BRANCH}
|
||||||
|
RUN npm install --no-package-lock
|
||||||
|
RUN npm start
|
||||||
|
|
||||||
|
# Set up coriolis
|
||||||
|
WORKDIR /src/app/coriolis
|
||||||
|
RUN npm install --no-package-lock
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
|
||||||
|
### STAGE 2: Production Environment ###
|
||||||
|
FROM fholzer/nginx-brotli as web
|
||||||
|
COPY nginx.conf /etc/nginx/nginx.conf
|
||||||
|
COPY --from=builder /src/app/coriolis/build /usr/share/nginx/html
|
||||||
|
WORKDIR /usr/share/nginx/html
|
||||||
|
EXPOSE 80
|
||||||
|
CMD ["nginx", "-c", "/etc/nginx/nginx.conf", "-g", "daemon off;"]
|
||||||
24
LICENSE.md
24
LICENSE.md
@@ -1,24 +0,0 @@
|
|||||||
All Data and [associated JSON](https://github.com/EDCD/coriolis-data) files are intellectual property and copyright of Frontier Developments plc ('Frontier', 'Frontier Developments') and are subject to their
|
|
||||||
[terms and conditions](https://www.frontierstore.net/terms-and-conditions/).
|
|
||||||
|
|
||||||
The code (Javascript, CSS, HTML, and SVG files only) specificially for Coriolis.io is released under the MIT License.
|
|
||||||
|
|
||||||
Copyright (c) 2015 Coriolis.io, Colin McLeod
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software (Javascript, CSS, HTML, and SVG files only), and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
THE SOFTWARE.
|
|
||||||
@@ -10,6 +10,11 @@ Coriolis was created using assets and imagery from Elite: Dangerous, with the pe
|
|||||||
|
|
||||||
Please [submit issues](https://github.com/EDCD/coriolis/issues), or better yet [pull requests](https://github.com/EDCD/coriolis/pulls) for any corrections or additions to the database or the code.
|
Please [submit issues](https://github.com/EDCD/coriolis/issues), or better yet [pull requests](https://github.com/EDCD/coriolis/pulls) for any corrections or additions to the database or the code.
|
||||||
|
|
||||||
|
### Translations
|
||||||
|
|
||||||
|
Please use the OneSky translation site to suggest new translations: http://edcd-coriolis.oneskyapp.com
|
||||||
|
These will be merged regularly by the project manager.
|
||||||
|
|
||||||
### Feature Requests, Suggestions & Bugs
|
### Feature Requests, Suggestions & Bugs
|
||||||
|
|
||||||
Chat to us on [Discord](https://discord.gg/0uwCh6R62aPRjk9w)!
|
Chat to us on [Discord](https://discord.gg/0uwCh6R62aPRjk9w)!
|
||||||
@@ -18,12 +23,12 @@ 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.
|
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
|
### Ship and Module Database
|
||||||
|
|
||||||
See the [Data wiki](https://github.com/cmmcleod/coriolis-data/wiki) for details on structure, etc.
|
See the [Data wiki](https://github.com/cmmcleod/coriolis-data/wiki) for details on structure, etc.
|
||||||
|
|
||||||
You can find hosted and compiled versions of these data-jsons under https://coriolis.io/data/ and https://beta.coriolis.io/data/.
|
|
||||||
You might want to load these as depedency instead of reyling on the npm-dependency.
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
|||||||
@@ -1,50 +1,50 @@
|
|||||||
{
|
{
|
||||||
"type_6_transporter": {
|
"type_6_transporter": {
|
||||||
"Cargo": "A0p0tdFal8d8s8f4-----04040303430101-.Iw18UA==.Aw18UA==.",
|
"Cargo": "A0p0tdFal8d8s8f4-----04040303430101.Iw1/kA==.Aw1/kA==.",
|
||||||
"Miner": "A0p5tdFal8d8s8f42l2l---040403451q0101-.Iw18UA==.Aw18UA==.",
|
"Miner": "A0p5tdFal8d8s8f42l2l---040403451q0101.Iw1/kA==.Aw1/kA==.",
|
||||||
"Hopper": "A0p0tdFal8d0s8f41717---030302024300--.Iw18UA==.Aw18UA==."
|
"Hopper": "A0p0tdFal8d0s8f41717---030302024300-.Iw1/kA==.Aw1/kA==."
|
||||||
},
|
},
|
||||||
"type_7_transport": {
|
"type_7_transport": {
|
||||||
"Cargo": "A0p0tiFfliddsdf5--------0505040403480101--.Iw18eQ==.Aw18eQ==.",
|
"Cargo": "A0p0tiFfliddsdf5--------0505040403480101.Iw18aQ==.Aw18aQ==.",
|
||||||
"Miner": "A0pdtiFflid8sdf5--2l2l----0505041v03450000--.Iw18eQ==.Aw18eQ==."
|
"Miner": "A0pdtiFflid8sdf5--2l2l----0505041v03450000.Iw18aQ==.Aw18aQ==."
|
||||||
},
|
},
|
||||||
"federal_dropship": {
|
"federal_dropship": {
|
||||||
"Cargo": "A0pdtiFflnddsif4-1717------05040448--020201-.Iw18RQ==.Aw18RQ==."
|
"Cargo": "A0pdtiFflnddsif4-1717------05040448--020201.Iw18eQ==.Aw18eQ==."
|
||||||
},
|
},
|
||||||
"asp": {
|
"asp": {
|
||||||
"Miner": "A2pftfFflidfskf50s0s24242l2l---04054a1q02022o27-.Iw18eQ==.Aw18eQ==."
|
"Miner": "A2pftfFflidfskf50s0s24242l2l---04054a1q02022o27.Iw18WQ==.Aw18WQ==."
|
||||||
},
|
},
|
||||||
"imperial_clipper": {
|
"imperial_clipper": {
|
||||||
"Cargo": "A0p5tiFflndisnf4--0s0s----0605450302020101-.Iw18WQ==.Aw18WQ==.",
|
"Cargo": "A0p5tiFflndisnf4--0s0s----0605450302020101.Iw18aQ==.Aw18aQ==.",
|
||||||
"Dream": "A2pktkFflndpskf40v0v0s0s0404040n4k5n5d2b29292o--.AwRj4yWU1Yg=.CwBhCYy6YRigzPIA.",
|
"Dream": "A2pktkFflndpskf40v0v0s0s0404040n4k5n5d2b29292o-.AwRj4yWU1I==.CwBhCYy6YRigzLIA.",
|
||||||
"Current": "A0patkFflndfskf4-----------------.AwRj4yWU1Yg=.CwBhCYy6YRigzPIA."
|
"Current": "A0patkFflndfskf4----------------.AwRj4yWU1I==.CwBhCYy6YRigzLIA."
|
||||||
},
|
},
|
||||||
"type_9_heavy": {
|
"type_9_heavy": {
|
||||||
"Current": "A0patsFklndnsif6---------0706054a0303020224--.AwRj4yo5iA==.EwBhEYy6d6g=."
|
"Current": "A0patsFklndnsif6---------0706054a0303020224.AwRj4yoo.EwBhEYy6dsg=."
|
||||||
},
|
},
|
||||||
"python": {
|
"python": {
|
||||||
"Cargo": "A0patnFflidsssf5---------050505040448020201-.Iw18eAMQ.Aw18RQ==.",
|
"Cargo": "A0patnFflidsssf5---------050505040448020201.Iw18eQ==.Aw18eQ==.",
|
||||||
"Miner": "A0pktkFflidpspf50v0v0v2m2m0404--050505Ce4a1v02022o-.Iw18eAMQ.IwBhBYy6dkCYRA==.",
|
"Miner": "A0pktkFflidpspf50v0v0v2m2m0404--050505Ce4a1v02022o.Iw18eQ==.IwBhBYy6dkCYg===.",
|
||||||
"Dream": "A2pptkFfliduspf50v0v0v27270404040m5n5n4f2d2d032t0201-.Iw1+gDByUA==.EwBhEYy6e0VEA===.",
|
"Dream": "A2pptkFfliduspf50v0v0v27270404040m5n5n4f2d2d032t0201.Iw1+gDBxA===.EwBhEYy6e0WEA===.",
|
||||||
"Missile": "A0pttoFjljdystf52f2g2d2ePh----04044j03---00--.Iw18eAMQ.Aw18RQ==."
|
"Missile": "A0pttoFjljdystf52f2g2d2ePh----04044j03---002h.Iw18eQ==.Aw18eQ==."
|
||||||
},
|
},
|
||||||
"anaconda": {
|
"anaconda": {
|
||||||
"Dream": "A4putpFklndzsuf52c0o0o0o1m1m0q0q0404040l0b0100004k5n5n112d2d04-0303326b-.AwRj4yo5dzhA.MwBhCYy6duvARhEA.",
|
"Dream": "A4putpFklndzsuf52c0o0o0o1m1m0q0q0404040l0b0100004k5n5n112d2d04-0303326b.AwRj4yo5dyg=.MwBhCYy6duvARiA=.",
|
||||||
"Cargo": "A0patnFklndnsxf5----------------06050505040404-45030301-.Iw18ZUAxA===.Aw18ZXEA.",
|
"Cargo": "A0patnFklndnsxf5----------------06050505040404-45030301.Iw18ZVA=.Aw18ZVA=.",
|
||||||
"Current": "A0patnFklndksxf5----------------06050505040404-03034524-.Iw18ZUAxA===.Aw18ZXEA.",
|
"Current": "A0patnFklndksxf5----------------06050505040404-03034524.Iw18ZVA=.Aw18ZVA=.",
|
||||||
"Explorer": "A0patnFklndksxf5--------0202------f7050505040s37--2i4524-.AwRj4yVKJ9jCA===.AwhMIyumQRgkA===.",
|
"Explorer": "A0patnFklndksxf5--------0202------f7050505040s37-2f2i4524.AwRj4yVKJ9hA.AwhMIyumQRhEA===.",
|
||||||
"Test": "A4putkFklkdzsuf52c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04---0303326b-.Iw18ZUAxA===.Aw18ZXEA."
|
"Test": "A4putkFklkdzsuf52c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04---0303326b.Iw18ZVA=.Aw18ZVA=."
|
||||||
},
|
},
|
||||||
"diamondback_explorer": {
|
"diamondback_explorer": {
|
||||||
"Explorer": "A0p0tdFfldddsdf5---0202--320p432i----.AwRj4zTZaA==.AwiMIyqo."
|
"Explorer": "A0p0tdFfldddsdf5---0202--320p432i2f-.AwRj4zTYg===.AwiMIyoo."
|
||||||
},
|
},
|
||||||
"vulture": {
|
"vulture": {
|
||||||
"Bounty Hunter": "A3patcFalddksff31e1e0404-0l4a-5d27662j--.AwRj4z2Gg===.MwBhBYy6oJmAjLMQ."
|
"Bounty Hunter": "A3patcFalddksff31e1e0404-0l4a-5d27662j.AwRj4z2I.MwBhBYy6oJmAjLIA."
|
||||||
},
|
},
|
||||||
"fer_de_lance": {
|
"fer_de_lance": {
|
||||||
"Attack": "A2pfthFalidpsff31r0s0s0s0s000404-04-4a-5d27--.Iw18aAMQ.CwBhrSu8EZxEA===."
|
"Attack": "A2pfthFalidpsff31r0s0s0s0s000404-04-4a-5d27-.Iw18aQ==.CwBhrSu8EZyA."
|
||||||
},
|
},
|
||||||
"eagle": {
|
"eagle": {
|
||||||
"Figther": "A4p0t5F5l3d5s5f20p0p24-4053-2j---.Iw18gDJQ.Aw19kA==."
|
"Figther": "A4p0t5F5l3d5s5f20p0p24-4053-2j-.Iw18kA==.Aw18kA==."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,366 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"header": {
|
|
||||||
"appName": "Inara",
|
|
||||||
"appVersion": "1.0",
|
|
||||||
"appURL": "https:\/\/inara.cz\/cmdr-fleet\/123\/123\/",
|
|
||||||
"appCustomProperties": {
|
|
||||||
"inaraCommanderID": 123,
|
|
||||||
"inaraShipID": 123
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"data": {
|
|
||||||
"Ship": "krait_mkii",
|
|
||||||
"ShipID": 7,
|
|
||||||
"ShipName": "pancake hammer",
|
|
||||||
"ShipIdent": "PH-01",
|
|
||||||
"HullValue": 44160710,
|
|
||||||
"ModulesValue": 111274094,
|
|
||||||
"Rebuy": 7771743,
|
|
||||||
"Modules": [
|
|
||||||
{
|
|
||||||
"Slot": "largehardpoint1",
|
|
||||||
"Item": "hpt_mininglaser_fixed_small",
|
|
||||||
"On": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "largehardpoint2",
|
|
||||||
"Item": "hpt_cannon_gimbal_large",
|
|
||||||
"On": true,
|
|
||||||
"Engineering": {
|
|
||||||
"BlueprintName": "weapon_overcharged",
|
|
||||||
"Level": 2,
|
|
||||||
"Quality": 1,
|
|
||||||
"ExperimentalEffect": "special_auto_loader"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "largehardpoint3",
|
|
||||||
"Item": "hpt_cannon_gimbal_large",
|
|
||||||
"On": true,
|
|
||||||
"Engineering": {
|
|
||||||
"BlueprintName": "weapon_overcharged",
|
|
||||||
"Level": 2,
|
|
||||||
"Quality": 1,
|
|
||||||
"ExperimentalEffect": "special_auto_loader"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "mediumhardpoint1",
|
|
||||||
"Item": "hpt_basicmissilerack_fixed_medium",
|
|
||||||
"On": true,
|
|
||||||
"Engineering": {
|
|
||||||
"BlueprintName": "weapon_highcapacity",
|
|
||||||
"Level": 5,
|
|
||||||
"Quality": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "mediumhardpoint2",
|
|
||||||
"Item": "hpt_basicmissilerack_fixed_medium",
|
|
||||||
"On": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "tinyhardpoint1",
|
|
||||||
"Item": "hpt_heatsinklauncher_turret_tiny",
|
|
||||||
"On": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "tinyhardpoint2",
|
|
||||||
"Item": "hpt_cloudscanner_size0_class3",
|
|
||||||
"On": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "tinyhardpoint3",
|
|
||||||
"Item": "hpt_shieldbooster_size0_class5",
|
|
||||||
"On": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "tinyhardpoint4",
|
|
||||||
"Item": "hpt_shieldbooster_size0_class5",
|
|
||||||
"On": true,
|
|
||||||
"Priority": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "slot01_size6",
|
|
||||||
"Item": "int_cargorack_size6_class1",
|
|
||||||
"On": true,
|
|
||||||
"Priority": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "slot02_size6",
|
|
||||||
"Item": "int_cargorack_size6_class1",
|
|
||||||
"On": true,
|
|
||||||
"Priority": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "slot03_size5",
|
|
||||||
"Item": "int_guardianfsdbooster_size5",
|
|
||||||
"On": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "slot04_size5",
|
|
||||||
"Item": "int_fighterbay_size5_class1",
|
|
||||||
"On": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "slot05_size4",
|
|
||||||
"Item": "int_shieldgenerator_size4_class5",
|
|
||||||
"On": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "slot06_size3",
|
|
||||||
"Item": "int_dronecontrol_collection_size3_class4",
|
|
||||||
"On": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "slot07_size3",
|
|
||||||
"Item": "int_dronecontrol_collection_size3_class4",
|
|
||||||
"On": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "slot08_size2",
|
|
||||||
"Item": "int_refinery_size2_class2",
|
|
||||||
"On": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "slot09_size1",
|
|
||||||
"Item": "int_dronecontrol_prospector_size1_class4",
|
|
||||||
"On": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "powerplant",
|
|
||||||
"Item": "int_powerplant_size7_class5",
|
|
||||||
"On": true,
|
|
||||||
"Priority": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "mainengines",
|
|
||||||
"Item": "int_engine_size6_class5",
|
|
||||||
"On": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "frameshiftdrive",
|
|
||||||
"Item": "int_hyperdrive_size5_class5",
|
|
||||||
"On": true,
|
|
||||||
"Engineering": {
|
|
||||||
"BlueprintName": "fsd_longrange",
|
|
||||||
"Level": 2,
|
|
||||||
"Quality": 0.861
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "lifesupport",
|
|
||||||
"Item": "int_lifesupport_size4_class2",
|
|
||||||
"On": true,
|
|
||||||
"Priority": 3
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "powerdistributor",
|
|
||||||
"Item": "int_powerdistributor_size7_class5",
|
|
||||||
"On": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "radar",
|
|
||||||
"Item": "int_sensors_size6_class2",
|
|
||||||
"On": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "fueltank",
|
|
||||||
"Item": "int_fueltank_size5_class3",
|
|
||||||
"On": true,
|
|
||||||
"Priority": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "armour",
|
|
||||||
"Item": "krait_mkii_armour_grade3",
|
|
||||||
"On": true,
|
|
||||||
"Priority": 1,
|
|
||||||
"Engineering": {
|
|
||||||
"BlueprintName": "armour_heavyduty",
|
|
||||||
"Level": 5,
|
|
||||||
"Quality": 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"header": {
|
|
||||||
"appName": "Inara",
|
|
||||||
"appVersion": "1.0",
|
|
||||||
"appURL": "https:\/\/inara.cz\/cmdr-fleet\/123\/123\/",
|
|
||||||
"appCustomProperties": {
|
|
||||||
"inaraCommanderID": 123,
|
|
||||||
"inaraShipID": 123
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"data": {
|
|
||||||
"Ship": "diamondbackxl",
|
|
||||||
"ShipID": 11,
|
|
||||||
"ShipName": "star Hopper",
|
|
||||||
"ShipIdent": "PH-02",
|
|
||||||
"HullValue": 1615649,
|
|
||||||
"ModulesValue": 16981039,
|
|
||||||
"Rebuy": 929837,
|
|
||||||
"Modules": [
|
|
||||||
{
|
|
||||||
"Slot": "tinyhardpoint1",
|
|
||||||
"Item": "hpt_heatsinklauncher_turret_tiny",
|
|
||||||
"On": true,
|
|
||||||
"Value": 3072
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "slot01_size4",
|
|
||||||
"Item": "int_fuelscoop_size4_class5",
|
|
||||||
"On": true,
|
|
||||||
"Priority": 3,
|
|
||||||
"Value": 2862364
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "slot02_size4",
|
|
||||||
"Item": "int_guardianfsdbooster_size4",
|
|
||||||
"On": true,
|
|
||||||
"Value": 2847499
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "slot03_size3",
|
|
||||||
"Item": "int_shieldgenerator_size3_class2",
|
|
||||||
"On": true,
|
|
||||||
"Value": 18812,
|
|
||||||
"Engineering": {
|
|
||||||
"BlueprintName": "shieldgenerator_thermic",
|
|
||||||
"Level": 3,
|
|
||||||
"Quality": 1,
|
|
||||||
"ExperimentalEffect": "special_shield_health"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "slot04_size3",
|
|
||||||
"Item": "int_repairer_size3_class5",
|
|
||||||
"On": true,
|
|
||||||
"Value": 2302911
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "slot05_size2",
|
|
||||||
"Item": "int_buggybay_size2_class2",
|
|
||||||
"On": true,
|
|
||||||
"Priority": 3,
|
|
||||||
"Value": 21600
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "slot06_size2",
|
|
||||||
"Item": "int_cargorack_size2_class1",
|
|
||||||
"On": true,
|
|
||||||
"Priority": 1,
|
|
||||||
"Value": 2852
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "slot07_size1",
|
|
||||||
"Item": "int_supercruiseassist",
|
|
||||||
"On": true,
|
|
||||||
"Priority": 3,
|
|
||||||
"Value": 9121
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "slot08_size1",
|
|
||||||
"Item": "int_detailedsurfacescanner_tiny",
|
|
||||||
"On": true,
|
|
||||||
"Value": 250000,
|
|
||||||
"Engineering": {
|
|
||||||
"BlueprintName": "sensor_expanded",
|
|
||||||
"Level": 5,
|
|
||||||
"Quality": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "powerplant",
|
|
||||||
"Item": "int_powerplant_size4_class5",
|
|
||||||
"On": true,
|
|
||||||
"Priority": 1,
|
|
||||||
"Value": 1441233,
|
|
||||||
"Engineering": {
|
|
||||||
"BlueprintName": "powerplant_boosted",
|
|
||||||
"Level": 1,
|
|
||||||
"Quality": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "mainengines",
|
|
||||||
"Item": "int_engine_size4_class5",
|
|
||||||
"On": true,
|
|
||||||
"Value": 1610080,
|
|
||||||
"Engineering": {
|
|
||||||
"BlueprintName": "engine_dirty",
|
|
||||||
"Level": 5,
|
|
||||||
"Quality": 1,
|
|
||||||
"ExperimentalEffect": "special_engine_lightweight"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "frameshiftdrive",
|
|
||||||
"Item": "int_hyperdrive_size5_class5",
|
|
||||||
"On": true,
|
|
||||||
"Value": 5103953,
|
|
||||||
"Engineering": {
|
|
||||||
"BlueprintName": "fsd_longrange",
|
|
||||||
"Level": 5,
|
|
||||||
"Quality": 1,
|
|
||||||
"ExperimentalEffect": "special_fsd_lightweight"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "lifesupport",
|
|
||||||
"Item": "int_lifesupport_size3_class2",
|
|
||||||
"On": true,
|
|
||||||
"Value": 10133,
|
|
||||||
"Engineering": {
|
|
||||||
"BlueprintName": "misc_lightweight",
|
|
||||||
"Level": 3,
|
|
||||||
"Quality": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "powerdistributor",
|
|
||||||
"Item": "int_powerdistributor_size4_class5",
|
|
||||||
"On": true,
|
|
||||||
"Value": 389022,
|
|
||||||
"Engineering": {
|
|
||||||
"BlueprintName": "powerdistributor_highfrequency",
|
|
||||||
"Level": 4,
|
|
||||||
"Quality": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "radar",
|
|
||||||
"Item": "int_sensors_size3_class2",
|
|
||||||
"On": true,
|
|
||||||
"Value": 10133,
|
|
||||||
"Engineering": {
|
|
||||||
"BlueprintName": "sensor_lightweight",
|
|
||||||
"Level": 5,
|
|
||||||
"Quality": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "fueltank",
|
|
||||||
"Item": "int_fueltank_size5_class3",
|
|
||||||
"On": true,
|
|
||||||
"Priority": 1,
|
|
||||||
"Value": 97754
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "armour",
|
|
||||||
"Item": "diamondbackxl_armour_grade1",
|
|
||||||
"On": true,
|
|
||||||
"Priority": 1,
|
|
||||||
"Engineering": {
|
|
||||||
"BlueprintName": "armour_heavyduty",
|
|
||||||
"Level": 5,
|
|
||||||
"Quality": 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"krait_mkii": {
|
|
||||||
"Imported pancake hammer": "A2pptkFflidussf52l1o1o2g2g020g040405051Ofr45C9C91oP3.Iw18eQ==.AwRgzKIkA===."
|
|
||||||
},
|
|
||||||
"diamondback_explorer": {
|
|
||||||
"Imported star Hopper": "A0pataFflddfsdf5---02---321P430iv6013w2i.Iw18SQ==.AwRm44GYpKg=."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,188 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"header": {
|
|
||||||
"appName": "Inara",
|
|
||||||
"appVersion": "1.0",
|
|
||||||
"appURL": "https:\/\/inara.cz\/cmdr-fleet\/123\/123\/",
|
|
||||||
"appCustomProperties": {
|
|
||||||
"inaraCommanderID": 123,
|
|
||||||
"inaraShipID": 123
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"data": {
|
|
||||||
"Ship": "krait_mkii",
|
|
||||||
"ShipID": 7,
|
|
||||||
"ShipName": "pancake hammer",
|
|
||||||
"ShipIdent": "PH-01",
|
|
||||||
"HullValue": 44160710,
|
|
||||||
"ModulesValue": 111274094,
|
|
||||||
"Rebuy": 7771743,
|
|
||||||
"Modules": [
|
|
||||||
{
|
|
||||||
"Slot": "largehardpoint1",
|
|
||||||
"Item": "hpt_mininglaser_fixed_small",
|
|
||||||
"On": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "largehardpoint2",
|
|
||||||
"Item": "hpt_cannon_gimbal_large",
|
|
||||||
"On": true,
|
|
||||||
"Engineering": {
|
|
||||||
"BlueprintName": "weapon_overcharged",
|
|
||||||
"Level": 2,
|
|
||||||
"Quality": 1,
|
|
||||||
"ExperimentalEffect": "special_auto_loader"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "largehardpoint3",
|
|
||||||
"Item": "hpt_cannon_gimbal_large",
|
|
||||||
"On": true,
|
|
||||||
"Engineering": {
|
|
||||||
"BlueprintName": "weapon_overcharged",
|
|
||||||
"Level": 2,
|
|
||||||
"Quality": 1,
|
|
||||||
"ExperimentalEffect": "special_auto_loader"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "mediumhardpoint1",
|
|
||||||
"Item": "hpt_basicmissilerack_fixed_medium",
|
|
||||||
"On": true,
|
|
||||||
"Engineering": {
|
|
||||||
"BlueprintName": "weapon_highcapacity",
|
|
||||||
"Level": 5,
|
|
||||||
"Quality": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "mediumhardpoint2",
|
|
||||||
"Item": "hpt_basicmissilerack_fixed_medium",
|
|
||||||
"On": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "tinyhardpoint1",
|
|
||||||
"Item": "hpt_heatsinklauncher_turret_tiny",
|
|
||||||
"On": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "tinyhardpoint2",
|
|
||||||
"Item": "hpt_cloudscanner_size0_class3",
|
|
||||||
"On": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "tinyhardpoint3",
|
|
||||||
"Item": "hpt_shieldbooster_size0_class5",
|
|
||||||
"On": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "tinyhardpoint4",
|
|
||||||
"Item": "hpt_shieldbooster_size0_class5",
|
|
||||||
"On": true,
|
|
||||||
"Priority": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "slot01_size6",
|
|
||||||
"Item": "int_cargorack_size6_class1",
|
|
||||||
"On": true,
|
|
||||||
"Priority": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "slot02_size6",
|
|
||||||
"Item": "int_cargorack_size6_class1",
|
|
||||||
"On": true,
|
|
||||||
"Priority": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "slot03_size5",
|
|
||||||
"Item": "int_guardianfsdbooster_size5",
|
|
||||||
"On": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "slot04_size5",
|
|
||||||
"Item": "int_fighterbay_size5_class1",
|
|
||||||
"On": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "slot05_size4",
|
|
||||||
"Item": "int_shieldgenerator_size4_class5",
|
|
||||||
"On": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "slot06_size3",
|
|
||||||
"Item": "int_dronecontrol_collection_size3_class4",
|
|
||||||
"On": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "slot07_size3",
|
|
||||||
"Item": "int_dronecontrol_collection_size3_class4",
|
|
||||||
"On": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "slot08_size2",
|
|
||||||
"Item": "int_refinery_size2_class2",
|
|
||||||
"On": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "slot09_size1",
|
|
||||||
"Item": "int_dronecontrol_prospector_size1_class4",
|
|
||||||
"On": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "powerplant",
|
|
||||||
"Item": "int_powerplant_size7_class5",
|
|
||||||
"On": true,
|
|
||||||
"Priority": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "mainengines",
|
|
||||||
"Item": "int_engine_size6_class5",
|
|
||||||
"On": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "frameshiftdrive",
|
|
||||||
"Item": "int_hyperdrive_size5_class5",
|
|
||||||
"On": true,
|
|
||||||
"Engineering": {
|
|
||||||
"BlueprintName": "fsd_longrange",
|
|
||||||
"Level": 2,
|
|
||||||
"Quality": 0.861
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "lifesupport",
|
|
||||||
"Item": "int_lifesupport_size4_class2",
|
|
||||||
"On": true,
|
|
||||||
"Priority": 3
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "powerdistributor",
|
|
||||||
"Item": "int_powerdistributor_size7_class5",
|
|
||||||
"On": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "radar",
|
|
||||||
"Item": "int_sensors_size6_class2",
|
|
||||||
"On": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "fueltank",
|
|
||||||
"Item": "int_fueltank_size5_class3",
|
|
||||||
"On": true,
|
|
||||||
"Priority": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Slot": "armour",
|
|
||||||
"Item": "krait_mkii_armour_grade3",
|
|
||||||
"On": true,
|
|
||||||
"Priority": 1,
|
|
||||||
"Engineering": {
|
|
||||||
"BlueprintName": "armour_heavyduty",
|
|
||||||
"Level": 5,
|
|
||||||
"Quality": 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
@@ -18,13 +18,13 @@ describe('Import Modal', function() {
|
|||||||
const mockContext = {
|
const mockContext = {
|
||||||
language: getLanguage('en'),
|
language: getLanguage('en'),
|
||||||
sizeRatio: 1,
|
sizeRatio: 1,
|
||||||
openMenu: jest.fn(),
|
openMenu: jest.genMockFunction(),
|
||||||
closeMenu: jest.fn(),
|
closeMenu: jest.genMockFunction(),
|
||||||
showModal: jest.fn(),
|
showModal: jest.genMockFunction(),
|
||||||
hideModal: jest.fn(),
|
hideModal: jest.genMockFunction(),
|
||||||
tooltip: jest.fn(),
|
tooltip: jest.genMockFunction(),
|
||||||
termtip: jest.fn(),
|
termtip: jest.genMockFunction(),
|
||||||
onWindowResize: jest.fn()
|
onWindowResize: jest.genMockFunction()
|
||||||
};
|
};
|
||||||
|
|
||||||
let modal, render, ContextProvider = Utils.createContextProvider(mockContext);
|
let modal, render, ContextProvider = Utils.createContextProvider(mockContext);
|
||||||
@@ -110,25 +110,21 @@ describe('Import Modal', function() {
|
|||||||
it('catches an invalid backup', function() {
|
it('catches an invalid backup', function() {
|
||||||
const importData = require('./fixtures/valid-backup');
|
const importData = require('./fixtures/valid-backup');
|
||||||
let invalidImportData = Object.assign({}, importData);
|
let invalidImportData = Object.assign({}, importData);
|
||||||
// Remove Asp Miner build used in comparison
|
//invalidImportData.builds.asp = null; // Remove Asp Miner build used in comparison
|
||||||
delete(invalidImportData.builds.asp);
|
delete(invalidImportData.builds.asp);
|
||||||
|
|
||||||
pasteText('"this is not valid"');
|
pasteText('"this is not valid"');
|
||||||
expect(modal.state.importValid).toBeFalsy();
|
expect(modal.state.importValid).toBeFalsy();
|
||||||
expect(modal.state.errorMsg).toEqual('Must be an object or array!');
|
expect(modal.state.errorMsg).toEqual('Must be an object or array!');
|
||||||
|
|
||||||
pasteText('{ "builds": "Should not be a string" }');
|
pasteText('{ "builds": "Should not be a string" }');
|
||||||
expect(modal.state.importValid).toBeFalsy();
|
expect(modal.state.importValid).toBeFalsy();
|
||||||
expect(modal.state.errorMsg).toEqual('builds must be an object!');
|
expect(modal.state.errorMsg).toEqual('builds must be an object!');
|
||||||
|
pasteText(JSON.stringify(importData).replace('anaconda', 'invalid_ship'));
|
||||||
pasteText(JSON.stringify(importData).replace(/anaconda/g, 'invalid_ship'));
|
|
||||||
expect(modal.state.importValid).toBeFalsy();
|
expect(modal.state.importValid).toBeFalsy();
|
||||||
expect(Object.keys(modal.state.builds)).not.toContain('anaconda');
|
expect(modal.state.errorMsg).toEqual('"invalid_ship" is not a valid Ship Id!');
|
||||||
|
|
||||||
pasteText(JSON.stringify(importData).replace('Dream', ''));
|
pasteText(JSON.stringify(importData).replace('Dream', ''));
|
||||||
expect(modal.state.importValid).toBeFalsy();
|
expect(modal.state.importValid).toBeFalsy();
|
||||||
expect(Object.keys(modal.state.builds.imperial_clipper).length).toEqual(3);
|
expect(modal.state.errorMsg).toEqual('Imperial Clipper build "" must be a string at least 1 character long!');
|
||||||
|
|
||||||
pasteText(JSON.stringify(invalidImportData));
|
pasteText(JSON.stringify(invalidImportData));
|
||||||
expect(modal.state.importValid).toBeFalsy();
|
expect(modal.state.importValid).toBeFalsy();
|
||||||
expect(modal.state.errorMsg).toEqual('asp build "Miner" data is missing!');
|
expect(modal.state.errorMsg).toEqual('asp build "Miner" data is missing!');
|
||||||
@@ -148,7 +144,7 @@ describe('Import Modal', function() {
|
|||||||
expect(modal.state.singleBuild).toBe(true);
|
expect(modal.state.singleBuild).toBe(true);
|
||||||
clickProceed();
|
clickProceed();
|
||||||
expect(MockRouter.go.mock.calls.length).toBe(1);
|
expect(MockRouter.go.mock.calls.length).toBe(1);
|
||||||
expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/anaconda?code=A4putkFklkdzsuf52c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04---0303326b-.AwRj4zNLeI%3D%3D.CwBhCYzBGW9qCTSqq5JA.&bn=Test%20My%20Ship');
|
expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/anaconda?code=A4putkFklkdzsuf52c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04---0303326b.AwRj4zNLaA%3D%3D.CwBhCYzBGW9qCTSqq5xA.&bn=Test%20My%20Ship');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('catches an invalid build', function() {
|
it('catches an invalid build', function() {
|
||||||
@@ -173,7 +169,7 @@ describe('Import Modal', function() {
|
|||||||
expect(modal.state.singleBuild).toBe(true);
|
expect(modal.state.singleBuild).toBe(true);
|
||||||
clickProceed();
|
clickProceed();
|
||||||
expect(MockRouter.go.mock.calls.length).toBe(1);
|
expect(MockRouter.go.mock.calls.length).toBe(1);
|
||||||
expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/anaconda?code=A4putkFklkdzsuf52c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04---0303326b-.AwRj4zNLeI%3D%3D.CwBhCYzBGW9qCTSqq5JA.H4sIAAAAAAAAE2MUe8HMwPD%2FPwMAAGvB0AkAAAA%3D&bn=Test%20My%20Ship');
|
expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/anaconda?code=A4putkFklkdzsuf52c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04---0303326b.AwRj4zNLaA%3D%3D.CwBhCYzBGW9qCTSqq5xA.H4sIAAAAAAAAA2MUe8HMwPD%2FPwMAAGvB0AkAAAA%3D&bn=Test%20My%20Ship');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -190,7 +186,7 @@ describe('Import Modal', function() {
|
|||||||
expect(modal.state.singleBuild).toBe(true);
|
expect(modal.state.singleBuild).toBe(true);
|
||||||
clickProceed();
|
clickProceed();
|
||||||
expect(MockRouter.go.mock.calls.length).toBe(1);
|
expect(MockRouter.go.mock.calls.length).toBe(1);
|
||||||
expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/asp?code=A0pftiFflfddsnf5------020202033c044002v6-2i-.AwRj4yvYg%3D%3D%3D.CwRgDBldHn5A.H4sIAAAAAAAAE2P858DAwPCXEUhwHPvx%2F78YG5AltB7I%2F8%2F0TwImJboDSPJ%2F%2B%2Ff%2Fv%2FKlX%2F%2F%2Fi3AwMTBIfARK%2FGf%2BJwVSxArStVAYqOjvz%2F%2F%2FJVo5GRhE2IBc4SKQSSz%2FDGEmCa398P8%2F%2F2%2BgTf%2F%2FA7kMAExxqlSAAAAA&bn=Multi-purpose%20Asp%20Explorer');
|
expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/asp?code=A0pftiFflfddsnf5------020202033c044002v62f2i.AwRj4yvI.CwRgDBldHnJA.H4sIAAAAAAAAA2P858DAwPCXEUhwHPvx%2F78YG5AltB7I%2F8%2F0TwImJboDSPJ%2F%2B%2Ff%2Fv%2FKlX%2F%2F%2Fi3AwMTBIfARK%2FGf%2BJwVSxArStVAYqOjvz%2F%2F%2FJVo5GRhE2IBc4SKQSSz%2FDGEmCa398P8%2F%2F2%2BgTf%2F%2FA7kMAExxqlSAAAAA&bn=Multi-purpose%20Asp%20Explorer');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('imports a valid v4 build with modifications', function() {
|
it('imports a valid v4 build with modifications', function() {
|
||||||
@@ -202,11 +198,11 @@ describe('Import Modal', function() {
|
|||||||
expect(modal.state.singleBuild).toBe(true);
|
expect(modal.state.singleBuild).toBe(true);
|
||||||
clickProceed();
|
clickProceed();
|
||||||
expect(MockRouter.go.mock.calls.length).toBe(1);
|
expect(MockRouter.go.mock.calls.length).toBe(1);
|
||||||
expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/imperial_courier?code=A0patzF5l0das8f31a1a270202000e402t0101----.AwRj4zOYg%3D%3D%3D.CwRgDBldLuZA.H4sIAAAAAAAAE12OPUvDYBSFT1OTfkRJjUkbbC3Yj8mlODgUISAtdOlety5ODv0Vgji7O7kJ%2FgzBQX%2BEY7Gg0NKhfY%2FnHQLFDBdynufe9%2BRMCmCb06g29oCgacjiRx6gY6oWKUT8UgLaszqQfHmSnpVFN1uSeXNsJVcj%2FA2EHlZkspIUpUc6UjTXGT85qwHuSEuVc%2F16r99kDQeSSjvSbSjpyUpNK10uJJ3aYqk6smwm1lQ9bOxw71TMm8VanEqq9JW1r3Qo%2BREOLnQHvbWmb7rZIu5VLIyGQGOukPv%2F0WQk5LeEAjPOUDwtAP6bShy2HKAz0HPO%2B5KsP25I79O2I7LvD%2Bz4Il1XAQAA&bn=Multi-purpose%20Imperial%20Courier');
|
expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/imperial_courier?code=A0patzF5l0das8f31a1a270202000e402t0101-2f.AwRj4zKA.CwRgDBldLiQ%3D.H4sIAAAAAAAAA12OPUvDYBSFT1OTfkRJjUkbbC3Yj8mlODgUISAtdOlety5ODv0Vgji7O7kJ%2FgzBQX%2BEY7Gg0NKhfY%2FnHQLFDBdynufe9%2BRMCmCb06g29oCgacjiRx6gY6oWKUT8UgLaszqQfHmSnpVFN1uSeXNsJVcj%2FA2EHlZkspIUpUc6UjTXGT85qwHuSEuVc%2F16r99kDQeSSjvSbSjpyUpNK10uJJ3aYqk6smwm1lQ9bOxw71TMm8VanEqq9JW1r3Qo%2BREOLnQHvbWmb7rZIu5VLIyGQGOukPv%2F0WQk5LeEAjPOUDwtAP6bShy2HKAz0HPO%2B5KsP25I79O2I7LvD%2Bz4Il1XAQAA&bn=Multi-purpose%20Imperial%20Courier');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Import Detailed Builds Array', function() {
|
describe('Import Detaild Builds Array', function() {
|
||||||
|
|
||||||
beforeEach(reset);
|
beforeEach(reset);
|
||||||
|
|
||||||
@@ -244,7 +240,7 @@ describe('Import Modal', function() {
|
|||||||
expect(modal.state.singleBuild).toBe(true);
|
expect(modal.state.singleBuild).toBe(true);
|
||||||
clickProceed();
|
clickProceed();
|
||||||
expect(MockRouter.go.mock.calls.length).toBe(1);
|
expect(MockRouter.go.mock.calls.length).toBe(1);
|
||||||
expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/federal_corvette?code=A2putsFklndzsxf50x0x7l28281919040404040402020l06p05sf63c5ifr--v66g--.AwRj4zNapI%3D%3D.CwRgDBldUExuBiIlWIA%3D.&bn=Imported%20Federal%20Corvette');
|
expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/federal_corvette?code=A2putsFklndzsxf50x0x7l28281919040404040402020l06p05sf63c5ifr--v66g2f.AwRj4zNaqA%3D%3D.CwRgDBldUExuBiIlUA%3D%3D.H4sIAAAAAAAAA12STy8DURTFb1szU53Ga8dg2qqqDmJDIoKFxJImumYjVrVqfAALC4lNbcUnkLCoDbEQu0bSlQVhI8JHsJBIQ73rXMkwMYuT9%2Bb87nl%2F7ovoRSL6ikD6TYNINZg5XsWUo7pfrBikr2USlRyXyDuLAhr6ZHanNLOzD5tjOiskysk5dOBvfTB7bjeRW0MNG3ohSBq1bKKxKwyLLUAjmwjpPu4wJx4xVbNI57heDfbUKUAy2xaRUQZpllHoHMHxKqjhhF4LgjtJiFHDmqbrEeVnUJOax7%2FSdRfRwBNotv9wo5kAuZMD2egKyDYcdYl1OBki6z%2BZQjaFnBPyFCM1LefF%2BcgrY0es9FKwbW8ZYj9gmBbxRVRdglMh6BNqnwsk4ouoO4HSIehNoBuBRHwR1QOmsBvHmk6IfMbd2fdCEka%2BjNSexPWGoEkcyX6CnxbxRZQtd%2BPpym%2B31xFtn0iSFPkf%2BBkttZlzB9KDFyBuFRfAGV0Ogoff8SSsCfjjD5hGWtLIwZB%2FgX5Zt%2BLHMI9My7sp6nzgZzekswTxVvCOkq%2FSXqb%2F3zfLxh6HrwIAAA%3D%3D&bn=Imported%20Federal%20Corvette');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('imports a valid companion API build', function() {
|
it('imports a valid companion API build', function() {
|
||||||
@@ -256,7 +252,7 @@ describe('Import Modal', function() {
|
|||||||
expect(modal.state.singleBuild).toBe(true);
|
expect(modal.state.singleBuild).toBe(true);
|
||||||
clickProceed();
|
clickProceed();
|
||||||
expect(MockRouter.go.mock.calls.length).toBe(1);
|
expect(MockRouter.go.mock.calls.length).toBe(1);
|
||||||
expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/beluga?code=A0pktsFplCdpsnf70t0t2727270004040404043c4fmimlmm04mc0iv62i--.AwRj4yusg%3D%3D%3D.CwRgDBldHi8IWIA%3D.&bn=Imported%20Beluga%20Liner');
|
expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/beluga?code=A0pktsFplCdpsnf70t0t2727270004040404043c4fmimlmm04mc0iv62i2f.AwRj4yukg%3D%3D%3D.CwRgDBldHi8IUA%3D%3D.H4sIAAAAAAAAA2P8Z8%2FAwPCXEUiIKTMxMPCv%2F%2Ff%2FP8cFIPGf6Z8YTEr0GjMDg%2FJWICERBOTzn%2Fn7%2F7%2FIO5Ai5n9SIEWsQEIoSxAolfbt%2F3%2BJPk4GBhE7YQYGYVmgcuVnf4Aq%2FwOVAAAyiFctbgAAAA%3D%3D&bn=Imported%20Beluga%20Liner');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('imports a valid companion API build', function() {
|
it('imports a valid companion API build', function() {
|
||||||
@@ -268,7 +264,7 @@ describe('Import Modal', function() {
|
|||||||
expect(modal.state.singleBuild).toBe(true);
|
expect(modal.state.singleBuild).toBe(true);
|
||||||
clickProceed();
|
clickProceed();
|
||||||
expect(MockRouter.go.mock.calls.length).toBe(1);
|
expect(MockRouter.go.mock.calls.length).toBe(1);
|
||||||
expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/type_7_transport?code=A0patfFflidasdf5----0404040005050504044d2402--.AwRj4yoo.CwRgDBlVK7HjEA%3D%3D.&bn=Imported%20Type-7%20Transporter');
|
expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/type_7_transport?code=A0patfFflidasdf5----0404040005050504044d2402.AwRj4yrI.CwRgDBlVK7EiA%3D%3D%3D.&bn=Imported%20Type-7%20Transporter');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('imports a valid companion API build', function() {
|
it('imports a valid companion API build', function() {
|
||||||
@@ -280,7 +276,7 @@ describe('Import Modal', function() {
|
|||||||
expect(modal.state.singleBuild).toBe(true);
|
expect(modal.state.singleBuild).toBe(true);
|
||||||
clickProceed();
|
clickProceed();
|
||||||
expect(MockRouter.go.mock.calls.length).toBe(1);
|
expect(MockRouter.go.mock.calls.length).toBe(1);
|
||||||
expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/cobra_mk_iii?code=A0p0tdFaldd3sdf4------34----2i--.AwRj4yqA.CwRgDMYExrezBig%3D.&bn=Imported%20Cobra%20Mk%20III');
|
expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/cobra_mk_iii?code=A0p0tdFaldd3sdf4------34---2f2i.AwRj4yKA.CwRgDMYExrezBUg%3D.&bn=Imported%20Cobra%20Mk%20III');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -328,41 +324,4 @@ describe('Import Modal', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Imports SLEF data', () => {
|
|
||||||
beforeEach(reset);
|
|
||||||
|
|
||||||
it('imports a single valid SLEF build', () => {
|
|
||||||
const importData = require('./fixtures/slef-single-build.json');
|
|
||||||
pasteText(JSON.stringify(importData));
|
|
||||||
|
|
||||||
expect(modal.state.importValid).toBeTruthy();
|
|
||||||
expect(modal.state.errorMsg).toEqual(null);
|
|
||||||
expect(modal.state.singleBuild).toBe(true);
|
|
||||||
clickProceed();
|
|
||||||
expect(MockRouter.go.mock.calls.length).toBe(1);
|
|
||||||
expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/krait_mkii?code=A2pptkFflidussf52l1o1o2g2g020g040405051Ofr45C9C91oP3.Iw18eQ%3D%3D.AwRgzKIkA%3D%3D%3D.&bn=Imported%20pancake%20hammer');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('imports multiple SLEF builds', () => {
|
|
||||||
const importData = require('./fixtures/slef-multiple-builds.json');
|
|
||||||
const expectedBuilds = require('./fixtures/slef-multiple-expected-builds.json');
|
|
||||||
pasteText(JSON.stringify(importData));
|
|
||||||
|
|
||||||
expect(modal.state.importValid).toBeTruthy();
|
|
||||||
expect(modal.state.errorMsg).toEqual(null);
|
|
||||||
expect(modal.state.singleBuild).toBe(false);
|
|
||||||
clickProceed();
|
|
||||||
expect(modal.state.processed).toBeTruthy();
|
|
||||||
clickImport();
|
|
||||||
|
|
||||||
const builds = Persist.getBuilds();
|
|
||||||
|
|
||||||
for (const shipModel in builds) {
|
|
||||||
for (const buildName in builds[shipModel]) {
|
|
||||||
expect(builds[shipModel][buildName])
|
|
||||||
.toEqual(expectedBuilds[shipModel][buildName]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|||||||
51
docker-compose.yml
Normal file
51
docker-compose.yml
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
version: '2.2'
|
||||||
|
|
||||||
|
services:
|
||||||
|
coriolis_prod:
|
||||||
|
image: edcd/coriolis:master
|
||||||
|
restart: always
|
||||||
|
volumes:
|
||||||
|
- ./nginx.conf:/etc/nginx/nginx.conf
|
||||||
|
networks:
|
||||||
|
- web
|
||||||
|
labels:
|
||||||
|
- "traefik.docker.network=web"
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.basic.frontend.rule=Host:coriolis.io,coriolis.edcd.io"
|
||||||
|
- "traefik.basic.port=80"
|
||||||
|
- "traefik.basic.protocol=http"
|
||||||
|
|
||||||
|
coriolis_dev:
|
||||||
|
image: edcd/coriolis:develop
|
||||||
|
restart: always
|
||||||
|
volumes:
|
||||||
|
- ./nginx.conf:/etc/nginx/nginx.conf
|
||||||
|
networks:
|
||||||
|
- web
|
||||||
|
labels:
|
||||||
|
- "traefik.docker.network=web"
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.basic.frontend.rule=Host:beta.coriolis.io,beta.coriolis.edcd.io"
|
||||||
|
- "traefik.basic.port=80"
|
||||||
|
- "traefik.basic.protocol=http"
|
||||||
|
|
||||||
|
coriolis_dw2:
|
||||||
|
image: edcd/coriolis:dw2
|
||||||
|
restart: always
|
||||||
|
volumes:
|
||||||
|
- ./nginx.conf:/etc/nginx/nginx.conf
|
||||||
|
networks:
|
||||||
|
- web
|
||||||
|
labels:
|
||||||
|
- "traefik.docker.network=web"
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.basic.frontend.rule=Host:dw2.coriolis.io"
|
||||||
|
- "traefik.basic.port=80"
|
||||||
|
- "traefik.basic.protocol=http"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
networks:
|
||||||
|
web:
|
||||||
|
external: true
|
||||||
96
nginx.conf
Normal file
96
nginx.conf
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
worker_processes 1;
|
||||||
|
user nobody nobody;
|
||||||
|
error_log /tmp/error.log;
|
||||||
|
pid /tmp/nginx.pid;
|
||||||
|
|
||||||
|
events {
|
||||||
|
|
||||||
|
worker_connections 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
http {
|
||||||
|
|
||||||
|
include /etc/nginx/mime.types;
|
||||||
|
default_type application/octet-stream;
|
||||||
|
sendfile on;
|
||||||
|
client_body_temp_path /tmp/client_body;
|
||||||
|
fastcgi_temp_path /tmp/fastcgi_temp;
|
||||||
|
proxy_temp_path /tmp/proxy_temp;
|
||||||
|
scgi_temp_path /tmp/scgi_temp;
|
||||||
|
uwsgi_temp_path /tmp/uwsgi_temp;
|
||||||
|
access_log /tmp/access.log;
|
||||||
|
error_log /tmp/error.log;
|
||||||
|
|
||||||
|
# https://nginx.org/en/docs/http/ngx_http_gzip_module.html
|
||||||
|
# Enable gzip compression.
|
||||||
|
# Default: off
|
||||||
|
gzip off;
|
||||||
|
|
||||||
|
# Compression level (1-9).
|
||||||
|
# 5 is a perfect compromise between size and CPU usage, offering about
|
||||||
|
# 75% reduction for most ASCII files (almost identical to level 9).
|
||||||
|
# Default: 1
|
||||||
|
gzip_comp_level 5;
|
||||||
|
|
||||||
|
# Don't compress anything that's already small and unlikely to shrink much
|
||||||
|
# if at all (the default is 20 bytes, which is bad as that usually leads to
|
||||||
|
# larger files after gzipping).
|
||||||
|
# Default: 20
|
||||||
|
gzip_min_length 256;
|
||||||
|
|
||||||
|
# Compress data even for clients that are connecting to us via proxies,
|
||||||
|
# identified by the "Via" header (required for CloudFront).
|
||||||
|
# Default: off
|
||||||
|
gzip_proxied any;
|
||||||
|
|
||||||
|
# Tell proxies to cache both the gzipped and regular version of a resource
|
||||||
|
# whenever the client's Accept-Encoding capabilities header varies;
|
||||||
|
# Avoids the issue where a non-gzip capable client (which is extremely rare
|
||||||
|
# today) would display gibberish if their proxy gave them the gzipped version.
|
||||||
|
# Default: off
|
||||||
|
gzip_vary on;
|
||||||
|
|
||||||
|
# Compress all output labeled with one of the following MIME-types.
|
||||||
|
# text/html is always compressed by gzip module.
|
||||||
|
# Default: text/html
|
||||||
|
gzip_types *;
|
||||||
|
brotli on;
|
||||||
|
# brotli_static on;
|
||||||
|
brotli_types *;
|
||||||
|
# This should be turned on if you are going to have pre-compressed copies (.gz) of
|
||||||
|
# static files available. If not it should be left off as it will cause extra I/O
|
||||||
|
# for the check. It is best if you enable this in a location{} block for
|
||||||
|
# a specific directory, or on an individual server{} level.
|
||||||
|
# gzip_static on;
|
||||||
|
keepalive_timeout 3000;
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
listen [::]:80;
|
||||||
|
index index.html;
|
||||||
|
server_name localhost;
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
autoindex on;
|
||||||
|
|
||||||
|
location ~* \.(?:manifest|appcache|html?|xml|json|css|js|map|jpg|jpeg|gif|png|ico|svg|eot|ttf|woff|woff2)$ {
|
||||||
|
add_header Access-Control-Allow-Origin *;
|
||||||
|
add_header Access-Control-Allow-Credentials true;
|
||||||
|
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
|
||||||
|
add_header Access-Control-Allow-Headers 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
|
||||||
|
access_log off;
|
||||||
|
}
|
||||||
|
location /service-worker.js {
|
||||||
|
expires -1;
|
||||||
|
add_header Access-Control-Allow-Origin *;
|
||||||
|
add_header Access-Control-Allow-Credentials true;
|
||||||
|
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
|
||||||
|
add_header Access-Control-Allow-Headers 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
|
||||||
|
access_log off;
|
||||||
|
}
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.html =404;
|
||||||
|
}
|
||||||
|
location /iframe.html {
|
||||||
|
try_files $uri $uri/ /iframe.html =404;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,7 +22,6 @@ import ComparisonPage from './pages/ComparisonPage';
|
|||||||
import ShipyardPage from './pages/ShipyardPage';
|
import ShipyardPage from './pages/ShipyardPage';
|
||||||
import ErrorDetails from './pages/ErrorDetails';
|
import ErrorDetails from './pages/ErrorDetails';
|
||||||
|
|
||||||
|
|
||||||
const zlib = require('pako');
|
const zlib = require('pako');
|
||||||
const request = require('superagent');
|
const request = require('superagent');
|
||||||
|
|
||||||
@@ -73,6 +72,7 @@ export default class Coriolis extends React.Component {
|
|||||||
route: {},
|
route: {},
|
||||||
sizeRatio: Persist.getSizeRatio()
|
sizeRatio: Persist.getSizeRatio()
|
||||||
};
|
};
|
||||||
|
this._getAnnouncements();
|
||||||
Router('', (r) => this._setPage(ShipyardPage, r));
|
Router('', (r) => this._setPage(ShipyardPage, r));
|
||||||
Router('/import?', (r) => this._importBuild(r));
|
Router('/import?', (r) => this._importBuild(r));
|
||||||
Router('/import/:data', (r) => this._importBuild(r));
|
Router('/import/:data', (r) => this._importBuild(r));
|
||||||
@@ -97,35 +97,30 @@ export default class Coriolis extends React.Component {
|
|||||||
const json = JSON.parse(data);
|
const json = JSON.parse(data);
|
||||||
console.info('Ship import data: ');
|
console.info('Ship import data: ');
|
||||||
console.info(json);
|
console.info(json);
|
||||||
let ship, importString;
|
let ship;
|
||||||
if (json) {
|
if (json && json.modules) {
|
||||||
if (json.length && json[0].data) { // SLEF
|
ship = CompanionApiUtils.shipFromJson(json);
|
||||||
if (json.length > 1) { // Multiple builds, open modal
|
} else if (json && json.Modules) {
|
||||||
importString = data;
|
ship = JournalUtils.shipFromLoadoutJSON(json);
|
||||||
} else { // Single build, import directly
|
|
||||||
ship = JournalUtils.shipFromLoadoutJSON(json[0].data);
|
|
||||||
}
|
|
||||||
} else { // not SLEF
|
|
||||||
if (json.modules) {
|
|
||||||
ship = CompanionApiUtils.shipFromJson(json);
|
|
||||||
} else if (json.Modules) {
|
|
||||||
ship = JournalUtils.shipFromLoadoutJSON(json);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ship) {
|
|
||||||
r.params.ship = ship.id;
|
|
||||||
r.params.code = ship.toString();
|
|
||||||
this._setPage(OutfittingPage, r);
|
|
||||||
} else if (importString) {
|
|
||||||
this._setPage(ShipyardPage, r);
|
|
||||||
this._showModal(<ModalImport importString={data}/>);
|
|
||||||
}
|
}
|
||||||
|
r.params.ship = ship.id;
|
||||||
|
r.params.code = ship.toString();
|
||||||
|
this._setPage(OutfittingPage, r)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this._onError('Failed to import ship', r.path, 0, 0, err);
|
this._onError('Failed to import ship', r.path, 0, 0, err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async _getAnnouncements() {
|
||||||
|
try {
|
||||||
|
const announces = await request.get('https://orbis.zone/api/announcement')
|
||||||
|
.query({ showInCoriolis: true });
|
||||||
|
this.setState({ announcements: announces.body });
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates / Sets the page and route context
|
* Updates / Sets the page and route context
|
||||||
* @param {[type]} page The page to be shown
|
* @param {[type]} page The page to be shown
|
||||||
@@ -399,18 +394,18 @@ export default class Coriolis extends React.Component {
|
|||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
let currentMenu = this.state.currentMenu;
|
let currentMenu = this.state.currentMenu;
|
||||||
|
|
||||||
return <div style={{ minHeight: '100%' }} onClick={this._closeMenu}
|
return <div style={{ minHeight: '100%' }} onClick={this._closeMenu}
|
||||||
className={this.state.noTouch ? 'no-touch' : null}>
|
className={this.state.noTouch ? 'no-touch' : null}>
|
||||||
<Header announcements={this.state.announcements} appCacheUpdate={this.state.appCacheUpdate}
|
<Header announcements={this.state.announcements} appCacheUpdate={this.state.appCacheUpdate}
|
||||||
currentMenu={currentMenu}/>
|
currentMenu={currentMenu}/>
|
||||||
<div className="announcement-container">{this.state.announcements.map(a => <Announcement
|
<div className="announcement-container">{this.state.announcements.map(a => <Announcement
|
||||||
text={a.text}/>)}</div>
|
text={a.message}/>)}</div>
|
||||||
{this.state.error ? this.state.error : this.state.page ? React.createElement(this.state.page, { currentMenu }) :
|
{this.state.error ? this.state.error : this.state.page ? React.createElement(this.state.page, { currentMenu }) :
|
||||||
<NotFoundPage/>}
|
<NotFoundPage/>}
|
||||||
{this.state.modal}
|
{this.state.modal}
|
||||||
{this.state.tooltip}
|
{this.state.tooltip}
|
||||||
<footer>
|
<footer>
|
||||||
|
|
||||||
<div className="right cap">
|
<div className="right cap">
|
||||||
<a href="https://github.com/EDCD/coriolis" target="_blank" rel="noopener noreferrer"
|
<a href="https://github.com/EDCD/coriolis" target="_blank" rel="noopener noreferrer"
|
||||||
title="Coriolis Github Project">{window.CORIOLIS_VERSION} - {window.CORIOLIS_DATE}</a>
|
title="Coriolis Github Project">{window.CORIOLIS_VERSION} - {window.CORIOLIS_DATE}</a>
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import Persist from './stores/Persist';
|
import Persist from './stores/Persist';
|
||||||
|
import ReactGA from 'react-ga';
|
||||||
|
|
||||||
|
ReactGA.initialize('UA-55840909-18');
|
||||||
let standalone = undefined;
|
let standalone = undefined;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -72,7 +74,6 @@ Router.go = function(path, state) {
|
|||||||
gaTrack(path);
|
gaTrack(path);
|
||||||
let ctx = new Context(path, state);
|
let ctx = new Context(path, state);
|
||||||
Router.dispatch(ctx);
|
Router.dispatch(ctx);
|
||||||
|
|
||||||
if (!ctx.unhandled) {
|
if (!ctx.unhandled) {
|
||||||
if (isStandAlone()) {
|
if (isStandAlone()) {
|
||||||
Persist.setState(ctx);
|
Persist.setState(ctx);
|
||||||
@@ -258,8 +259,16 @@ Route.prototype.match = function(path, params) {
|
|||||||
* @param {string} path Path to track
|
* @param {string} path Path to track
|
||||||
*/
|
*/
|
||||||
function gaTrack(path) {
|
function gaTrack(path) {
|
||||||
const _paq = window._paq || [];
|
const match = path.match(/\/outfit\/(.*)(\?code=.*)/);
|
||||||
_paq.push(['trackPageView']);
|
if (match) {
|
||||||
|
if (match[1]) {
|
||||||
|
ReactGA.ga('set', 'contentGroup1', match[1]);
|
||||||
|
}
|
||||||
|
if (match[2]) {
|
||||||
|
ReactGA.ga('set', 'contentGroup2', match[2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ReactGA.pageview(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -78,11 +78,7 @@ const GRPCAT = {
|
|||||||
// Mining
|
// Mining
|
||||||
'scl': 'mining',
|
'scl': 'mining',
|
||||||
'pwa': 'mining',
|
'pwa': 'mining',
|
||||||
'sdm': 'mining',
|
'sdm': 'mining'
|
||||||
|
|
||||||
// Assists
|
|
||||||
'dc': 'flight assists',
|
|
||||||
'sua': 'flight assists',
|
|
||||||
};
|
};
|
||||||
// Order here is the order in which items will be shown in the modules menu
|
// Order here is the order in which items will be shown in the modules menu
|
||||||
const CATEGORIES = {
|
const CATEGORIES = {
|
||||||
@@ -97,8 +93,7 @@ const CATEGORIES = {
|
|||||||
'rf': ['rf'],
|
'rf': ['rf'],
|
||||||
'shields': ['sg', 'bsg', 'psg', 'scb'],
|
'shields': ['sg', 'bsg', 'psg', 'scb'],
|
||||||
'structural reinforcement': ['hr', 'mrp'],
|
'structural reinforcement': ['hr', 'mrp'],
|
||||||
'flight assists': ['dc', 'sua'],
|
'dc': ['dc'],
|
||||||
|
|
||||||
// Hardpoints
|
// Hardpoints
|
||||||
'lasers': ['pl', 'ul', 'bl'],
|
'lasers': ['pl', 'ul', 'bl'],
|
||||||
'projectiles': ['mc', 'c', 'fc', 'pa', 'rg'],
|
'projectiles': ['mc', 'c', 'fc', 'pa', 'rg'],
|
||||||
@@ -126,7 +121,7 @@ export default class AvailableModulesMenu extends TranslatedComponent {
|
|||||||
onSelect: PropTypes.func.isRequired,
|
onSelect: PropTypes.func.isRequired,
|
||||||
diffDetails: PropTypes.func,
|
diffDetails: PropTypes.func,
|
||||||
m: PropTypes.object,
|
m: PropTypes.object,
|
||||||
ship: PropTypes.object.isRequired,
|
shipMass: PropTypes.number,
|
||||||
warning: PropTypes.func,
|
warning: PropTypes.func,
|
||||||
firstSlotId: PropTypes.string,
|
firstSlotId: PropTypes.string,
|
||||||
lastSlotId: PropTypes.string,
|
lastSlotId: PropTypes.string,
|
||||||
@@ -134,6 +129,10 @@ export default class AvailableModulesMenu extends TranslatedComponent {
|
|||||||
slotDiv: PropTypes.object
|
slotDiv: PropTypes.object
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static defaultProps = {
|
||||||
|
shipMass: 0
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
* @param {Object} props React Component properties
|
* @param {Object} props React Component properties
|
||||||
@@ -155,15 +154,15 @@ export default class AvailableModulesMenu extends TranslatedComponent {
|
|||||||
*/
|
*/
|
||||||
_initState(props, context) {
|
_initState(props, context) {
|
||||||
let translate = context.language.translate;
|
let translate = context.language.translate;
|
||||||
let { m, warning, onSelect, modules, ship } = props;
|
let { m, warning, shipMass, onSelect, modules, firstSlotId, lastSlotId } = props;
|
||||||
let list, currentGroup;
|
let list, currentGroup;
|
||||||
|
|
||||||
let buildGroup = this._buildGroup.bind(
|
let buildGroup = this._buildGroup.bind(
|
||||||
this,
|
this,
|
||||||
ship,
|
|
||||||
translate,
|
translate,
|
||||||
m,
|
m,
|
||||||
warning,
|
warning,
|
||||||
|
shipMass - (m && m.mass ? m.mass : 0),
|
||||||
(m, event) => {
|
(m, event) => {
|
||||||
this._hideDiff(event);
|
this._hideDiff(event);
|
||||||
onSelect(m);
|
onSelect(m);
|
||||||
@@ -251,16 +250,18 @@ export default class AvailableModulesMenu extends TranslatedComponent {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate React Components for Module Group
|
* Generate React Components for Module Group
|
||||||
* @param {Ship} ship Ship the selection is for
|
|
||||||
* @param {Function} translate Translate function
|
* @param {Function} translate Translate function
|
||||||
* @param {Object} mountedModule Mounted Module
|
* @param {Object} mountedModule Mounted Module
|
||||||
* @param {Function} warningFunc Warning function
|
* @param {Function} warningFunc Warning function
|
||||||
|
* @param {number} mass Mass
|
||||||
* @param {function} onSelect Select/Mount callback
|
* @param {function} onSelect Select/Mount callback
|
||||||
* @param {string} grp Group name
|
* @param {string} grp Group name
|
||||||
* @param {Array} modules Available modules
|
* @param {Array} modules Available modules
|
||||||
|
* @param {string} firstSlotId id of first slot item
|
||||||
|
* @param {string} lastSlotId id of last slot item
|
||||||
* @return {React.Component} Available Module Group contents
|
* @return {React.Component} Available Module Group contents
|
||||||
*/
|
*/
|
||||||
_buildGroup(ship, translate, mountedModule, warningFunc, onSelect, grp, modules) {
|
_buildGroup(translate, mountedModule, warningFunc, mass, onSelect, grp, modules, firstSlotId, lastSlotId) {
|
||||||
let prevClass = null, prevRating = null, prevName;
|
let prevClass = null, prevRating = null, prevName;
|
||||||
let elems = [];
|
let elems = [];
|
||||||
|
|
||||||
@@ -281,11 +282,10 @@ export default class AvailableModulesMenu extends TranslatedComponent {
|
|||||||
prevName = m.name;
|
prevName = m.name;
|
||||||
if (ModuleUtils.isShieldGenerator(m.grp)) {
|
if (ModuleUtils.isShieldGenerator(m.grp)) {
|
||||||
// Shield generators care about maximum hull mass
|
// Shield generators care about maximum hull mass
|
||||||
disabled = ship.hullMass > m.maxmass;
|
disabled = mass > m.maxmass;
|
||||||
// If the mounted module is experimental as well, we can replace it so
|
} else if (m.maxmass) {
|
||||||
// the maximum does not apply
|
// Thrusters care about total mass
|
||||||
} else if (m.experimental && (!mountedModule || !mountedModule.experimental)) {
|
disabled = mass + m.mass > m.maxmass;
|
||||||
disabled = 4 <= ship.hardpoints.filter(o => o.m && o.m.experimental).length;
|
|
||||||
}
|
}
|
||||||
let active = mountedModule && mountedModule.id === m.id;
|
let active = mountedModule && mountedModule.id === m.id;
|
||||||
let classes = cn(m.name ? 'lc' : 'c', {
|
let classes = cn(m.name ? 'lc' : 'c', {
|
||||||
|
|||||||
@@ -306,8 +306,8 @@ export default class CostSection extends TranslatedComponent {
|
|||||||
<tr className='main'>
|
<tr className='main'>
|
||||||
<th colSpan='2' className='sortable le' onClick={this._sortCostBy.bind(this,'m')}>
|
<th colSpan='2' className='sortable le' onClick={this._sortCostBy.bind(this,'m')}>
|
||||||
{translate('module')}
|
{translate('module')}
|
||||||
{shipDiscount ? <u className='cap optional-hide' style={{ marginLeft: '0.5em' }}>{`[${translate('ship')} ${formats.pct(-1 * shipDiscount)}]`}</u> : null}
|
{shipDiscount ? <u className='cap optional-hide' style={{ marginLeft: '0.5em' }}>{`[${translate('ship')} -${formats.pct(shipDiscount)}]`}</u> : null}
|
||||||
{moduleDiscount ? <u className='cap optional-hide' style={{ marginLeft: '0.5em' }}>{`[${translate('modules')} ${formats.pct(-1 * moduleDiscount)}]`}</u> : null}
|
{moduleDiscount ? <u className='cap optional-hide' style={{ marginLeft: '0.5em' }}>{`[${translate('modules')} -${formats.pct(moduleDiscount)}]`}</u> : null}
|
||||||
</th>
|
</th>
|
||||||
<th className='sortable le' onClick={this._sortCostBy.bind(this, 'cr')} >{translate('credits')}</th>
|
<th className='sortable le' onClick={this._sortCostBy.bind(this, 'cr')} >{translate('credits')}</th>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -52,12 +52,12 @@ export default class Defence extends TranslatedComponent {
|
|||||||
* @return {React.Component} contents
|
* @return {React.Component} contents
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
const { opponent, sys, opponentWep } = this.props;
|
const { ship, sys, opponentWep } = this.props;
|
||||||
const { language, tooltip, termtip } = this.context;
|
const { language, tooltip, termtip } = this.context;
|
||||||
const { formats, translate, units } = language;
|
const { formats, translate, units } = language;
|
||||||
const { shield, armour, shielddamage, armourdamage } = this.state;
|
const { shield, armour, shielddamage, armourdamage } = this.state;
|
||||||
|
|
||||||
const pd = opponent.standard[4].m;
|
const pd = ship.standard[4].m;
|
||||||
|
|
||||||
const shieldSourcesData = [];
|
const shieldSourcesData = [];
|
||||||
const effectiveShieldData = [];
|
const effectiveShieldData = [];
|
||||||
|
|||||||
@@ -104,10 +104,10 @@ export default class HardpointSlot extends Slot {
|
|||||||
onMouseOut={tooltip.bind(null, null)}>{translate('shotdmg')}: {formats.round1(m.getDamage())}</div> : null}
|
onMouseOut={tooltip.bind(null, null)}>{translate('shotdmg')}: {formats.round1(m.getDamage())}</div> : null}
|
||||||
{m.getEps() ? <div className={'l'} onMouseOver={termtip.bind(null, m.getClip() ? 'epsseps' : 'eps')}
|
{m.getEps() ? <div className={'l'} onMouseOver={termtip.bind(null, m.getClip() ? 'epsseps' : 'eps')}
|
||||||
onMouseOut={tooltip.bind(null, null)}>{translate('EPS')}: {formats.round1(m.getEps())}{u.MW} {m.getClip() ?
|
onMouseOut={tooltip.bind(null, null)}>{translate('EPS')}: {formats.round1(m.getEps())}{u.MW} {m.getClip() ?
|
||||||
<span>({formats.round1(m.getEps() * m.getSustainedFactor())}{u.MW})</span> : null}</div> : null}
|
<span>({formats.round1((m.getClip() * m.getEps() / m.getRoF()) / ((m.getClip() / m.getRoF()) + m.getReload()))}{u.MW})</span> : null}</div> : null}
|
||||||
{m.getHps() ? <div className={'l'} onMouseOver={termtip.bind(null, m.getClip() ? 'hpsshps' : 'hps')}
|
{m.getHps() ? <div className={'l'} onMouseOver={termtip.bind(null, m.getClip() ? 'hpsshps' : 'hps')}
|
||||||
onMouseOut={tooltip.bind(null, null)}>{translate('HPS')}: {formats.round1(m.getHps())} {m.getClip() ?
|
onMouseOut={tooltip.bind(null, null)}>{translate('HPS')}: {formats.round1(m.getHps())} {m.getClip() ?
|
||||||
<span>({formats.round1(m.getHps() * m.getSustainedFactor())})</span> : null}</div> : null}
|
<span>({formats.round1((m.getClip() * m.getHps() / m.getRoF()) / ((m.getClip() / m.getRoF()) + m.getReload()))})</span> : null}</div> : null}
|
||||||
{m.getDps() && m.getEps() ? <div className={'l'} onMouseOver={termtip.bind(null, 'dpe')}
|
{m.getDps() && m.getEps() ? <div className={'l'} onMouseOver={termtip.bind(null, 'dpe')}
|
||||||
onMouseOut={tooltip.bind(null, null)}>{translate('DPE')}: {formats.f1(m.getDps() / m.getEps())}</div> : null}
|
onMouseOut={tooltip.bind(null, null)}>{translate('DPE')}: {formats.f1(m.getDps() / m.getEps())}</div> : null}
|
||||||
{m.getRoF() ? <div className={'l'} onMouseOver={termtip.bind(null, 'rof')}
|
{m.getRoF() ? <div className={'l'} onMouseOver={termtip.bind(null, 'rof')}
|
||||||
@@ -121,7 +121,7 @@ export default class HardpointSlot extends Slot {
|
|||||||
{m.getShieldBoost() ? <div className={'l'}>+{formats.pct1(m.getShieldBoost())}</div> : null}
|
{m.getShieldBoost() ? <div className={'l'}>+{formats.pct1(m.getShieldBoost())}</div> : null}
|
||||||
{m.getAmmo() ? <div
|
{m.getAmmo() ? <div
|
||||||
className={'l'}>{translate('ammunition')}: {formats.int(m.getClip())}/{formats.int(m.getAmmo())}</div> : null}
|
className={'l'}>{translate('ammunition')}: {formats.int(m.getClip())}/{formats.int(m.getAmmo())}</div> : null}
|
||||||
{m.getReload() ? <div className={'l'}>{translate('wep_reload')}: {formats.round(m.getReload())}{u.s}</div> : null}
|
{m.getReload() ? <div className={'l'}>{translate('reload')}: {formats.round(m.getReload())}{u.s}</div> : null}
|
||||||
{m.getShotSpeed() ? <div
|
{m.getShotSpeed() ? <div
|
||||||
className={'l'}>{translate('shotspeed')}: {formats.int(m.getShotSpeed())}{u.mps}</div> : null}
|
className={'l'}>{translate('shotspeed')}: {formats.int(m.getShotSpeed())}{u.mps}</div> : null}
|
||||||
{m.getPiercing() ? <div className={'l'}>{translate('piercing')}: {formats.int(m.getPiercing())}</div> : null}
|
{m.getPiercing() ? <div className={'l'}>{translate('piercing')}: {formats.int(m.getPiercing())}</div> : null}
|
||||||
|
|||||||
@@ -149,14 +149,14 @@ export default class HardpointSlotSection extends SlotSection {
|
|||||||
<ul>
|
<ul>
|
||||||
<li className='lc' tabIndex='0' onClick={_fill.bind(this, 'pa', 'F')} onKeyDown={this._keyDown} ref={smRef => this.sectionRefArr['pa-F'] = smRef}>{translate('pa')}</li>
|
<li className='lc' tabIndex='0' onClick={_fill.bind(this, 'pa', 'F')} onKeyDown={this._keyDown} ref={smRef => this.sectionRefArr['pa-F'] = smRef}>{translate('pa')}</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div className='select-group cap'>{translate('rg')}</div>
|
|
||||||
<ul>
|
|
||||||
<li className='lc' tabIndex='0' onClick={_fill.bind(this, 'rg', 'F')} onKeyDown={this._keyDown} ref={smRef => this.sectionRefArr['rg-F'] = smRef}>{translate('rg')}</li>
|
|
||||||
</ul>
|
|
||||||
<div className='select-group cap'>{translate('nl')}</div>
|
<div className='select-group cap'>{translate('nl')}</div>
|
||||||
<ul>
|
<ul>
|
||||||
<li className='lc' tabIndex='0' onClick={_fill.bind(this, 'nl', 'F')} onKeyDown={this._keyDown} ref={smRef => this.sectionRefArr['nl-F'] = smRef}>{translate('nl')}</li>
|
<li className='lc' tabIndex='0' onClick={_fill.bind(this, 'nl', 'F')} onKeyDown={this._keyDown} ref={smRef => this.sectionRefArr['nl-F'] = smRef}>{translate('nl')}</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<div className='select-group cap'>{translate('ggc')}</div>
|
||||||
|
<ul>
|
||||||
|
<li className='lc' tabIndex='0' onClick={_fill.bind(this, 'ggc', 'F')} onKeyDown={this._keyDown} ref={smRef => this.sectionRefArr['ggc-F'] = smRef}>{translate('ggc')}</li>
|
||||||
|
</ul>
|
||||||
<div className='select-group cap'>{translate('rfl')}</div>
|
<div className='select-group cap'>{translate('rfl')}</div>
|
||||||
<ul>
|
<ul>
|
||||||
<li className='c' tabIndex='0' onClick={_fill.bind(this, 'rfl', 'F')} onKeyDown={this._keyDown} ref={smRef => this.sectionRefArr['rfl-F'] = smRef}><MountFixed className='lg'/></li>
|
<li className='c' tabIndex='0' onClick={_fill.bind(this, 'rfl', 'F')} onKeyDown={this._keyDown} ref={smRef => this.sectionRefArr['rfl-F'] = smRef}><MountFixed className='lg'/></li>
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { Ships } from 'coriolis-data/dist';
|
|||||||
import Persist from '../stores/Persist';
|
import Persist from '../stores/Persist';
|
||||||
import { toDetailedExport } from '../shipyard/Serializer';
|
import { toDetailedExport } from '../shipyard/Serializer';
|
||||||
import Ship from '../shipyard/Ship';
|
import Ship from '../shipyard/Ship';
|
||||||
|
import ModalBatchOrbis from './ModalBatchOrbis';
|
||||||
import ModalDeleteAll from './ModalDeleteAll';
|
import ModalDeleteAll from './ModalDeleteAll';
|
||||||
import ModalExport from './ModalExport';
|
import ModalExport from './ModalExport';
|
||||||
import ModalHelp from './ModalHelp';
|
import ModalHelp from './ModalHelp';
|
||||||
@@ -240,6 +241,43 @@ export default class Header extends TranslatedComponent {
|
|||||||
/>);
|
/>);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uploads all ship-builds to orbis
|
||||||
|
* @param {e} e Event
|
||||||
|
*/
|
||||||
|
_uploadAllBuildsToOrbis(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
const data = Persist.getBuilds();
|
||||||
|
let postObject = [];
|
||||||
|
for (const ship in data) {
|
||||||
|
for (const code in data[ship]) {
|
||||||
|
const shipModel = ship;
|
||||||
|
if (!shipModel) {
|
||||||
|
throw 'No such ship found: "' + ship + '"';
|
||||||
|
}
|
||||||
|
const shipTemplate = Ships[shipModel];
|
||||||
|
const shipPostObject = {};
|
||||||
|
let shipInstance = new Ship(shipModel, shipTemplate.properties, shipTemplate.slots);
|
||||||
|
shipInstance.buildWith(null);
|
||||||
|
shipInstance.buildFrom(data[ship][code]);
|
||||||
|
shipPostObject.coriolisId = shipInstance.id;
|
||||||
|
shipPostObject.coriolisShip = shipInstance;
|
||||||
|
|
||||||
|
shipPostObject.coriolisShip.url = window.location.origin + outfitURL(shipModel, data[ship][code], code);
|
||||||
|
shipPostObject.title = code || shipInstance.id;
|
||||||
|
shipPostObject.description = code || shipInstance.id;
|
||||||
|
shipPostObject.ShipName = shipInstance.id;
|
||||||
|
shipPostObject.Ship = shipInstance.id;
|
||||||
|
postObject.push(shipPostObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(postObject);
|
||||||
|
|
||||||
|
this.context.showModal(<ModalBatchOrbis
|
||||||
|
ships={postObject}
|
||||||
|
/>);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show export modal with detailed export
|
* Show export modal with detailed export
|
||||||
* @param {SyntheticEvent} e Event
|
* @param {SyntheticEvent} e Event
|
||||||
@@ -311,7 +349,7 @@ export default class Header extends TranslatedComponent {
|
|||||||
_getShipsMenu() {
|
_getShipsMenu() {
|
||||||
let shipList = [];
|
let shipList = [];
|
||||||
|
|
||||||
for (let s of this.shipOrder) {
|
for (let s in Ships) {
|
||||||
shipList.push(<ActiveLink key={s} href={outfitURL(s)} className='block'>{Ships[s].properties.name}</ActiveLink>);
|
shipList.push(<ActiveLink key={s} href={outfitURL(s)} className='block'>{Ships[s].properties.name}</ActiveLink>);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -388,10 +426,7 @@ export default class Header extends TranslatedComponent {
|
|||||||
if (this.props.announcements) {
|
if (this.props.announcements) {
|
||||||
announcements = [];
|
announcements = [];
|
||||||
for (let announce of this.props.announcements) {
|
for (let announce of this.props.announcements) {
|
||||||
if (announce.expiry < Date.now()) {
|
announcements.push(<Announcement text={announce.message} />);
|
||||||
continue;
|
|
||||||
}
|
|
||||||
announcements.push(<Announcement text={announce.text} />);
|
|
||||||
announcements.push(<hr/>);
|
announcements.push(<hr/>);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -461,6 +496,7 @@ export default class Header extends TranslatedComponent {
|
|||||||
{translate('builds')} & {translate('comparisons')}
|
{translate('builds')} & {translate('comparisons')}
|
||||||
<li><Link href="#" className='block' onClick={this._showBackup.bind(this)}>{translate('backup')}</Link></li>
|
<li><Link href="#" className='block' onClick={this._showBackup.bind(this)}>{translate('backup')}</Link></li>
|
||||||
<li><Link href="#" className='block' onClick={this._showDetailedExport.bind(this)}>{translate('detailed export')}</Link></li>
|
<li><Link href="#" className='block' onClick={this._showDetailedExport.bind(this)}>{translate('detailed export')}</Link></li>
|
||||||
|
<li><Link href="#" className='block' onClick={this._uploadAllBuildsToOrbis.bind(this)}>{translate('upload all builds to orbis')}</Link></li>
|
||||||
<li><Link href="#" className='block' onClick={this._showImport.bind(this)}>{translate('import')}</Link></li>
|
<li><Link href="#" className='block' onClick={this._showImport.bind(this)}>{translate('import')}</Link></li>
|
||||||
<li><Link href="#" className='block' onClick={this._showDeleteAll.bind(this)}>{translate('delete all')}</Link></li>
|
<li><Link href="#" className='block' onClick={this._showDeleteAll.bind(this)}>{translate('delete all')}</Link></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ export default class InternalSlot extends Slot {
|
|||||||
{ m.rangeLS ? <div className={'l'}>{translate('range')}: {m.rangeLS}{u.Ls}</div> : null }
|
{ m.rangeLS ? <div className={'l'}>{translate('range')}: {m.rangeLS}{u.Ls}</div> : null }
|
||||||
{ m.rangeLS === null ? <div className={'l'}>∞{u.Ls}</div> : null }
|
{ m.rangeLS === null ? <div className={'l'}>∞{u.Ls}</div> : null }
|
||||||
{ m.rangeRating ? <div className={'l'}>{translate('range')}: {m.rangeRating}</div> : null }
|
{ m.rangeRating ? <div className={'l'}>{translate('range')}: {m.rangeRating}</div> : null }
|
||||||
|
{ m.maximum ? <div className={'l'}>{translate('max')}: {(m.maximum)}</div> : null }
|
||||||
{ m.passengers ? <div className={'l'}>{translate('passengers')}: {m.passengers}</div> : null }
|
{ m.passengers ? <div className={'l'}>{translate('passengers')}: {m.passengers}</div> : null }
|
||||||
{ m.getRegenerationRate() ? <div className='l'>{translate('regen')}: {formats.round1(m.getRegenerationRate())}{u.ps}</div> : null }
|
{ m.getRegenerationRate() ? <div className='l'>{translate('regen')}: {formats.round1(m.getRegenerationRate())}{u.ps}</div> : null }
|
||||||
{ m.getBrokenRegenerationRate() ? <div className='l'>{translate('brokenregen')}: {formats.round1(m.getBrokenRegenerationRate())}{u.ps}</div> : null }
|
{ m.getBrokenRegenerationRate() ? <div className='l'>{translate('brokenregen')}: {formats.round1(m.getBrokenRegenerationRate())}{u.ps}</div> : null }
|
||||||
|
|||||||
93
src/app/components/ModalBatchOrbis.jsx
Normal file
93
src/app/components/ModalBatchOrbis.jsx
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import request from 'superagent';
|
||||||
|
import TranslatedComponent from './TranslatedComponent';
|
||||||
|
import { orbisUpload } from '../utils/ShortenUrl';
|
||||||
|
import Persist from '../stores/Persist';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permalink modal
|
||||||
|
*/
|
||||||
|
export default class ModalBatchOrbis extends TranslatedComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
ships: PropTypes.any.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param {Object} props React Component properties
|
||||||
|
*/
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
orbisCreds: Persist.getOrbisCreds(),
|
||||||
|
resp: ''
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send ship to Orbis.zone
|
||||||
|
* @param {SyntheticEvent} e React Event
|
||||||
|
* @return {Promise} Promise sending post request to orbis
|
||||||
|
*/
|
||||||
|
sendToOrbis(e) {
|
||||||
|
let agent;
|
||||||
|
try {
|
||||||
|
agent = request.agent(); // apparently this crashes somehow
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
if (!agent) {
|
||||||
|
agent = request;
|
||||||
|
}
|
||||||
|
const API_ORBIS = 'https://orbis.zone/api/builds/add/batch';
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
try {
|
||||||
|
agent
|
||||||
|
.post(API_ORBIS)
|
||||||
|
.withCredentials()
|
||||||
|
.redirects(0)
|
||||||
|
.set('Content-Type', 'application/json')
|
||||||
|
.send(this.props.ships)
|
||||||
|
.end((err, response) => {
|
||||||
|
console.log(response);
|
||||||
|
if (err) {
|
||||||
|
console.error(err);
|
||||||
|
this.setState({ resp: response.text });
|
||||||
|
reject('Bad Request');
|
||||||
|
} else {
|
||||||
|
this.setState({ resp: 'All builds uploaded. Check https://orbis.zone' });
|
||||||
|
resolve('All builds uploaded. Check https://orbis.zone');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
reject(e.message ? e.message : e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render the modal
|
||||||
|
* @return {React.Component} Modal Content
|
||||||
|
*/
|
||||||
|
render() {
|
||||||
|
let translate = this.context.language.translate;
|
||||||
|
this.sendToOrbis = this.sendToOrbis.bind(this);
|
||||||
|
|
||||||
|
return <div className='modal' onClick={ (e) => e.stopPropagation() }>
|
||||||
|
<h2>{translate('permalink')}</h2>
|
||||||
|
<br/>
|
||||||
|
<a className='button' href="https://orbis.zone/api/auth">Log in / signup to Orbis</a>
|
||||||
|
<br/><br/>
|
||||||
|
<h3 >{translate('success')}</h3>
|
||||||
|
<input value={this.state.resp} readOnly size={25} onFocus={ (e) => e.target.select() }/>
|
||||||
|
<br/><br/>
|
||||||
|
<p>Orbis.zone is currently in a trial period, and may be wiped at any time as development progresses. Some elements are also still placeholders.</p>
|
||||||
|
<button className={'l cb dismiss cap'} disabled={!!this.state.failed} onClick={this.sendToOrbis}>{translate('PHASE_UPLOAD_ORBIS')}</button>
|
||||||
|
<button className={'r dismiss cap'} onClick={this.context.hideModal}>{translate('close')}</button>
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,10 +11,7 @@ import * as ModuleUtils from '../shipyard/ModuleUtils';
|
|||||||
import { fromDetailedBuild } from '../shipyard/Serializer';
|
import { fromDetailedBuild } from '../shipyard/Serializer';
|
||||||
import { Download } from './SvgIcons';
|
import { Download } from './SvgIcons';
|
||||||
import { outfitURL } from '../utils/UrlGenerators';
|
import { outfitURL } from '../utils/UrlGenerators';
|
||||||
import { shipFromJson, shipModelFromJson } from '../utils/CompanionApiUtils';
|
import * as CompanionApiUtils from '../utils/CompanionApiUtils';
|
||||||
import { shipFromLoadoutJSON } from '../utils/JournalUtils';
|
|
||||||
|
|
||||||
const zlib = require('pako');
|
|
||||||
|
|
||||||
const textBuildRegex = new RegExp('^\\[([\\w \\-]+)\\]\n');
|
const textBuildRegex = new RegExp('^\\[([\\w \\-]+)\\]\n');
|
||||||
const lineRegex = new RegExp('^([\\dA-Z]{1,2}): (\\d)([A-I])[/]?([FGT])?([SD])? ([\\w\\- ]+)');
|
const lineRegex = new RegExp('^([\\dA-Z]{1,2}): (\\d)([A-I])[/]?([FGT])?([SD])? ([\\w\\- ]+)');
|
||||||
@@ -89,7 +86,6 @@ export default class ModalImport extends TranslatedComponent {
|
|||||||
|
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
importString: PropTypes.string, // Optional: Default data for import modal
|
|
||||||
builds: PropTypes.object, // Optional: Import object
|
builds: PropTypes.object, // Optional: Import object
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -103,12 +99,11 @@ export default class ModalImport extends TranslatedComponent {
|
|||||||
this.state = {
|
this.state = {
|
||||||
builds: props.builds,
|
builds: props.builds,
|
||||||
canEdit: !props.builds,
|
canEdit: !props.builds,
|
||||||
loadoutEvent: null,
|
|
||||||
comparisons: null,
|
comparisons: null,
|
||||||
shipDiscount: null,
|
shipDiscount: null,
|
||||||
moduleDiscount: null,
|
moduleDiscount: null,
|
||||||
errorMsg: null,
|
errorMsg: null,
|
||||||
importString: props.importString || null,
|
importString: null,
|
||||||
importValid: false,
|
importValid: false,
|
||||||
insurance: null
|
insurance: null
|
||||||
};
|
};
|
||||||
@@ -116,28 +111,12 @@ export default class ModalImport extends TranslatedComponent {
|
|||||||
this._process = this._process.bind(this);
|
this._process = this._process.bind(this);
|
||||||
this._import = this._import.bind(this);
|
this._import = this._import.bind(this);
|
||||||
this._importBackup = this._importBackup.bind(this);
|
this._importBackup = this._importBackup.bind(this);
|
||||||
this._importLoadout = this._importLoadout.bind(this);
|
|
||||||
this._importDetailedArray = this._importDetailedArray.bind(this);
|
this._importDetailedArray = this._importDetailedArray.bind(this);
|
||||||
this._importTextBuild = this._importTextBuild.bind(this);
|
this._importTextBuild = this._importTextBuild.bind(this);
|
||||||
this._importCompanionApiBuild = this._importCompanionApiBuild.bind(this);
|
this._importCompanionApiBuild = this._importCompanionApiBuild.bind(this);
|
||||||
this._validateImport = this._validateImport.bind(this);
|
this._validateImport = this._validateImport.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Import a Loadout event from Elite: Dangerous journal files
|
|
||||||
* @param {Object} data Loadout event
|
|
||||||
* @throws {string} If import fails
|
|
||||||
*/
|
|
||||||
_importLoadout(data) {
|
|
||||||
if (data && data.Ship && data.Modules) {
|
|
||||||
const deflated = zlib.deflate(JSON.stringify(data), { to: 'string' });
|
|
||||||
let compressed = btoa(deflated);
|
|
||||||
this.setState({loadoutEvent: compressed});
|
|
||||||
} else {
|
|
||||||
throw 'Loadout event must contain Ship and Modules';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Import a Coriolis backup
|
* Import a Coriolis backup
|
||||||
* @param {Object} importData Backup Data
|
* @param {Object} importData Backup Data
|
||||||
@@ -180,7 +159,7 @@ export default class ModalImport extends TranslatedComponent {
|
|||||||
}
|
}
|
||||||
// Check for module discount
|
// Check for module discount
|
||||||
if (!isNaN(importData.moduleDiscount)) {
|
if (!isNaN(importData.moduleDiscount)) {
|
||||||
this.setState({ moduleDiscount: importData.moduleDiscount * 1 });
|
this.setState({ shipDiscount: importData.moduleDiscount * 1 });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof importData.insurance == 'string') {
|
if (typeof importData.insurance == 'string') {
|
||||||
@@ -216,8 +195,8 @@ export default class ModalImport extends TranslatedComponent {
|
|||||||
* @throws {string} if parse/import fails
|
* @throws {string} if parse/import fails
|
||||||
*/
|
*/
|
||||||
_importCompanionApiBuild(build) {
|
_importCompanionApiBuild(build) {
|
||||||
const shipModel = shipModelFromJson(build);
|
const shipModel = CompanionApiUtils.shipModelFromJson(build);
|
||||||
const ship = shipFromJson(build);
|
const ship = CompanionApiUtils.shipFromJson(build);
|
||||||
|
|
||||||
let builds = {};
|
let builds = {};
|
||||||
builds[shipModel] = {};
|
builds[shipModel] = {};
|
||||||
@@ -323,30 +302,6 @@ export default class ModalImport extends TranslatedComponent {
|
|||||||
this.setState({ builds, singleBuild: true });
|
this.setState({ builds, singleBuild: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Import SLEF formatted builds. Sets state to a map of the builds on success
|
|
||||||
* and flags if there was only a single build.
|
|
||||||
*
|
|
||||||
* @param {string} importData - Array of the list of builds.
|
|
||||||
* @throws {string} If parse / import fails
|
|
||||||
*/
|
|
||||||
_importSlefBuilds(importData) {
|
|
||||||
const builds = importData.reduce((memo, { data }) => {
|
|
||||||
const shipModel = shipModelFromJson(data);
|
|
||||||
const ship = shipFromLoadoutJSON(data);
|
|
||||||
const shipTemplate = Ships[shipModel];
|
|
||||||
const shipName = data.ShipName || shipTemplate.properties.name;
|
|
||||||
|
|
||||||
const key = `Imported ${shipName}`;
|
|
||||||
memo[shipModel] = {};
|
|
||||||
memo[shipModel][key] = ship.toString();
|
|
||||||
|
|
||||||
return memo;
|
|
||||||
}, {});
|
|
||||||
|
|
||||||
this.setState({ builds, singleBuild: Object.keys(builds).length === 1 });
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate the import string / text box contents
|
* Validate the import string / text box contents
|
||||||
* @param {SyntheticEvent} event Event
|
* @param {SyntheticEvent} event Event
|
||||||
@@ -381,10 +336,8 @@ export default class ModalImport extends TranslatedComponent {
|
|||||||
throw 'Must be an object or array!';
|
throw 'Must be an object or array!';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (importData?.[0]?.header?.appName) { // has SLEF envelope?
|
if (importData.modules != null && importData.modules.Armour != null) { // Only the companion API has this information
|
||||||
this._importSlefBuilds(importData);
|
this._importCompanionApiBuild(importData); // Single sihp definition
|
||||||
} else if (importData.modules != null && importData.modules.Armour != null) { // Only the companion API has this information
|
|
||||||
this._importCompanionApiBuild(importData); // Single ship definition
|
|
||||||
} else if (importData.ship != null && importData.ship.modules != null && importData.ship.modules.Armour != null) { // Only the companion API has this information
|
} else if (importData.ship != null && importData.ship.modules != null && importData.ship.modules.Armour != null) { // Only the companion API has this information
|
||||||
this._importCompanionApiBuild(importData.ship); // Complete API dump
|
this._importCompanionApiBuild(importData.ship); // Complete API dump
|
||||||
} else if (importData instanceof Array) { // Must be detailed export json
|
} else if (importData instanceof Array) { // Must be detailed export json
|
||||||
@@ -392,14 +345,12 @@ export default class ModalImport extends TranslatedComponent {
|
|||||||
} else if (importData.ship && typeof importData.name !== undefined) { // Using JSON from a single ship build export
|
} else if (importData.ship && typeof importData.name !== undefined) { // Using JSON from a single ship build export
|
||||||
this._importDetailedArray([importData]); // Convert to array with singleobject
|
this._importDetailedArray([importData]); // Convert to array with singleobject
|
||||||
this.setState({ singleBuild: true });
|
this.setState({ singleBuild: true });
|
||||||
} else if (importData.Modules != null && importData.Modules[0] != null) {
|
|
||||||
this._importLoadout(importData);
|
|
||||||
} else { // Using Backup JSON
|
} else { // Using Backup JSON
|
||||||
this._importBackup(importData);
|
this._importBackup(importData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
// console.log(e.stack);
|
||||||
this.setState({ errorMsg: (typeof e == 'string') ? e : 'Cannot Parse the data!' });
|
this.setState({ errorMsg: (typeof e == 'string') ? e : 'Cannot Parse the data!' });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -413,10 +364,6 @@ export default class ModalImport extends TranslatedComponent {
|
|||||||
_process() {
|
_process() {
|
||||||
let builds = null, comparisons = null;
|
let builds = null, comparisons = null;
|
||||||
|
|
||||||
if (this.state.loadoutEvent) {
|
|
||||||
return Router.go(`/import?data=${this.state.loadoutEvent}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If only importing a single build go straight to the outfitting page
|
// If only importing a single build go straight to the outfitting page
|
||||||
if (this.state.singleBuild) {
|
if (this.state.singleBuild) {
|
||||||
builds = this.state.builds;
|
builds = this.state.builds;
|
||||||
@@ -533,7 +480,7 @@ export default class ModalImport extends TranslatedComponent {
|
|||||||
if (!state.processed) {
|
if (!state.processed) {
|
||||||
importStage = (
|
importStage = (
|
||||||
<div>
|
<div>
|
||||||
<textarea spellCheck={false} className='cb json' ref={node => this.importField = node} onChange={this._validateImport} defaultValue={this.state.importString} placeholder={translate('PHRASE_IMPORT')} />
|
<textarea className='cb json' ref={node => this.importField = node} onChange={this._validateImport} defaultValue={this.state.importString} placeholder={translate('PHRASE_IMPORT')} />
|
||||||
<button id='proceed' className='l cap' onClick={this._process} disabled={!state.importValid} >{translate('proceed')}</button>
|
<button id='proceed' className='l cap' onClick={this._process} disabled={!state.importValid} >{translate('proceed')}</button>
|
||||||
<div className='l warning' style={{ marginLeft:'3em' }}>{state.errorMsg}</div>
|
<div className='l warning' style={{ marginLeft:'3em' }}>{state.errorMsg}</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -570,7 +517,7 @@ export default class ModalImport extends TranslatedComponent {
|
|||||||
{comparisonRows}
|
{comparisonRows}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.state.canEdit) {
|
if(this.state.canEdit) {
|
||||||
|
|||||||
141
src/app/components/ModalOrbis.jsx
Normal file
141
src/app/components/ModalOrbis.jsx
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import TranslatedComponent from './TranslatedComponent';
|
||||||
|
import { orbisUpload } from '../utils/ShortenUrl';
|
||||||
|
import Persist from '../stores/Persist';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permalink modal
|
||||||
|
*/
|
||||||
|
export default class ModalOrbis extends TranslatedComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
ship: PropTypes.any.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param {Object} props React Component properties
|
||||||
|
*/
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
orbisCreds: Persist.getOrbisCreds(),
|
||||||
|
orbisUrl: '...',
|
||||||
|
ship: this.props.ship,
|
||||||
|
authenticatedStatus: 'Checking...'
|
||||||
|
};
|
||||||
|
this.orbisCategory = this.orbisCategory.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send ship to Orbis.zone
|
||||||
|
* @param {SyntheticEvent} e React Event
|
||||||
|
*/
|
||||||
|
sendToOrbis(e) {
|
||||||
|
const target = e.target;
|
||||||
|
target.disabled = true;
|
||||||
|
this.setState({ orbisUrl: 'Sending...' }, () => {
|
||||||
|
orbisUpload(this.props.ship, this.state.orbisCreds)
|
||||||
|
.then(orbisUrl => {
|
||||||
|
target.disabled = false;
|
||||||
|
this.setState({ orbisUrl });
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
target.disabled = false;
|
||||||
|
this.setState({ orbisUrl: 'Error - ' + err });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Orbis.zone auth status
|
||||||
|
* @returns {Object} auth status
|
||||||
|
*/
|
||||||
|
getOrbisAuthStatus() {
|
||||||
|
return fetch('https://orbis.zone/api/checkauth', {
|
||||||
|
credentials: 'include',
|
||||||
|
mode: 'cors'
|
||||||
|
})
|
||||||
|
.then(data => data.json())
|
||||||
|
.then(res => {
|
||||||
|
this.setState({ authenticatedStatus: res.status || res.error });
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error(err);
|
||||||
|
this.setState({ authenticatedStatus: err.message });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for changing cmdr name
|
||||||
|
* @param {SyntheticEvent} e React Event
|
||||||
|
*/
|
||||||
|
orbisPasswordHandler(e) {
|
||||||
|
let password = e.target.value;
|
||||||
|
this.setState({ orbisCreds: { email: this.state.orbisCreds.email, password } }, () => {
|
||||||
|
Persist.setOrbisCreds(this.state.orbisCreds);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for changing cmdr name
|
||||||
|
* @param {SyntheticEvent} e React Event
|
||||||
|
*/
|
||||||
|
orbisUsername(e) {
|
||||||
|
let orbisUsername = e.target.value;
|
||||||
|
this.setState({ orbisCreds: { email: orbisUsername, password: this.state.orbisCreds.password } }, () => {
|
||||||
|
Persist.setOrbisCreds(this.state.orbisCreds);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for changing category
|
||||||
|
* @param {SyntheticEvent} e React Event
|
||||||
|
*/
|
||||||
|
orbisCategory(e) {
|
||||||
|
let ship = this.state.ship;
|
||||||
|
let cat = e.target.value;
|
||||||
|
ship.category = cat;
|
||||||
|
this.setState({ship});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render the modal
|
||||||
|
* @return {React.Component} Modal Content
|
||||||
|
*/
|
||||||
|
render() {
|
||||||
|
let translate = this.context.language.translate;
|
||||||
|
this.orbisPasswordHandler = this.orbisPasswordHandler.bind(this);
|
||||||
|
this.orbisUsername = this.orbisUsername.bind(this);
|
||||||
|
this.sendToOrbis = this.sendToOrbis.bind(this);
|
||||||
|
this.getOrbisAuthStatus();
|
||||||
|
return <div className='modal' onClick={ (e) => e.stopPropagation() }>
|
||||||
|
<h2>{translate('upload to orbis')}</h2>
|
||||||
|
<br/>
|
||||||
|
<label>Orbis auth status: </label>
|
||||||
|
<input value={this.state.authenticatedStatus} readOnly size={25} onFocus={ (e) => e.target.select() }/>
|
||||||
|
<br/><br/>
|
||||||
|
<a className='button' href="https://orbis.zone/api/auth">Log in / signup to Orbis</a>
|
||||||
|
<br/><br/>
|
||||||
|
<h3>Category</h3>
|
||||||
|
<select onChange={this.orbisCategory}>
|
||||||
|
<option value="">No Category</option>
|
||||||
|
<option>Combat</option>
|
||||||
|
<option>Mining</option>
|
||||||
|
<option>Trading</option>
|
||||||
|
<option>Exploration</option>
|
||||||
|
<option>Passenger Liner</option>
|
||||||
|
<option>PvP</option>
|
||||||
|
</select>
|
||||||
|
<br/><br/>
|
||||||
|
<h3 >{translate('Orbis link')}</h3>
|
||||||
|
<input value={this.state.orbisUrl} readOnly size={25} onFocus={ (e) => e.target.select() }/>
|
||||||
|
<br/><br/>
|
||||||
|
<p>Orbis.zone is currently in a trial period, and may be wiped at any time as development progresses. Some elements are also still placeholders.</p>
|
||||||
|
<button className={'l cb dismiss cap'} disabled={!!this.state.failed} onClick={this.sendToOrbis}>{translate('PHASE_UPLOAD_ORBIS')}</button>
|
||||||
|
<button className={'r dismiss cap'} onClick={this.context.hideModal}>{translate('close')}</button>
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -109,18 +109,17 @@ export default class ModalShoppingList extends TranslatedComponent {
|
|||||||
*/
|
*/
|
||||||
sendToEDEng(event) {
|
sendToEDEng(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
let translate = this.context.language.translate;
|
|
||||||
const target = event.target;
|
const target = event.target;
|
||||||
target.disabled = this.state.blueprints.length > 0;
|
target.disabled = this.state.blueprints.length > 0;
|
||||||
if (this.state.blueprints.length === 0) {
|
if (this.state.blueprints.length === 0) {
|
||||||
target.innerText = translate('No modded components.');
|
target.innerText = 'No modded components.';
|
||||||
target.disabled = true;
|
target.disabled = true;
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
target.innerText = translate('Send to EDEngineer');
|
target.innerText = 'Send to EDEngineer';
|
||||||
target.disabled = false;
|
target.disabled = false;
|
||||||
}, 3000);
|
}, 3000);
|
||||||
} else {
|
} else {
|
||||||
target.innerText = translate('Sending...');
|
target.innerText = 'Sending...';
|
||||||
}
|
}
|
||||||
let countSent = 0;
|
let countSent = 0;
|
||||||
let countTotal = this.state.blueprints.length;
|
let countTotal = this.state.blueprints.length;
|
||||||
@@ -140,7 +139,7 @@ export default class ModalShoppingList extends TranslatedComponent {
|
|||||||
countSent++;
|
countSent++;
|
||||||
if (countSent === countTotal) {
|
if (countSent === countTotal) {
|
||||||
target.disabled = false;
|
target.disabled = false;
|
||||||
target.innerText = translate('Send to EDEngineer');
|
target.innerText = 'Send to EDEngineer';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -231,32 +230,32 @@ export default class ModalShoppingList extends TranslatedComponent {
|
|||||||
this.sendToEDEng = this.sendToEDEng.bind(this);
|
this.sendToEDEng = this.sendToEDEng.bind(this);
|
||||||
return <div className='modal' onClick={ (e) => e.stopPropagation() }>
|
return <div className='modal' onClick={ (e) => e.stopPropagation() }>
|
||||||
<h2>{translate('PHRASE_SHOPPING_MATS')}</h2>
|
<h2>{translate('PHRASE_SHOPPING_MATS')}</h2>
|
||||||
<label>{translate('Grade 1 rolls ')}</label>
|
<label>Grade 1 rolls </label>
|
||||||
<input id={1} type={'number'} min={0} defaultValue={this.state.matsPerGrade[1]} onChange={this.changeHandler} />
|
<input id={1} type={'number'} min={0} defaultValue={this.state.matsPerGrade[1]} onChange={this.changeHandler} />
|
||||||
<br/>
|
<br/>
|
||||||
<label>{translate('Grade 2 rolls ')}</label>
|
<label>Grade 2 rolls </label>
|
||||||
<input id={2} type={'number'} min={0} defaultValue={this.state.matsPerGrade[2]} onChange={this.changeHandler} />
|
<input id={2} type={'number'} min={0} defaultValue={this.state.matsPerGrade[2]} onChange={this.changeHandler} />
|
||||||
<br/>
|
<br/>
|
||||||
<label>{translate('Grade 3 rolls ')}</label>
|
<label>Grade 3 rolls </label>
|
||||||
<input id={3} type={'number'} min={0} value={this.state.matsPerGrade[3]} onChange={this.changeHandler} />
|
<input id={3} type={'number'} min={0} value={this.state.matsPerGrade[3]} onChange={this.changeHandler} />
|
||||||
<br/>
|
<br/>
|
||||||
<label>{translate('Grade 4 rolls ')}</label>
|
<label>Grade 4 rolls </label>
|
||||||
<input id={4} type={'number'} min={0} value={this.state.matsPerGrade[4]} onChange={this.changeHandler} />
|
<input id={4} type={'number'} min={0} value={this.state.matsPerGrade[4]} onChange={this.changeHandler} />
|
||||||
<br/>
|
<br/>
|
||||||
<label>{translate('Grade 5 rolls ')}</label>
|
<label>Grade 5 rolls </label>
|
||||||
<input id={5} type={'number'} min={0} value={this.state.matsPerGrade[5]} onChange={this.changeHandler} />
|
<input id={5} type={'number'} min={0} value={this.state.matsPerGrade[5]} onChange={this.changeHandler} />
|
||||||
<div>
|
<div>
|
||||||
<textarea className='cb json' readOnly value={this.state.matsList} />
|
<textarea className='cb json' readOnly value={this.state.matsList} />
|
||||||
</div>
|
</div>
|
||||||
<label hidden={!compatible} className={'l cap'}>{translate('CMDR Name')}</label>
|
<label hidden={!compatible} className={'l cap'}>CMDR Name </label>
|
||||||
<br/>
|
<br/>
|
||||||
<select hidden={!compatible} className={'cmdr-select l cap'} onChange={this.cmdrChangeHandler} defaultValue={this.state.cmdrName}>
|
<select hidden={!compatible} className={'cmdr-select l cap'} onChange={this.cmdrChangeHandler} defaultValue={this.state.cmdrName}>
|
||||||
{this.state.cmdrs.map(e => <option key={e}>{e}</option>)}
|
{this.state.cmdrs.map(e => <option key={e}>{e}</option>)}
|
||||||
</select>
|
</select>
|
||||||
<br/>
|
<br/>
|
||||||
<p hidden={!this.state.failed} id={'failed'} className={'l'}>{translate('PHRASE_FAIL_EDENGINEER')}</p>
|
<p hidden={!this.state.failed} id={'failed'} className={'l'}>Failed to send to EDEngineer (Launch EDEngineer and make sure the API is started then refresh the page.)</p>
|
||||||
<p hidden={compatible} id={'browserbad'} className={'l'}>{translate('PHRASE_FIREFOX_EDENGINEER')}</p>
|
<p hidden={compatible} id={'browserbad'} className={'l'}>Sending to EDEngineer is not compatible with Firefox's security settings. Please try again with Chrome.</p>
|
||||||
<button className={'l cb dismiss cap'} disabled={!!this.state.failed || !compatible} onClick={this.sendToEDEng}>{translate('Send to EDEngineer')}</button>
|
<button className={'l cb dismiss cap'} disabled={!!this.state.failed || !compatible} onClick={this.sendToEDEng}>{translate('Send To EDEngineer')}</button>
|
||||||
<button className={'r dismiss cap'} onClick={this.context.hideModal}>{translate('close')}</button>
|
<button className={'r dismiss cap'} onClick={this.context.hideModal}>{translate('close')}</button>
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,7 @@ import PropTypes from 'prop-types';
|
|||||||
import TranslatedComponent from './TranslatedComponent';
|
import TranslatedComponent from './TranslatedComponent';
|
||||||
import cn from 'classnames';
|
import cn from 'classnames';
|
||||||
import NumberEditor from 'react-number-editor';
|
import NumberEditor from 'react-number-editor';
|
||||||
import { isChangeValueBeneficial } from '../utils/BlueprintFunctions';
|
import { isValueBeneficial } from '../utils/BlueprintFunctions';
|
||||||
import { Modifications } from 'coriolis-data/dist';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Modification
|
* Modification
|
||||||
@@ -80,7 +79,6 @@ export default class Modification extends TranslatedComponent {
|
|||||||
let { translate, formats, units } = this.context.language;
|
let { translate, formats, units } = this.context.language;
|
||||||
let { m, name } = this.props;
|
let { m, name } = this.props;
|
||||||
let modValue = m.getChange(name);
|
let modValue = m.getChange(name);
|
||||||
let isOverwrite = Modifications.modifications[name].method === 'overwrite';
|
|
||||||
|
|
||||||
if (name === 'damagedist') {
|
if (name === 'damagedist') {
|
||||||
// We don't show damage distribution
|
// We don't show damage distribution
|
||||||
@@ -119,10 +117,10 @@ export default class Modification extends TranslatedComponent {
|
|||||||
</td>
|
</td>
|
||||||
<td style={{ textAlign: 'center' }} className={
|
<td style={{ textAlign: 'center' }} className={
|
||||||
modValue ?
|
modValue ?
|
||||||
isChangeValueBeneficial(name, modValue) ? 'secondary' : 'warning' :
|
isValueBeneficial(name, modValue) ? 'secondary' : 'warning' :
|
||||||
''
|
''
|
||||||
}>
|
}>
|
||||||
{formats.f2(modValue / 100) || 0}{isOverwrite ? '' : '%'}
|
{formats.f2(modValue / 100) || 0}%
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
@@ -478,7 +478,7 @@ export default class ModificationsMenu extends TranslatedComponent {
|
|||||||
<tbody>
|
<tbody>
|
||||||
{ showRolls ?
|
{ showRolls ?
|
||||||
<tr>
|
<tr>
|
||||||
<td tabIndex="0" className={ cn('section-menu button-inline-menu', { active: false }) }> { translate('mroll') }: </td>
|
<td tabIndex="0" className={ cn('section-menu button-inline-menu', { active: false }) }> { translate('roll') }: </td>
|
||||||
<td tabIndex="0" className={ cn('section-menu button-inline-menu', { active: blueprintCv === 0 }) } style={{ cursor: 'pointer' }} onClick={_rollWorst} onKeyDown={ this._keyDown } onMouseOver={termtip.bind(null, 'PHRASE_BLUEPRINT_WORST')} onMouseOut={tooltip.bind(null, null)}> { translate('0%') } </td>
|
<td tabIndex="0" className={ cn('section-menu button-inline-menu', { active: blueprintCv === 0 }) } style={{ cursor: 'pointer' }} onClick={_rollWorst} onKeyDown={ this._keyDown } onMouseOver={termtip.bind(null, 'PHRASE_BLUEPRINT_WORST')} onMouseOut={tooltip.bind(null, null)}> { translate('0%') } </td>
|
||||||
<td tabIndex="0" className={ cn('section-menu button-inline-menu', { active: blueprintCv === 50 })} style={{ cursor: 'pointer' }} onClick={_rollFifty} onKeyDown={ this._keyDown } onMouseOver={termtip.bind(null, 'PHRASE_BLUEPRINT_FIFTY')} onMouseOut={tooltip.bind(null, null)}> { translate('50%') } </td>
|
<td tabIndex="0" className={ cn('section-menu button-inline-menu', { active: blueprintCv === 50 })} style={{ cursor: 'pointer' }} onClick={_rollFifty} onKeyDown={ this._keyDown } onMouseOver={termtip.bind(null, 'PHRASE_BLUEPRINT_FIFTY')} onMouseOut={tooltip.bind(null, null)}> { translate('50%') } </td>
|
||||||
<td tabIndex="0" className={ cn('section-menu button-inline-menu', { active: blueprintCv === 100 })} style={{ cursor: 'pointer' }} onClick={_rollFull} onKeyDown={ this._keyDown } onMouseOver={termtip.bind(null, 'PHRASE_BLUEPRINT_BEST')} onMouseOut={tooltip.bind(null, null)}> { translate('100%') } </td>
|
<td tabIndex="0" className={ cn('section-menu button-inline-menu', { active: blueprintCv === 100 })} style={{ cursor: 'pointer' }} onClick={_rollFull} onKeyDown={ this._keyDown } onMouseOver={termtip.bind(null, 'PHRASE_BLUEPRINT_BEST')} onMouseOut={tooltip.bind(null, null)}> { translate('100%') } </td>
|
||||||
|
|||||||
@@ -243,13 +243,8 @@ export default class Offence extends TranslatedComponent {
|
|||||||
<td className='ri'><span onMouseOver={termtip.bind(null, baseSDpsTooltipDetails)} onMouseOut={tooltip.bind(null, null)}>{formats.f1(weapon.sdps.base.total)}</span></td>
|
<td className='ri'><span onMouseOver={termtip.bind(null, baseSDpsTooltipDetails)} onMouseOut={tooltip.bind(null, null)}>{formats.f1(weapon.sdps.base.total)}</span></td>
|
||||||
<td className='ri'><span onMouseOver={termtip.bind(null, effectiveShieldsSDpsTooltipDetails)} onMouseOut={tooltip.bind(null, null)}>{formats.f1(weapon.sdps.shields.total)}</span></td>
|
<td className='ri'><span onMouseOver={termtip.bind(null, effectiveShieldsSDpsTooltipDetails)} onMouseOut={tooltip.bind(null, null)}>{formats.f1(weapon.sdps.shields.total)}</span></td>
|
||||||
<td className='ri'><span onMouseOver={termtip.bind(null, effectivenessShieldsTooltipDetails)} onMouseOut={tooltip.bind(null, null)}>{formats.pct1(weapon.effectiveness.shields.total)}</span></td>
|
<td className='ri'><span onMouseOver={termtip.bind(null, effectivenessShieldsTooltipDetails)} onMouseOut={tooltip.bind(null, null)}>{formats.pct1(weapon.effectiveness.shields.total)}</span></td>
|
||||||
|
|
||||||
<td className='ri'><span>{formats.f1(weapon.effectiveness.shields.dpe)}</span></td>
|
|
||||||
|
|
||||||
<td className='ri'><span onMouseOver={termtip.bind(null, effectiveArmourSDpsTooltipDetails)} onMouseOut={tooltip.bind(null, null)}>{formats.f1(weapon.sdps.armour.total)}</span></td>
|
<td className='ri'><span onMouseOver={termtip.bind(null, effectiveArmourSDpsTooltipDetails)} onMouseOut={tooltip.bind(null, null)}>{formats.f1(weapon.sdps.armour.total)}</span></td>
|
||||||
<td className='ri'><span onMouseOver={termtip.bind(null, effectivenessArmourTooltipDetails)} onMouseOut={tooltip.bind(null, null)}>{formats.pct1(weapon.effectiveness.armour.total)}</span></td>
|
<td className='ri'><span onMouseOver={termtip.bind(null, effectivenessArmourTooltipDetails)} onMouseOut={tooltip.bind(null, null)}>{formats.pct1(weapon.effectiveness.armour.total)}</span></td>
|
||||||
|
|
||||||
<td className='ri'><span>{formats.f1(weapon.effectiveness.armour.dpe)}</span></td>
|
|
||||||
</tr>);
|
</tr>);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,20 +271,15 @@ export default class Offence extends TranslatedComponent {
|
|||||||
<tr className='main'>
|
<tr className='main'>
|
||||||
<th rowSpan='2' className='sortable' onClick={sortOrder.bind(this, 'n')}>{translate('weapon')}</th>
|
<th rowSpan='2' className='sortable' onClick={sortOrder.bind(this, 'n')}>{translate('weapon')}</th>
|
||||||
<th colSpan='1'>{translate('overall')}</th>
|
<th colSpan='1'>{translate('overall')}</th>
|
||||||
<th colSpan='3'>{translate('opponent\'s shields')}</th>
|
<th colSpan='2'>{translate('opponent\'s shields')}</th>
|
||||||
<th colSpan='3'>{translate('opponent\'s armour')}</th>
|
<th colSpan='2'>{translate('opponent\'s armour')}</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th className='lft sortable' onMouseOver={termtip.bind(null, 'TT_EFFECTIVE_SDPS_SHIELDS')} onMouseOut={tooltip.bind(null, null)} onClick={sortOrder.bind(this, 'esdpss')}>{'sdps'}</th>
|
<th className='lft sortable' onMouseOver={termtip.bind(null, 'TT_EFFECTIVE_SDPS_SHIELDS')} onMouseOut={tooltip.bind(null, null)} onClick={sortOrder.bind(this, 'esdpss')}>{'sdps'}</th>
|
||||||
<th className='lft sortable' onMouseOver={termtip.bind(null, 'TT_EFFECTIVE_SDPS_SHIELDS')} onMouseOut={tooltip.bind(null, null)} onClick={sortOrder.bind(this, 'esdpss')}>{'sdps'}</th>
|
<th className='lft sortable' onMouseOver={termtip.bind(null, 'TT_EFFECTIVE_SDPS_SHIELDS')} onMouseOut={tooltip.bind(null, null)} onClick={sortOrder.bind(this, 'esdpss')}>{'sdps'}</th>
|
||||||
<th className='sortable' onMouseOver={termtip.bind(null, 'TT_EFFECTIVENESS_SHIELDS')} onMouseOut={tooltip.bind(null, null)}onClick={sortOrder.bind(this, 'es')}>{'eft'}</th>
|
<th className='sortable' onMouseOver={termtip.bind(null, 'TT_EFFECTIVENESS_SHIELDS')} onMouseOut={tooltip.bind(null, null)}onClick={sortOrder.bind(this, 'es')}>{'eft'}</th>
|
||||||
|
|
||||||
<th className='sortable'>{'dpe'}</th>
|
|
||||||
|
|
||||||
<th className='lft sortable' onMouseOver={termtip.bind(null, 'TT_EFFECTIVE_SDPS_ARMOUR')} onMouseOut={tooltip.bind(null, null)}onClick={sortOrder.bind(this, 'esdpsh')}>{'sdps'}</th>
|
<th className='lft sortable' onMouseOver={termtip.bind(null, 'TT_EFFECTIVE_SDPS_ARMOUR')} onMouseOut={tooltip.bind(null, null)}onClick={sortOrder.bind(this, 'esdpsh')}>{'sdps'}</th>
|
||||||
<th className='sortable' onMouseOver={termtip.bind(null, 'TT_EFFECTIVENESS_ARMOUR')} onMouseOut={tooltip.bind(null, null)}onClick={sortOrder.bind(this, 'eh')}>{'eft'}</th>
|
<th className='sortable' onMouseOver={termtip.bind(null, 'TT_EFFECTIVENESS_ARMOUR')} onMouseOut={tooltip.bind(null, null)}onClick={sortOrder.bind(this, 'eh')}>{'eft'}</th>
|
||||||
|
|
||||||
<th className='sortable'>{'dpe'}</th>
|
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@@ -300,10 +290,8 @@ export default class Offence extends TranslatedComponent {
|
|||||||
<td className='ri'><span onMouseOver={termtip.bind(null, totalSDpsTooltipDetails)} onMouseOut={tooltip.bind(null, null)}>={formats.f1(totalSDps)}</span></td>
|
<td className='ri'><span onMouseOver={termtip.bind(null, totalSDpsTooltipDetails)} onMouseOut={tooltip.bind(null, null)}>={formats.f1(totalSDps)}</span></td>
|
||||||
<td className='ri'><span onMouseOver={termtip.bind(null, totalShieldsSDpsTooltipDetails)} onMouseOut={tooltip.bind(null, null)}>={formats.f1(totalShieldsSDps)}</span></td>
|
<td className='ri'><span onMouseOver={termtip.bind(null, totalShieldsSDpsTooltipDetails)} onMouseOut={tooltip.bind(null, null)}>={formats.f1(totalShieldsSDps)}</span></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td></td>
|
|
||||||
<td className='ri'><span onMouseOver={termtip.bind(null, totalArmourSDpsTooltipDetails)} onMouseOut={tooltip.bind(null, null)}>={formats.f1(totalArmourSDps)}</span></td>
|
<td className='ri'><span onMouseOver={termtip.bind(null, totalArmourSDpsTooltipDetails)} onMouseOut={tooltip.bind(null, null)}>={formats.f1(totalArmourSDps)}</span></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td></td>
|
|
||||||
</tr>
|
</tr>
|
||||||
}
|
}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ export default class OutfittingSubpages extends TranslatedComponent {
|
|||||||
<th style={{ width:'25%' }} className={cn({ active: tab == 'power' })} onClick={this._showTab.bind(this, 'power')} >{translate('power and costs')}</th>
|
<th style={{ width:'25%' }} className={cn({ active: tab == 'power' })} onClick={this._showTab.bind(this, 'power')} >{translate('power and costs')}</th>
|
||||||
<th style={{ width:'25%' }} className={cn({ active: tab == 'profiles' })} onClick={this._showTab.bind(this, 'profiles')} >{translate('profiles')}</th>
|
<th style={{ width:'25%' }} className={cn({ active: tab == 'profiles' })} onClick={this._showTab.bind(this, 'profiles')} >{translate('profiles')}</th>
|
||||||
<th style={{ width:'25%' }} className={cn({ active: tab == 'offence' })} onClick={this._showTab.bind(this, 'offence')} >{translate('offence')}</th>
|
<th style={{ width:'25%' }} className={cn({ active: tab == 'offence' })} onClick={this._showTab.bind(this, 'offence')} >{translate('offence')}</th>
|
||||||
<th style={{ width:'25%' }} className={cn({ active: tab == 'defence' })} onClick={this._showTab.bind(this, 'defence')} >{translate('tab_defence')}</th>
|
<th style={{ width:'25%' }} className={cn({ active: tab == 'defence' })} onClick={this._showTab.bind(this, 'defence')} >{translate('defence')}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
</table>
|
</table>
|
||||||
|
|||||||
@@ -50,7 +50,6 @@ export default class ShipSummaryTable extends TranslatedComponent {
|
|||||||
const speedTooltip = canThrust ? 'TT_SUMMARY_SPEED' : 'TT_SUMMARY_SPEED_NONFUNCTIONAL';
|
const speedTooltip = canThrust ? 'TT_SUMMARY_SPEED' : 'TT_SUMMARY_SPEED_NONFUNCTIONAL';
|
||||||
const canBoost = ship.canBoost(cargo, ship.fuelCapacity);
|
const canBoost = ship.canBoost(cargo, ship.fuelCapacity);
|
||||||
const boostTooltip = canBoost ? 'TT_SUMMARY_BOOST' : canThrust ? 'TT_SUMMARY_BOOST_NONFUNCTIONAL' : 'TT_SUMMARY_SPEED_NONFUNCTIONAL';
|
const boostTooltip = canBoost ? 'TT_SUMMARY_BOOST' : canThrust ? 'TT_SUMMARY_BOOST_NONFUNCTIONAL' : 'TT_SUMMARY_SPEED_NONFUNCTIONAL';
|
||||||
const canJump = ship.getSlotStatus(ship.standard[2]) == 3;
|
|
||||||
const sgMetrics = Calc.shieldMetrics(ship, pips.sys);
|
const sgMetrics = Calc.shieldMetrics(ship, pips.sys);
|
||||||
const shipBoost = canBoost ? Calc.calcBoost(ship) : 'No Boost';
|
const shipBoost = canBoost ? Calc.calcBoost(ship) : 'No Boost';
|
||||||
const restingHeat = Math.sqrt(((ship.standard[0].m.pgen * ship.standard[0].m.eff) / ship.heatCapacity) / 0.2);
|
const restingHeat = Math.sqrt(((ship.standard[0].m.pgen * ship.standard[0].m.eff) / ship.heatCapacity) / 0.2);
|
||||||
@@ -72,7 +71,7 @@ export default class ShipSummaryTable extends TranslatedComponent {
|
|||||||
<tr className='main'>
|
<tr className='main'>
|
||||||
<th rowSpan={2} className={ cn({ 'bg-warning-disabled': !canThrust }) }>{translate('speed')}</th>
|
<th rowSpan={2} className={ cn({ 'bg-warning-disabled': !canThrust }) }>{translate('speed')}</th>
|
||||||
<th rowSpan={2} className={ cn({ 'bg-warning-disabled': !canBoost }) }>{translate('boost')}</th>
|
<th rowSpan={2} className={ cn({ 'bg-warning-disabled': !canBoost }) }>{translate('boost')}</th>
|
||||||
<th colSpan={5} className={ cn({ 'bg-warning-disabled': !canJump }) }>{translate('jump range')}</th>
|
<th colSpan={5}>{translate('jump range')}</th>
|
||||||
<th rowSpan={2}>{translate('shield')}</th>
|
<th rowSpan={2}>{translate('shield')}</th>
|
||||||
<th rowSpan={2}>{translate('integrity')}</th>
|
<th rowSpan={2}>{translate('integrity')}</th>
|
||||||
<th rowSpan={2}>{translate('DPS')}</th>
|
<th rowSpan={2}>{translate('DPS')}</th>
|
||||||
@@ -86,15 +85,15 @@ export default class ShipSummaryTable extends TranslatedComponent {
|
|||||||
<th onMouseEnter={termtip.bind(null, 'hull hardness', { cap: 0 })} onMouseLeave={hide} rowSpan={2}>{translate('hrd')}</th>
|
<th onMouseEnter={termtip.bind(null, 'hull hardness', { cap: 0 })} onMouseLeave={hide} rowSpan={2}>{translate('hrd')}</th>
|
||||||
<th rowSpan={2}>{translate('crew')}</th>
|
<th rowSpan={2}>{translate('crew')}</th>
|
||||||
<th onMouseEnter={termtip.bind(null, 'mass lock factor', { cap: 0 })} onMouseLeave={hide} rowSpan={2}>{translate('MLF')}</th>
|
<th onMouseEnter={termtip.bind(null, 'mass lock factor', { cap: 0 })} onMouseLeave={hide} rowSpan={2}>{translate('MLF')}</th>
|
||||||
<th onMouseEnter={termtip.bind(null, 'TT_SUMMARY_BOOST_INTERVAL', { cap: 0 })} onMouseLeave={hide} rowSpan={2}>{translate('boost interval')}</th>
|
<th onMouseEnter={termtip.bind(null, 'TT_SUMMARY_BOOST_TIME', { cap: 0 })} onMouseLeave={hide} rowSpan={2}>{translate('boost time')}</th>
|
||||||
<th rowSpan={2}>{translate('resting heat (Beta)')}</th>
|
<th rowSpan={2}>{translate('resting heat (Beta)')}</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th className={ cn({ 'lft': true, 'bg-warning-disabled': !canJump }) }>{translate('max')}</th>
|
<th className='lft'>{translate('max')}</th>
|
||||||
<th className={ cn({ 'bg-warning-disabled': !canJump }) }>{translate('unladen')}</th>
|
<th>{translate('unladen')}</th>
|
||||||
<th className={ cn({ 'bg-warning-disabled': !canJump }) }>{translate('laden')}</th>
|
<th>{translate('laden')}</th>
|
||||||
<th className={ cn({ 'bg-warning-disabled': !canJump }) }>{translate('total unladen')}</th>
|
<th>{translate('total unladen')}</th>
|
||||||
<th className={ cn({ 'bg-warning-disabled': !canJump }) }>{translate('total laden')}</th>
|
<th>{translate('total laden')}</th>
|
||||||
<th className='lft'>{translate('hull')}</th>
|
<th className='lft'>{translate('hull')}</th>
|
||||||
<th>{translate('unladen')}</th>
|
<th>{translate('unladen')}</th>
|
||||||
<th>{translate('laden')}</th>
|
<th>{translate('laden')}</th>
|
||||||
@@ -104,11 +103,11 @@ export default class ShipSummaryTable extends TranslatedComponent {
|
|||||||
<tr>
|
<tr>
|
||||||
<td onMouseEnter={termtip.bind(null, speedTooltip, { cap: 0 })} onMouseLeave={hide}>{ canThrust ? <span>{int(ship.calcSpeed(4, ship.fuelCapacity, 0, false))}{u['m/s']}</span> : <span className='warning'>0 <Warning/></span> }</td>
|
<td onMouseEnter={termtip.bind(null, speedTooltip, { cap: 0 })} onMouseLeave={hide}>{ canThrust ? <span>{int(ship.calcSpeed(4, ship.fuelCapacity, 0, false))}{u['m/s']}</span> : <span className='warning'>0 <Warning/></span> }</td>
|
||||||
<td onMouseEnter={termtip.bind(null, boostTooltip, { cap: 0 })} onMouseLeave={hide}>{ canBoost ? <span>{int(ship.calcSpeed(4, ship.fuelCapacity, 0, true))}{u['m/s']}</span> : <span className='warning'>0 <Warning/></span> }</td>
|
<td onMouseEnter={termtip.bind(null, boostTooltip, { cap: 0 })} onMouseLeave={hide}>{ canBoost ? <span>{int(ship.calcSpeed(4, ship.fuelCapacity, 0, true))}{u['m/s']}</span> : <span className='warning'>0 <Warning/></span> }</td>
|
||||||
<td onMouseEnter={termtip.bind(null, 'TT_SUMMARY_MAX_SINGLE_JUMP', { cap: 0 })} onMouseLeave={hide}>{ canJump ? <span>{ f2(Calc.jumpRange(ship.unladenMass + ship.standard[2].m.getMaxFuelPerJump(), ship.standard[2].m, ship.standard[2].m.getMaxFuelPerJump(), ship))}{u.LY}</span> : <span className='warning'>0 <Warning/></span> }</td>
|
<td><span onMouseEnter={termtip.bind(null, 'TT_SUMMARY_MAX_SINGLE_JUMP', { cap: 0 })} onMouseLeave={hide}>{f2(Calc.jumpRange(ship.unladenMass + ship.standard[2].m.getMaxFuelPerJump(), ship.standard[2].m, ship.standard[2].m.getMaxFuelPerJump(), ship))}{u.LY}</span></td>
|
||||||
<td onMouseEnter={termtip.bind(null, 'TT_SUMMARY_UNLADEN_SINGLE_JUMP', { cap: 0 })} onMouseLeave={hide}>{ canJump ? <span>{f2(Calc.jumpRange(ship.unladenMass + ship.fuelCapacity, ship.standard[2].m, ship.fuelCapacity, ship))}{u.LY}</span> : <span className='warning'>0 <Warning/></span> }</td>
|
<td><span onMouseEnter={termtip.bind(null, 'TT_SUMMARY_UNLADEN_SINGLE_JUMP', { cap: 0 })} onMouseLeave={hide}>{f2(Calc.jumpRange(ship.unladenMass + ship.fuelCapacity, ship.standard[2].m, ship.fuelCapacity, ship))}{u.LY}</span></td>
|
||||||
<td onMouseEnter={termtip.bind(null, 'TT_SUMMARY_LADEN_SINGLE_JUMP', { cap: 0 })} onMouseLeave={hide}>{ canJump ? <span>{f2(Calc.jumpRange(ship.unladenMass + ship.fuelCapacity + ship.cargoCapacity, ship.standard[2].m, ship.fuelCapacity, ship))}{u.LY}</span> : <span className='warning'>0 <Warning/></span> }</td>
|
<td><span onMouseEnter={termtip.bind(null, 'TT_SUMMARY_LADEN_SINGLE_JUMP', { cap: 0 })} onMouseLeave={hide}>{f2(Calc.jumpRange(ship.unladenMass + ship.fuelCapacity + ship.cargoCapacity, ship.standard[2].m, ship.fuelCapacity, ship))}{u.LY}</span></td>
|
||||||
<td onMouseEnter={termtip.bind(null, 'TT_SUMMARY_UNLADEN_TOTAL_JUMP', { cap: 0 })} onMouseLeave={hide}>{ canJump ? <span>{f2(Calc.totalJumpRange(ship.unladenMass + ship.fuelCapacity, ship.standard[2].m, ship.fuelCapacity, ship))}{u.LY}</span> : <span className='warning'>0 <Warning/></span> }</td>
|
<td onMouseEnter={termtip.bind(null, 'TT_SUMMARY_UNLADEN_TOTAL_JUMP', { cap: 0 })} onMouseLeave={hide}>{f2(Calc.totalJumpRange(ship.unladenMass + ship.fuelCapacity, ship.standard[2].m, ship.fuelCapacity, ship))}{u.LY}</td>
|
||||||
<td onMouseEnter={termtip.bind(null, 'TT_SUMMARY_LADEN_TOTAL_JUMP', { cap: 0 })} onMouseLeave={hide}>{ canJump ? <span>{f2(Calc.totalJumpRange(ship.unladenMass + ship.fuelCapacity + ship.cargoCapacity, ship.standard[2].m, ship.fuelCapacity, ship))}{u.LY}</span> : <span className='warning'>0 <Warning/></span> }</td>
|
<td onMouseEnter={termtip.bind(null, 'TT_SUMMARY_LADEN_TOTAL_JUMP', { cap: 0 })} onMouseLeave={hide}>{f2(Calc.totalJumpRange(ship.unladenMass + ship.fuelCapacity + ship.cargoCapacity, ship.standard[2].m, ship.fuelCapacity, ship))}{u.LY}</td>
|
||||||
<td className={sgClassNames} onMouseEnter={termtip.bind(null, sgTooltip, { cap: 0 })} onMouseLeave={hide}>{int(ship.shield)}{u.MJ}</td>
|
<td className={sgClassNames} onMouseEnter={termtip.bind(null, sgTooltip, { cap: 0 })} onMouseLeave={hide}>{int(ship.shield)}{u.MJ}</td>
|
||||||
<td onMouseEnter={termtip.bind(null, 'TT_SUMMARY_INTEGRITY', { cap: 0 })} onMouseLeave={hide}>{int(ship.armour)}</td>
|
<td onMouseEnter={termtip.bind(null, 'TT_SUMMARY_INTEGRITY', { cap: 0 })} onMouseLeave={hide}>{int(ship.armour)}</td>
|
||||||
<td onMouseEnter={termtip.bind(null, 'TT_SUMMARY_DPS', { cap: 0 })} onMouseLeave={hide}>{f1(ship.totalDps)}</td>
|
<td onMouseEnter={termtip.bind(null, 'TT_SUMMARY_DPS', { cap: 0 })} onMouseLeave={hide}>{f1(ship.totalDps)}</td>
|
||||||
@@ -160,10 +159,10 @@ export default class ShipSummaryTable extends TranslatedComponent {
|
|||||||
<td>{formats.pct1(ship.shieldThermRes)}</td>
|
<td>{formats.pct1(ship.shieldThermRes)}</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
|
|
||||||
<td>{int(ship && sgMetrics.summary > 0 ? sgMetrics.summary : 0)}{u.MJ}</td>
|
<td>{int(ship && ship.shield > 0 ? ship.shield : 0)}{u.MJ}</td>
|
||||||
<td>{int(ship && sgMetrics.summary > 0 ? sgMetrics.summary / sgMetrics.explosive.base : 0)}{u.MJ}</td>
|
<td>{int(ship && ship.shield > 0 ? ship.shield * ((1 / (1 - (ship.shieldExplRes)))) : 0)}{u.MJ}</td>
|
||||||
<td>{int(ship && sgMetrics.summary ? sgMetrics.summary / sgMetrics.kinetic.base : 0)}{u.MJ}</td>
|
<td>{int(ship && ship.shield > 0 ? ship.shield * ((1 / (1 - (ship.shieldKinRes)))) : 0)}{u.MJ}</td>
|
||||||
<td>{int(ship && sgMetrics.summary ? sgMetrics.summary / sgMetrics.thermal.base : 0)}{u.MJ}</td>
|
<td>{int(ship && ship.shield > 0 ? ship.shield * ((1 / (1 - (ship.shieldThermRes)))) : 0)}{u.MJ}</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td>{sgMetrics && sgMetrics.recover === Math.Inf ? translate('Never') : formats.time(sgMetrics.recover)}</td>
|
<td>{sgMetrics && sgMetrics.recover === Math.Inf ? translate('Never') : formats.time(sgMetrics.recover)}</td>
|
||||||
<td>{sgMetrics && sgMetrics.recharge === Math.Inf ? translate('Never') : formats.time(sgMetrics.recharge)}</td>
|
<td>{sgMetrics && sgMetrics.recharge === Math.Inf ? translate('Never') : formats.time(sgMetrics.recharge)}</td>
|
||||||
@@ -198,11 +197,11 @@ export default class ShipSummaryTable extends TranslatedComponent {
|
|||||||
<td>{formats.pct1(ship.hullKinRes)}</td>
|
<td>{formats.pct1(ship.hullKinRes)}</td>
|
||||||
<td>{formats.pct1(ship.hullThermRes)}</td>
|
<td>{formats.pct1(ship.hullThermRes)}</td>
|
||||||
<td>{formats.pct1(ship.hullCausRes)}</td>
|
<td>{formats.pct1(ship.hullCausRes)}</td>
|
||||||
<td>{int(armourMetrics.total)}</td>
|
<td>{int(ship.armour)}</td>
|
||||||
<td>{int(armourMetrics.total / armourMetrics.explosive.total)}</td>
|
<td>{int(ship.armour * ((1 / (1 - (ship.hullExplRes)))))}</td>
|
||||||
<td>{int(armourMetrics.total/ armourMetrics.kinetic.total)}</td>
|
<td>{int(ship.armour * ((1 / (1 - (ship.hullKinRes)))))}</td>
|
||||||
<td>{int(armourMetrics.total / armourMetrics.thermal.total)}</td>
|
<td>{int(ship.armour * ((1 / (1 - (ship.hullThermRes)))))}</td>
|
||||||
<td>{int(armourMetrics.total/ armourMetrics.caustic.total)}</td>
|
<td>{int(ship.armour * ((1 / (1 - (ship.hullCausRes)))))}</td>
|
||||||
<td>{int(armourMetrics.modulearmour)}</td>
|
<td>{int(armourMetrics.modulearmour)}</td>
|
||||||
<td>{int(armourMetrics.moduleprotection * 100) + '%'}</td>
|
<td>{int(armourMetrics.moduleprotection * 100) + '%'}</td>
|
||||||
|
|
||||||
|
|||||||
@@ -127,8 +127,8 @@ export default class Slot extends TranslatedComponent {
|
|||||||
menu = <AvailableModulesMenu
|
menu = <AvailableModulesMenu
|
||||||
className={this._getClassNames()}
|
className={this._getClassNames()}
|
||||||
modules={availableModules()}
|
modules={availableModules()}
|
||||||
|
shipMass={ship.hullMass}
|
||||||
m={m}
|
m={m}
|
||||||
ship={ship}
|
|
||||||
onSelect={onSelect}
|
onSelect={onSelect}
|
||||||
warning={warning}
|
warning={warning}
|
||||||
diffDetails={diffDetails.bind(ship, this.context.language)}
|
diffDetails={diffDetails.bind(ship, this.context.language)}
|
||||||
|
|||||||
@@ -195,15 +195,6 @@ export default class SlotSection extends TranslatedComponent {
|
|||||||
if (targetSlot && canMount(this.props.ship, targetSlot, m.grp, m.class)) {
|
if (targetSlot && canMount(this.props.ship, targetSlot, m.grp, m.class)) {
|
||||||
const mCopy = m.clone();
|
const mCopy = m.clone();
|
||||||
this.props.ship.use(targetSlot, mCopy, false);
|
this.props.ship.use(targetSlot, mCopy, false);
|
||||||
let experimentalNum = this.props.ship.hardpoints
|
|
||||||
.filter(s => s.m && s.m.experimental).length;
|
|
||||||
// Remove the module on the last slot if we now exceed the number of
|
|
||||||
// experimentals allowed
|
|
||||||
if (m.experimental && 4 < experimentalNum) {
|
|
||||||
this.props.ship.updateStats(originSlot, null, originSlot.m);
|
|
||||||
originSlot.m = null; // Empty the slot
|
|
||||||
originSlot.discountedCost = 0;
|
|
||||||
}
|
|
||||||
// Copy power info
|
// Copy power info
|
||||||
targetSlot.enabled = originSlot.enabled;
|
targetSlot.enabled = originSlot.enabled;
|
||||||
targetSlot.priority = originSlot.priority;
|
targetSlot.priority = originSlot.priority;
|
||||||
|
|||||||
@@ -109,8 +109,8 @@ export default class StandardSlot extends TranslatedComponent {
|
|||||||
menu = <AvailableModulesMenu
|
menu = <AvailableModulesMenu
|
||||||
className='standard'
|
className='standard'
|
||||||
modules={modules}
|
modules={modules}
|
||||||
|
shipMass={ModuleUtils.isShieldGenerator(m.grp) ? ship.hullMass : ship.unladenMass}
|
||||||
m={m}
|
m={m}
|
||||||
ship={ship}
|
|
||||||
onSelect={onSelect}
|
onSelect={onSelect}
|
||||||
warning={warning}
|
warning={warning}
|
||||||
diffDetails={diffDetails.bind(ship, this.context.language)}
|
diffDetails={diffDetails.bind(ship, this.context.language)}
|
||||||
|
|||||||
@@ -20,16 +20,28 @@ export default class StandardSlotSection extends SlotSection {
|
|||||||
super(props, context, 'standard', 'core internal');
|
super(props, context, 'standard', 'core internal');
|
||||||
this._optimizeStandard = this._optimizeStandard.bind(this);
|
this._optimizeStandard = this._optimizeStandard.bind(this);
|
||||||
this._selectBulkhead = this._selectBulkhead.bind(this);
|
this._selectBulkhead = this._selectBulkhead.bind(this);
|
||||||
|
this._showDW2Menu = this._showDW2Menu.bind(this);
|
||||||
|
this._dw2 = this._dw2.bind(this);
|
||||||
this.selectedRefId = null;
|
this.selectedRefId = null;
|
||||||
this.firstRefId = 'maxjump';
|
this.firstRefId = 'maxjump';
|
||||||
this.lastRefId = 'racer';
|
this.lastRefId = 'dw2';
|
||||||
|
this.state = {
|
||||||
|
showDW2: false,
|
||||||
|
DW2Tier: -1,
|
||||||
|
DW2Eng: -1,
|
||||||
|
DW2Role: '',
|
||||||
|
DW2Gfsb: false,
|
||||||
|
DW2Gpp: false,
|
||||||
|
DW2Fighter: false
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle focus if the component updates
|
* Handle focus if the component updates
|
||||||
* @param {Object} prevProps React Component properties
|
* @param {Object} prevProps React Component properties
|
||||||
*/
|
*/
|
||||||
componentDidUpdate(prevProps) {
|
componentDidUpdate(prevProps) {
|
||||||
this._handleSectionFocus(prevProps,this.firstRefId, this.lastRefId);
|
this._handleSectionFocus(prevProps, this.firstRefId, this.lastRefId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -72,6 +84,114 @@ export default class StandardSlotSection extends SlotSection {
|
|||||||
this._close();
|
this._close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DW2 Build
|
||||||
|
*/
|
||||||
|
_dw2() {
|
||||||
|
this.selectedRefId = 'dw2';
|
||||||
|
this.setState({ showDW2: false });
|
||||||
|
ShipRoles.dw2Build(this.props.ship, this.state.DW2Tier, this.state.DW2Eng, this.state.DW2Role, this.state.DW2Gfsb, this.state.DW2Gpp, this.state.DW2Fighter);
|
||||||
|
this.props.ship.updateModificationsString();
|
||||||
|
this.props.onChange();
|
||||||
|
this.props.onCargoChange(this.props.ship.cargoCapacity);
|
||||||
|
this.props.onFuelChange(this.props.ship.fuelCapacity);
|
||||||
|
this._close();
|
||||||
|
}
|
||||||
|
|
||||||
|
_showDW2Menu(translate) {
|
||||||
|
return (
|
||||||
|
<div className='select' onClick={(e) => e.stopPropagation()} onContextMenu={stopCtxPropagation}>
|
||||||
|
<div className='select-group cap'>{translate('Tier')}</div>
|
||||||
|
<ul id={'tier'}>
|
||||||
|
<li className={cn({ active: this.state.DW2Tier === 1 }, 'lc')} tabIndex="0"
|
||||||
|
onClick={() => this.setState({ DW2Tier: 1 })} onKeyDown={this._keyDown}
|
||||||
|
>{translate('1 - Max. Jump Range, Unshielded')}</li>
|
||||||
|
<li className={cn({ active: this.state.DW2Tier === 2 }, 'lc')} tabIndex="0"
|
||||||
|
onClick={() => this.setState({ DW2Tier: 2 })} onKeyDown={this._keyDown}
|
||||||
|
>{translate('2 - Max. Jump Range, Minimal Shields')}</li>
|
||||||
|
<li className={cn({ active: this.state.DW2Tier === 3 }, 'lc')} tabIndex="0"
|
||||||
|
onClick={() => this.setState({ DW2Tier: 3 })} onKeyDown={this._keyDown}
|
||||||
|
>{translate('3 - Max. Jump Range, Optimal Shields')}</li>
|
||||||
|
<li className={cn({ active: this.state.DW2Tier === 4 }, 'lc')} tabIndex="0"
|
||||||
|
onClick={() => this.setState({ DW2Tier: 4 })} onKeyDown={this._keyDown}
|
||||||
|
>{translate('4 - Max. Jump Range, Optimal Shields & Thrusters')}</li>
|
||||||
|
</ul>
|
||||||
|
<hr/>
|
||||||
|
<div className='select-group cap'>{translate('Engineering Level')}</div>
|
||||||
|
<ul id={'engLevel'}>
|
||||||
|
<li className={cn({ active: this.state.DW2Eng === 1 }, 'lc')} tabIndex="0"
|
||||||
|
onClick={() => this.setState({ DW2Eng: 1 })} onKeyDown={this._keyDown}
|
||||||
|
>{translate('No engineering')}</li>
|
||||||
|
<li className={cn({ active: this.state.DW2Eng === 2 }, 'lc')} tabIndex="0"
|
||||||
|
onClick={() => this.setState({ DW2Eng: 2 })} onKeyDown={this._keyDown}
|
||||||
|
>{translate('Only Felicity Farseer and Elvira Martuuk')}</li>
|
||||||
|
<li className={cn({ active: this.state.DW2Eng === 3 }, 'lc')} tabIndex="0"
|
||||||
|
onClick={() => this.setState({ DW2Eng: 3 })} onKeyDown={this._keyDown}
|
||||||
|
>{translate('All exploration engineers')}</li>
|
||||||
|
</ul>
|
||||||
|
<hr/>
|
||||||
|
<div className='select-group cap'>{translate('Role')}</div>
|
||||||
|
<ul id={'role'}>
|
||||||
|
<li className={cn({ active: this.state.DW2Role === 'exploration' }, 'lc')} tabIndex="0"
|
||||||
|
onClick={() => this.setState({ DW2Role: 'exploration' })}
|
||||||
|
onKeyDown={this._keyDown}
|
||||||
|
>{translate('Space exploration')}</li>
|
||||||
|
<li className={cn({ active: this.state.DW2Role === 'surface' }, 'lc')} tabIndex="0"
|
||||||
|
onClick={() => this.setState({ DW2Role: 'surface' })}
|
||||||
|
onKeyDown={this._keyDown}
|
||||||
|
>{translate('Surface exploration')}</li>
|
||||||
|
<li className={cn({ active: this.state.DW2Role === 'materialProspector' }, 'lc')} tabIndex="0"
|
||||||
|
onClick={() => this.setState({ DW2Role: 'materialProspector' })}
|
||||||
|
onKeyDown={this._keyDown}
|
||||||
|
>{translate('Material prospector')}</li>
|
||||||
|
<li className={cn({ active: this.state.DW2Role === 'propectorMining' }, 'lc')} tabIndex="0"
|
||||||
|
onClick={() => this.setState({ DW2Role: 'propectorMining' })}
|
||||||
|
onKeyDown={this._keyDown}
|
||||||
|
>{translate('Prospector/Sapper Miner')}</li>
|
||||||
|
<li className={cn({ active: this.state.DW2Role === 'bigRigMining' }, 'lc')} tabIndex="0"
|
||||||
|
onClick={() => this.setState({ DW2Role: 'bigRigMining' })}
|
||||||
|
onKeyDown={this._keyDown}
|
||||||
|
>{translate('Big Rig, full mining')}</li>
|
||||||
|
<li className={cn({ active: this.state.DW2Role === 'fuelRat' }, 'lc')} tabIndex="0"
|
||||||
|
onClick={() => this.setState({ DW2Role: 'fuelRat' })} onKeyDown={this._keyDown}
|
||||||
|
>{translate('Fuel Rat')}</li>
|
||||||
|
<li className={cn({ active: this.state.DW2Role === 'mechanic' }, 'lc')} tabIndex="0"
|
||||||
|
onClick={() => this.setState({ DW2Role: 'mechanic' })} onKeyDown={this._keyDown}
|
||||||
|
>{translate('Mechanic')}</li>
|
||||||
|
<li className={cn({ active: this.state.DW2Role === 'trucker' }, 'lc')} tabIndex="0"
|
||||||
|
onClick={() => this.setState({ DW2Role: 'trucker' })} onKeyDown={this._keyDown}
|
||||||
|
>{translate('Trucker')}</li>
|
||||||
|
</ul>
|
||||||
|
<hr/>
|
||||||
|
<ul>
|
||||||
|
<li className={cn({ active: this.state.DW2Gfsb === true }, 'lc')}
|
||||||
|
onClick={() => this.setState({ DW2Gfsb: this.state.DW2Gfsb !== true })}>
|
||||||
|
Add Guardian FSD Booster
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<ul>
|
||||||
|
<li className={cn({ active: this.state.DW2Gpp === true }, 'lc')}
|
||||||
|
onClick={() => this.setState({ DW2Gpp: this.state.DW2Gpp !== true })}>
|
||||||
|
Add Guardian Power Plant
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<ul>
|
||||||
|
<li className={cn({ active: this.state.DW2Fighter === true }, 'lc')}
|
||||||
|
onClick={() => this.setState({ DW2Fighter: this.state.DW2Fighter !== true })}>
|
||||||
|
Add Fighter
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<hr/>
|
||||||
|
<ul>
|
||||||
|
<li onClick={this._dw2} className={cn('lc')} tabIndex="0"
|
||||||
|
onKeyDown={this._keyDown}>
|
||||||
|
<button className="button">Apply</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Miner Build
|
* Miner Build
|
||||||
* @param {Boolean} shielded True if shield generator should be included
|
* @param {Boolean} shielded True if shield generator should be included
|
||||||
@@ -177,7 +297,6 @@ export default class StandardSlotSection extends SlotSection {
|
|||||||
warning={m => m instanceof Module ? m.getMaxMass() < (ship.unladenMass + cargo + fuel - st[1].m.mass + m.mass) : m.maxmass < (ship.unladenMass + cargo + fuel - st[1].m.mass + m.mass)}
|
warning={m => m instanceof Module ? m.getMaxMass() < (ship.unladenMass + cargo + fuel - st[1].m.mass + m.mass) : m.maxmass < (ship.unladenMass + cargo + fuel - st[1].m.mass + m.mass)}
|
||||||
/>;
|
/>;
|
||||||
|
|
||||||
|
|
||||||
slots[3] = <StandardSlot
|
slots[3] = <StandardSlot
|
||||||
key='fsd'
|
key='fsd'
|
||||||
slot={st[2]}
|
slot={st[2]}
|
||||||
@@ -232,7 +351,7 @@ export default class StandardSlotSection extends SlotSection {
|
|||||||
selected={currentMenu == st[6]}
|
selected={currentMenu == st[6]}
|
||||||
onChange={this.props.onChange}
|
onChange={this.props.onChange}
|
||||||
ship={ship}
|
ship={ship}
|
||||||
warning= {m => m.fuel < st[2].m.maxfuel} // Show warning when fuel tank is smaller than FSD Max Fuel
|
warning={m => m.fuel < st[2].m.maxfuel} // Show warning when fuel tank is smaller than FSD Max Fuel
|
||||||
/>;
|
/>;
|
||||||
|
|
||||||
return slots;
|
return slots;
|
||||||
@@ -245,19 +364,34 @@ export default class StandardSlotSection extends SlotSection {
|
|||||||
*/
|
*/
|
||||||
_getSectionMenu(translate) {
|
_getSectionMenu(translate) {
|
||||||
let planetaryDisabled = this.props.ship.internal.length < 4;
|
let planetaryDisabled = this.props.ship.internal.length < 4;
|
||||||
|
if (this.state.showDW2 === true) {
|
||||||
|
return this._showDW2Menu(translate);
|
||||||
|
}
|
||||||
return <div className='select' onClick={(e) => e.stopPropagation()} onContextMenu={stopCtxPropagation}>
|
return <div className='select' onClick={(e) => e.stopPropagation()} onContextMenu={stopCtxPropagation}>
|
||||||
<ul>
|
<ul>
|
||||||
<li className='lc' tabIndex="0" onClick={this._optimizeStandard} onKeyDown={this._keyDown} ref={smRef => this.sectionRefArr['maxjump'] = smRef}>{translate('Maximize Jump Range')}</li>
|
<li className='lc' tabIndex="0" onClick={this._optimizeStandard} onKeyDown={this._keyDown}
|
||||||
|
ref={smRef => this.sectionRefArr['maxjump'] = smRef}>{translate('Maximize Jump Range')}</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div className='select-group cap'>{translate('roles')}</div>
|
<div className='select-group cap'>{translate('roles')}</div>
|
||||||
<ul>
|
<ul>
|
||||||
<li className='lc' tabIndex="0" onClick={this._multiPurpose.bind(this, false, 0)} onKeyDown={this._keyDown} ref={smRef => this.sectionRefArr['multipurpose'] = smRef}>{translate('Multi-purpose')}</li>
|
<li className='lc' tabIndex="0" onClick={this._multiPurpose.bind(this, false, 0)} onKeyDown={this._keyDown}
|
||||||
<li className='lc' tabIndex="0" onClick={this._multiPurpose.bind(this, true, 2)} onKeyDown={this._keyDown} ref={smRef => this.sectionRefArr['combat'] = smRef}>{translate('Combat')}</li>
|
ref={smRef => this.sectionRefArr['multipurpose'] = smRef}>{translate('Multi-purpose')}</li>
|
||||||
<li className='lc' tabIndex="0" onClick={this._optimizeCargo.bind(this, true)} onKeyDown={this._keyDown} ref={smRef => this.sectionRefArr['trader'] = smRef}>{translate('Trader')}</li>
|
<li className='lc' tabIndex="0" onClick={this._multiPurpose.bind(this, true, 2)} onKeyDown={this._keyDown}
|
||||||
<li className='lc' tabIndex="0" onClick={this._optimizeExplorer.bind(this, false)} onKeyDown={this._keyDown} ref={smRef => this.sectionRefArr['explorer'] = smRef}>{translate('Explorer')}</li>
|
ref={smRef => this.sectionRefArr['combat'] = smRef}>{translate('Combat')}</li>
|
||||||
<li className={cn('lc', { disabled: planetaryDisabled })} tabIndex={planetaryDisabled ? '' : '0'} onClick={!planetaryDisabled && this._optimizeExplorer.bind(this, true)} onKeyDown={this._keyDown} ref={smRef => this.sectionRefArr['planetary'] = smRef}>{translate('Planetary Explorer')}</li>
|
<li className='lc' tabIndex="0" onClick={this._optimizeCargo.bind(this, true)} onKeyDown={this._keyDown}
|
||||||
<li className='lc' tabIndex="0" onClick={this._optimizeMiner.bind(this, true)} onKeyDown={this._keyDown} ref={smRef => this.sectionRefArr['miner'] = smRef}>{translate('Miner')}</li>
|
ref={smRef => this.sectionRefArr['trader'] = smRef}>{translate('Trader')}</li>
|
||||||
<li className='lc' tabIndex="0" onClick={this._optimizeRacer.bind(this)} onKeyDown={this._keyDown} ref={smRef => this.sectionRefArr['racer'] = smRef}>{translate('Racer')}</li>
|
<li className='lc' tabIndex="0" onClick={this._optimizeExplorer.bind(this, false)} onKeyDown={this._keyDown}
|
||||||
|
ref={smRef => this.sectionRefArr['explorer'] = smRef}>{translate('Explorer')}</li>
|
||||||
|
<li className={cn('lc', { disabled: planetaryDisabled })} tabIndex={planetaryDisabled ? '' : '0'}
|
||||||
|
onClick={!planetaryDisabled && this._optimizeExplorer.bind(this, true)} onKeyDown={this._keyDown}
|
||||||
|
ref={smRef => this.sectionRefArr['planetary'] = smRef}>{translate('Planetary Explorer')}</li>
|
||||||
|
<li className='lc' tabIndex="0" onClick={this._optimizeMiner.bind(this, true)} onKeyDown={this._keyDown}
|
||||||
|
ref={smRef => this.sectionRefArr['miner'] = smRef}>{translate('Miner')}</li>
|
||||||
|
<li className='lc' tabIndex="0" onClick={this._optimizeRacer.bind(this)} onKeyDown={this._keyDown}
|
||||||
|
ref={smRef => this.sectionRefArr['racer'] = smRef}>{translate('Racer')}</li>
|
||||||
|
<li className='lc' tabIndex="0" onClick={() => this.setState({ showDW2: !this.state.showDW2 })}
|
||||||
|
onKeyDown={this._keyDown}
|
||||||
|
ref={smRef => this.sectionRefArr['dw2'] = smRef}>{translate('DW2')}</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -247,8 +247,7 @@ export class OrbisIcon extends SvgIcon {
|
|||||||
<path d="m155.34 679.12 173.25-190.21-15.626-13.721-170.9 190.4zm31.01 31.714 202.41-169.1-16.418-14.417-198.76 170.43z"/>
|
<path d="m155.34 679.12 173.25-190.21-15.626-13.721-170.9 190.4zm31.01 31.714 202.41-169.1-16.418-14.417-198.76 170.43z"/>
|
||||||
<path d="m702.66 178.87-173.25 190.21 15.625 13.721 170.9-190.4zm-31.01-31.714-202.41 169.1 16.418 14.417 198.76-170.43z" />
|
<path d="m702.66 178.87-173.25 190.21 15.625 13.721 170.9-190.4zm-31.01-31.714-202.41 169.1 16.418 14.417 198.76-170.43z" />
|
||||||
<rect transform="matrix(-.7071 -.7071 .7071 -.7071 429.34 1036.2)" x="387.09" y="420.77" width="84.379" height="16.859" />
|
<rect transform="matrix(-.7071 -.7071 .7071 -.7071 429.34 1036.2)" x="387.09" y="420.77" width="84.379" height="16.859" />
|
||||||
</g>
|
</g>);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import * as IT from './it';
|
|||||||
import * as RU from './ru';
|
import * as RU from './ru';
|
||||||
import * as PL from './pl';
|
import * as PL from './pl';
|
||||||
import * as PT from './pt';
|
import * as PT from './pt';
|
||||||
import * as CN from './cn';
|
|
||||||
import * as d3 from 'd3';
|
import * as d3 from 'd3';
|
||||||
|
|
||||||
let fallbackTerms = EN.terms;
|
let fallbackTerms = EN.terms;
|
||||||
@@ -28,7 +27,6 @@ export function getLanguage(langCode) {
|
|||||||
case 'ru': lang = RU; break;
|
case 'ru': lang = RU; break;
|
||||||
case 'pl': lang = PL; break;
|
case 'pl': lang = PL; break;
|
||||||
case 'pt': lang = PT; break;
|
case 'pt': lang = PT; break;
|
||||||
case 'cn': lang = CN; break;
|
|
||||||
default:
|
default:
|
||||||
lang = EN;
|
lang = EN;
|
||||||
}
|
}
|
||||||
@@ -96,6 +94,5 @@ export const Languages = {
|
|||||||
fr: 'Français',
|
fr: 'Français',
|
||||||
ru: 'ру́сский',
|
ru: 'ру́сский',
|
||||||
pl: 'polski',
|
pl: 'polski',
|
||||||
pt: 'português',
|
pt: 'português'
|
||||||
cn: '中文'
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
export const formats = {
|
|
||||||
decimal: '.',
|
|
||||||
thousands: ',',
|
|
||||||
grouping: [3],
|
|
||||||
currency: ['¥', ''],
|
|
||||||
dateTime: '%a %b %e %X %Y',
|
|
||||||
date: '%Y年%m月%d日',
|
|
||||||
time: '%H:%M:%S',
|
|
||||||
periods: ['AM', 'PM'],
|
|
||||||
days: ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],
|
|
||||||
shortDays: ['周日', '周一', '周二', '周三', '周四', '周五', '周六'],
|
|
||||||
months: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
|
|
||||||
shortMonths: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月']
|
|
||||||
};
|
|
||||||
|
|
||||||
export { default as terms } from './cn.json';
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -63,7 +63,7 @@
|
|||||||
"TT_SUMMARY_SPEED": "With full fuel tank and 4 pips to ENG",
|
"TT_SUMMARY_SPEED": "With full fuel tank and 4 pips to ENG",
|
||||||
"TT_SUMMARY_SPEED_NONFUNCTIONAL": "Thrusters powered off or over maximum mass with full fuel and cargo loads",
|
"TT_SUMMARY_SPEED_NONFUNCTIONAL": "Thrusters powered off or over maximum mass with full fuel and cargo loads",
|
||||||
"TT_SUMMARY_BOOST": "With full fuel tank and 4 pips to ENG",
|
"TT_SUMMARY_BOOST": "With full fuel tank and 4 pips to ENG",
|
||||||
"TT_SUMMARY_BOOST_INTERVAL": "Time between each boost with 4 pips to ENG",
|
"TT_SUMMARY_BOOST_TIME": "Time between each boost with 4 pips to ENG",
|
||||||
"TT_SUMMARY_BOOST_NONFUNCTIONAL": "Power distributor not able to supply enough power to boost",
|
"TT_SUMMARY_BOOST_NONFUNCTIONAL": "Power distributor not able to supply enough power to boost",
|
||||||
"TT_SUMMARY_SHIELDS": "Raw shield strength, including boosters",
|
"TT_SUMMARY_SHIELDS": "Raw shield strength, including boosters",
|
||||||
"TT_SUMMARY_SHIELDS_SCB": "Raw shield strength, including boosters and SCBs",
|
"TT_SUMMARY_SHIELDS_SCB": "Raw shield strength, including boosters and SCBs",
|
||||||
@@ -81,8 +81,6 @@
|
|||||||
"TT_SUMMARY_UNLADEN_TOTAL_JUMP": "Farthest possible range with no cargo, a full fuel tank, and jumping as far as possible each time",
|
"TT_SUMMARY_UNLADEN_TOTAL_JUMP": "Farthest possible range with no cargo, a full fuel tank, and jumping as far as possible each time",
|
||||||
"TT_SUMMARY_LADEN_TOTAL_JUMP": "Farthest possible range with full cargo, a full fuel tank, and jumping as far as possible each time",
|
"TT_SUMMARY_LADEN_TOTAL_JUMP": "Farthest possible range with full cargo, a full fuel tank, and jumping as far as possible each time",
|
||||||
"HELP_MODIFICATIONS_MENU": "Click on a number to enter a new value, or drag along the bar for small changes",
|
"HELP_MODIFICATIONS_MENU": "Click on a number to enter a new value, or drag along the bar for small changes",
|
||||||
"PHRASE_FAIL_EDENGINEER": "Failed to send to EDEngineer (Launch EDEngineer and make sure the API is started then refresh the page.)",
|
|
||||||
"PHRASE_FIREFOX_EDENGINEER": "Sending to EDEngineer is not compatible with Firefox's security settings. Please try again with Chrome.",
|
|
||||||
"am": "Auto Field-Maintenance Unit",
|
"am": "Auto Field-Maintenance Unit",
|
||||||
"bh": "Bulkheads",
|
"bh": "Bulkheads",
|
||||||
"bl": "Beam Laser",
|
"bl": "Beam Laser",
|
||||||
@@ -153,7 +151,6 @@
|
|||||||
"sfn": "Shutdown Field Neutraliser",
|
"sfn": "Shutdown Field Neutraliser",
|
||||||
"sg": "Shield Generator",
|
"sg": "Shield Generator",
|
||||||
"ss": "Surface Scanners",
|
"ss": "Surface Scanners",
|
||||||
"sua": "Supercruise Assist",
|
|
||||||
"t": "thrusters",
|
"t": "thrusters",
|
||||||
"tp": "Torpedo Pylon",
|
"tp": "Torpedo Pylon",
|
||||||
"ul": "Burst Laser",
|
"ul": "Burst Laser",
|
||||||
@@ -175,7 +172,6 @@
|
|||||||
"ammunition": "Ammo",
|
"ammunition": "Ammo",
|
||||||
"secs": "s",
|
"secs": "s",
|
||||||
"rebuildsperbay": "Rebuilds per bay",
|
"rebuildsperbay": "Rebuilds per bay",
|
||||||
"mroll": "Roll",
|
|
||||||
"worst": "Worst",
|
"worst": "Worst",
|
||||||
"average": "Average",
|
"average": "Average",
|
||||||
"random": "Random",
|
"random": "Random",
|
||||||
@@ -205,7 +201,7 @@
|
|||||||
"internal protection": "Internal protection",
|
"internal protection": "Internal protection",
|
||||||
"external protection": "External protection",
|
"external protection": "External protection",
|
||||||
"engagement range": "Engagement range",
|
"engagement range": "Engagement range",
|
||||||
"boost interval": "Boost interval",
|
"boost time": "Boost time",
|
||||||
"total": "Total",
|
"total": "Total",
|
||||||
"ammo": "Ammunition maximum",
|
"ammo": "Ammunition maximum",
|
||||||
"boot": "Boot time",
|
"boot": "Boot time",
|
||||||
@@ -324,7 +320,6 @@
|
|||||||
"never": "never",
|
"never": "never",
|
||||||
"stock": "stock",
|
"stock": "stock",
|
||||||
"boost": "boost",
|
"boost": "boost",
|
||||||
"tab_defence": "defence",
|
|
||||||
"federation rank 1": "Recruit",
|
"federation rank 1": "Recruit",
|
||||||
"federation rank 2": "Cadet",
|
"federation rank 2": "Cadet",
|
||||||
"federation rank 3": "Midshipman",
|
"federation rank 3": "Midshipman",
|
||||||
|
|||||||
@@ -59,7 +59,7 @@
|
|||||||
"empty all": "vide tout",
|
"empty all": "vide tout",
|
||||||
"Enter Name": "Entrer nom",
|
"Enter Name": "Entrer nom",
|
||||||
"Explorer": "explorateur",
|
"Explorer": "explorateur",
|
||||||
"farthest range": "gamme la plus rapide",
|
"fastest range": "gamme la plus rapide",
|
||||||
"fuel": "carburant",
|
"fuel": "carburant",
|
||||||
"fuel level": "niveau de carburant",
|
"fuel level": "niveau de carburant",
|
||||||
"full tank": "Réservoir plein",
|
"full tank": "Réservoir plein",
|
||||||
|
|||||||
@@ -2,15 +2,15 @@ export const formats = {
|
|||||||
decimal: ',',
|
decimal: ',',
|
||||||
thousands: '.',
|
thousands: '.',
|
||||||
grouping: [3],
|
grouping: [3],
|
||||||
currency: ['$', ''],
|
currency: ['', ' €'],
|
||||||
dateTime: '%A, %e de %B de %Y, %X',
|
dateTime: '%A, %e de %B de %Y, %X',
|
||||||
date: '%d/%m/%Y',
|
date: '%d/%m/%Y',
|
||||||
time: '%H:%M:%S',
|
time: '%H:%M:%S',
|
||||||
periods: ['AM', 'PM'],
|
periods: ['AM', 'PM'],
|
||||||
days: ['domingo', 'segunda', 'terça', 'quarta', 'quinta', 'sexta', 'sábado'],
|
days: ['domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes', 'sábado'],
|
||||||
shortDays: ['dom', 'seg', 'ter', 'qua', 'qui', 'sex', 'sab'],
|
shortDays: ['dom', 'lun', 'mar', 'mié', 'jue', 'vie', 'sáb'],
|
||||||
months: ['janeiro', 'fevereiro', 'março', 'abril', 'maio', 'junho', 'julho', 'agosto', 'setembro', 'outubro', 'novembro', 'dezembro'],
|
months: ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio', 'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre'],
|
||||||
shortMonths: ['jan', 'fev', 'mar', 'abr', 'mai', 'jun', 'jul', 'ago', 'set', 'out', 'nov', 'dez']
|
shortMonths: ['ene', 'feb', 'mar', 'abr', 'may', 'jun', 'jul', 'ago', 'sep', 'oct', 'nov', 'dic']
|
||||||
};
|
};
|
||||||
|
|
||||||
export { default as terms } from './pt.json';
|
export { default as terms } from './pt.json';
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -16,16 +16,13 @@
|
|||||||
"PHRASE_ENGAGEMENT_RANGE": "Дистанция между кораблём и целью",
|
"PHRASE_ENGAGEMENT_RANGE": "Дистанция между кораблём и целью",
|
||||||
"PHRASE_SELECT_BLUEPRINT": "Нажмите чтобы выбрать чертёж",
|
"PHRASE_SELECT_BLUEPRINT": "Нажмите чтобы выбрать чертёж",
|
||||||
"PHRASE_BLUEPRINT_WORST": "Худшие основные значения для чертежа",
|
"PHRASE_BLUEPRINT_WORST": "Худшие основные значения для чертежа",
|
||||||
"PHRASE_BLUEPRINT_FIFTY": "50% значения для чертежа",
|
|
||||||
"PHRASE_BLUEPRINT_SEVEN_FIVE": "75% значения для чертежа",
|
|
||||||
"PHRASE_BLUEPRINT_RANDOM": "Случайный выбор между худшими и лучшими значениями для этого чертежа",
|
"PHRASE_BLUEPRINT_RANDOM": "Случайный выбор между худшими и лучшими значениями для этого чертежа",
|
||||||
"PHRASE_BLUEPRINT_BEST": "Лучшие основные значения для чертежа",
|
"PHRASE_BLUEPRINT_BEST": "Лучшие основные значения для чертежа",
|
||||||
"PHRASE_BLUEPRINT_EXTREME": "Лучшие положительные и худшие отрицательные основные значения для чертежа",
|
"PHRASE_BLUEPRINT_EXTREME": "Лучшие положительные и худшие отрицательные основные значения для чертежа",
|
||||||
"PHRASE_BLUEPRINT_RESET": "Сбросить все модификаторы и чертеж",
|
"PHRASE_BLUEPRINT_RESET": "Убрать все изменения и чертёж",
|
||||||
"PHRASE_SELECT_SPECIAL": "Нажмите, чтобы выбрать экспериментальный эффект",
|
"PHRASE_SELECT_SPECIAL": "Нажмите, чтобы выбрать экспериментальный эффект",
|
||||||
"PHRASE_NO_SPECIAL": "Без экспериментального эффекта",
|
"PHRASE_NO_SPECIAL": "Без экспериментального эффекта",
|
||||||
"PHRASE_SHOPPING_LIST": "Станции, что продают эту сборку",
|
"PHRASE_SHOPPING_LIST": "Станции, что продают эту сборку",
|
||||||
"PHRASE_SHOPPING_MATS": "Материалы которые нужны для сборки",
|
|
||||||
"PHRASE_REFIT_SHOPPING_LIST": "Станции, что продают необходимые модули",
|
"PHRASE_REFIT_SHOPPING_LIST": "Станции, что продают необходимые модули",
|
||||||
"PHRASE_TOTAL_EFFECTIVE_SHIELD": "Общий урон, что может быть нанесён в каждым типе, если используются все щитонакопители",
|
"PHRASE_TOTAL_EFFECTIVE_SHIELD": "Общий урон, что может быть нанесён в каждым типе, если используются все щитонакопители",
|
||||||
"PHRASE_TIME_TO_LOSE_SHIELDS": "Щиты продержатся",
|
"PHRASE_TIME_TO_LOSE_SHIELDS": "Щиты продержатся",
|
||||||
@@ -39,11 +36,9 @@
|
|||||||
"PHRASE_TIME_TO_LOSE_ARMOUR": "Броня продержится",
|
"PHRASE_TIME_TO_LOSE_ARMOUR": "Броня продержится",
|
||||||
"PHRASE_MODULE_PROTECTION_EXTERNAL": "Защита гнёзд",
|
"PHRASE_MODULE_PROTECTION_EXTERNAL": "Защита гнёзд",
|
||||||
"PHRASE_MODULE_PROTECTION_INTERNAL": "Защита всех остальных модулей",
|
"PHRASE_MODULE_PROTECTION_INTERNAL": "Защита всех остальных модулей",
|
||||||
"PHRASE_OVERALL_DAMAGE": "Разбивка источников устойчивого ДПС",
|
|
||||||
"PHRASE_SHIELD_DAMAGE": "Подробности источников поддерживаемого ДПС против щитов",
|
"PHRASE_SHIELD_DAMAGE": "Подробности источников поддерживаемого ДПС против щитов",
|
||||||
"PHRASE_ARMOUR_DAMAGE": "Подробности источников поддерживаемого ДПС против брони",
|
"PHRASE_ARMOUR_DAMAGE": "Подробности источников поддерживаемого ДПС против брони",
|
||||||
"PHRASE_TIME_TO_REMOVE_SHIELDS": "Снимет щиты за",
|
"PHRASE_TIME_TO_REMOVE_SHIELDS": "Снимет щиты за",
|
||||||
"PHRASE_MULTI_CREW_CAPACITOR_POINTS": "Щелкните правой кновкой мыши чтобы объединить в группу.",
|
|
||||||
"TT_TIME_TO_REMOVE_SHIELDS": "Непрерывным огнём из всех орудий",
|
"TT_TIME_TO_REMOVE_SHIELDS": "Непрерывным огнём из всех орудий",
|
||||||
"PHRASE_TIME_TO_REMOVE_ARMOUR": "Снимет броню за",
|
"PHRASE_TIME_TO_REMOVE_ARMOUR": "Снимет броню за",
|
||||||
"TT_TIME_TO_REMOVE_ARMOUR": "Непрерывным огнём из всех орудий",
|
"TT_TIME_TO_REMOVE_ARMOUR": "Непрерывным огнём из всех орудий",
|
||||||
@@ -63,10 +58,8 @@
|
|||||||
"TT_SUMMARY_SPEED": "С полным топливным баком и 4 пунктами в ДВИ",
|
"TT_SUMMARY_SPEED": "С полным топливным баком и 4 пунктами в ДВИ",
|
||||||
"TT_SUMMARY_SPEED_NONFUNCTIONAL": "Маневровые двигатели выключены или превышена максимальная масса с топливом и грузом",
|
"TT_SUMMARY_SPEED_NONFUNCTIONAL": "Маневровые двигатели выключены или превышена максимальная масса с топливом и грузом",
|
||||||
"TT_SUMMARY_BOOST": "С полным топливным баком и 4 пунктами в ДВИ",
|
"TT_SUMMARY_BOOST": "С полным топливным баком и 4 пунктами в ДВИ",
|
||||||
"TT_SUMMARY_BOOST_INTERVAL": "Время заполнения с 4 пунктами в СИС",
|
|
||||||
"TT_SUMMARY_BOOST_NONFUNCTIONAL": "Распределитель питания не может обеспечить достаточно энергии для форсажа",
|
"TT_SUMMARY_BOOST_NONFUNCTIONAL": "Распределитель питания не может обеспечить достаточно энергии для форсажа",
|
||||||
"TT_SUMMARY_SHIELDS": "Чистая сила щита, включая усилители",
|
"TT_SUMMARY_SHIELDS": "Чистая сила щита, включая усилители",
|
||||||
"TT_SUMMARY_SHIELDS_SCB": "Прочность щита, включая бустеры и SCB",
|
|
||||||
"TT_SUMMARY_SHIELDS_NONFUNCTIONAL": "Шитогенератор отсутствует или выключен",
|
"TT_SUMMARY_SHIELDS_NONFUNCTIONAL": "Шитогенератор отсутствует или выключен",
|
||||||
"TT_SUMMARY_INTEGRITY": "Целостность корабля, включая переборки и наборы для усиления корпуса",
|
"TT_SUMMARY_INTEGRITY": "Целостность корабля, включая переборки и наборы для усиления корпуса",
|
||||||
"TT_SUMMARY_HULL_MASS": "Масса корпуса без каких-либо модулей",
|
"TT_SUMMARY_HULL_MASS": "Масса корпуса без каких-либо модулей",
|
||||||
@@ -81,14 +74,11 @@
|
|||||||
"TT_SUMMARY_UNLADEN_TOTAL_JUMP": "Самая дальняя общая дистанция без груза, с полным топливным баком и при прыжках на максимальное расстояние",
|
"TT_SUMMARY_UNLADEN_TOTAL_JUMP": "Самая дальняя общая дистанция без груза, с полным топливным баком и при прыжках на максимальное расстояние",
|
||||||
"TT_SUMMARY_LADEN_TOTAL_JUMP": "Самая дальняя общая дистанция с полным грузовым отсеком, с полным топливным баком и при прыжках на максимальное расстояние",
|
"TT_SUMMARY_LADEN_TOTAL_JUMP": "Самая дальняя общая дистанция с полным грузовым отсеком, с полным топливным баком и при прыжках на максимальное расстояние",
|
||||||
"HELP_MODIFICATIONS_MENU": "Нажмите на номер, чтобы ввести новое значение, или потяните вдоль полосы для малых изменений",
|
"HELP_MODIFICATIONS_MENU": "Нажмите на номер, чтобы ввести новое значение, или потяните вдоль полосы для малых изменений",
|
||||||
"PHRASE_FAIL_EDENGINEER": "Не удалось отправить в EDEngineer (запустите EDEngineer и убедитесь, что API запущен, затем обновите страницу).",
|
|
||||||
"PHRASE_FIREFOX_EDENGINEER": "Отправка в EDEngineer несовместима с настройками безопасности Firefox. Пожалуйста, попробуйте еще раз в Google Chrome.",
|
|
||||||
"am": "Блок Автом. Полевого Ремонта",
|
"am": "Блок Автом. Полевого Ремонта",
|
||||||
"bh": "Переборки",
|
"bh": "Переборки",
|
||||||
"bl": "Пучковый лазер",
|
"bl": "Пучковый лазер",
|
||||||
"bsg": "Двухпоточный щитогенератор",
|
"bsg": "Двухпоточный щитогенератор",
|
||||||
"c": "Орудие",
|
"c": "Орудие",
|
||||||
"causres": "Caustic resistance",
|
|
||||||
"cc": "Контроллер магнитного снаряда для сбора",
|
"cc": "Контроллер магнитного снаряда для сбора",
|
||||||
"ch": "Разбрасыватель дипольных отражателей",
|
"ch": "Разбрасыватель дипольных отражателей",
|
||||||
"cr": "Грузовой стеллаж",
|
"cr": "Грузовой стеллаж",
|
||||||
@@ -108,17 +98,14 @@
|
|||||||
"kw": "Сканер преступников",
|
"kw": "Сканер преступников",
|
||||||
"ls": "Система жизнеобеспечения",
|
"ls": "Система жизнеобеспечения",
|
||||||
"mc": "Многоствольное орудие",
|
"mc": "Многоствольное орудие",
|
||||||
"axmc": "Многоствольное орудие АИ",
|
|
||||||
"ml": "Проходочный лазер",
|
"ml": "Проходочный лазер",
|
||||||
"mr": "Ракетный лоток",
|
"mr": "Ракетный лоток",
|
||||||
"axmr": "Блок ракет АИ",
|
|
||||||
"mrp": "Набор для усиления модуля",
|
"mrp": "Набор для усиления модуля",
|
||||||
"nl": "Мины",
|
"nl": "Мины",
|
||||||
"pa": "Ускоритель плазмы",
|
"pa": "Ускоритель плазмы",
|
||||||
"pas": "Комплект для сближения с планетой",
|
"pas": "Комплект для сближения с планетой",
|
||||||
"pc": "Контроллер магнитного снаряда для геологоразведки",
|
"pc": "Контроллер магнитного снаряда для геологоразведки",
|
||||||
"pce": "Каюта пассажира эконом-класса",
|
"pce": "Каюта пассажира эконом-класса",
|
||||||
"passenger capacity": "количество пассажиров",
|
|
||||||
"pci": "Каюта пассажира бизнес-класса",
|
"pci": "Каюта пассажира бизнес-класса",
|
||||||
"pcm": "Каюта пассажира первого класса",
|
"pcm": "Каюта пассажира первого класса",
|
||||||
"pcq": "Каюта пассажира класса люкс",
|
"pcq": "Каюта пассажира класса люкс",
|
||||||
@@ -126,46 +113,20 @@
|
|||||||
"pl": "Импульсный лазер",
|
"pl": "Импульсный лазер",
|
||||||
"po": "Точечная оборона",
|
"po": "Точечная оборона",
|
||||||
"pp": "Силовая установка",
|
"pp": "Силовая установка",
|
||||||
"gpp": "Силовая установка Cтражей",
|
|
||||||
"gpd": "Гибридный распределитель питания Стражей",
|
|
||||||
"gpc": "Плазменная пушка Стражей",
|
|
||||||
"ggc": "Пушка Гаусса Стражей",
|
|
||||||
"gsrp": "Набор для усиления щита Стражей",
|
|
||||||
"gfsb": "Ускоритель FSD Стражей",
|
|
||||||
"ghrp": "Набор для усиления корпуса Стражей",
|
|
||||||
"gmrp": "Набор для усиления модуля Стражей",
|
|
||||||
"pwa": "Анализатор импульсных волн",
|
|
||||||
"abl": "Абразивный бластер",
|
|
||||||
"scl": "Пусковая установка для сейсмических снарядов",
|
|
||||||
"sdm": "Вытесняющая ракета для добычи глубинных залежей",
|
|
||||||
"tbsc": "Шоковое орудие",
|
|
||||||
"gsc": "Осколочное орудие Стражей",
|
|
||||||
"psg": "Призматический щитогенератор",
|
"psg": "Призматический щитогенератор",
|
||||||
"pv": "Гараж для планетарного транспорта",
|
"pv": "Гараж для планетарного транспорта",
|
||||||
"rf": "Устройство переработки",
|
"rf": "Устройство переработки",
|
||||||
"rfl": "Зенитная установка (снаряды с дистанционным подрывом)",
|
|
||||||
"rg": "Электромагнитная пушка",
|
"rg": "Электромагнитная пушка",
|
||||||
"rsl": "Дроны-исследователи",
|
|
||||||
"s": "Сенсоры",
|
"s": "Сенсоры",
|
||||||
"sb": "Усилитель щита",
|
"sb": "Усилитель щита",
|
||||||
"sc": "Сканер обнаружения",
|
"sc": "Сканер обнаружения",
|
||||||
"scb": "Щитонакопитель",
|
"scb": "Щитонакопитель",
|
||||||
"sfn": "Нейтрализатор глушащего поля",
|
|
||||||
"sg": "Щитогенератор",
|
"sg": "Щитогенератор",
|
||||||
"ss": "Сканер поверхностей",
|
"ss": "Сканер поверхностей",
|
||||||
"sua": "Помощь в гиперкрейсерском режиме",
|
|
||||||
"t": "Маневровые двигатели",
|
"t": "Маневровые двигатели",
|
||||||
"tp": "Торпедная стойка",
|
"tp": "Торпедная стойка",
|
||||||
"ul": "Пульсирующие лазеры",
|
"ul": "Пульсирующие лазеры",
|
||||||
"Send To EDEngineer": "Отправить в EDEngineer",
|
|
||||||
"ws": "Сканер следа FSD",
|
"ws": "Сканер следа FSD",
|
||||||
"rpl": "Дроны-ремонтники",
|
|
||||||
"rcpl": "ДРоны-разведчики",
|
|
||||||
"xs": "Сканер «инопланетянин»",
|
|
||||||
"tbem": "Блок энзимных ракет",
|
|
||||||
"tbrfl": "Установка для стрельбы стреловидными снарядами с дистанционным подрывом",
|
|
||||||
"dtl": "Дроны-очистители",
|
|
||||||
"mahr": "Набор для усиления корпуса из Метасплава",
|
|
||||||
"emptyrestricted": "пусто (ограниченно)",
|
"emptyrestricted": "пусто (ограниченно)",
|
||||||
"damage dealt to": "Урон нанесён",
|
"damage dealt to": "Урон нанесён",
|
||||||
"damage received from": "Урон получен от",
|
"damage received from": "Урон получен от",
|
||||||
@@ -175,7 +136,6 @@
|
|||||||
"ammunition": "Припасы",
|
"ammunition": "Припасы",
|
||||||
"secs": "с",
|
"secs": "с",
|
||||||
"rebuildsperbay": "Построек за полосу",
|
"rebuildsperbay": "Построек за полосу",
|
||||||
"mroll": "Roll",
|
|
||||||
"worst": "Худшее",
|
"worst": "Худшее",
|
||||||
"average": "Среднее",
|
"average": "Среднее",
|
||||||
"random": "Случайное",
|
"random": "Случайное",
|
||||||
@@ -188,7 +148,6 @@
|
|||||||
"dpssdps": "Урон в секунду (поддерживаемый урон в секунду)",
|
"dpssdps": "Урон в секунду (поддерживаемый урон в секунду)",
|
||||||
"eps": "Энергия в секунду",
|
"eps": "Энергия в секунду",
|
||||||
"epsseps": "Энергия в секунду (поддерживаемая энергия в секунду)",
|
"epsseps": "Энергия в секунду (поддерживаемая энергия в секунду)",
|
||||||
"fallofffromrange": "Спад",
|
|
||||||
"hps": "Нагрев в секунду",
|
"hps": "Нагрев в секунду",
|
||||||
"hpsshps": "Нагрев в секунду (поддерживаемый нагрев в секунду)",
|
"hpsshps": "Нагрев в секунду (поддерживаемый нагрев в секунду)",
|
||||||
"damage by": "Урон",
|
"damage by": "Урон",
|
||||||
@@ -205,15 +164,13 @@
|
|||||||
"internal protection": "Внутренняя защита",
|
"internal protection": "Внутренняя защита",
|
||||||
"external protection": "Внешняя защита",
|
"external protection": "Внешняя защита",
|
||||||
"engagement range": "Боевое расстояние",
|
"engagement range": "Боевое расстояние",
|
||||||
"boost interval": "Интервал повышения",
|
|
||||||
"total": "Всего",
|
"total": "Всего",
|
||||||
"ammo": "Макс. боекомплект",
|
"ammo": "Боекомплект",
|
||||||
"boot": "Время загрузки",
|
"boot": "Время загрузки",
|
||||||
"hacktime": "Время взлома",
|
|
||||||
"brokenregen": "Скорость восстановления при пробое",
|
"brokenregen": "Скорость восстановления при пробое",
|
||||||
"burst": "Длина очереди",
|
"burst": "Длина очереди",
|
||||||
"burstrof": "Скорострельность очереди",
|
"burstrof": "Скорострельность очереди",
|
||||||
"clip": "Размер боекомплекта",
|
"clip": "Боекомплект",
|
||||||
"damage": "Урон",
|
"damage": "Урон",
|
||||||
"distdraw": "Тяга распределителя",
|
"distdraw": "Тяга распределителя",
|
||||||
"duration": "Продолжительность",
|
"duration": "Продолжительность",
|
||||||
@@ -242,14 +199,11 @@
|
|||||||
"rof": "Скорострельность",
|
"rof": "Скорострельность",
|
||||||
"angle": "Угол сканера",
|
"angle": "Угол сканера",
|
||||||
"scanrate": "Скорость сканера",
|
"scanrate": "Скорость сканера",
|
||||||
"proberadius": "Радиус зонда",
|
|
||||||
"scantime": "Время сканирования",
|
"scantime": "Время сканирования",
|
||||||
"shield": "Щит",
|
"shield": "Щит",
|
||||||
"armour": "Броня",
|
|
||||||
"shieldboost": "Усиление щитов",
|
"shieldboost": "Усиление щитов",
|
||||||
"shieldreinforcement": "Усилитель щита",
|
"shieldreinforcement": "Усилитель щита",
|
||||||
"shotspeed": "Скорость выстрела",
|
"shotspeed": "Скорость выстрела",
|
||||||
"shotdmg": "Урон за выстрел(DPS)",
|
|
||||||
"spinup": "Время раскрутки",
|
"spinup": "Время раскрутки",
|
||||||
"syscap": "Ресурс систем",
|
"syscap": "Ресурс систем",
|
||||||
"sysrate": "Перезарядка систем",
|
"sysrate": "Перезарядка систем",
|
||||||
@@ -280,12 +234,9 @@
|
|||||||
"explosive": "Взрывч.",
|
"explosive": "Взрывч.",
|
||||||
"kinetic": "Механич.",
|
"kinetic": "Механич.",
|
||||||
"thermal": "Тепл.",
|
"thermal": "Тепл.",
|
||||||
"caustic": "Каустик",
|
|
||||||
"generator": "Генератор",
|
"generator": "Генератор",
|
||||||
"boosters": "Усилители",
|
"boosters": "Усилители",
|
||||||
"cells": "Ячейки",
|
"cells": "Ячейки",
|
||||||
"shield addition": "ДОбавления к щиту",
|
|
||||||
"jump addition": "ДОбавления к прыжку",
|
|
||||||
"bulkheads": "Переборки",
|
"bulkheads": "Переборки",
|
||||||
"reinforcement": "Усилители",
|
"reinforcement": "Усилители",
|
||||||
"power and costs": "Энергия и стоимость",
|
"power and costs": "Энергия и стоимость",
|
||||||
@@ -318,45 +269,13 @@
|
|||||||
"opponent": "Противник",
|
"opponent": "Противник",
|
||||||
"opponent's shields": "Щит противника",
|
"opponent's shields": "Щит противника",
|
||||||
"opponent's armour": "Броня противника",
|
"opponent's armour": "Броня противника",
|
||||||
"overall damage": "overall damage",
|
|
||||||
"shield damage sources": "источники урона по щиту",
|
"shield damage sources": "источники урона по щиту",
|
||||||
"armour damage sources": "источники урона по броне",
|
"armour damage sources": "источники урона по броне",
|
||||||
"never": "Никогда",
|
"never": "Никогда",
|
||||||
"stock": "базовый",
|
"stock": "базовый",
|
||||||
"boost": "форсаж",
|
"boost": "форсаж",
|
||||||
"tab_defence": "defence",
|
"/s": "/с",
|
||||||
"federation rank 1": "Рекрут",
|
"m/s": "м/с",
|
||||||
"federation rank 2": "Кадет",
|
|
||||||
"federation rank 3": "Гардемарин",
|
|
||||||
"federation rank 4": "Старшина",
|
|
||||||
"federation rank 5": "Главный старшина",
|
|
||||||
"federation rank 6": "Уорент-офицер",
|
|
||||||
"federation rank 7": "Энсин",
|
|
||||||
"federation rank 8": "Лейтенант",
|
|
||||||
"federation rank 9": "Капитан-лейтенант",
|
|
||||||
"federation rank 10": "Начальник гарнизона",
|
|
||||||
"federation rank 11": "Командир корабля",
|
|
||||||
"federation rank 12": "Контр-адмирал",
|
|
||||||
"federation rank 13": " Вице-адмирал",
|
|
||||||
"federation rank 14": "Адмирал",
|
|
||||||
"federation rank required": "Минимальный ранг федерации для покупки",
|
|
||||||
"empire rank 1": "Чужак",
|
|
||||||
"empire rank 2": "Крепостной",
|
|
||||||
"empire rank 3": "Мастер",
|
|
||||||
"empire rank 4": "Оруженосец",
|
|
||||||
"empire rank 5": "Рыцарь",
|
|
||||||
"empire rank 6": "Лорд",
|
|
||||||
"empire rank 7": "Барон",
|
|
||||||
"empire rank 8": "Виконт",
|
|
||||||
"empire rank 9": "Граф",
|
|
||||||
"empire rank 10": "Эрл",
|
|
||||||
"empire rank 11": "Маркиз",
|
|
||||||
"empire rank 12": "Герцог",
|
|
||||||
"empire rank 13": "Принц",
|
|
||||||
"empire rank 14": "Король",
|
|
||||||
"empire rank required": "Минимальный ранг империи для покупки",
|
|
||||||
"\/s": "\/с",
|
|
||||||
"m\/s": "м\/с",
|
|
||||||
"Ls": "Св.сек",
|
"Ls": "Св.сек",
|
||||||
"LY": "Св.лет",
|
"LY": "Св.лет",
|
||||||
"CR": "кр.",
|
"CR": "кр.",
|
||||||
@@ -380,7 +299,7 @@
|
|||||||
"edit data": "Редактирование",
|
"edit data": "Редактирование",
|
||||||
"empty all": "пусто все",
|
"empty all": "пусто все",
|
||||||
"Enter Name": "Введите имя",
|
"Enter Name": "Введите имя",
|
||||||
"farthest range": "быстрый диапазон",
|
"fastest range": "быстрый диапазон",
|
||||||
"fuel level": "уровень топлива",
|
"fuel level": "уровень топлива",
|
||||||
"full tank": "Полный бак",
|
"full tank": "Полный бак",
|
||||||
"internal compartments": "внутренние отсеки",
|
"internal compartments": "внутренние отсеки",
|
||||||
@@ -396,6 +315,7 @@
|
|||||||
"about": "О ...",
|
"about": "О ...",
|
||||||
"action": "Действие",
|
"action": "Действие",
|
||||||
"added": "Добавлено",
|
"added": "Добавлено",
|
||||||
|
"armour": "Броня",
|
||||||
"available": "доступно",
|
"available": "доступно",
|
||||||
"backup": "Резервная копия",
|
"backup": "Резервная копия",
|
||||||
"bins": "контейнеры",
|
"bins": "контейнеры",
|
||||||
@@ -443,7 +363,7 @@
|
|||||||
"repair": "Починка",
|
"repair": "Починка",
|
||||||
"ret": "Убр.",
|
"ret": "Убр.",
|
||||||
"retracted": "Убрано",
|
"retracted": "Убрано",
|
||||||
"ROF": "В\/сек",
|
"ROF": "В/сек",
|
||||||
"save": "Сохранить",
|
"save": "Сохранить",
|
||||||
"sell": "Продать",
|
"sell": "Продать",
|
||||||
"settings": "Настройки",
|
"settings": "Настройки",
|
||||||
|
|||||||
@@ -94,6 +94,39 @@ export default class AboutPage extends Page {
|
|||||||
</a>
|
</a>
|
||||||
.
|
.
|
||||||
</p>
|
</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>
|
||||||
|
<form
|
||||||
|
action="https://www.paypal.com/cgi-bin/webscr"
|
||||||
|
method="post"
|
||||||
|
target="_top"
|
||||||
|
>
|
||||||
|
<input type="hidden" name="cmd" value="_s-xclick" />
|
||||||
|
<input type="hidden" name="hosted_button_id" value="SJBKT2SWEEU68" />
|
||||||
|
<input
|
||||||
|
type="image"
|
||||||
|
src="https://www.paypalobjects.com/en_AU/i/btn/btn_donate_SM.gif"
|
||||||
|
border="0"
|
||||||
|
name="submit"
|
||||||
|
alt="PayPal – The safer, easier way to pay online!"
|
||||||
|
/>
|
||||||
|
<img
|
||||||
|
alt=""
|
||||||
|
border="0"
|
||||||
|
src="https://www.paypalobjects.com/en_AU/i/scr/pixel.gif"
|
||||||
|
width="1"
|
||||||
|
height="1"
|
||||||
|
/>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import {
|
|||||||
LinkIcon,
|
LinkIcon,
|
||||||
ShoppingIcon,
|
ShoppingIcon,
|
||||||
MatIcon,
|
MatIcon,
|
||||||
|
OrbisIcon
|
||||||
} from '../components/SvgIcons';
|
} from '../components/SvgIcons';
|
||||||
import LZString from 'lz-string';
|
import LZString from 'lz-string';
|
||||||
import ShipSummaryTable from '../components/ShipSummaryTable';
|
import ShipSummaryTable from '../components/ShipSummaryTable';
|
||||||
@@ -36,6 +37,7 @@ import OutfittingSubpages from '../components/OutfittingSubpages';
|
|||||||
import ModalExport from '../components/ModalExport';
|
import ModalExport from '../components/ModalExport';
|
||||||
import ModalPermalink from '../components/ModalPermalink';
|
import ModalPermalink from '../components/ModalPermalink';
|
||||||
import ModalShoppingList from '../components/ModalShoppingList';
|
import ModalShoppingList from '../components/ModalShoppingList';
|
||||||
|
import ModalOrbis from '../components/ModalOrbis';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Document Title Generator
|
* Document Title Generator
|
||||||
@@ -678,6 +680,23 @@ export default class OutfittingPage extends Page {
|
|||||||
this.context.showModal(<ModalPermalink url={window.location.href} />);
|
this.context.showModal(<ModalPermalink url={window.location.href} />);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate Orbis link
|
||||||
|
*/
|
||||||
|
_genOrbis() {
|
||||||
|
const data = {};
|
||||||
|
const ship = this.state.ship;
|
||||||
|
ship.coriolisId = ship.id;
|
||||||
|
data.coriolisShip = ship;
|
||||||
|
data.url = window.location.href;
|
||||||
|
data.title = this.state.buildName || ship.id;
|
||||||
|
data.description = this.state.buildName || ship.id;
|
||||||
|
data.ShipName = ship.id;
|
||||||
|
data.Ship = ship.id;
|
||||||
|
console.log(data);
|
||||||
|
this.context.showModal(<ModalOrbis ship={data} />);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open up a window for EDDB with a shopping list of our components
|
* Open up a window for EDDB with a shopping list of our components
|
||||||
*/
|
*/
|
||||||
@@ -927,6 +946,13 @@ export default class OutfittingPage extends Page {
|
|||||||
>
|
>
|
||||||
<LinkIcon className="lg" />
|
<LinkIcon className="lg" />
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={this._genOrbis}
|
||||||
|
onMouseOver={termtip.bind(null, 'PHASE_UPLOAD_ORBIS')}
|
||||||
|
onMouseOut={hide}
|
||||||
|
>
|
||||||
|
<OrbisIcon className="lg" />
|
||||||
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={this._genShoppingList}
|
onClick={this._genShoppingList}
|
||||||
onMouseOver={termtip.bind(null, 'PHRASE_SHOPPING_MATS')}
|
onMouseOver={termtip.bind(null, 'PHRASE_SHOPPING_MATS')}
|
||||||
|
|||||||
@@ -50,6 +50,19 @@ export default class Page extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pages are 'pure' components that only render when props, state, or context changes.
|
||||||
|
* This method performs a shallow comparison to determine change.
|
||||||
|
*
|
||||||
|
* @param {Object} np Next/Incoming properties
|
||||||
|
* @param {Object} ns Next/Incoming state
|
||||||
|
* @param {Object} nc Next/Incoming context
|
||||||
|
* @return {Boolean} True if props, state, or context has changed
|
||||||
|
*/
|
||||||
|
shouldComponentUpdate(np, ns, nc) {
|
||||||
|
return !shallowEqual(this.props, np) || !shallowEqual(this.state, ns) || !shallowEqual(this.context, nc);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the window title upon mount
|
* Update the window title upon mount
|
||||||
*/
|
*/
|
||||||
@@ -62,14 +75,6 @@ export default class Page extends React.Component {
|
|||||||
*/
|
*/
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
document.title = this.state.title || 'Coriolis';
|
document.title = this.state.title || 'Coriolis';
|
||||||
try {
|
|
||||||
(window.adsbygoogle = window.adsbygoogle || []).push({
|
|
||||||
google_ad_client: "ca-pub-3709458261881414",
|
|
||||||
enable_page_level_ads: true
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -126,14 +126,12 @@ export default class ShipyardPage extends Page {
|
|||||||
title: 'Coriolis EDCD Edition - Shipyard',
|
title: 'Coriolis EDCD Edition - Shipyard',
|
||||||
shipPredicate: 'name',
|
shipPredicate: 'name',
|
||||||
shipDesc: true,
|
shipDesc: true,
|
||||||
shipSummaries: ShipyardPage.cachedShipSummaries,
|
shipSummaries: ShipyardPage.cachedShipSummaries
|
||||||
compare: {},
|
|
||||||
groupCompared: false,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Higlight the current ship in the table on mouse over
|
* Higlight the current ship in the table
|
||||||
* @param {String} shipId Ship Id
|
* @param {String} shipId Ship Id
|
||||||
* @param {SyntheticEvent} event Event
|
* @param {SyntheticEvent} event Event
|
||||||
*/
|
*/
|
||||||
@@ -142,24 +140,6 @@ export default class ShipyardPage extends Page {
|
|||||||
this.setState({ shipId });
|
this.setState({ shipId });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Toggle compare highlighting for ships in the table
|
|
||||||
* @param {String} shipId Ship Id
|
|
||||||
*/
|
|
||||||
_toggleCompare(shipId) {
|
|
||||||
let compare = this.state.compare;
|
|
||||||
compare[shipId] = !compare[shipId];
|
|
||||||
this.setState({ compare });
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Toggle grouping of compared ships in the table
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
_toggleGroupCompared() {
|
|
||||||
this.setState({groupCompared: !this.state.groupCompared})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update state with the specified sort predicates
|
* Update state with the specified sort predicates
|
||||||
* @param {String} shipPredicate Sort predicate - property name
|
* @param {String} shipPredicate Sort predicate - property name
|
||||||
@@ -200,11 +180,10 @@ export default class ShipyardPage extends Page {
|
|||||||
style={{ height: '1.5em' }}
|
style={{ height: '1.5em' }}
|
||||||
className={cn({
|
className={cn({
|
||||||
highlighted: noTouch && this.state.shipId === s.id,
|
highlighted: noTouch && this.state.shipId === s.id,
|
||||||
comparehighlight: this.state.compare[s.id],
|
|
||||||
})}
|
})}
|
||||||
onMouseEnter={noTouch && this._highlightShip.bind(this, s.id)}
|
onMouseEnter={noTouch && this._highlightShip.bind(this, s.id)}
|
||||||
onClick={() => this._toggleCompare(s.id)}
|
|
||||||
>
|
>
|
||||||
|
<td className="ri">{s.manufacturer}</td>
|
||||||
<td className="ri">{fInt(s.retailCost)}</td>
|
<td className="ri">{fInt(s.retailCost)}</td>
|
||||||
<td className="ri cap">{translate(SizeMap[s.class])}</td>
|
<td className="ri cap">{translate(SizeMap[s.class])}</td>
|
||||||
<td className="ri">{fInt(s.crew)}</td>
|
<td className="ri">{fInt(s.crew)}</td>
|
||||||
@@ -255,7 +234,7 @@ export default class ShipyardPage extends Page {
|
|||||||
let hide = this.context.tooltip.bind(null, null);
|
let hide = this.context.tooltip.bind(null, null);
|
||||||
let fInt = formats.int;
|
let fInt = formats.int;
|
||||||
let fRound = formats.round;
|
let fRound = formats.round;
|
||||||
let { shipSummaries, shipPredicate, shipPredicateIndex, compare, groupCompared } = this.state;
|
let { shipSummaries, shipPredicate, shipPredicateIndex } = this.state;
|
||||||
let sortShips = (predicate, index) =>
|
let sortShips = (predicate, index) =>
|
||||||
this._sortShips.bind(this, predicate, index);
|
this._sortShips.bind(this, predicate, index);
|
||||||
|
|
||||||
@@ -288,15 +267,6 @@ export default class ShipyardPage extends Page {
|
|||||||
valB = val;
|
valB = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (groupCompared) {
|
|
||||||
if (compare[a.id] && !compare[b.id]) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (!compare[a.id] && compare[b.id]) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (valA == valB) {
|
if (valA == valB) {
|
||||||
if (a.name > b.name) {
|
if (a.name > b.name) {
|
||||||
return 1;
|
return 1;
|
||||||
@@ -328,10 +298,8 @@ export default class ShipyardPage extends Page {
|
|||||||
style={{ height: '1.5em' }}
|
style={{ height: '1.5em' }}
|
||||||
className={cn({
|
className={cn({
|
||||||
highlighted: noTouch && this.state.shipId === s.id,
|
highlighted: noTouch && this.state.shipId === s.id,
|
||||||
comparehighlight: this.state.compare[s.id],
|
|
||||||
})}
|
})}
|
||||||
onMouseEnter={noTouch && this._highlightShip.bind(this, s.id)}
|
onMouseEnter={noTouch && this._highlightShip.bind(this, s.id)}
|
||||||
onClick={() => this._toggleCompare(s.id)}
|
|
||||||
>
|
>
|
||||||
<td className="le">
|
<td className="le">
|
||||||
<Link href={'/outfit/' + s.id}>{s.name} {s.beta === true ? '(Beta)' : null}</Link>
|
<Link href={'/outfit/' + s.id}>{s.name} {s.beta === true ? '(Beta)' : null}</Link>
|
||||||
@@ -342,10 +310,18 @@ export default class ShipyardPage extends Page {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="page" style={{fontSize: sizeRatio + 'em'}}>
|
<div className="page" style={{ fontSize: sizeRatio + 'em' }}>
|
||||||
<div className="content-wrapper">
|
<div
|
||||||
<div className="shipyard-table-wrapper">
|
style={{
|
||||||
<table style={{width: '12em', position: 'absolute', zIndex: 1}} className="shipyard-table">
|
whiteSpace: 'nowrap',
|
||||||
|
margin: '0 auto',
|
||||||
|
fontSize: '0.8em',
|
||||||
|
position: 'relative',
|
||||||
|
display: 'inline-block',
|
||||||
|
maxWidth: '100%'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<table style={{ width: '12em', position: 'absolute', zIndex: 1 }}>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th className="le rgt"> </th>
|
<th className="le rgt"> </th>
|
||||||
@@ -363,10 +339,17 @@ export default class ShipyardPage extends Page {
|
|||||||
{shipRows}
|
{shipRows}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<div style={{ overflowX: 'auto', maxWidth: '100%' }}>
|
<div style={{ overflowX: 'scroll', maxWidth: '100%' }}>
|
||||||
<table style={{ marginLeft: 'calc(12em - 1px)', zIndex: 0 }} className="shipyard-table">
|
<table style={{ marginLeft: 'calc(12em - 1px)', zIndex: 0 }}>
|
||||||
<thead>
|
<thead>
|
||||||
<tr className="main">
|
<tr className="main">
|
||||||
|
<th
|
||||||
|
rowSpan={3}
|
||||||
|
className="sortable"
|
||||||
|
onClick={sortShips('manufacturer')}
|
||||||
|
>
|
||||||
|
{translate('manufacturer')}
|
||||||
|
</th>
|
||||||
<th> </th>
|
<th> </th>
|
||||||
<th
|
<th
|
||||||
rowSpan={3}
|
rowSpan={3}
|
||||||
@@ -614,10 +597,6 @@ export default class ShipyardPage extends Page {
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="table-tools" >
|
|
||||||
<label><input type="checkbox" checked={this.state.groupCompared} onClick={() => this._toggleGroupCompared()}/>Group highlighted ships</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,9 +14,8 @@ export function jumpRange(mass, fsd, fuel, ship) {
|
|||||||
const fsdOptimalMass = fsd instanceof Module ? fsd.getOptMass() : fsd.optmass;
|
const fsdOptimalMass = fsd instanceof Module ? fsd.getOptMass() : fsd.optmass;
|
||||||
let jumpAddition = 0;
|
let jumpAddition = 0;
|
||||||
if (ship) {
|
if (ship) {
|
||||||
mass += ship.reserveFuelCapacity || 0;
|
|
||||||
for (const module of ship.internal) {
|
for (const module of ship.internal) {
|
||||||
if (module && module.m && module.m.grp === 'gfsb' && ship.getSlotStatus(module) == 3) {
|
if (module && module.m && module.m.grp === 'gfsb') {
|
||||||
jumpAddition += module.m.getJumpBoost();
|
jumpAddition += module.m.getJumpBoost();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -341,34 +340,67 @@ export function shieldMetrics(ship, sys) {
|
|||||||
const maxSysResistance = this.sysResistance(4);
|
const maxSysResistance = this.sysResistance(4);
|
||||||
|
|
||||||
let shield = {};
|
let shield = {};
|
||||||
|
const dimReturnLine = (res) => 1 - (1 - res) * 0.7;
|
||||||
|
|
||||||
const shieldGeneratorSlot = ship.findInternalByGroup('sg');
|
const shieldGeneratorSlot = ship.findInternalByGroup('sg');
|
||||||
if (shieldGeneratorSlot && shieldGeneratorSlot.enabled && shieldGeneratorSlot.m) {
|
if (shieldGeneratorSlot && shieldGeneratorSlot.enabled && shieldGeneratorSlot.m) {
|
||||||
const shieldGenerator = shieldGeneratorSlot.m;
|
const shieldGenerator = shieldGeneratorSlot.m;
|
||||||
|
let res = {
|
||||||
|
kin: shieldGenerator.kinres,
|
||||||
|
therm: shieldGenerator.thermres,
|
||||||
|
expl: shieldGenerator.explres
|
||||||
|
};
|
||||||
// Boosters
|
// Boosters
|
||||||
let boost = 1;
|
let boost = 1;
|
||||||
let boosterExplDmg = 1;
|
let boosterExplDmg = 1;
|
||||||
let boosterKinDmg = 1;
|
let boosterKinDmg = 1;
|
||||||
let boosterThermDmg = 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) {
|
for (let slot of ship.hardpoints) {
|
||||||
if (slot.enabled && slot.m && slot.m.grp == 'sb') {
|
if (slot.enabled && slot.m && slot.m.grp == 'sb') {
|
||||||
boost += slot.m.getShieldBoost();
|
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());
|
boosterExplDmg = boosterExplDmg * (1 - slot.m.getExplosiveResistance());
|
||||||
boosterKinDmg = boosterKinDmg * (1 - slot.m.getKineticResistance());
|
boosterKinDmg = boosterKinDmg * (1 - slot.m.getKineticResistance());
|
||||||
boosterThermDmg = boosterThermDmg * (1 - slot.m.getThermalResistance());
|
boosterThermDmg = boosterThermDmg * (1 - slot.m.getThermalResistance());
|
||||||
}
|
}
|
||||||
|
if (slot.m && slot.m.grp == 'gsrp') {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Calculate diminishing returns for boosters
|
// Calculate diminishing returns for boosters
|
||||||
// Diminishing returns not currently in-game
|
// Diminishing returns not currently in-game
|
||||||
// boost = Math.min(boost, (1 - Math.pow(Math.E, -0.7 * boost)) * 2.5);
|
// boost = Math.min(boost, (1 - Math.pow(Math.E, -0.7 * boost)) * 2.5);
|
||||||
|
|
||||||
|
|
||||||
// Remove base shield generator strength
|
// Remove base shield generator strength
|
||||||
boost -= 1;
|
boost -= 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;
|
||||||
|
// }
|
||||||
let shieldAddition = 0;
|
let shieldAddition = 0;
|
||||||
if (ship) {
|
if (ship) {
|
||||||
for (const module of ship.internal) {
|
for (const module of ship.internal) {
|
||||||
if (module && module.m && module.m.grp === 'gsrp' && module.enabled) {
|
if (module && module.m && module.m.grp === 'gsrp') {
|
||||||
shieldAddition += module.m.getShieldAddition();
|
shieldAddition += module.m.getShieldAddition();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -433,7 +465,6 @@ export function shieldMetrics(ship, sys) {
|
|||||||
boosters: boostersStrength,
|
boosters: boostersStrength,
|
||||||
addition: shieldAddition,
|
addition: shieldAddition,
|
||||||
cells: ship.shieldCells,
|
cells: ship.shieldCells,
|
||||||
summary: generatorStrength + boostersStrength + shieldAddition,
|
|
||||||
total: generatorStrength + boostersStrength + ship.shieldCells + shieldAddition,
|
total: generatorStrength + boostersStrength + ship.shieldCells + shieldAddition,
|
||||||
recover,
|
recover,
|
||||||
recharge,
|
recharge,
|
||||||
@@ -466,7 +497,7 @@ export function shieldMetrics(ship, sys) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
let sgExplosiveDmg = 1 - shieldGenerator.getExplosiveResistance();
|
let sgExplosiveDmg = 1 - shieldGenerator.getExplosiveResistance();
|
||||||
let sgSbExplosiveDmg = diminishingReturnsShields(sgExplosiveDmg, sgExplosiveDmg * boosterExplDmg);
|
let sgSbExplosiveDmg = diminishDamageMult(sgExplosiveDmg * 0.7, (1 - shieldGenerator.getExplosiveResistance()) * boosterExplDmg);
|
||||||
/** @type {ShieldDamageMults} */
|
/** @type {ShieldDamageMults} */
|
||||||
shield.explosive = {
|
shield.explosive = {
|
||||||
generator: sgExplosiveDmg,
|
generator: sgExplosiveDmg,
|
||||||
@@ -478,7 +509,7 @@ export function shieldMetrics(ship, sys) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let sgKineticDmg = 1 - shieldGenerator.getKineticResistance();
|
let sgKineticDmg = 1 - shieldGenerator.getKineticResistance();
|
||||||
let sgSbKineticDmg = diminishingReturnsShields(sgKineticDmg, sgKineticDmg * boosterKinDmg);
|
let sgSbKineticDmg = diminishDamageMult(sgKineticDmg * 0.7, (1 - shieldGenerator.getKineticResistance()) * boosterKinDmg);
|
||||||
/** @type {ShieldDamageMults} */
|
/** @type {ShieldDamageMults} */
|
||||||
shield.kinetic = {
|
shield.kinetic = {
|
||||||
generator: sgKineticDmg,
|
generator: sgKineticDmg,
|
||||||
@@ -490,7 +521,7 @@ export function shieldMetrics(ship, sys) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let sgThermalDmg = 1 - shieldGenerator.getThermalResistance();
|
let sgThermalDmg = 1 - shieldGenerator.getThermalResistance();
|
||||||
let sgSbThermalDmg = diminishingReturnsShields(sgThermalDmg , sgThermalDmg * boosterThermDmg);
|
let sgSbThermalDmg = diminishDamageMult(sgThermalDmg * 0.7, (1 - shieldGenerator.getThermalResistance()) * boosterThermDmg);
|
||||||
/** @type {ShieldDamageMults} */
|
/** @type {ShieldDamageMults} */
|
||||||
shield.thermal = {
|
shield.thermal = {
|
||||||
generator: sgThermalDmg,
|
generator: sgThermalDmg,
|
||||||
@@ -530,28 +561,58 @@ export function armourMetrics(ship) {
|
|||||||
let moduleArmour = 0;
|
let moduleArmour = 0;
|
||||||
let moduleProtection = 1;
|
let moduleProtection = 1;
|
||||||
const bulkheads = ship.bulkheads.m;
|
const bulkheads = ship.bulkheads.m;
|
||||||
let hullExplDmgs = [];
|
let hullExplDmg = 1;
|
||||||
let hullKinDmgs = [];
|
let hullKinDmg = 1;
|
||||||
let hullThermDmgs = [];
|
let hullThermDmg = 1;
|
||||||
let hullCausDmgs = [];
|
let hullCausDmg = 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
|
// Armour from HRPs and module armour from MRPs
|
||||||
for (let slot of ship.internal) {
|
for (let slot of ship.internal) {
|
||||||
if (slot.m && slot.enabled && (slot.m.grp === 'hr' || slot.m.grp === 'ghrp' || slot.m.grp == 'mahr')) {
|
if (slot.m && (slot.m.grp === 'hr' || slot.m.grp === 'ghrp' || slot.m.grp == 'mahr')) {
|
||||||
armourReinforcement += slot.m.getHullReinforcement();
|
armourReinforcement += slot.m.getHullReinforcement();
|
||||||
// Hull boost for HRPs is applied against the ship's base armour
|
// Hull boost for HRPs is applied against the ship's base armour
|
||||||
armourReinforcement += ship.baseArmour * slot.m.getModValue('hullboost') / 10000;
|
armourReinforcement += ship.baseArmour * slot.m.getModValue('hullboost') / 10000;
|
||||||
hullExplDmgs.push(1 - slot.m.getExplosiveResistance());
|
// res.expl += slot.m.getExplosiveResistance();
|
||||||
hullKinDmgs.push(1 - slot.m.getKineticResistance());
|
// res.kin += slot.m.getKineticResistance();
|
||||||
hullThermDmgs.push(1 - slot.m.getThermalResistance());
|
// res.therm += slot.m.getThermalResistance();
|
||||||
hullCausDmgs.push(1 - slot.m.getCausticResistance());
|
hullExplDmg = hullExplDmg * (1 - slot.m.getExplosiveResistance());
|
||||||
|
hullKinDmg = hullKinDmg * (1 - slot.m.getKineticResistance());
|
||||||
|
hullThermDmg = hullThermDmg * (1 - slot.m.getThermalResistance());
|
||||||
|
hullCausDmg = hullCausDmg * (1 - slot.m.getCausticResistance());
|
||||||
}
|
}
|
||||||
if (slot.m && slot.enabled && (slot.m.grp == 'mrp' || slot.m.grp == 'gmrp')) {
|
if (slot.m && (slot.m.grp == 'mrp' || slot.m.grp == 'gmrp')) {
|
||||||
moduleArmour += slot.m.getIntegrity();
|
moduleArmour += slot.m.getIntegrity();
|
||||||
moduleProtection = moduleProtection * (1 - slot.m.getProtection());
|
moduleProtection = moduleProtection * (1 - slot.m.getProtection());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
moduleProtection = 1 - moduleProtection;
|
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;
|
||||||
|
// }
|
||||||
|
|
||||||
const armour = {
|
const armour = {
|
||||||
bulkheads: armourBulkheads,
|
bulkheads: armourBulkheads,
|
||||||
reinforcement: armourReinforcement,
|
reinforcement: armourReinforcement,
|
||||||
@@ -568,8 +629,8 @@ export function armourMetrics(ship) {
|
|||||||
total: 1
|
total: 1
|
||||||
};
|
};
|
||||||
|
|
||||||
let armourExplDmg = 1 - ship.bulkheads.m.getExplosiveResistance();
|
let armourExplDmg = diminishDamageMult(0.7, 1 - ship.bulkheads.m.getExplosiveResistance());
|
||||||
let armourReinforcedExplDmg = diminishingReturnsArmour(armourExplDmg, ...hullExplDmgs);
|
let armourReinforcedExplDmg = diminishDamageMult(0.7, (1 - ship.bulkheads.m.getExplosiveResistance()) * hullExplDmg);
|
||||||
armour.explosive = {
|
armour.explosive = {
|
||||||
bulkheads: armourExplDmg,
|
bulkheads: armourExplDmg,
|
||||||
reinforcement: armourReinforcedExplDmg / armourExplDmg,
|
reinforcement: armourReinforcedExplDmg / armourExplDmg,
|
||||||
@@ -577,8 +638,8 @@ export function armourMetrics(ship) {
|
|||||||
res: 1 - armourReinforcedExplDmg
|
res: 1 - armourReinforcedExplDmg
|
||||||
};
|
};
|
||||||
|
|
||||||
let armourKinDmg = 1 - ship.bulkheads.m.getKineticResistance();
|
let armourKinDmg = diminishDamageMult(0.7, 1 - ship.bulkheads.m.getKineticResistance());
|
||||||
let armourReinforcedKinDmg = diminishingReturnsArmour(armourKinDmg, ...hullKinDmgs);
|
let armourReinforcedKinDmg = diminishDamageMult(0.7, (1 - ship.bulkheads.m.getKineticResistance()) * hullKinDmg);
|
||||||
armour.kinetic = {
|
armour.kinetic = {
|
||||||
bulkheads: armourKinDmg,
|
bulkheads: armourKinDmg,
|
||||||
reinforcement: armourReinforcedKinDmg / armourKinDmg,
|
reinforcement: armourReinforcedKinDmg / armourKinDmg,
|
||||||
@@ -586,8 +647,8 @@ export function armourMetrics(ship) {
|
|||||||
res: 1 - armourReinforcedKinDmg
|
res: 1 - armourReinforcedKinDmg
|
||||||
};
|
};
|
||||||
|
|
||||||
let armourThermDmg = 1 - ship.bulkheads.m.getThermalResistance();
|
let armourThermDmg = diminishDamageMult(0.7, 1 - ship.bulkheads.m.getThermalResistance());
|
||||||
let armourReinforcedThermDmg = diminishingReturnsArmour(armourThermDmg, ...hullThermDmgs);
|
let armourReinforcedThermDmg = diminishDamageMult(0.7, (1 - ship.bulkheads.m.getThermalResistance()) * hullThermDmg);
|
||||||
armour.thermal = {
|
armour.thermal = {
|
||||||
bulkheads: armourThermDmg,
|
bulkheads: armourThermDmg,
|
||||||
reinforcement: armourReinforcedThermDmg / armourThermDmg,
|
reinforcement: armourReinforcedThermDmg / armourThermDmg,
|
||||||
@@ -595,8 +656,8 @@ export function armourMetrics(ship) {
|
|||||||
res: 1 - armourReinforcedThermDmg
|
res: 1 - armourReinforcedThermDmg
|
||||||
};
|
};
|
||||||
|
|
||||||
let armourCausDmg = 1 - ship.bulkheads.m.getCausticResistance();
|
let armourCausDmg = diminishDamageMult(0.7, 1 - ship.bulkheads.m.getCausticResistance());
|
||||||
let armourReinforcedCausDmg = diminishingReturnsArmour(armourCausDmg, ...hullCausDmgs);
|
let armourReinforcedCausDmg = diminishDamageMult(0.7, (1 - ship.bulkheads.m.getCausticResistance()) * hullCausDmg);
|
||||||
armour.caustic = {
|
armour.caustic = {
|
||||||
bulkheads: armourCausDmg,
|
bulkheads: armourCausDmg,
|
||||||
reinforcement: armourReinforcedCausDmg / armourCausDmg,
|
reinforcement: armourReinforcedCausDmg / armourCausDmg,
|
||||||
@@ -842,14 +903,12 @@ export function _weaponSustainedDps(m, opponent, opponentShields, opponentArmour
|
|||||||
shields: {
|
shields: {
|
||||||
range: 1,
|
range: 1,
|
||||||
sys: opponentHasShields ? opponentShields.absolute.sys : 1,
|
sys: opponentHasShields ? opponentShields.absolute.sys : 1,
|
||||||
resistance: 1,
|
resistance: 1
|
||||||
dpe: 1
|
|
||||||
},
|
},
|
||||||
armour: {
|
armour: {
|
||||||
range: 1,
|
range: 1,
|
||||||
hardness: 1,
|
hardness: 1,
|
||||||
resistance: 1,
|
resistance: 1
|
||||||
dpe: 1
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -909,19 +968,11 @@ export function _weaponSustainedDps(m, opponent, opponentShields, opponentArmour
|
|||||||
weapon.damage.shields.total = weapon.damage.shields.absolute + weapon.damage.shields.explosive + weapon.damage.shields.kinetic + weapon.damage.shields.thermal;
|
weapon.damage.shields.total = weapon.damage.shields.absolute + weapon.damage.shields.explosive + weapon.damage.shields.kinetic + weapon.damage.shields.thermal;
|
||||||
weapon.damage.armour.total = weapon.damage.armour.absolute + weapon.damage.armour.explosive + weapon.damage.armour.kinetic + weapon.damage.armour.thermal;
|
weapon.damage.armour.total = weapon.damage.armour.absolute + weapon.damage.armour.explosive + weapon.damage.armour.kinetic + weapon.damage.armour.thermal;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
weapon.effectiveness.shields.resistance *= shieldsResistance;
|
weapon.effectiveness.shields.resistance *= shieldsResistance;
|
||||||
weapon.effectiveness.armour.resistance *= armourResistance;
|
weapon.effectiveness.armour.resistance *= armourResistance;
|
||||||
|
|
||||||
|
|
||||||
weapon.effectiveness.shields.total = weapon.effectiveness.shields.range * weapon.effectiveness.shields.sys * weapon.effectiveness.shields.resistance;
|
weapon.effectiveness.shields.total = weapon.effectiveness.shields.range * weapon.effectiveness.shields.sys * weapon.effectiveness.shields.resistance;
|
||||||
weapon.effectiveness.armour.total = weapon.effectiveness.armour.range * weapon.effectiveness.armour.resistance * weapon.effectiveness.armour.hardness;
|
weapon.effectiveness.armour.total = weapon.effectiveness.armour.range * weapon.effectiveness.armour.resistance * weapon.effectiveness.armour.hardness;
|
||||||
|
|
||||||
weapon.effectiveness.shields.dpe = weapon.damage.shields.total / m.getEps();
|
|
||||||
weapon.effectiveness.armour.dpe = weapon.damage.armour.total / m.getEps();
|
|
||||||
|
|
||||||
|
|
||||||
return weapon;
|
return weapon;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -963,10 +1014,7 @@ export function timeToDrainWep(ship, wep) {
|
|||||||
*/
|
*/
|
||||||
export function timeToDeplete(amount, dps, eps, capacity, recharge) {
|
export function timeToDeplete(amount, dps, eps, capacity, recharge) {
|
||||||
const drainPerSecond = eps - recharge;
|
const drainPerSecond = eps - recharge;
|
||||||
// If there is nothing to remove, we're don instantly
|
if (drainPerSecond <= 0) {
|
||||||
if (!amount) {
|
|
||||||
return 0;
|
|
||||||
} if (drainPerSecond <= 0) {
|
|
||||||
// Simple result
|
// Simple result
|
||||||
return amount / dps;
|
return amount / dps;
|
||||||
} else {
|
} else {
|
||||||
@@ -985,50 +1033,15 @@ export function timeToDeplete(amount, dps, eps, capacity, recharge) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether diminishing returns should be applied to shield damage
|
* Applies diminishing returns to resistances.
|
||||||
* multipliers and does so if necessary.
|
* @param {number} diminishFrom The base resistance up to which no diminishing returns are applied.
|
||||||
* @param {number} shieldMult Damage multiplier of shield generator
|
* @param {number} damageMult Resistance as damage multiplier
|
||||||
* @param {number} combinedMult Damage multiplier of shields and shield boosters
|
* @returns {number} Actual damage multiplier
|
||||||
* @returns {number} Overall damage multiplier
|
|
||||||
*/
|
*/
|
||||||
export function diminishingReturnsShields(shieldMult, combinedMult) {
|
export function diminishDamageMult(diminishFrom, damageMult) {
|
||||||
let max = shieldMult * 0.7;
|
if (damageMult > diminishFrom) {
|
||||||
if (combinedMult < max) {
|
return damageMult;
|
||||||
return mapIntoDiminishingRange(max / 2, max, combinedMult);
|
|
||||||
} else {
|
} else {
|
||||||
return combinedMult;
|
return (diminishFrom / 2) + 0.5 * damageMult;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks whether diminishing returns should be applied to armour damage
|
|
||||||
* multipliers and does so if necessary.
|
|
||||||
* @param {...any} mults Damage multipliers of alloys and hull reinforcement
|
|
||||||
* packages
|
|
||||||
* @returns {number} Overall damage multiplier
|
|
||||||
*/
|
|
||||||
export function diminishingReturnsArmour(...mults) {
|
|
||||||
let max = Math.min(0.7, ...mults);
|
|
||||||
let combined = mults.reduce((aggr, v) => aggr * v);
|
|
||||||
let diminished = mapIntoDiminishingRange(0.35, max, combined);
|
|
||||||
if (diminished < 0.7) {
|
|
||||||
return diminished;
|
|
||||||
} else {
|
|
||||||
return combined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Applies diminishing returns to a damage multiplier. Effictively, the range
|
|
||||||
* [`0`, `max`]` is mapped into the range [`min`, `max`] for the value `now`.
|
|
||||||
* It can also happen, that `now` is outside of the range [`min`, `max`], then
|
|
||||||
* `now` is actually improved, i.e. enlarged.
|
|
||||||
* @param {number} min Best theoretical damage multiplier
|
|
||||||
* @param {number} max Damage multiplier from which diminishing returns start to
|
|
||||||
* be applied
|
|
||||||
* @param {number} now The current damage multiplier
|
|
||||||
* @returns {number} Remapped damage multiplier
|
|
||||||
*/
|
|
||||||
export function mapIntoDiminishingRange(min, max, now) {
|
|
||||||
return min + (max - min) * (now / max);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -57,7 +57,6 @@ export const ModuleGroupToName = {
|
|||||||
ghrp: 'Guardian Hull Reinforcement Package',
|
ghrp: 'Guardian Hull Reinforcement Package',
|
||||||
gmrp: 'Guardian Module Reinforcement Package',
|
gmrp: 'Guardian Module Reinforcement Package',
|
||||||
mahr: 'Meta Alloy Hull Reinforcement Package',
|
mahr: 'Meta Alloy Hull Reinforcement Package',
|
||||||
sua: 'Supercruise Assist',
|
|
||||||
|
|
||||||
// Hard Points
|
// Hard Points
|
||||||
bl: 'Beam Laser',
|
bl: 'Beam Laser',
|
||||||
@@ -207,7 +206,7 @@ export const ShipFacets = [
|
|||||||
i: 9
|
i: 9
|
||||||
},
|
},
|
||||||
{ // 10
|
{ // 10
|
||||||
title: 'farthest range',
|
title: 'fastest range',
|
||||||
props: ['unladenFastestRange', 'ladenFastestRange'],
|
props: ['unladenFastestRange', 'ladenFastestRange'],
|
||||||
lbls: ['unladen', 'laden'],
|
lbls: ['unladen', 'laden'],
|
||||||
unit: 'LY',
|
unit: 'LY',
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
import * as ModuleUtils from './ModuleUtils';
|
import * as ModuleUtils from './ModuleUtils';
|
||||||
import { Modifications } from 'coriolis-data/dist';
|
import { Modifications } from 'coriolis-data/dist';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { SI_PREFIXES, STATS_FORMATTING } from './StatsFormatting';
|
import { STATS_FORMATTING, SI_PREFIXES } from './StatsFormatting';
|
||||||
import { includes } from 'lodash';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Module - active module in a ship's buildout
|
* Module - active module in a ship's buildout
|
||||||
@@ -42,7 +41,8 @@ export default class Module {
|
|||||||
* @return {object} The value of the modification. If it is a numeric value then it is returned as an integer value scaled so that 1.23% == 123
|
* @return {object} The value of the modification. If it is a numeric value then it is returned as an integer value scaled so that 1.23% == 123
|
||||||
*/
|
*/
|
||||||
getModValue(name, raw) {
|
getModValue(name, raw) {
|
||||||
let result = this.mods && this.mods[name] ? this.mods[name] : null;
|
let baseVal = this[name];
|
||||||
|
let result = this.mods && this.mods[name] ? this.mods[name] : null;
|
||||||
|
|
||||||
if ((!raw) && this.blueprint && this.blueprint.special) {
|
if ((!raw) && this.blueprint && this.blueprint.special) {
|
||||||
// This module has a special effect, see if we need to alter our returned value
|
// This module has a special effect, see if we need to alter our returned value
|
||||||
@@ -51,8 +51,7 @@ export default class Module {
|
|||||||
// this special effect modifies our returned value
|
// this special effect modifies our returned value
|
||||||
const modification = Modifications.modifications[name];
|
const modification = Modifications.modifications[name];
|
||||||
const multiplier = modification.type === 'percentage' ? 10000 : 100;
|
const multiplier = modification.type === 'percentage' ? 10000 : 100;
|
||||||
|
if (name === 'explres' || name === 'kinres' || name === 'thermres' || name === 'causres') {
|
||||||
if (includes(['explres', 'kinres', 'thermres', 'causres'], name)) {
|
|
||||||
// Apply resistance modding mechanisms to special effects subsequently
|
// Apply resistance modding mechanisms to special effects subsequently
|
||||||
result = result + modifierActions[name] * (1 - (this[name] + result / multiplier)) * 100;
|
result = result + modifierActions[name] * (1 - (this[name] + result / multiplier)) * 100;
|
||||||
} else if (modification.method === 'additive') {
|
} else if (modification.method === 'additive') {
|
||||||
@@ -60,7 +59,14 @@ export default class Module {
|
|||||||
} else if (modification.method === 'overwrite') {
|
} else if (modification.method === 'overwrite') {
|
||||||
result = modifierActions[name];
|
result = modifierActions[name];
|
||||||
} else {
|
} else {
|
||||||
result = result + modifierActions[name] * multiplier;
|
// rate of fire is special, as it's really burst interval. Handle that here
|
||||||
|
let mod = null;
|
||||||
|
if (name === 'rof') {
|
||||||
|
mod = 1 / (1 + modifierActions[name]) - 1;
|
||||||
|
} else {
|
||||||
|
mod = modifierActions[name];
|
||||||
|
}
|
||||||
|
result = (((1 + result / multiplier) * (1 + mod)) - 1) * multiplier;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -99,7 +105,14 @@ export default class Module {
|
|||||||
} else if (modification.method === 'overwrite') {
|
} else if (modification.method === 'overwrite') {
|
||||||
value = null;
|
value = null;
|
||||||
} else {
|
} else {
|
||||||
value = ((value / 10000 + 1) / (1 + modifierActions[name]) - 1) * 10000;
|
// rate of fire is special, as it's really burst interval. Handle that here
|
||||||
|
let mod = null;
|
||||||
|
if (name === 'rof') {
|
||||||
|
mod = 1 / (1 + modifierActions[name]) - 1;
|
||||||
|
} else {
|
||||||
|
mod = modifierActions[name];
|
||||||
|
}
|
||||||
|
value = ((value / 10000 + 1) / (1 + mod) - 1) * 10000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -118,13 +131,6 @@ export default class Module {
|
|||||||
* @return {Number} The value queried
|
* @return {Number} The value queried
|
||||||
*/
|
*/
|
||||||
get(name, modified = true) {
|
get(name, modified = true) {
|
||||||
if (name == 'rof' && isNaN(this[name])) {
|
|
||||||
let fireint = this['fireint'];
|
|
||||||
if (!isNaN(fireint)) {
|
|
||||||
this['rof'] = 1 / fireint;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let val;
|
let val;
|
||||||
if (modified) {
|
if (modified) {
|
||||||
val = this._getModifiedValue(name);
|
val = this._getModifiedValue(name);
|
||||||
@@ -160,20 +166,14 @@ export default class Module {
|
|||||||
modValue = value - baseValue;
|
modValue = value - baseValue;
|
||||||
} else if (name === 'shieldboost' || name === 'hullboost') {
|
} else if (name === 'shieldboost' || name === 'hullboost') {
|
||||||
modValue = (1 + value) / (1 + baseValue) - 1;
|
modValue = (1 + value) / (1 + baseValue) - 1;
|
||||||
} else if (name === 'rof') {
|
|
||||||
let burst = this.get('burst', true) || 1;
|
|
||||||
let burstInt = 1 / (this.get('burstrof', true) / 1);
|
|
||||||
|
|
||||||
let interval = burst / value;
|
|
||||||
let newFireint = (interval - (burst - 1) * burstInt);
|
|
||||||
modValue = newFireint / this['fireint'] - 1;
|
|
||||||
} else { // multiplicative
|
} else { // multiplicative
|
||||||
modValue = baseValue == 0 ? 0 : value / baseValue - 1;
|
modValue = value / baseValue - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (modification.type === 'percentage') {
|
if (modification.type === 'percentage') {
|
||||||
modValue = modValue * 10000;
|
modValue = modValue * 10000;
|
||||||
} else if (modification.type === 'numeric') {
|
} else if (modification.type === 'numeric' && name !== 'burst' &&
|
||||||
|
name !== 'burstrof') {
|
||||||
modValue = modValue * 100;
|
modValue = modValue * 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,14 +191,7 @@ export default class Module {
|
|||||||
*/
|
*/
|
||||||
getPretty(name, modified = true, places = 2) {
|
getPretty(name, modified = true, places = 2) {
|
||||||
const formattingOptions = STATS_FORMATTING[name];
|
const formattingOptions = STATS_FORMATTING[name];
|
||||||
let val;
|
let val = this.get(name, modified) || 0;
|
||||||
if (formattingOptions && formattingOptions.synthetic) {
|
|
||||||
val = (this[formattingOptions.synthetic]).call(this, modified);
|
|
||||||
} else {
|
|
||||||
val = this.get(name, modified);
|
|
||||||
}
|
|
||||||
val = val || 0;
|
|
||||||
|
|
||||||
if (formattingOptions && formattingOptions.format.startsWith('pct')) {
|
if (formattingOptions && formattingOptions.format.startsWith('pct')) {
|
||||||
return 100 * val;
|
return 100 * val;
|
||||||
}
|
}
|
||||||
@@ -257,17 +250,12 @@ export default class Module {
|
|||||||
} else if (name === 'shieldboost' || name === 'hullboost') {
|
} else if (name === 'shieldboost' || name === 'hullboost') {
|
||||||
result = (1 + result) * (1 + modValue) - 1;
|
result = (1 + result) * (1 + modValue) - 1;
|
||||||
} else {
|
} else {
|
||||||
// Rate of fire modifiers are special as they actually are modifiers
|
|
||||||
// for fire interval. Translate them accordingly here:
|
|
||||||
if (name == 'rof') {
|
|
||||||
modValue = 1 / (1 + modValue) - 1;
|
|
||||||
}
|
|
||||||
result = result * (1 + modValue);
|
result = result * (1 + modValue);
|
||||||
}
|
}
|
||||||
} else if (name === 'burstrof' || name === 'burst') {
|
} else if (name === 'burstrof') {
|
||||||
// Burst and burst rate of fire are special, as it can not exist but
|
// Burst and burst rate of fire are special, as it can not exist but
|
||||||
// have a modification
|
// have a modification
|
||||||
result = modValue;
|
result = modValue / 100;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -289,7 +277,11 @@ export default class Module {
|
|||||||
formatModifiedValue(name, language, unit, val) {
|
formatModifiedValue(name, language, unit, val) {
|
||||||
const formattingOptions = STATS_FORMATTING[name];
|
const formattingOptions = STATS_FORMATTING[name];
|
||||||
if (val === undefined) {
|
if (val === undefined) {
|
||||||
val = this.getPretty(name, true);
|
if (formattingOptions && formattingOptions.synthetic) {
|
||||||
|
val = (this[formattingOptions.synthetic]).call(this, true);
|
||||||
|
} else {
|
||||||
|
val = this._getModifiedValue(name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val = val || 0;
|
val = val || 0;
|
||||||
@@ -359,18 +351,14 @@ export default class Module {
|
|||||||
|
|
||||||
if (formattingOptions && formattingOptions.change) {
|
if (formattingOptions && formattingOptions.change) {
|
||||||
let changeFormatting = formattingOptions.change;
|
let changeFormatting = formattingOptions.change;
|
||||||
let baseVal = this[name] || 0;
|
let baseVal = this[name];
|
||||||
let absVal = this._getModifiedValue(name);
|
let absVal = this._getModifiedValue(name);
|
||||||
if (changeFormatting === 'additive') {
|
if (changeFormatting === 'additive') {
|
||||||
val = absVal - baseVal;
|
val = absVal - baseVal;
|
||||||
} else if (changeFormatting === 'multiplicative') {
|
} else if (changeFormatting === 'multiplicative') {
|
||||||
val = absVal / baseVal - 1;
|
val = absVal / baseVal - 1;
|
||||||
}
|
}
|
||||||
if (Modifications.modifications[name].method === 'overwrite') {
|
val *= 10000;
|
||||||
val *= 100;
|
|
||||||
} else {
|
|
||||||
val *= 10000;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
@@ -584,9 +572,20 @@ export default class Module {
|
|||||||
* @return {Number} the falloff of this module
|
* @return {Number} the falloff of this module
|
||||||
*/
|
*/
|
||||||
getFalloff(modified = true) {
|
getFalloff(modified = true) {
|
||||||
|
if (!modified) {
|
||||||
|
const range = this.getRange(false);
|
||||||
|
const falloff = this.get('falloff', false);
|
||||||
|
return (falloff > range ? range : falloff);
|
||||||
|
}
|
||||||
|
|
||||||
// Falloff from range is mapped to range
|
// Falloff from range is mapped to range
|
||||||
if (modified && this.mods && this.mods['fallofffromrange']) {
|
if (this.mods && this.mods['fallofffromrange']) {
|
||||||
return this.getRange();
|
return this.getRange();
|
||||||
|
// Need to find out if we have a focused modification, in which case our
|
||||||
|
// falloff is scaled to range
|
||||||
|
} else if (this.blueprint && this.blueprint.name === 'Focused') {
|
||||||
|
const rangeMod = this.getModValue('range') / 10000;
|
||||||
|
return this.falloff * (1 + rangeMod);
|
||||||
// Standard falloff calculation
|
// Standard falloff calculation
|
||||||
} else {
|
} else {
|
||||||
const range = this.getRange();
|
const range = this.getRange();
|
||||||
@@ -640,6 +639,15 @@ export default class Module {
|
|||||||
return this.get('protection', modified);
|
return this.get('protection', modified);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the delay for this module
|
||||||
|
* @param {Boolean} [modified=true] Whether to take modifications into account
|
||||||
|
* @return {Number} the delay of this module
|
||||||
|
*/
|
||||||
|
getDelay(modified = true) {
|
||||||
|
return this.get('delay', modified);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the duration for this module
|
* Get the duration for this module
|
||||||
* @param {Boolean} [modified=true] Whether to take modifications into account
|
* @param {Boolean} [modified=true] Whether to take modifications into account
|
||||||
@@ -695,7 +703,8 @@ export default class Module {
|
|||||||
let result = 0;
|
let result = 0;
|
||||||
if (this['maxmass']) {
|
if (this['maxmass']) {
|
||||||
result = this['maxmass'];
|
result = this['maxmass'];
|
||||||
if (result && modified && !ModuleUtils.isShieldGenerator(this['grp'])) {
|
// max mass is only modified for non-shield boosters
|
||||||
|
if (result && modified && this.grp !== 'sg') {
|
||||||
let mult = this.getModValue('optmass') / 10000;
|
let mult = this.getModValue('optmass') / 10000;
|
||||||
if (mult) { result = result * (1 + mult); }
|
if (mult) { result = result * (1 + mult); }
|
||||||
}
|
}
|
||||||
@@ -784,6 +793,24 @@ export default class Module {
|
|||||||
return this.get('distdraw', modified);
|
return this.get('distdraw', modified);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the thermal load for this module
|
||||||
|
* @param {Boolean} [modified=true] Whether to take modifications into account
|
||||||
|
* @return {Number} the thermal load of this module
|
||||||
|
*/
|
||||||
|
getThermalLoad(modified = true) {
|
||||||
|
return this.get('thermload', modified);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the rounds per shot for this module
|
||||||
|
* @param {Boolean} [modified=true] Whether to take modifications into account
|
||||||
|
* @return {Number} the rounds per shot of this module
|
||||||
|
*/
|
||||||
|
getRoundsPerShot(modified = true) {
|
||||||
|
return this.get('roundspershot', modified);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the DPS for this module
|
* Get the DPS for this module
|
||||||
* @param {Boolean} [modified=true] Whether to take modifications into account
|
* @param {Boolean} [modified=true] Whether to take modifications into account
|
||||||
@@ -807,39 +834,25 @@ export default class Module {
|
|||||||
return this.getDps(modified) / this.getEps(modified);
|
return this.getDps(modified) / this.getEps(modified);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the factor that gets applied when calculating certain "sustained"
|
|
||||||
* values, e.g. `SDPS = this.getSustainedFactor() * DPS`.
|
|
||||||
* @param {Boolean} [modified=true] Whether to take modifications into account
|
|
||||||
*/
|
|
||||||
getSustainedFactor(modified = true) {
|
|
||||||
let clipSize = this.getClip(modified);
|
|
||||||
if (clipSize) {
|
|
||||||
// If auto-loader is applied, effective clip size will be nearly doubled
|
|
||||||
// as you get one reload for every two shots fired.
|
|
||||||
if (this.blueprint && this.blueprint.special && this.blueprint.special.edname === 'special_auto_loader' && modified) {
|
|
||||||
clipSize += clipSize - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
let burstSize = this.get('burst', modified) || 1;
|
|
||||||
let rof = this.getRoF(modified);
|
|
||||||
// rof averages burstfire + pause until next interval but for sustained
|
|
||||||
// rof we need to take another burst without pause into account
|
|
||||||
let burstOverhead = (burstSize - 1) / (this.get('burstrof', modified) || 1);
|
|
||||||
let srof = clipSize / ((clipSize - burstSize) / rof + burstOverhead + this.getReload(modified));
|
|
||||||
return srof / rof;
|
|
||||||
} else {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the SDPS for this module
|
* Get the SDPS for this module
|
||||||
* @param {Boolean} [modified=true] Whether to take modifications into account
|
* @param {Boolean} [modified=true] Whether to take modifications into account
|
||||||
* @return {Number} The SDPS of this module
|
* @return {Number} The SDPS of this module
|
||||||
*/
|
*/
|
||||||
getSDps(modified = true) {
|
getSDps(modified = true) {
|
||||||
return this.getDps(modified) * this.getSustainedFactor(modified);
|
let dps = this.getDps(modified);
|
||||||
|
if (this.getClip(modified)) {
|
||||||
|
let clipSize = this.getClip(modified);
|
||||||
|
// If auto-loader is applied, effective clip size will be nearly doubled
|
||||||
|
// as you get one reload for every two shots fired.
|
||||||
|
if (this.blueprint && this.blueprint.special && this.blueprint.special.edname === 'special_auto_loader' && modified) {
|
||||||
|
clipSize += clipSize - 1;
|
||||||
|
}
|
||||||
|
let timeToDeplete = clipSize / this.getRoF(modified);
|
||||||
|
return dps * timeToDeplete / (timeToDeplete + this.getReload(modified));
|
||||||
|
} else {
|
||||||
|
return dps;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -863,7 +876,7 @@ export default class Module {
|
|||||||
*/
|
*/
|
||||||
getHps(modified = true) {
|
getHps(modified = true) {
|
||||||
// HPS is a synthetic value
|
// HPS is a synthetic value
|
||||||
let heat = this.get('thermload', modified);
|
let heat = this.getThermalLoad(modified);
|
||||||
// We don't use rpshot here as dist draw is per combined shot
|
// We don't use rpshot here as dist draw is per combined shot
|
||||||
let rof = this.getRoF(modified) || 1;
|
let rof = this.getRoF(modified) || 1;
|
||||||
|
|
||||||
@@ -900,6 +913,24 @@ export default class Module {
|
|||||||
return this.get('reload', modified);
|
return this.get('reload', modified);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the burst size for this module
|
||||||
|
* @param {Boolean} [modified=true] Whether to take modifications into account
|
||||||
|
* @return {Number} the burst size of this module
|
||||||
|
*/
|
||||||
|
getBurst(modified = true) {
|
||||||
|
return this.get('burst', modified);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the burst rate of fire for this module
|
||||||
|
* @param {Boolean} [modified=true] Whether to take modifications into account
|
||||||
|
* @return {Number} the burst rate of fire of this module
|
||||||
|
*/
|
||||||
|
getBurstRoF(modified = true) {
|
||||||
|
return this.get('burstrof', modified);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the rate of fire for this module.
|
* Get the rate of fire for this module.
|
||||||
* The rate of fire is a combination value, and needs to take in to account
|
* The rate of fire is a combination value, and needs to take in to account
|
||||||
@@ -910,8 +941,8 @@ export default class Module {
|
|||||||
* @return {Number} the rate of fire for this module
|
* @return {Number} the rate of fire for this module
|
||||||
*/
|
*/
|
||||||
getRoF(modified = true) {
|
getRoF(modified = true) {
|
||||||
const burst = this.get('burst', modified) || 1;
|
const burst = this.getBurst(modified) || 1;
|
||||||
const burstRoF = this.get('burstrof', modified) || 1;
|
const burstRoF = this.getBurstRoF(modified) || 1;
|
||||||
const intRoF = this.get('rof', modified);
|
const intRoF = this.get('rof', modified);
|
||||||
|
|
||||||
return burst / (((burst - 1) / burstRoF) + 1 / intRoF);
|
return burst / (((burst - 1) / burstRoF) + 1 / intRoF);
|
||||||
|
|||||||
@@ -164,13 +164,13 @@ export default class ModuleSet {
|
|||||||
/**
|
/**
|
||||||
* Finds the lightest usable Shield Generator
|
* Finds the lightest usable Shield Generator
|
||||||
* @param {number} hullMass Ship hull mass
|
* @param {number} hullMass Ship hull mass
|
||||||
* @return {Object} Thruster
|
* @param {string} rating The optional rating of the shield
|
||||||
|
* @return {Object} Shield Generator
|
||||||
*/
|
*/
|
||||||
lightestShieldGenerator(hullMass) {
|
lightestShieldGenerator(hullMass, rating) {
|
||||||
let sg = this.internal.sg[0];
|
let sg = this.internal.sg[0];
|
||||||
|
|
||||||
for (let s of this.internal.sg) {
|
for (let s of this.internal.sg) {
|
||||||
if (s.mass < sg.mass && s.maxmass > hullMass) {
|
if ((!rating || rating === s.rating) && s.mass <= sg.mass && s.maxmass > hullMass) {
|
||||||
sg = s;
|
sg = s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { Ships, Modifications } from 'coriolis-data/dist';
|
|||||||
import { chain } from 'lodash';
|
import { chain } from 'lodash';
|
||||||
const zlib = require('zlib');
|
const zlib = require('zlib');
|
||||||
|
|
||||||
const UNIQUE_MODULES = ['psg', 'sg', 'bsg', 'rf', 'fs', 'fh', 'gfsb', 'dc'];
|
const UNIQUE_MODULES = ['psg', 'sg', 'bsg', 'rf', 'fs', 'fh', 'gfsb'];
|
||||||
|
|
||||||
// Constants for modifications struct
|
// Constants for modifications struct
|
||||||
const SLOT_ID_DONE = -1;
|
const SLOT_ID_DONE = -1;
|
||||||
@@ -1308,7 +1308,7 @@ export default class Ship {
|
|||||||
let fsd = this.standard[2].m; // Frame Shift Drive;
|
let fsd = this.standard[2].m; // Frame Shift Drive;
|
||||||
let { unladenMass, fuelCapacity } = this;
|
let { unladenMass, fuelCapacity } = this;
|
||||||
this.unladenRange = this.calcUnladenRange(); // Includes fuel weight for jump
|
this.unladenRange = this.calcUnladenRange(); // Includes fuel weight for jump
|
||||||
this.fullTankRange = Calc.jumpRange(unladenMass + fuelCapacity, fsd, fuelCapacity, this); // Full Tank
|
this.fullTankRange = Calc.jumpRange(unladenMass + fuelCapacity, fsd, this); // Full Tank
|
||||||
this.ladenRange = this.calcLadenRange(); // Includes full tank and caro
|
this.ladenRange = this.calcLadenRange(); // Includes full tank and caro
|
||||||
this.unladenFastestRange = Calc.totalJumpRange(unladenMass + this.fuelCapacity, fsd, fuelCapacity, this);
|
this.unladenFastestRange = Calc.totalJumpRange(unladenMass + this.fuelCapacity, fsd, fuelCapacity, this);
|
||||||
this.ladenFastestRange = Calc.totalJumpRange(unladenMass + this.fuelCapacity + this.cargoCapacity, fsd, fuelCapacity, this);
|
this.ladenFastestRange = Calc.totalJumpRange(unladenMass + this.fuelCapacity + this.cargoCapacity, fsd, fuelCapacity, this);
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import * as ModuleUtils from './ModuleUtils';
|
import * as ModuleUtils from './ModuleUtils';
|
||||||
|
import { Modifications } from 'coriolis-data/dist';
|
||||||
import { canMount } from '../utils/SlotFunctions';
|
import { canMount } from '../utils/SlotFunctions';
|
||||||
|
import { getBlueprint, setPercent } from '../utils/BlueprintFunctions';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Standard / typical role for multi-purpose or combat (if shielded with better bulkheads)
|
* Standard / typical role for multi-purpose or combat (if shielded with better bulkheads)
|
||||||
@@ -14,7 +16,7 @@ export function multiPurpose(ship, shielded, bulkheadIndex) {
|
|||||||
.useBulkhead(bulkheadIndex);
|
.useBulkhead(bulkheadIndex);
|
||||||
|
|
||||||
if (shielded) {
|
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
|
if (canMount(ship, slot, 'sg')) { // Assuming largest slot can hold an eligible shield
|
||||||
ship.use(slot, ModuleUtils.findInternal('sg', slot.maxClass, 'A'));
|
ship.use(slot, ModuleUtils.findInternal('sg', slot.maxClass, 'A'));
|
||||||
ship.setSlotEnabled(slot, true);
|
ship.setSlotEnabled(slot, true);
|
||||||
@@ -24,6 +26,577 @@ export function multiPurpose(ship, shielded, bulkheadIndex) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Distant Worlds 2 role
|
||||||
|
* Tiers:
|
||||||
|
* 1- Max. Jump Range, Unshielded
|
||||||
|
* 2- Max. Jump Range, Minimal Shields
|
||||||
|
* 3- Max. Jump Range, Optimal Shields
|
||||||
|
* 4- Max. Jump Range, Optimal Shields & Thrusters
|
||||||
|
*
|
||||||
|
* Engineering level:
|
||||||
|
* No engineering
|
||||||
|
* Only Felicity Farseer and Elvira Martuuk
|
||||||
|
* All exploration related engineers
|
||||||
|
*
|
||||||
|
* Role
|
||||||
|
* Exploration
|
||||||
|
* Surface exploration
|
||||||
|
* Big Rig, full mining
|
||||||
|
* Saper / Prospector mining
|
||||||
|
* Fuel rat
|
||||||
|
* Repair rat
|
||||||
|
* Mechanic
|
||||||
|
* Trucker
|
||||||
|
*
|
||||||
|
* @param ship {Ship} Ship instance
|
||||||
|
* @param tier {Number}
|
||||||
|
* @param engineeringLevel {Number}
|
||||||
|
* @param role {String}
|
||||||
|
* @param gfsb {Boolean} add Guardian FSD Booster
|
||||||
|
* @param gpp {Boolean} add Guardian Power Plant
|
||||||
|
* @param fighter {Boolean} add fighter if supported
|
||||||
|
*/
|
||||||
|
export function dw2Build(ship, tier, engineeringLevel, role, gfsb, gpp, fighter) {
|
||||||
|
ship
|
||||||
|
.emptyInternal()
|
||||||
|
.emptyHardpoints()
|
||||||
|
.emptyUtility();
|
||||||
|
const fsd = ModuleUtils.findStandard('fsd', ship.standard[2].maxClass, 'A');
|
||||||
|
ship.use(ship.standard[2], fsd);
|
||||||
|
ship.use(ship.standard[3], ModuleUtils.findStandard('ls', ship.standard[3].maxClass, 'D'));
|
||||||
|
ship.use(ship.standard[4], ModuleUtils.findStandard('pd', 1, 'D'));
|
||||||
|
ship.use(ship.standard[5], ModuleUtils.findStandard('s', ship.standard[5].maxClass, 'D'));
|
||||||
|
const fuelNeeded = ship.standard[2].m.maxfuel * 2;
|
||||||
|
const fuelTank = ship.availCS.standard[6]
|
||||||
|
.filter(e => e.fuel)
|
||||||
|
.filter(e => e.fuel >= fuelNeeded);
|
||||||
|
ship.use(ship.standard[6], fuelTank[0]);
|
||||||
|
ship.useBulkhead(0, false);
|
||||||
|
if (engineeringLevel === 2) {
|
||||||
|
const bp = getBlueprint('FSD_LongRange', ship.standard[2]);
|
||||||
|
bp.grade = 5;
|
||||||
|
bp.special = Modifications.specials['special_fsd_heavy'];
|
||||||
|
ship.standard[2].m.blueprint = bp;
|
||||||
|
setPercent(ship, ship.standard[2].m, 100);
|
||||||
|
// Sensors G3 LW
|
||||||
|
const sBP = getBlueprint('Sensor_Sensor_LightWeight', ship.standard[5]);
|
||||||
|
sBP.grade = 3;
|
||||||
|
ship.standard[5].m.blueprint = sBP;
|
||||||
|
setPercent(ship, ship.standard[5].m, 100);
|
||||||
|
} else if (engineeringLevel === 3) {
|
||||||
|
// Armour G5 HD + Deep Plating
|
||||||
|
const armourBP = getBlueprint('Armour_HeavyDuty', ship.bulkheads);
|
||||||
|
armourBP.grade = 5;
|
||||||
|
armourBP.special = Modifications.specials['special_armour_chunky'];
|
||||||
|
ship.bulkheads.m.blueprint = armourBP;
|
||||||
|
setPercent(ship, ship.bulkheads.m, 100);
|
||||||
|
// FSD G5 IR + Mass Manager
|
||||||
|
const fsdBP = getBlueprint('FSD_LongRange', ship.standard[2]);
|
||||||
|
fsdBP.grade = 5;
|
||||||
|
fsdBP.special = Modifications.specials['special_fsd_heavy'];
|
||||||
|
ship.standard[2].m.blueprint = fsdBP;
|
||||||
|
setPercent(ship, ship.standard[2].m, 100);
|
||||||
|
// LS G4 LW
|
||||||
|
const lsBP = getBlueprint('LifeSupport_LightWeight', ship.standard[3]);
|
||||||
|
lsBP.grade = 4;
|
||||||
|
ship.standard[3].m.blueprint = lsBP;
|
||||||
|
setPercent(ship, ship.standard[3].m, 100);
|
||||||
|
// Sensors G5 LW
|
||||||
|
const sBP = getBlueprint('Sensor_Sensor_LightWeight', ship.standard[5]);
|
||||||
|
sBP.grade = 5;
|
||||||
|
ship.standard[5].m.blueprint = sBP;
|
||||||
|
setPercent(ship, ship.standard[5].m, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ship.id === 'imperial_clipper') {
|
||||||
|
const fs = ModuleUtils.findInternal('fs', 4, 'A');
|
||||||
|
const slot = ship.internal.filter(a => a.maxClass === 4)[0];
|
||||||
|
ship.use(slot, fs);
|
||||||
|
} else if (ship.id === 'imperial_cutter') {
|
||||||
|
const fs = ModuleUtils.findInternal('fs', 6, 'A');
|
||||||
|
const slot = ship.internal.filter(a => a.maxClass === 6)[0];
|
||||||
|
ship.use(slot, fs);
|
||||||
|
} else if (fsd.class === 2 && fsd.rating === 'A') {
|
||||||
|
let fs = ModuleUtils.findInternal('fs', 2, 'A');
|
||||||
|
let slot = ship.internal.filter(a => a.maxClass >= 2).filter(a => a.maxClass >= fs.class)
|
||||||
|
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))
|
||||||
|
[0];
|
||||||
|
if (slot.m) {
|
||||||
|
fs = ModuleUtils.findInternal('fs', 1, 'A');
|
||||||
|
slot = ship.internal.filter(a => a.maxClass === 1)[0];
|
||||||
|
ship.use(slot, fs);
|
||||||
|
} else {
|
||||||
|
ship.use(slot, fs);
|
||||||
|
}
|
||||||
|
} else if (fsd.class === 3 && fsd.rating === 'A') {
|
||||||
|
let fs = ModuleUtils.findInternal('fs', 3, 'B');
|
||||||
|
let slot = ship.internal.filter(a => a.maxClass >= 3).filter(a => a.maxClass >= fs.class)
|
||||||
|
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))
|
||||||
|
[0];
|
||||||
|
if (slot.m) {
|
||||||
|
fs = ModuleUtils.findInternal('fs', 2, 'A');
|
||||||
|
slot = ship.internal.filter(a => a.maxClass === 2)[0];
|
||||||
|
ship.use(slot, fs);
|
||||||
|
} else {
|
||||||
|
ship.use(slot, fs);
|
||||||
|
}
|
||||||
|
} else if (fsd.class === 4 && fsd.rating === 'A') {
|
||||||
|
let fs = ModuleUtils.findInternal('fs', 4, 'b');
|
||||||
|
let slot = ship.internal.filter(a => a.maxClass >= 4).filter(a => a.maxClass >= fs.class)
|
||||||
|
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))
|
||||||
|
[0];
|
||||||
|
if (slot.m) {
|
||||||
|
fs = ModuleUtils.findInternal('fs', 3, 'A');
|
||||||
|
slot = ship.internal.filter(a => a.maxClass === 3)[0];
|
||||||
|
ship.use(slot, fs);
|
||||||
|
} else {
|
||||||
|
ship.use(slot, fs);
|
||||||
|
}
|
||||||
|
} else if (fsd.class === 5 && fsd.rating === 'A') {
|
||||||
|
let fs = ModuleUtils.findInternal('fs', 5, 'B');
|
||||||
|
let slot = ship.internal.filter(a => a.maxClass >= 5).filter(a => a.maxClass >= fs.class)
|
||||||
|
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))
|
||||||
|
[0];
|
||||||
|
if (slot.m) {
|
||||||
|
fs = ModuleUtils.findInternal('fs', 4, 'A');
|
||||||
|
slot = ship.internal.filter(a => a.maxClass === 4).filter(a => a.maxClass >= fs.class)
|
||||||
|
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))
|
||||||
|
[0];
|
||||||
|
if (fs) {
|
||||||
|
ship.use(slot, fs);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (fs) {
|
||||||
|
ship.use(slot, fs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (fsd.class === 6 && fsd.rating === 'A') {
|
||||||
|
let fs = ModuleUtils.findInternal('fs', 6, 'B');
|
||||||
|
let slot = ship.internal.filter(a => a.maxClass >= 6)
|
||||||
|
.filter(a => a.maxClass >= fs.class)
|
||||||
|
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))
|
||||||
|
[0];
|
||||||
|
if (slot.m) {
|
||||||
|
fs = ModuleUtils.findInternal('fs', 5, 'A');
|
||||||
|
slot = ship.internal.filter(a => a.maxClass === 5)[0];
|
||||||
|
if (fs) {
|
||||||
|
ship.use(slot, fs);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (fs) {
|
||||||
|
ship.use(slot, fs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (fsd.class === 7 && fsd.rating === 'A') {
|
||||||
|
let fs = ModuleUtils.findInternal('fs', 7, 'B');
|
||||||
|
let slot = ship.internal.filter(a => a.maxClass >= 7).filter(a => a.maxClass >= fs.class)
|
||||||
|
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))
|
||||||
|
[0];
|
||||||
|
if (slot && slot.m) {
|
||||||
|
fs = ModuleUtils.findInternal('fs', 6, 'A');
|
||||||
|
slot = ship.internal.filter(a => a.maxClass === 6)[0];
|
||||||
|
if (fs) {
|
||||||
|
ship.use(slot, fs);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (fs) {
|
||||||
|
ship.use(slot, fs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tier !== 1) {
|
||||||
|
const fuelNeeded = ship.standard[2].m.maxfuel * 3;
|
||||||
|
const fuelTank = ship.availCS.standard[6]
|
||||||
|
.filter(e => e.fuel)
|
||||||
|
.filter(e => e.fuel >= fuelNeeded);
|
||||||
|
if (fuelTank[0]) {
|
||||||
|
ship.use(ship.standard[6], fuelTank[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tier === 2) {
|
||||||
|
if (ship.id === 'alliance_chieftain' || ship.id === 'alliance_crusader' || ship.id === 'federal_gunship' || ship.id === 'vulture') {
|
||||||
|
const hrp = ModuleUtils.findInternal('hrp', 3, 'D');
|
||||||
|
const slot = ship.internal.filter(e => e.eligible && e.maxClass === 3);
|
||||||
|
if (hrp) {
|
||||||
|
ship.use(slot, hrp);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const sg = ship.getAvailableModules().lightestShieldGenerator(ship.ladenMass);
|
||||||
|
const slot = ship.internal.filter(a => !a.m)
|
||||||
|
.filter(a => a.maxClass >= sg.class)
|
||||||
|
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))
|
||||||
|
[0];
|
||||||
|
if (sg) {
|
||||||
|
ship.use(slot, sg);
|
||||||
|
}
|
||||||
|
if (engineeringLevel === 2) {
|
||||||
|
// ELP G3
|
||||||
|
const shieldBP = getBlueprint('ShieldGenerator_Optimised', ship.findShieldGenerator());
|
||||||
|
shieldBP.grade = 3;
|
||||||
|
ship.findShieldGenerator().blueprint = shieldBP;
|
||||||
|
setPercent(ship, ship.findShieldGenerator(), 100);
|
||||||
|
} else if (engineeringLevel === 3) {
|
||||||
|
// ELP G5
|
||||||
|
const shieldBP = getBlueprint('ShieldGenerator_Optimised', ship.findShieldGenerator());
|
||||||
|
shieldBP.grade = 5;
|
||||||
|
ship.findShieldGenerator().blueprint = shieldBP;
|
||||||
|
setPercent(ship, ship.findShieldGenerator(), 100);
|
||||||
|
}
|
||||||
|
// const shieldOrder = [1, 2, 3, 4, 5, 6, 7, 8].reverse();
|
||||||
|
// const shieldInternals = ship.internal.filter(a => !a.m)
|
||||||
|
// .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);
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
} else if (tier === 3 || tier === 4) {
|
||||||
|
const sg = ship.getAvailableModules().lightestShieldGenerator(ship.hullMass, 'A');
|
||||||
|
const slot = ship.internal.filter(a => !a.m)
|
||||||
|
.filter(a => a.maxClass >= sg.class)
|
||||||
|
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))
|
||||||
|
[0];
|
||||||
|
if (sg) {
|
||||||
|
ship.use(slot, sg);
|
||||||
|
}
|
||||||
|
if (engineeringLevel === 1) {
|
||||||
|
// ELP G3
|
||||||
|
const shieldBP = getBlueprint('ShieldGenerator_Optimised', ship.findShieldGenerator());
|
||||||
|
shieldBP.grade = 3;
|
||||||
|
shieldBP.special = Modifications.specials['special_shield_lightweight'];
|
||||||
|
ship.findShieldGenerator().blueprint = shieldBP;
|
||||||
|
setPercent(ship, ship.findShieldGenerator(), 100);
|
||||||
|
} else if (engineeringLevel === 2) {
|
||||||
|
// ELP G5
|
||||||
|
const shieldBP = getBlueprint('ShieldGenerator_Optimised', ship.findShieldGenerator());
|
||||||
|
shieldBP.grade = 5;
|
||||||
|
shieldBP.special = Modifications.specials['special_shield_lightweight'];
|
||||||
|
ship.findShieldGenerator().blueprint = shieldBP;
|
||||||
|
setPercent(ship, ship.findShieldGenerator(), 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tier === 4) {
|
||||||
|
let t;
|
||||||
|
if (canMount(ship, ship.standard[1], 't', ship.standard[1].maxClass - 1)) {
|
||||||
|
t = ModuleUtils.findStandard('t', ship.standard[1].maxClass - 1, 'A');
|
||||||
|
} else {
|
||||||
|
t = ModuleUtils.findStandard('t', ship.standard[1].maxClass, 'A');
|
||||||
|
}
|
||||||
|
if (t) {
|
||||||
|
ship.use(ship.standard[1], t);
|
||||||
|
}
|
||||||
|
if (engineeringLevel === 1) {
|
||||||
|
// DD G3
|
||||||
|
const tBP = getBlueprint('Engine_Dirty', ship.standard[1]);
|
||||||
|
tBP.grade = 3;
|
||||||
|
tBP.special = Modifications.specials['special_engine_lightweight'];
|
||||||
|
ship.standard[1].m.blueprint = tBP;
|
||||||
|
setPercent(ship, ship.standard[1].m, 100);
|
||||||
|
} else if (engineeringLevel === 2) {
|
||||||
|
// DD G5
|
||||||
|
const tBP = getBlueprint('Engine_Dirty', ship.standard[1]);
|
||||||
|
tBP.grade = 5;
|
||||||
|
tBP.special = Modifications.specials['special_engine_lightweight'];
|
||||||
|
ship.standard[1].m.blueprint = tBP;
|
||||||
|
setPercent(ship, ship.standard[1].m, 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tier === 4 || tier === 3) {
|
||||||
|
if (engineeringLevel === 3) {
|
||||||
|
const pd = ship.availCS.standard[4]
|
||||||
|
.filter(d => d.rating === 'D')
|
||||||
|
.filter(d => (d.engcap * 1.728) >= ship.boostEnergy)
|
||||||
|
.sort((a, b) => a.class.toString().localeCompare(b.class.toString()))[0];
|
||||||
|
if (pd) {
|
||||||
|
ship.use(ship.standard[4], pd);
|
||||||
|
}
|
||||||
|
// CE G5
|
||||||
|
const pdBP = getBlueprint('PowerDistributor_HighFrequency', ship.standard[4]);
|
||||||
|
pdBP.grade = 5;
|
||||||
|
pdBP.special = Modifications.specials['special_powerdistributor_capacity'];
|
||||||
|
ship.standard[4].m.blueprint = pdBP;
|
||||||
|
setPercent(ship, ship.standard[4].m, 100);
|
||||||
|
} else {
|
||||||
|
const pd = ship.availCS.standard[4]
|
||||||
|
.filter(d => d.rating === 'D')
|
||||||
|
.sort((a, b) => a.engcap > b.engcap)
|
||||||
|
[0];
|
||||||
|
if (pd) {
|
||||||
|
ship.use(ship.standard[4], pd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (tier === 4) {
|
||||||
|
if (engineeringLevel === 3) {
|
||||||
|
const pd = ship.availCS.standard[4]
|
||||||
|
.filter(d => d.rating === 'D')
|
||||||
|
.sort((a, b) => b.class.toString().localeCompare(a.class.toString()))[0];
|
||||||
|
if (pd) {
|
||||||
|
ship.use(ship.standard[4], pd);
|
||||||
|
}
|
||||||
|
// CE G5
|
||||||
|
const pdBP = getBlueprint('PowerDistributor_HighFrequency', ship.standard[4]);
|
||||||
|
pdBP.grade = 5;
|
||||||
|
pdBP.special = Modifications.specials['special_powerdistributor_capacity'];
|
||||||
|
ship.standard[4].m.blueprint = pdBP;
|
||||||
|
setPercent(ship, ship.standard[4].m, 100);
|
||||||
|
} else {
|
||||||
|
const pd = ship.availCS.standard[4]
|
||||||
|
.filter(d => d.rating === 'D')
|
||||||
|
.sort((a, b) => b.class.toString().localeCompare(a.class.toString()))[0];
|
||||||
|
if (pd) {
|
||||||
|
ship.use(ship.standard[4], pd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ship.fighterHangars && fighter) {
|
||||||
|
const slot = ship.internal.filter(s => s.maxClass >= 5 && !s.m)
|
||||||
|
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))
|
||||||
|
[0];
|
||||||
|
const mod = ModuleUtils.findInternal('fh', 5, 'D');
|
||||||
|
if (slot && mod) {
|
||||||
|
ship.use(slot, mod);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tier === 1) {
|
||||||
|
const pd = ModuleUtils.findStandard('pd', 1, 'D');
|
||||||
|
if (pd) {
|
||||||
|
ship.use(ship.standard[4]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let dssPriority = 0;
|
||||||
|
let srvPriority = 0;
|
||||||
|
let afmu = true;
|
||||||
|
let cargo = false;
|
||||||
|
let miningLaserPriority = 0;
|
||||||
|
let refinery = false;
|
||||||
|
let collector = false;
|
||||||
|
let prospector = false;
|
||||||
|
let miningTools = false;
|
||||||
|
let refuelLimpets = false;
|
||||||
|
let repairLimpets = false;
|
||||||
|
console.log(role);
|
||||||
|
if (role === 'exploration') {
|
||||||
|
dssPriority = 2;
|
||||||
|
afmu = true;
|
||||||
|
} else if (role === 'surface') {
|
||||||
|
dssPriority = 2;
|
||||||
|
srvPriority = 2;
|
||||||
|
} else if (role === 'materialProspector') {
|
||||||
|
miningLaserPriority = 2;
|
||||||
|
srvPriority = 1;
|
||||||
|
} else if (role === 'propectorMining') {
|
||||||
|
dssPriority = 1;
|
||||||
|
prospector = true;
|
||||||
|
miningLaserPriority = 1;
|
||||||
|
cargo = true;
|
||||||
|
miningTools = true;
|
||||||
|
|
||||||
|
} else if (role === 'bigRigMining') {
|
||||||
|
dssPriority = 1;
|
||||||
|
miningLaserPriority = 2;
|
||||||
|
cargo = true;
|
||||||
|
collector = true;
|
||||||
|
refinery = true;
|
||||||
|
miningTools = true;
|
||||||
|
|
||||||
|
} else if (role === 'fuelRat') {
|
||||||
|
refuelLimpets = true;
|
||||||
|
cargo = true;
|
||||||
|
srvPriority = 1;
|
||||||
|
|
||||||
|
} else if (role === 'mechanic') {
|
||||||
|
repairLimpets = true;
|
||||||
|
cargo = true;
|
||||||
|
srvPriority = 1;
|
||||||
|
} else if (role === 'trucker') {
|
||||||
|
cargo = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dssPriority === 2) {
|
||||||
|
const mod = ModuleUtils.findModule('ss', '2i');
|
||||||
|
const slot = ship.internal.filter(s => !s.m)
|
||||||
|
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))[0];
|
||||||
|
console.log(slot);
|
||||||
|
console.log(mod);
|
||||||
|
ship.use(slot, mod);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (srvPriority === 2) {
|
||||||
|
let mod;
|
||||||
|
let slot = ship.internal.filter(s => !s.m)
|
||||||
|
.filter(s => s.maxClass >= 6)
|
||||||
|
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))[0];
|
||||||
|
if (slot) {
|
||||||
|
mod = ModuleUtils.findModule('pv', 'v2');
|
||||||
|
ship.use(slot, mod);
|
||||||
|
} else if (!slot) {
|
||||||
|
slot = ship.internal.filter(s => !s.m)
|
||||||
|
.filter(s => s.maxClass >= 4)
|
||||||
|
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))[0];
|
||||||
|
if (slot) {
|
||||||
|
mod = ModuleUtils.findModule('pv', 'v4');
|
||||||
|
ship.use(slot, mod);
|
||||||
|
} else {
|
||||||
|
slot = ship.internal.filter(s => !s.m)
|
||||||
|
.filter(s => s.maxClass >= 2)
|
||||||
|
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))[0];
|
||||||
|
if (slot) {
|
||||||
|
mod = ModuleUtils.findModule('pv', 'v6');
|
||||||
|
ship.use(slot, mod);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cargo === true) {
|
||||||
|
const slot = ship.internal.filter(s => !s.m)
|
||||||
|
.sort((a, b) => b.maxClass.toString().localeCompare(a.maxClass.toString()))[0];
|
||||||
|
const mod = ModuleUtils.findInternal('cr', slot.maxClass, 'E');
|
||||||
|
ship.use(slot, mod);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (refuelLimpets === true) {
|
||||||
|
const mod = ModuleUtils.findModule('fx', 'F4');
|
||||||
|
const slot = ship.internal.filter(s => !s.m)
|
||||||
|
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))[0];
|
||||||
|
ship.use(mod, slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (repairLimpets === true) {
|
||||||
|
const slot = ship.internal.filter(s => !s.m)
|
||||||
|
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))[0];
|
||||||
|
let mod;
|
||||||
|
if (slot.maxClass >= 3) {
|
||||||
|
mod = ModuleUtils.findModule('rpl', '9e');
|
||||||
|
} else {
|
||||||
|
mod = ModuleUtils.findModule('rpl', '9s');
|
||||||
|
}
|
||||||
|
ship.use(mod, slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prospector === true) {
|
||||||
|
const slot = ship.internal.filter(s => !s.m)
|
||||||
|
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))[0];
|
||||||
|
let mod;
|
||||||
|
if (slot.maxClass >= 3) {
|
||||||
|
mod = ModuleUtils.findModule('pc', 'P9');
|
||||||
|
} else {
|
||||||
|
mod = ModuleUtils.findModule('pc', 'P4');
|
||||||
|
}
|
||||||
|
ship.use(mod, slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (collector === true) {
|
||||||
|
const slots = ship.internal.filter(s => !s.m)
|
||||||
|
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()));
|
||||||
|
if (slots.length >= 2) {
|
||||||
|
let slot = slots.find(s => s.maxClass >= 5);
|
||||||
|
let mod;
|
||||||
|
if (slot) {
|
||||||
|
mod = ModuleUtils.findInternal('cc', slot.maxClass, 'D');
|
||||||
|
} else if (slots.find(s => s.maxClass <= 4)) {
|
||||||
|
slot = slots.find(s => s.maxClass <= 4);
|
||||||
|
mod = ModuleUtils.findInternal('cc', slot.maxClass, 'D');
|
||||||
|
}
|
||||||
|
ship.use(slot, mod);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (refinery === true) {
|
||||||
|
const slots = ship.internal.filter(s => !s.m)
|
||||||
|
.filter(s => s.maxClass >= 4)
|
||||||
|
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))[0];
|
||||||
|
if (slots) {
|
||||||
|
const mod = ModuleUtils.findInternal('rf', 4, 'A');
|
||||||
|
ship.use(slots, mod);
|
||||||
|
} else {
|
||||||
|
const slot = ship.internal.filter(s => !s.m)
|
||||||
|
.filter(s => s.maxClass <= 3)
|
||||||
|
.sort((a, b) => b.maxClass.toString().localeCompare(a.maxClass.toString()))[0];
|
||||||
|
const mod = ModuleUtils.findInternal('rf', slot.maxClass, 'A');
|
||||||
|
ship.use(slots, mod);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dssPriority === 1) {
|
||||||
|
const slot = ship.internal.filter(s => !s.m)
|
||||||
|
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))[0];
|
||||||
|
const dss = ModuleUtils.findInternal('ss', 1, 'C')
|
||||||
|
if (slot) {
|
||||||
|
ship.use(slot, dss);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (srvPriority === 1) {
|
||||||
|
const slot = ship.internal.filter(s => !s.m)
|
||||||
|
.filter(s => s.maxClass >= 2)
|
||||||
|
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()));
|
||||||
|
if (slot.find(s => s.maxClass >= 4)) {
|
||||||
|
const slot = slot.find(s => s.maxClass >= 4);
|
||||||
|
const srv = ModuleUtils.findInternal('pv', 4, 'G')
|
||||||
|
ship.use(slot, srv);
|
||||||
|
} else if (slot.find(s => s.maxClass >= 2)) {
|
||||||
|
const slot = slot.find(s => s.maxClass >= 2);
|
||||||
|
const srv = ModuleUtils.findInternal('pv', 2, 'G')
|
||||||
|
ship.use(slot, srv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gfsb === true) {
|
||||||
|
const slots = ship.internal.filter(s => !s.m)
|
||||||
|
.filter(s => s.maxClass >= 1)
|
||||||
|
.sort((a, b) => b.maxClass.toString().localeCompare(a.maxClass.toString()));
|
||||||
|
if (slots.find(s => s.maxClass >= 5)) {
|
||||||
|
const mod = ModuleUtils.findInternal('gfsb', 5, 'H');
|
||||||
|
ship.use(slots.find(s => s.maxClass >= 5), mod)
|
||||||
|
} else if (slots.find(s => s.maxClass >= 4)) {
|
||||||
|
const mod = ModuleUtils.findInternal('gfsb', 4, 'H');
|
||||||
|
ship.use(slots.find(s => s.maxClass >= 4), mod)
|
||||||
|
} else if (slots.find(s => s.maxClass >= 3)) {
|
||||||
|
const mod = ModuleUtils.findInternal('gfsb', 3, 'H');
|
||||||
|
ship.use(slots.find(s => s.maxClass >= 3), mod)
|
||||||
|
} else if (slots.find(s => s.maxClass >= 2)) {
|
||||||
|
const mod = ModuleUtils.findInternal('gfsb', 2, 'H');
|
||||||
|
ship.use(slots.find(s => s.maxClass >= 2), mod)
|
||||||
|
} else if (slots.find(s => s.maxClass >= 1)) {
|
||||||
|
const mod = ModuleUtils.findInternal('gfsb', 1, 'H');
|
||||||
|
ship.use(slots.find(s => s.maxClass >= 1), mod)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// const pp = ship.getAvailableModules().lightestPowerPlant(Math.max(ship.powerRetracted, ship.powerDeployed), 'A');
|
||||||
|
// const t = ship.getAvailableModules().lightestThruster(ship.ladenMass);
|
||||||
|
// ship.use(ship.standard[0], pp);
|
||||||
|
// ship.use(ship.standard[1], t);
|
||||||
|
|
||||||
|
// ship.useLightestStandard(standardOpts);
|
||||||
|
ship.updatePowerGenerated()
|
||||||
|
.updatePowerUsed()
|
||||||
|
.recalculateMass()
|
||||||
|
.updateJumpStats()
|
||||||
|
.recalculateShield()
|
||||||
|
.recalculateShieldCells()
|
||||||
|
.recalculateArmour()
|
||||||
|
.recalculateDps()
|
||||||
|
.recalculateEps()
|
||||||
|
.recalculateHps()
|
||||||
|
.updateMovement()
|
||||||
|
.updateModificationsString();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Trader Role
|
* Trader Role
|
||||||
* @param {Ship} ship Ship instance
|
* @param {Ship} ship Ship instance
|
||||||
@@ -36,7 +609,7 @@ export function trader(ship, shielded, standardOpts) {
|
|||||||
let sg = ship.getAvailableModules().lightestShieldGenerator(ship.hullMass);
|
let sg = ship.getAvailableModules().lightestShieldGenerator(ship.hullMass);
|
||||||
ship.useStandard('A')
|
ship.useStandard('A')
|
||||||
.use(ship.standard[3], ModuleUtils.standard(3, ship.standard[3].maxClass + 'D')) // D Life Support
|
.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[1], ModuleUtils.standard(1, ship.standard[1].maxClass + 'D')) // D Power Plant
|
||||||
.use(ship.standard[4], ModuleUtils.standard(4, ship.standard[4].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
|
.use(ship.standard[5], ModuleUtils.standard(5, ship.standard[5].maxClass + 'D')); // D Sensors
|
||||||
|
|
||||||
@@ -45,7 +618,7 @@ export function trader(ship, shielded, standardOpts) {
|
|||||||
.filter(a => (!a.eligible) || a.eligible.sg)
|
.filter(a => (!a.eligible) || a.eligible.sg)
|
||||||
.filter(a => a.maxClass >= sg.class)
|
.filter(a => a.maxClass >= sg.class)
|
||||||
.sort((a, b) => shieldOrder.indexOf(a.maxClass) - shieldOrder.indexOf(b.maxClass));
|
.sort((a, b) => shieldOrder.indexOf(a.maxClass) - shieldOrder.indexOf(b.maxClass));
|
||||||
shieldInternals.some(function(slot) {
|
shieldInternals.some(function (slot) {
|
||||||
if (canMount(ship, slot, 'sg')) { // Assuming largest slot can hold an eligible shield
|
if (canMount(ship, slot, 'sg')) { // Assuming largest slot can hold an eligible shield
|
||||||
const shield = ModuleUtils.findInternal('sg', slot.maxClass, 'A');
|
const shield = ModuleUtils.findInternal('sg', slot.maxClass, 'A');
|
||||||
if (shield && shield.maxmass > ship.hullMass) {
|
if (shield && shield.maxmass > ship.hullMass) {
|
||||||
@@ -87,11 +660,11 @@ export function trader(ship, shielded, standardOpts) {
|
|||||||
*/
|
*/
|
||||||
export function explorer(ship, planetary) {
|
export function explorer(ship, planetary) {
|
||||||
let standardOpts = { ppRating: 'A' },
|
let standardOpts = { ppRating: 'A' },
|
||||||
heatSinkCount = 2, // Fit 2 heat sinks if possible
|
heatSinkCount = 2, // Fit 2 heat sinks if possible
|
||||||
usedSlots = [],
|
usedSlots = [],
|
||||||
sgSlot,
|
sgSlot,
|
||||||
fuelScoopSlot,
|
fuelScoopSlot,
|
||||||
sg = ship.getAvailableModules().lightestShieldGenerator(ship.hullMass);
|
sg = ship.getAvailableModules().lightestShieldGenerator(ship.hullMass);
|
||||||
|
|
||||||
if (!planetary) { // Non-planetary explorers don't really need to boost
|
if (!planetary) { // Non-planetary explorers don't really need to boost
|
||||||
standardOpts.pd = '1D';
|
standardOpts.pd = '1D';
|
||||||
@@ -216,9 +789,9 @@ export function explorer(ship, planetary) {
|
|||||||
export function miner(ship, shielded) {
|
export function miner(ship, shielded) {
|
||||||
shielded = true;
|
shielded = true;
|
||||||
let standardOpts = { ppRating: 'A' },
|
let standardOpts = { ppRating: 'A' },
|
||||||
miningLaserCount = 2,
|
miningLaserCount = 2,
|
||||||
usedSlots = [],
|
usedSlots = [],
|
||||||
sg = ship.getAvailableModules().lightestShieldGenerator(ship.hullMass);
|
sg = ship.getAvailableModules().lightestShieldGenerator(ship.hullMass);
|
||||||
|
|
||||||
// Cargo hatch should be enabled
|
// Cargo hatch should be enabled
|
||||||
ship.setSlotEnabled(ship.cargoHatch, true);
|
ship.setSlotEnabled(ship.cargoHatch, true);
|
||||||
@@ -269,7 +842,7 @@ export function miner(ship, shielded) {
|
|||||||
|
|
||||||
// Dual mining lasers of highest possible class; remove anything else
|
// Dual mining lasers of highest possible class; remove anything else
|
||||||
const miningLaserOrder = [2, 3, 4, 1, 0];
|
const miningLaserOrder = [2, 3, 4, 1, 0];
|
||||||
const miningLaserHardpoints = ship.hardpoints.concat().sort(function(a, b) {
|
const miningLaserHardpoints = ship.hardpoints.concat().sort(function (a, b) {
|
||||||
return miningLaserOrder.indexOf(a.maxClass) - miningLaserOrder.indexOf(b.maxClass);
|
return miningLaserOrder.indexOf(a.maxClass) - miningLaserOrder.indexOf(b.maxClass);
|
||||||
});
|
});
|
||||||
for (let s of miningLaserHardpoints) {
|
for (let s of miningLaserHardpoints) {
|
||||||
@@ -283,7 +856,7 @@ export function miner(ship, shielded) {
|
|||||||
|
|
||||||
// Number of collector limpets required to be active is a function of the size of the ship and the power of the lasers
|
// 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)
|
const miningLaserDps = ship.hardpoints.filter(h => h.m != null)
|
||||||
.reduce(function(a, b) {
|
.reduce(function (a, b) {
|
||||||
return a + b.m.getDps();
|
return a + b.m.getDps();
|
||||||
}, 0);
|
}, 0);
|
||||||
// Find out how many internal slots we have, and their potential cargo size
|
// Find out how many internal slots we have, and their potential cargo size
|
||||||
@@ -314,7 +887,7 @@ export function miner(ship, shielded) {
|
|||||||
|
|
||||||
// Power distributor to power the mining lasers indefinitely
|
// Power distributor to power the mining lasers indefinitely
|
||||||
const wepRateRequired = ship.hardpoints.filter(h => h.m != null)
|
const wepRateRequired = ship.hardpoints.filter(h => h.m != null)
|
||||||
.reduce(function(a, b) {
|
.reduce(function (a, b) {
|
||||||
return a + b.m.getEps();
|
return a + b.m.getEps();
|
||||||
}, 0);
|
}, 0);
|
||||||
standardOpts.pd = ship.getAvailableModules().matchingPowerDist({ weprate: wepRateRequired }).id;
|
standardOpts.pd = ship.getAvailableModules().matchingPowerDist({ weprate: wepRateRequired }).id;
|
||||||
@@ -336,9 +909,9 @@ export function miner(ship, shielded) {
|
|||||||
*/
|
*/
|
||||||
export function racer(ship) {
|
export function racer(ship) {
|
||||||
let standardOpts = {},
|
let standardOpts = {},
|
||||||
usedSlots = [],
|
usedSlots = [],
|
||||||
sgSlot,
|
sgSlot,
|
||||||
sg = ship.getAvailableModules().lightestShieldGenerator(ship.hullMass);
|
sg = ship.getAvailableModules().lightestShieldGenerator(ship.hullMass);
|
||||||
|
|
||||||
// Cargo hatch can be disabled
|
// Cargo hatch can be disabled
|
||||||
ship.setSlotEnabled(ship.cargoHatch, false);
|
ship.setSlotEnabled(ship.cargoHatch, false);
|
||||||
|
|||||||
@@ -26,8 +26,8 @@ export const STATS_FORMATTING = {
|
|||||||
'ammo': { 'format': 'int', },
|
'ammo': { 'format': 'int', },
|
||||||
'boot': { 'format': 'int', 'unit': 'secs' },
|
'boot': { 'format': 'int', 'unit': 'secs' },
|
||||||
'brokenregen': { 'format': 'round1', 'unit': 'ps' },
|
'brokenregen': { 'format': 'round1', 'unit': 'ps' },
|
||||||
'burst': { 'format': 'int', 'change': 'additive' },
|
'burst': { 'format': 'int' },
|
||||||
'burstrof': { 'format': 'round1', 'unit': 'ps', 'change': 'additive' },
|
'burstrof': { 'format': 'round1', 'unit': 'ps' },
|
||||||
'causres': { 'format': 'pct' },
|
'causres': { 'format': 'pct' },
|
||||||
'clip': { 'format': 'int' },
|
'clip': { 'format': 'int' },
|
||||||
'damage': { 'format': 'round' },
|
'damage': { 'format': 'round' },
|
||||||
@@ -61,7 +61,7 @@ export const STATS_FORMATTING = {
|
|||||||
'ranget': { 'format': 'f1', 'unit': 's' },
|
'ranget': { 'format': 'f1', 'unit': 's' },
|
||||||
'regen': { 'format': 'round1', 'unit': 'ps' },
|
'regen': { 'format': 'round1', 'unit': 'ps' },
|
||||||
'reload': { 'format': 'int', 'unit': 's' },
|
'reload': { 'format': 'int', 'unit': 's' },
|
||||||
'rof': { 'format': 'round1', 'unit': 'ps', 'synthetic': 'getRoF', 'higherbetter': true },
|
'rof': { 'format': 'round1', 'unit': 'ps' },
|
||||||
'angle': { 'format': 'round1', 'unit': 'ang' },
|
'angle': { 'format': 'round1', 'unit': 'ang' },
|
||||||
'scanrate': { 'format': 'int' },
|
'scanrate': { 'format': 'int' },
|
||||||
'scantime': { 'format': 'round1', 'unit': 's' },
|
'scantime': { 'format': 'round1', 'unit': 's' },
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ const LS_KEY_SIZE_RATIO = 'sizeRatio';
|
|||||||
const LS_KEY_TOOLTIPS = 'tooltips';
|
const LS_KEY_TOOLTIPS = 'tooltips';
|
||||||
const LS_KEY_MODULE_RESISTANCES = 'moduleResistances';
|
const LS_KEY_MODULE_RESISTANCES = 'moduleResistances';
|
||||||
const LS_KEY_ROLLS = 'matsPerGrade';
|
const LS_KEY_ROLLS = 'matsPerGrade';
|
||||||
|
const LS_KEY_ORBIS = 'orbis';
|
||||||
|
|
||||||
let LS;
|
let LS;
|
||||||
|
|
||||||
@@ -94,6 +95,7 @@ export class Persist extends EventEmitter {
|
|||||||
let buildJson = _get(LS_KEY_BUILDS);
|
let buildJson = _get(LS_KEY_BUILDS);
|
||||||
let comparisonJson = _get(LS_KEY_COMPARISONS);
|
let comparisonJson = _get(LS_KEY_COMPARISONS);
|
||||||
|
|
||||||
|
this.orbisCreds = _get(LS_KEY_ORBIS) || { email: '', password: '' };
|
||||||
this.onStorageChange = this.onStorageChange.bind(this);
|
this.onStorageChange = this.onStorageChange.bind(this);
|
||||||
this.langCode = _getString(LS_KEY_LANG) || 'en';
|
this.langCode = _getString(LS_KEY_LANG) || 'en';
|
||||||
this.insurance = insurance && Insurance[insurance.toLowerCase()] !== undefined ? insurance : 'standard';
|
this.insurance = insurance && Insurance[insurance.toLowerCase()] !== undefined ? insurance : 'standard';
|
||||||
@@ -167,6 +169,10 @@ export class Persist extends EventEmitter {
|
|||||||
this.matsPerGrade = JSON.parse(newValue);
|
this.matsPerGrade = JSON.parse(newValue);
|
||||||
this.emit('matsPerGrade', this.matsPerGrade);
|
this.emit('matsPerGrade', this.matsPerGrade);
|
||||||
break;
|
break;
|
||||||
|
case LS_KEY_ORBIS:
|
||||||
|
this.orbisCreds = JSON.parse(newValue);
|
||||||
|
this.emit('orbis', this.orbisCreds);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// On JSON.Parse Error - don't sync or do anything
|
// On JSON.Parse Error - don't sync or do anything
|
||||||
@@ -192,6 +198,24 @@ export class Persist extends EventEmitter {
|
|||||||
this.emit('language', langCode);
|
this.emit('language', langCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current orbis.zone credentials
|
||||||
|
* @return {String} language code
|
||||||
|
*/
|
||||||
|
getOrbisCreds() {
|
||||||
|
return this.orbisCreds;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update and save the orbis.zone credentials
|
||||||
|
* @param {Object} creds object with username and password properties.
|
||||||
|
*/
|
||||||
|
setOrbisCreds(creds) {
|
||||||
|
this.langCode = creds;
|
||||||
|
_put(LS_KEY_ORBIS, creds);
|
||||||
|
this.emit('orbis', creds);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show tooltips setting
|
* Show tooltips setting
|
||||||
* @param {boolean} show Optional - update setting
|
* @param {boolean} show Optional - update setting
|
||||||
|
|||||||
@@ -1,435 +1,417 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Modifications } from 'coriolis-data/dist';
|
import { Modifications } from 'coriolis-data/dist';
|
||||||
import { STATS_FORMATTING } from '../shipyard/StatsFormatting';
|
|
||||||
|
/**
|
||||||
/**
|
* Generate a tooltip with details of a blueprint's specials
|
||||||
* Generate a tooltip with details of a blueprint's specials
|
* @param {Object} translate The translate object
|
||||||
* @param {Object} translate The translate object
|
* @param {Object} blueprint The blueprint at the required grade
|
||||||
* @param {Object} blueprint The blueprint at the required grade
|
* @param {string} grp The group of the module
|
||||||
* @param {string} grp The group of the module
|
* @param {Object} m The module to compare with
|
||||||
* @param {Object} m The module to compare with
|
* @param {string} specialName The name of the special
|
||||||
* @param {string} specialName The name of the special
|
* @returns {Object} The react components
|
||||||
* @returns {Object} The react components
|
*/
|
||||||
*/
|
export function specialToolTip(translate, blueprint, grp, m, specialName) {
|
||||||
export function specialToolTip(translate, blueprint, grp, m, specialName) {
|
const effects = [];
|
||||||
const effects = [];
|
if (!blueprint || !blueprint.features) {
|
||||||
if (!blueprint || !blueprint.features) {
|
return undefined;
|
||||||
return undefined;
|
}
|
||||||
}
|
if (m) {
|
||||||
if (m) {
|
// We also add in any benefits from specials that aren't covered above
|
||||||
// We also add in any benefits from specials that aren't covered above
|
if (m.blueprint) {
|
||||||
if (m.blueprint) {
|
for (const feature in Modifications.modifierActions[specialName]) {
|
||||||
for (const feature in Modifications.modifierActions[specialName]) {
|
// if (!blueprint.features[feature] && !m.mods.feature) {
|
||||||
// if (!blueprint.features[feature] && !m.mods.feature) {
|
const featureDef = Modifications.modifications[feature];
|
||||||
const featureDef = Modifications.modifications[feature];
|
if (featureDef && !featureDef.hidden) {
|
||||||
if (featureDef && !featureDef.hidden) {
|
let symbol = '';
|
||||||
let symbol = '';
|
if (feature === 'jitter') {
|
||||||
if (feature === 'jitter') {
|
symbol = '°';
|
||||||
symbol = '°';
|
} else if (featureDef.type === 'percentage') {
|
||||||
} else if (featureDef.type === 'percentage') {
|
symbol = '%';
|
||||||
symbol = '%';
|
}
|
||||||
}
|
let current = m.getModValue(feature) - m.getModValue(feature, true);
|
||||||
let current = m.getModValue(feature) - m.getModValue(feature, true);
|
if (featureDef.type === 'percentage') {
|
||||||
if (featureDef.type === 'percentage') {
|
current = Math.round(current / 10) / 10;
|
||||||
current = Math.round(current / 10) / 10;
|
} else if (featureDef.type === 'numeric') {
|
||||||
} else if (featureDef.type === 'numeric') {
|
current /= 100;
|
||||||
current /= 100;
|
}
|
||||||
}
|
const currentIsBeneficial = isValueBeneficial(feature, current);
|
||||||
const currentIsBeneficial = isValueBeneficial(feature, current);
|
|
||||||
|
effects.push(
|
||||||
effects.push(
|
<tr key={feature + '_specialTT'}>
|
||||||
<tr key={feature + '_specialTT'}>
|
<td style={{ textAlign: 'left' }}>{translate(feature, grp)}</td>
|
||||||
<td style={{ textAlign: 'left' }}>{translate(feature, grp)}</td>
|
<td> </td>
|
||||||
<td> </td>
|
<td className={current === 0 ? '' : currentIsBeneficial ? 'secondary' : 'warning'}
|
||||||
<td className={current === 0 ? '' : currentIsBeneficial ? 'secondary' : 'warning'}
|
style={{ textAlign: 'right' }}>{current}{symbol}</td>
|
||||||
style={{ textAlign: 'right' }}>{current}{symbol}</td>
|
<td> </td>
|
||||||
<td> </td>
|
</tr>
|
||||||
</tr>
|
);
|
||||||
);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
return (
|
||||||
return (
|
<div>
|
||||||
<div>
|
<table width='100%'>
|
||||||
<table width='100%'>
|
<tbody>
|
||||||
<tbody>
|
{effects}
|
||||||
{effects}
|
</tbody>
|
||||||
</tbody>
|
</table>
|
||||||
</table>
|
</div>
|
||||||
</div>
|
);
|
||||||
);
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
/**
|
* Generate a tooltip with details of a blueprint's effects
|
||||||
* Generate a tooltip with details of a blueprint's effects
|
* @param {Object} translate The translate object
|
||||||
* @param {Object} translate The translate object
|
* @param {Object} blueprint The blueprint at the required grade
|
||||||
* @param {Object} blueprint The blueprint at the required grade
|
* @param {Array} engineers The engineers supplying this blueprint
|
||||||
* @param {Array} engineers The engineers supplying this blueprint
|
* @param {string} grp The group of the module
|
||||||
* @param {string} grp The group of the module
|
* @param {Object} m The module to compare with
|
||||||
* @param {Object} m The module to compare with
|
* @returns {Object} The react components
|
||||||
* @returns {Object} The react components
|
*/
|
||||||
*/
|
export function blueprintTooltip(translate, blueprint, engineers, grp, m) {
|
||||||
export function blueprintTooltip(translate, blueprint, engineers, grp, m) {
|
const effects = [];
|
||||||
const effects = [];
|
if (!blueprint || !blueprint.features) {
|
||||||
if (!blueprint || !blueprint.features) {
|
return undefined;
|
||||||
return undefined;
|
}
|
||||||
}
|
for (const feature in blueprint.features) {
|
||||||
for (const feature in blueprint.features) {
|
const featureIsBeneficial = isBeneficial(feature, blueprint.features[feature]);
|
||||||
const featureIsBeneficial = isBeneficial(feature, blueprint.features[feature]);
|
const featureDef = Modifications.modifications[feature];
|
||||||
const featureDef = Modifications.modifications[feature];
|
if (!featureDef.hidden) {
|
||||||
if (!featureDef.hidden) {
|
let symbol = '';
|
||||||
let symbol = '';
|
if (feature === 'jitter') {
|
||||||
if (feature === 'jitter') {
|
symbol = '°';
|
||||||
symbol = '°';
|
} else if (featureDef.type === 'percentage') {
|
||||||
} else if (featureDef.type === 'percentage') {
|
symbol = '%';
|
||||||
symbol = '%';
|
}
|
||||||
}
|
let lowerBound = blueprint.features[feature][0];
|
||||||
let lowerBound = blueprint.features[feature][0];
|
let upperBound = blueprint.features[feature][1];
|
||||||
let upperBound = blueprint.features[feature][1];
|
if (featureDef.type === 'percentage') {
|
||||||
if (featureDef.type === 'percentage') {
|
lowerBound = Math.round(lowerBound * 1000) / 10;
|
||||||
lowerBound = Math.round(lowerBound * 1000) / 10;
|
upperBound = Math.round(upperBound * 1000) / 10;
|
||||||
upperBound = Math.round(upperBound * 1000) / 10;
|
}
|
||||||
}
|
const lowerIsBeneficial = isValueBeneficial(feature, lowerBound);
|
||||||
const lowerIsBeneficial = isValueBeneficial(feature, lowerBound);
|
const upperIsBeneficial = isValueBeneficial(feature, upperBound);
|
||||||
const upperIsBeneficial = isValueBeneficial(feature, upperBound);
|
if (m) {
|
||||||
if (m) {
|
// We have a module - add in the current value
|
||||||
// We have a module - add in the current value
|
let current = m.getModValue(feature);
|
||||||
let current = m.getModValue(feature);
|
if (featureDef.type === 'percentage' || featureDef.name === 'burst' || featureDef.name === 'burstrof') {
|
||||||
if (featureDef.type === 'percentage' || featureDef.name === 'burst' || featureDef.name === 'burstrof') {
|
current = Math.round(current / 10) / 10;
|
||||||
current = Math.round(current / 10) / 10;
|
} else if (featureDef.type === 'numeric') {
|
||||||
} else if (featureDef.type === 'numeric') {
|
current /= 100;
|
||||||
current /= 100;
|
}
|
||||||
}
|
const currentIsBeneficial = isValueBeneficial(feature, current);
|
||||||
const currentIsBeneficial = isValueBeneficial(feature, current);
|
effects.push(
|
||||||
effects.push(
|
<tr key={feature}>
|
||||||
<tr key={feature}>
|
<td style={{ textAlign: 'left' }}>{translate(feature, grp)}</td>
|
||||||
<td style={{ textAlign: 'left' }}>{translate(feature, grp)}</td>
|
<td className={lowerBound === 0 ? '' : lowerIsBeneficial ? 'secondary' : 'warning'} style={{ textAlign: 'right' }}>{lowerBound}{symbol}</td>
|
||||||
<td className={lowerBound === 0 ? '' : lowerIsBeneficial ? 'secondary' : 'warning'} style={{ textAlign: 'right' }}>{lowerBound}{symbol}</td>
|
<td className={current === 0 ? '' : currentIsBeneficial ? 'secondary' : 'warning'} style={{ textAlign: 'right' }}>{current}{symbol}</td>
|
||||||
<td className={current === 0 ? '' : currentIsBeneficial ? 'secondary' : 'warning'} style={{ textAlign: 'right' }}>{current}{symbol}</td>
|
<td className={upperBound === 0 ? '' : upperIsBeneficial ? 'secondary' : 'warning'} style={{ textAlign: 'right' }}>{upperBound}{symbol}</td>
|
||||||
<td className={upperBound === 0 ? '' : upperIsBeneficial ? 'secondary' : 'warning'} style={{ textAlign: 'right' }}>{upperBound}{symbol}</td>
|
</tr>
|
||||||
</tr>
|
);
|
||||||
);
|
} else {
|
||||||
} else {
|
// We do not have a module, no value
|
||||||
// We do not have a module, no value
|
effects.push(
|
||||||
effects.push(
|
<tr key={feature}>
|
||||||
<tr key={feature}>
|
<td style={{ textAlign: 'left' }}>{translate(feature, grp)}</td>
|
||||||
<td style={{ textAlign: 'left' }}>{translate(feature, grp)}</td>
|
<td className={lowerBound === 0 ? '' : lowerIsBeneficial ? 'secondary' : 'warning'} style={{ textAlign: 'right' }}>{lowerBound}{symbol}</td>
|
||||||
<td className={lowerBound === 0 ? '' : lowerIsBeneficial ? 'secondary' : 'warning'} style={{ textAlign: 'right' }}>{lowerBound}{symbol}</td>
|
<td className={upperBound === 0 ? '' : upperIsBeneficial ? 'secondary' : 'warning'} style={{ textAlign: 'right' }}>{upperBound}{symbol}</td>
|
||||||
<td className={upperBound === 0 ? '' : upperIsBeneficial ? 'secondary' : 'warning'} style={{ textAlign: 'right' }}>{upperBound}{symbol}</td>
|
</tr>
|
||||||
</tr>
|
);
|
||||||
);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
if (m) {
|
||||||
if (m) {
|
// Because we have a module add in any benefits that aren't part of the primary blueprint
|
||||||
// Because we have a module add in any benefits that aren't part of the primary blueprint
|
for (const feature in m.mods) {
|
||||||
for (const feature in m.mods) {
|
if (!blueprint.features[feature]) {
|
||||||
if (!blueprint.features[feature]) {
|
const featureDef = Modifications.modifications[feature];
|
||||||
const featureDef = Modifications.modifications[feature];
|
if (featureDef && !featureDef.hidden) {
|
||||||
if (featureDef && !featureDef.hidden) {
|
let symbol = '';
|
||||||
let symbol = '';
|
if (feature === 'jitter') {
|
||||||
if (feature === 'jitter') {
|
symbol = '°';
|
||||||
symbol = '°';
|
} else if (featureDef.type === 'percentage') {
|
||||||
} else if (featureDef.type === 'percentage') {
|
symbol = '%';
|
||||||
symbol = '%';
|
}
|
||||||
}
|
let current = m.getModValue(feature);
|
||||||
let current = m.getModValue(feature);
|
if (featureDef.type === 'percentage' || featureDef.name === 'burst' || featureDef.name === 'burstrof') {
|
||||||
if (featureDef.type === 'percentage' || featureDef.name === 'burst' || featureDef.name === 'burstrof') {
|
current = Math.round(current / 10) / 10;
|
||||||
current = Math.round(current / 10) / 10;
|
} else if (featureDef.type === 'numeric') {
|
||||||
} else if (featureDef.type === 'numeric') {
|
current /= 100;
|
||||||
current /= 100;
|
}
|
||||||
}
|
const currentIsBeneficial = isValueBeneficial(feature, current);
|
||||||
const currentIsBeneficial = isValueBeneficial(feature, current);
|
effects.push(
|
||||||
effects.push(
|
<tr key={feature}>
|
||||||
<tr key={feature}>
|
<td style={{ textAlign: 'left' }}>{translate(feature, grp)}</td>
|
||||||
<td style={{ textAlign: 'left' }}>{translate(feature, grp)}</td>
|
<td> </td>
|
||||||
<td> </td>
|
<td className={current === 0 ? '' : currentIsBeneficial ? 'secondary' : 'warning'} style={{ textAlign: 'right' }}>{current}{symbol}</td>
|
||||||
<td className={current === 0 ? '' : currentIsBeneficial ? 'secondary' : 'warning'} style={{ textAlign: 'right' }}>{current}{symbol}</td>
|
<td> </td>
|
||||||
<td> </td>
|
</tr>
|
||||||
</tr>
|
);
|
||||||
);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
// We also add in any benefits from specials that aren't covered above
|
||||||
// We also add in any benefits from specials that aren't covered above
|
if (m.blueprint && m.blueprint.special) {
|
||||||
if (m.blueprint && m.blueprint.special) {
|
for (const feature in Modifications.modifierActions[m.blueprint.special.edname]) {
|
||||||
for (const feature in Modifications.modifierActions[m.blueprint.special.edname]) {
|
if (!blueprint.features[feature] && !m.mods.feature) {
|
||||||
if (!blueprint.features[feature] && !m.mods.feature) {
|
const featureDef = Modifications.modifications[feature];
|
||||||
const featureDef = Modifications.modifications[feature];
|
if (featureDef && !featureDef.hidden) {
|
||||||
if (featureDef && !featureDef.hidden) {
|
let symbol = '';
|
||||||
let symbol = '';
|
if (feature === 'jitter') {
|
||||||
if (feature === 'jitter') {
|
symbol = '°';
|
||||||
symbol = '°';
|
} else if (featureDef.type === 'percentage') {
|
||||||
} else if (featureDef.type === 'percentage') {
|
symbol = '%';
|
||||||
symbol = '%';
|
}
|
||||||
}
|
let current = m.getModValue(feature);
|
||||||
let current = m.getModValue(feature);
|
if (featureDef.type === 'percentage' || featureDef.name === 'burst' || featureDef.name === 'burstrof') {
|
||||||
if (featureDef.type === 'percentage' || featureDef.name === 'burst' || featureDef.name === 'burstrof') {
|
current = Math.round(current / 10) / 10;
|
||||||
current = Math.round(current / 10) / 10;
|
} else if (featureDef.type === 'numeric') {
|
||||||
} else if (featureDef.type === 'numeric') {
|
current /= 100;
|
||||||
current /= 100;
|
}
|
||||||
}
|
const currentIsBeneficial = isValueBeneficial(feature, current);
|
||||||
const currentIsBeneficial = isValueBeneficial(feature, current);
|
effects.push(
|
||||||
effects.push(
|
<tr key={feature}>
|
||||||
<tr key={feature}>
|
<td style={{ textAlign: 'left' }}>{translate(feature, grp)}</td>
|
||||||
<td style={{ textAlign: 'left' }}>{translate(feature, grp)}</td>
|
<td> </td>
|
||||||
<td> </td>
|
<td className={current === 0 ? '' : currentIsBeneficial ? 'secondary' : 'warning'} style={{ textAlign: 'right' }}>{current}{symbol}</td>
|
||||||
<td className={current === 0 ? '' : currentIsBeneficial ? 'secondary' : 'warning'} style={{ textAlign: 'right' }}>{current}{symbol}</td>
|
<td> </td>
|
||||||
<td> </td>
|
</tr>
|
||||||
</tr>
|
);
|
||||||
);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
let components;
|
||||||
let components;
|
if (!m) {
|
||||||
if (!m) {
|
components = [];
|
||||||
components = [];
|
for (const component in blueprint.components) {
|
||||||
for (const component in blueprint.components) {
|
components.push(
|
||||||
components.push(
|
<tr key={component}>
|
||||||
<tr key={component}>
|
<td style={{ textAlign: 'left' }}>{translate(component)}</td>
|
||||||
<td style={{ textAlign: 'left' }}>{translate(component)}</td>
|
<td style={{ textAlign: 'right' }}>{blueprint.components[component]}</td>
|
||||||
<td style={{ textAlign: 'right' }}>{blueprint.components[component]}</td>
|
</tr>
|
||||||
</tr>
|
);
|
||||||
);
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
let engineersList;
|
||||||
let engineersList;
|
if (engineers) {
|
||||||
if (engineers) {
|
engineersList = [];
|
||||||
engineersList = [];
|
for (const engineer of engineers) {
|
||||||
for (const engineer of engineers) {
|
engineersList.push(
|
||||||
engineersList.push(
|
<tr key={engineer}>
|
||||||
<tr key={engineer}>
|
<td style={{ textAlign: 'left' }}>{engineer}</td>
|
||||||
<td style={{ textAlign: 'left' }}>{engineer}</td>
|
</tr>
|
||||||
</tr>
|
);
|
||||||
);
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
return (
|
||||||
return (
|
<div>
|
||||||
<div>
|
<table width='100%'>
|
||||||
<table width='100%'>
|
<thead>
|
||||||
<thead>
|
<tr>
|
||||||
<tr>
|
<td>{translate('feature')}</td>
|
||||||
<td>{translate('feature')}</td>
|
<td>{translate('worst')}</td>
|
||||||
<td>{translate('worst')}</td>
|
{m ? <td>{translate('current')}</td> : null }
|
||||||
{m ? <td>{translate('current')}</td> : null }
|
<td>{translate('best')}</td>
|
||||||
<td>{translate('best')}</td>
|
</tr>
|
||||||
</tr>
|
</thead>
|
||||||
</thead>
|
<tbody>
|
||||||
<tbody>
|
{effects}
|
||||||
{effects}
|
</tbody>
|
||||||
</tbody>
|
</table>
|
||||||
</table>
|
{ components ? <table width='100%'>
|
||||||
{ components ? <table width='100%'>
|
<thead>
|
||||||
<thead>
|
<tr>
|
||||||
<tr>
|
<td>{translate('component')}</td>
|
||||||
<td>{translate('component')}</td>
|
<td>{translate('amount')}</td>
|
||||||
<td>{translate('amount')}</td>
|
</tr>
|
||||||
</tr>
|
</thead>
|
||||||
</thead>
|
<tbody>
|
||||||
<tbody>
|
{components}
|
||||||
{components}
|
</tbody>
|
||||||
</tbody>
|
</table> : null }
|
||||||
</table> : null }
|
{ engineersList ? <table width='100%'>
|
||||||
{ engineersList ? <table width='100%'>
|
<thead>
|
||||||
<thead>
|
<tr>
|
||||||
<tr>
|
<td>{translate('engineers')}</td>
|
||||||
<td>{translate('engineers')}</td>
|
</tr>
|
||||||
</tr>
|
</thead>
|
||||||
</thead>
|
<tbody>
|
||||||
<tbody>
|
{engineersList}
|
||||||
{engineersList}
|
</tbody>
|
||||||
</tbody>
|
</table> : null }
|
||||||
</table> : null }
|
</div>
|
||||||
</div>
|
);
|
||||||
);
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
/**
|
* Is this blueprint feature beneficial?
|
||||||
* Is this blueprint feature beneficial?
|
* @param {string} feature The name of the feature
|
||||||
* @param {string} feature The name of the feature
|
* @param {array} values The value of the feature
|
||||||
* @param {array} values The value of the feature
|
* @returns {boolean} True if this feature is beneficial
|
||||||
* @returns {boolean} True if this feature is beneficial
|
*/
|
||||||
*/
|
export function isBeneficial(feature, values) {
|
||||||
export function isBeneficial(feature, values) {
|
const fact = (values[0] < 0 || (values[0] === 0 && values[1] < 0));
|
||||||
const fact = (values[0] < 0 || (values[0] === 0 && values[1] < 0));
|
if (Modifications.modifications[feature].higherbetter) {
|
||||||
if (Modifications.modifications[feature].higherbetter) {
|
return !fact;
|
||||||
return !fact;
|
} else {
|
||||||
} else {
|
return fact;
|
||||||
return fact;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
/**
|
* Is this feature value beneficial?
|
||||||
* Is this feature value beneficial?
|
* @param {string} feature The name of the feature
|
||||||
* @param {string} feature The name of the feature
|
* @param {number} value The value of the feature
|
||||||
* @param {number} value The value of the feature
|
* @returns {boolean} True if this value is beneficial
|
||||||
* @returns {boolean} True if this value is beneficial
|
*/
|
||||||
*/
|
export function isValueBeneficial(feature, value) {
|
||||||
export function isValueBeneficial(feature, value) {
|
if (Modifications.modifications[feature].higherbetter) {
|
||||||
if (Modifications.modifications[feature].higherbetter) {
|
return value > 0;
|
||||||
return value > 0;
|
} else {
|
||||||
} else {
|
return value < 0;
|
||||||
return value < 0;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
/**
|
* Get a blueprint with a given name and an optional module
|
||||||
* Is the change as shown beneficial?
|
* @param {string} name The name of the blueprint
|
||||||
* @param {string} feature The name of the feature
|
* @param {Object} module The module for which to obtain this blueprint
|
||||||
* @param {number} value The value of the feature as percentage change
|
* @returns {Object} The matching blueprint
|
||||||
* @returns True if the value is beneficial
|
*/
|
||||||
*/
|
export function getBlueprint(name, module) {
|
||||||
export function isChangeValueBeneficial(feature, value) {
|
// Start with a copy of the blueprint
|
||||||
let changeHigherBetter = STATS_FORMATTING[feature].higherbetter;
|
const findMod = val => Object.keys(Modifications.blueprints).find(elem => elem.toString().toLowerCase().search(val.toString().toLowerCase().replace(/(OutfittingFieldType_|persecond)/igm, '')) >= 0);
|
||||||
if (changeHigherBetter === undefined) {
|
const found = Modifications.blueprints[findMod(name)];
|
||||||
return isValueBeneficial(feature, value);
|
if (!found || !found.fdname) {
|
||||||
}
|
return {};
|
||||||
|
}
|
||||||
if (changeHigherBetter) {
|
const blueprint = JSON.parse(JSON.stringify(found));
|
||||||
return value > 0;
|
return blueprint;
|
||||||
} else {
|
}
|
||||||
return value < 0;
|
|
||||||
}
|
/**
|
||||||
}
|
* 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
|
||||||
* Get a blueprint with a given name and an optional module
|
* @param {Number} percent The percent to set values to of full.
|
||||||
* @param {string} name The name of the blueprint
|
*/
|
||||||
* @param {Object} module The module for which to obtain this blueprint
|
export function setPercent(ship, m, percent) {
|
||||||
* @returns {Object} The matching blueprint
|
ship.clearModifications(m);
|
||||||
*/
|
// Pick given value as multiplier
|
||||||
export function getBlueprint(name, module) {
|
const mult = percent / 100;
|
||||||
// Start with a copy of the blueprint
|
const features = m.blueprint.grades[m.blueprint.grade].features;
|
||||||
const findMod = val => Object.keys(Modifications.blueprints).find(elem => elem.toString().toLowerCase().search(val.toString().toLowerCase().replace(/(OutfittingFieldType_|persecond)/igm, '')) >= 0);
|
for (const featureName in features) {
|
||||||
const found = Modifications.blueprints[findMod(name)];
|
let value;
|
||||||
if (!found || !found.fdname) {
|
if (Modifications.modifications[featureName].higherbetter) {
|
||||||
return {};
|
// Higher is better, but is this making it better or worse?
|
||||||
}
|
if (features[featureName][0] < 0 || (features[featureName][0] === 0 && features[featureName][1] < 0)) {
|
||||||
const blueprint = JSON.parse(JSON.stringify(found));
|
value = features[featureName][1] + ((features[featureName][0] - features[featureName][1]) * mult);
|
||||||
return blueprint;
|
} else {
|
||||||
}
|
value = features[featureName][0] + ((features[featureName][1] - features[featureName][0]) * mult);
|
||||||
|
}
|
||||||
/**
|
} else {
|
||||||
* Provide 'percent' primary modifications
|
// Higher is worse, but is this making it better or worse?
|
||||||
* @param {Object} ship The ship for which to perform the modifications
|
if (features[featureName][0] < 0 || (features[featureName][0] === 0 && features[featureName][1] < 0)) {
|
||||||
* @param {Object} m The module for which to perform the modifications
|
value = features[featureName][0] + ((features[featureName][1] - features[featureName][0]) * mult);
|
||||||
* @param {Number} percent The percent to set values to of full.
|
} else {
|
||||||
*/
|
value = features[featureName][1] + ((features[featureName][0] - features[featureName][1]) * mult);
|
||||||
export function setPercent(ship, m, percent) {
|
}
|
||||||
ship.clearModifications(m);
|
}
|
||||||
// Pick given value as multiplier
|
|
||||||
const mult = percent / 100;
|
_setValue(ship, m, featureName, value);
|
||||||
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?
|
* Provide 'random' primary modifications
|
||||||
if (features[featureName][0] < 0 || (features[featureName][0] === 0 && features[featureName][1] < 0)) {
|
* @param {Object} ship The ship for which to perform the modifications
|
||||||
value = features[featureName][1] + ((features[featureName][0] - features[featureName][1]) * mult);
|
* @param {Object} m The module for which to perform the modifications
|
||||||
} else {
|
*/
|
||||||
value = features[featureName][0] + ((features[featureName][1] - features[featureName][0]) * mult);
|
export function setRandom(ship, m) {
|
||||||
}
|
// Pick a single value for our randomness
|
||||||
} else {
|
setPercent(ship, m, Math.random() * 100);
|
||||||
// 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 {
|
* Set a modification feature value
|
||||||
value = features[featureName][1] + ((features[featureName][0] - features[featureName][1]) * mult);
|
* @param {Object} ship The ship for which to perform the modifications
|
||||||
}
|
* @param {Object} m The module for which to perform the modifications
|
||||||
}
|
* @param {string} featureName The feature being set
|
||||||
|
* @param {number} value The value being set for the feature
|
||||||
_setValue(ship, m, featureName, value);
|
*/
|
||||||
}
|
function _setValue(ship, m, featureName, value) {
|
||||||
}
|
if (Modifications.modifications[featureName].type == 'percentage') {
|
||||||
|
ship.setModification(m, featureName, value * 10000);
|
||||||
/**
|
} else if (Modifications.modifications[featureName].type == 'numeric') {
|
||||||
* Provide 'random' primary modifications
|
ship.setModification(m, featureName, value * 100);
|
||||||
* @param {Object} ship The ship for which to perform the modifications
|
} else {
|
||||||
* @param {Object} m The module for which to perform the modifications
|
ship.setModification(m, featureName, value);
|
||||||
*/
|
}
|
||||||
export function setRandom(ship, m) {
|
}
|
||||||
// Pick a single value for our randomness
|
|
||||||
setPercent(ship, m, Math.random() * 100);
|
/**
|
||||||
}
|
* 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.
|
||||||
* Set a modification feature value
|
*/
|
||||||
* @param {Object} ship The ship for which to perform the modifications
|
export function getPercent(m) {
|
||||||
* @param {Object} m The module for which to perform the modifications
|
let result = null;
|
||||||
* @param {string} featureName The feature being set
|
const features = m.blueprint.grades[m.blueprint.grade].features;
|
||||||
* @param {number} value The value being set for the feature
|
for (const featureName in features) {
|
||||||
*/
|
if (features[featureName][0] === features[featureName][1]) {
|
||||||
function _setValue(ship, m, featureName, value) {
|
continue;
|
||||||
if (Modifications.modifications[featureName].type == 'percentage') {
|
}
|
||||||
ship.setModification(m, featureName, value * 10000);
|
|
||||||
} else if (Modifications.modifications[featureName].type == 'numeric') {
|
let value = _getValue(m, featureName);
|
||||||
ship.setModification(m, featureName, value * 100);
|
let mult;
|
||||||
} else {
|
if (featureName == 'shieldboost') {
|
||||||
ship.setModification(m, featureName, value);
|
mult = ((1 + value) * (1 + m.shieldboost)) - 1 - m.shieldboost;
|
||||||
}
|
} else 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);
|
||||||
* Provide 'percent' primary query
|
} else {
|
||||||
* @param {Object} m The module for which to perform the query
|
mult = Math.round((value - features[featureName][0]) / (features[featureName][1] - features[featureName][0]) * 100);
|
||||||
* @returns {Number} percent The percentage indicator of current applied values.
|
}
|
||||||
*/
|
} else {
|
||||||
export function getPercent(m) {
|
// Higher is worse, but is this making it better or worse?
|
||||||
let result = null;
|
if (features[featureName][0] < 0 || (features[featureName][0] === 0 && features[featureName][1] < 0)) {
|
||||||
const features = m.blueprint.grades[m.blueprint.grade].features;
|
mult = Math.round((value - features[featureName][0]) / (features[featureName][1] - features[featureName][0]) * 100);
|
||||||
for (const featureName in features) {
|
} else {
|
||||||
if (features[featureName][0] === features[featureName][1]) {
|
mult = Math.round((value - features[featureName][1]) / (features[featureName][0] - features[featureName][1]) * 100);
|
||||||
continue;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let value = _getValue(m, featureName);
|
if (result && result != mult) {
|
||||||
let mult;
|
return null;
|
||||||
if (Modifications.modifications[featureName].higherbetter) {
|
} else if (result != mult) {
|
||||||
// Higher is better, but is this making it better or worse?
|
result = mult;
|
||||||
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);
|
return result;
|
||||||
}
|
}
|
||||||
} 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)) {
|
* Query a feature value
|
||||||
mult = Math.round((value - features[featureName][0]) / (features[featureName][1] - features[featureName][0]) * 100);
|
* @param {Object} m The module for which to perform the query
|
||||||
} else {
|
* @param {string} featureName The feature being queried
|
||||||
mult = Math.round((value - features[featureName][1]) / (features[featureName][0] - features[featureName][1]) * 100);
|
* @returns {number} The value of the modification as a %
|
||||||
}
|
*/
|
||||||
}
|
function _getValue(m, featureName) {
|
||||||
|
if (Modifications.modifications[featureName].type == 'percentage') {
|
||||||
if (result && result != mult) {
|
return m.getModValue(featureName, true) / 10000;
|
||||||
return null;
|
} else if (Modifications.modifications[featureName].type == 'numeric') {
|
||||||
} else if (result != mult) {
|
return m.getModValue(featureName, true) / 100;
|
||||||
result = mult;
|
} else {
|
||||||
}
|
return m.getModValue(featureName, true);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Query a feature value
|
|
||||||
* @param {Object} m The module for which to perform the query
|
|
||||||
* @param {string} featureName The feature being queried
|
|
||||||
* @returns {number} The value of the modification as a %
|
|
||||||
*/
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -249,13 +249,6 @@ function _addModifications(module, modifiers, blueprint, grade, specialModificat
|
|||||||
if (!modifiers) return;
|
if (!modifiers) return;
|
||||||
let special;
|
let special;
|
||||||
if (specialModifications) {
|
if (specialModifications) {
|
||||||
if (specialModifications == 'special_plasma_slug') {
|
|
||||||
if (module.symbol.match(/PlasmaAccelerator/i)) {
|
|
||||||
specialModifications = 'special_plasma_slug_pa';
|
|
||||||
} else {
|
|
||||||
specialModifications = 'special_plasma_slug_cooled';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
special = Modifications.specials[specialModifications];
|
special = Modifications.specials[specialModifications];
|
||||||
}
|
}
|
||||||
// Add the blueprint definition, grade and special
|
// Add the blueprint definition, grade and special
|
||||||
@@ -281,9 +274,6 @@ function _addModifications(module, modifiers, blueprint, grade, specialModificat
|
|||||||
if (value === Infinity) {
|
if (value === Infinity) {
|
||||||
value = modifiers[i].Value * 100;
|
value = modifiers[i].Value * 100;
|
||||||
}
|
}
|
||||||
if (modifiers[i].Label.search('DamageFalloffRange') >= 0) {
|
|
||||||
value = (modifiers[i].Value / module.range - 1) * 100;
|
|
||||||
}
|
|
||||||
if (modifiers[i].Label.search('Resistance') >= 0) {
|
if (modifiers[i].Label.search('Resistance') >= 0) {
|
||||||
value = (modifiers[i].Value * 100) - (modifiers[i].OriginalValue * 100);
|
value = (modifiers[i].Value * 100) - (modifiers[i].OriginalValue * 100);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ function orbisShorten(url, success, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const API_ORBIS = 'https://api.orbis.zone/ships';
|
const API_ORBIS = 'https://orbis.zone/api/builds/add';
|
||||||
/**
|
/**
|
||||||
* Upload to Orbis
|
* Upload to Orbis
|
||||||
* @param {object} ship The URL to shorten
|
* @param {object} ship The URL to shorten
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Persist from '../stores/Persist';
|
import Persist from '../stores/Persist';
|
||||||
import * as ModuleUtils from '../shipyard/ModuleUtils';
|
import * as ModuleUtils from '../shipyard/ModuleUtils';
|
||||||
import Module from '../shipyard/Module';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if a slot on a ship can mount a module of a particular class and group
|
* Determine if a slot on a ship can mount a module of a particular class and group
|
||||||
@@ -140,21 +139,20 @@ function diff(format, mVal, mmVal) {
|
|||||||
export function diffDetails(language, m, mm) {
|
export function diffDetails(language, m, mm) {
|
||||||
let { formats, translate, units } = language;
|
let { formats, translate, units } = language;
|
||||||
let propDiffs = [];
|
let propDiffs = [];
|
||||||
m = new Module(m);
|
|
||||||
|
|
||||||
// Module-specific items
|
// Module-specific items
|
||||||
|
|
||||||
if (m.grp === 'pp') {
|
if (m.grp === 'pp') {
|
||||||
let mPowerGeneration = m.getPowerGeneration() || 0;
|
let mPowerGeneration = m.pgen || 0;
|
||||||
let mmPowerGeneration = mm ? mm.getPowerGeneration() : 0;
|
let mmPowerGeneration = mm ? mm.getPowerGeneration() : 0;
|
||||||
if (mPowerGeneration != mmPowerGeneration) propDiffs.push(<div key='pgen'>{translate('pgen')}: <span className={diffClass(mPowerGeneration, mmPowerGeneration)}>{diff(formats.round, mPowerGeneration, mmPowerGeneration)}{units.MW}</span></div>);
|
if (mPowerGeneration != mmPowerGeneration) propDiffs.push(<div key='pgen'>{translate('pgen')}: <span className={diffClass(mPowerGeneration, mmPowerGeneration)}>{diff(formats.round, mPowerGeneration, mmPowerGeneration)}{units.MJ}</span></div>);
|
||||||
} else {
|
} else {
|
||||||
let mPowerUsage = m.getPowerUsage() || 0;
|
let mPowerUsage = m.power || 0;
|
||||||
let mmPowerUsage = mm ? mm.getPowerUsage() || 0 : 0;
|
let mmPowerUsage = mm ? mm.getPowerUsage() || 0 : 0;
|
||||||
if (mPowerUsage != mmPowerUsage) propDiffs.push(<div key='power'>{translate('power')}: <span className={diffClass(mPowerUsage, mmPowerUsage, true)}>{diff(formats.round, mPowerUsage, mmPowerUsage)}{units.MW}</span></div>);
|
if (mPowerUsage != mmPowerUsage) propDiffs.push(<div key='power'>{translate('power')}: <span className={diffClass(mPowerUsage, mmPowerUsage, true)}>{diff(formats.round, mPowerUsage, mmPowerUsage)}{units.MJ}</span></div>);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mDps = m.getDps() || 0;
|
let mDps = m.damage * (m.rpshot || 1) * (m.rof || 1);
|
||||||
let mmDps = mm ? mm.getDps() || 0 : 0;
|
let mmDps = mm ? mm.getDps() || 0 : 0;
|
||||||
if (mDps && mDps != mmDps) propDiffs.push(<div key='dps'>{translate('dps')}: <span className={diffClass(mmDps, mDps, true)}>{diff(formats.round, mDps, mmDps)}</span></div>);
|
if (mDps && mDps != mmDps) propDiffs.push(<div key='dps'>{translate('dps')}: <span className={diffClass(mmDps, mDps, true)}>{diff(formats.round, mDps, mmDps)}</span></div>);
|
||||||
|
|
||||||
@@ -166,7 +164,7 @@ export function diffDetails(language, m, mm) {
|
|||||||
|
|
||||||
if (mAffectsShield) {
|
if (mAffectsShield) {
|
||||||
if (m.grp == 'sb') { // Both m and mm must be utility modules if this is true
|
if (m.grp == 'sb') { // Both m and mm must be utility modules if this is true
|
||||||
newShield = this.calcShieldStrengthWith(null, m.getShieldBoost() - (mm ? mm.getShieldBoost() || 0 : 0));
|
newShield = this.calcShieldStrengthWith(null, m.shieldboost - (mm ? mm.getShieldBoost() || 0 : 0));
|
||||||
} else {
|
} else {
|
||||||
newShield = this.calcShieldStrengthWith(m);
|
newShield = this.calcShieldStrengthWith(m);
|
||||||
}
|
}
|
||||||
@@ -181,7 +179,7 @@ export function diffDetails(language, m, mm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (m.grp === 'mrp') {
|
if (m.grp === 'mrp') {
|
||||||
let mProtection = m.getProtection();
|
let mProtection = m.protection;
|
||||||
let mmProtection = mm ? mm.getProtection() || 0 : 0;
|
let mmProtection = mm ? mm.getProtection() || 0 : 0;
|
||||||
if (mProtection != mmProtection) {
|
if (mProtection != mmProtection) {
|
||||||
propDiffs.push(<div key='protection'>{translate('protection')}: <span className={diffClass(mmProtection, mProtection, true)}>{diff(formats.pct, mProtection, mmProtection)}</span></div>);
|
propDiffs.push(<div key='protection'>{translate('protection')}: <span className={diffClass(mmProtection, mProtection, true)}>{diff(formats.pct, mProtection, mmProtection)}</span></div>);
|
||||||
@@ -189,7 +187,7 @@ export function diffDetails(language, m, mm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (m.grp === 'hr') {
|
if (m.grp === 'hr') {
|
||||||
let mHullReinforcement = m.getHullReinforcement();
|
let mHullReinforcement = m.hullreinforcement;
|
||||||
let mmHullReinforcement = mm ? mm.getHullReinforcement() || 0 : 0;
|
let mmHullReinforcement = mm ? mm.getHullReinforcement() || 0 : 0;
|
||||||
if (mHullReinforcement && mHullReinforcement != mmHullReinforcement) propDiffs.push(<div key='hullreinforcement'>{translate('hullreinforcement')}: <span className={diffClass(mmHullReinforcement, mHullReinforcement, true)}>{diff(formats.round, mHullReinforcement, mmHullReinforcement)}</span></div>);
|
if (mHullReinforcement && mHullReinforcement != mmHullReinforcement) propDiffs.push(<div key='hullreinforcement'>{translate('hullreinforcement')}: <span className={diffClass(mmHullReinforcement, mHullReinforcement, true)}>{diff(formats.round, mHullReinforcement, mmHullReinforcement)}</span></div>);
|
||||||
}
|
}
|
||||||
@@ -221,7 +219,7 @@ export function diffDetails(language, m, mm) {
|
|||||||
let mmCost = mm ? mm.cost : 0;
|
let mmCost = mm ? mm.cost : 0;
|
||||||
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>);
|
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.getMass() || 0;
|
let mMass = m.mass || 0;
|
||||||
let mmMass = mm ? mm.getMass() : 0;
|
let mmMass = mm ? mm.getMass() : 0;
|
||||||
if (mMass != mmMass) propDiffs.push(<div key='mass'>{translate('mass')}: <span className={diffClass(mMass, mmMass, true)}>{diff(formats.round, mMass, mmMass)}{units.T}</span></div>);
|
if (mMass != mmMass) propDiffs.push(<div key='mass'>{translate('mass')}: <span className={diffClass(mMass, mmMass, true)}>{diff(formats.round, mMass, mmMass)}{units.T}</span></div>);
|
||||||
|
|
||||||
@@ -242,7 +240,7 @@ export function diffDetails(language, m, mm) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mIntegrity = m.getIntegrity() || 0;
|
let mIntegrity = m.integrity || 0;
|
||||||
let mmIntegrity = mm ? mm.getIntegrity() || 0 : 0;
|
let mmIntegrity = mm ? mm.getIntegrity() || 0 : 0;
|
||||||
if (mIntegrity != mmIntegrity) {
|
if (mIntegrity != mmIntegrity) {
|
||||||
propDiffs.push(<div key='integrity'>{translate('integrity')}: <span className={diffClass(mmIntegrity, mIntegrity, true)}>{diff(formats.round, mIntegrity, mmIntegrity)}</span></div>);
|
propDiffs.push(<div key='integrity'>{translate('integrity')}: <span className={diffClass(mmIntegrity, mIntegrity, true)}>{diff(formats.round, mIntegrity, mmIntegrity)}</span></div>);
|
||||||
|
|||||||
@@ -8,8 +8,6 @@
|
|||||||
<meta name="description" content="A ship builder, outfitting and comparison
|
<meta name="description" content="A ship builder, outfitting and comparison
|
||||||
tool for Elite Dangerous">
|
tool for Elite Dangerous">
|
||||||
<meta name="mobile-web-app-capable" content="yes">
|
<meta name="mobile-web-app-capable" content="yes">
|
||||||
|
|
||||||
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0,
|
<meta name="viewport" content="width=device-width, initial-scale=1.0,
|
||||||
maximum-scale=1.0, user-scalable=0">
|
maximum-scale=1.0, user-scalable=0">
|
||||||
<link rel="manifest" href="/manifest.json">
|
<link rel="manifest" href="/manifest.json">
|
||||||
@@ -27,26 +25,40 @@
|
|||||||
<meta name="msapplication-TileImage" content="/mstile-144x144.png">
|
<meta name="msapplication-TileImage" content="/mstile-144x144.png">
|
||||||
<meta name="msapplication-config" content="/browserconfig.xml">
|
<meta name="msapplication-config" content="/browserconfig.xml">
|
||||||
<meta name="theme-color" content="#000000">
|
<meta name="theme-color" content="#000000">
|
||||||
<!-- <script data-ad-client="ca-pub-3709458261881414" async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script> -->
|
|
||||||
<script>
|
<script>
|
||||||
window.CORIOLIS_GAPI_KEY = '<%- htmlWebpackPlugin.options.gapiKey %>';
|
window.CORIOLIS_GAPI_KEY = '<%- htmlWebpackPlugin.options.gapiKey %>';
|
||||||
window.CORIOLIS_VERSION = '<%- htmlWebpackPlugin.options.version %>';
|
window.CORIOLIS_VERSION = '<%- htmlWebpackPlugin.options.version %>';
|
||||||
window.CORIOLIS_DATE = '<%- htmlWebpackPlugin.options.date.toISOString().slice(0, 10) %>';
|
window.CORIOLIS_DATE = '<%- htmlWebpackPlugin.options.date.toISOString().slice(0, 10) %>';
|
||||||
window.BUGSNAG_VERSION = '<%- htmlWebpackPlugin.options.version + '-' + htmlWebpackPlugin.options.date.toISOString() %>';
|
window.BUGSNAG_VERSION = '<%- htmlWebpackPlugin.options.version + '-' + htmlWebpackPlugin.options.date.toISOString() %>';
|
||||||
</script>
|
</script>
|
||||||
<!-- Global site tag (gtag.js) - Google Analytics -->
|
<% if (htmlWebpackPlugin.options.uaTracking) { %>
|
||||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-55840909-18"></script>
|
<script>
|
||||||
<script>
|
window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
|
||||||
window.dataLayer = window.dataLayer || [];
|
ga('create', '<%- htmlWebpackPlugin.options.uaTracking %>', 'auto');
|
||||||
function gtag(){dataLayer.push(arguments);}
|
ga('send', 'pageview');
|
||||||
gtag('js', new Date());
|
|
||||||
|
|
||||||
gtag('config', 'UA-55840909-18');
|
|
||||||
</script>
|
</script>
|
||||||
|
<script async src='https://www.google-analytics.com/analytics.js'></script>
|
||||||
|
<% } %>
|
||||||
|
|
||||||
|
<!-- Piwik -->
|
||||||
|
<!-- <script type="text/javascript">
|
||||||
|
var _paq = _paq || [];
|
||||||
|
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
|
||||||
|
_paq.push(["setCookieDomain", "*.coriolis.edcd.io"]);
|
||||||
|
_paq.push(['trackPageView']);
|
||||||
|
_paq.push(['enableLinkTracking']);
|
||||||
|
(function() {
|
||||||
|
var u="//stats.isadankme.me/";
|
||||||
|
_paq.push(['setTrackerUrl', u+'piwik.php']);
|
||||||
|
_paq.push(['setSiteId', '4']);
|
||||||
|
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
|
||||||
|
g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s);
|
||||||
|
})();
|
||||||
|
</script>-->
|
||||||
|
<!-- End Piwik Code -->
|
||||||
|
|
||||||
|
<!-- Bugsnag -->
|
||||||
<!-- Bugsnag -->
|
|
||||||
<script src="https://d2wy8f7a9ursnm.cloudfront.net/v5.0.0/bugsnag.min.js"></script>
|
<script src="https://d2wy8f7a9ursnm.cloudfront.net/v5.0.0/bugsnag.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
window.bugsnagClient = bugsnag('ba9fae819372850fb660755341fa6ef5', {appVersion: window.BUGSNAG_VERSION || undefined})
|
window.bugsnagClient = bugsnag('ba9fae819372850fb660755341fa6ef5', {appVersion: window.BUGSNAG_VERSION || undefined})
|
||||||
@@ -54,8 +66,7 @@
|
|||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body style="background-color:#000;">
|
<body style="background-color:#000;">
|
||||||
<section id="coriolis">
|
<section id="coriolis"></section>
|
||||||
|
|
||||||
</section>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -2,8 +2,6 @@
|
|||||||
@bgDarken: 40%;
|
@bgDarken: 40%;
|
||||||
@disabledDarken: 15%;
|
@disabledDarken: 15%;
|
||||||
@bgTransparency: 10%;
|
@bgTransparency: 10%;
|
||||||
@bgHighlight: 5%;
|
|
||||||
@fgHighlight: 10%;
|
|
||||||
|
|
||||||
// Foreground colors
|
// Foreground colors
|
||||||
@fg: #CCC;
|
@fg: #CCC;
|
||||||
@@ -23,14 +21,9 @@
|
|||||||
@bgBlack: #000;
|
@bgBlack: #000;
|
||||||
@primary-bg: fadeout(darken(@primary, 47%), 15%);
|
@primary-bg: fadeout(darken(@primary, 47%), 15%);
|
||||||
@alt-primary-bg: fadeout(darken(@primary, 42%), 15%); // Lighter brown background
|
@alt-primary-bg: fadeout(darken(@primary, 42%), 15%); // Lighter brown background
|
||||||
@secondary-bg: fadeout(darken(@secondary, @bgDarken), @bgTransparency); // Blue background
|
@secondary-bg: fadeout(darken(@secondary, @bgDarken), @bgTransparency); // Brown background
|
||||||
@warning-bg: fadeout(darken(@warning, @bgDarken), @bgTransparency); // Dark Red
|
@warning-bg: fadeout(darken(@warning, @bgDarken), @bgTransparency); // Dark Red
|
||||||
|
|
||||||
@alt-primary-bg-highlighted: lighten(@alt-primary-bg, @bgHighlight);
|
|
||||||
@fg-highlighted: lighten(@fg, @fgHighlight);
|
|
||||||
@primary-darker: darken(@primary, 30%);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.fg {
|
.fg {
|
||||||
color: @fg;
|
color: @fg;
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ textarea {
|
|||||||
width:100%;
|
width:100%;
|
||||||
min-height: 10em;
|
min-height: 10em;
|
||||||
resize: vertical;
|
resize: vertical;
|
||||||
user-select: text;
|
user-select: auto;
|
||||||
margin:2em 0;
|
margin:2em 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,45 +49,4 @@ a.ship {
|
|||||||
font-size: 0.7em;
|
font-size: 0.7em;
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.shipyard-table-wrapper {
|
|
||||||
white-space: nowrap;
|
|
||||||
margin: 0 auto;
|
|
||||||
font-size: 0.8em;
|
|
||||||
position: relative;
|
|
||||||
display: inline-block;
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.shipyard-table{
|
|
||||||
tbody tr.comparehighlight{
|
|
||||||
background-color: @secondary-bg;
|
|
||||||
color: @fg-highlighted;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.shipyard-table-wrapper {
|
|
||||||
border-bottom: 1px solid @primary-darker;
|
|
||||||
}
|
|
||||||
|
|
||||||
.shipyard-table-wrapper div .shipyard-table td:last-child {
|
|
||||||
border-right: 1px solid @primary-darker;
|
|
||||||
}
|
|
||||||
.shipyard-table-wrapper > .shipyard-table td:first-child {
|
|
||||||
border-left: 1px solid @primary-darker;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content-wrapper{
|
|
||||||
display: inline-block;
|
|
||||||
margin: 0 auto;
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-tools{
|
|
||||||
text-align: left;
|
|
||||||
color: @primary;
|
|
||||||
label{
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -52,7 +52,7 @@ tbody tr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.no-touch &.highlight:hover, .no-touch &.highlighted {
|
.no-touch &.highlight:hover, .no-touch &.highlighted {
|
||||||
background-color: @alt-primary-bg-highlighted; //@warning-bg;
|
background-color: @warning-bg;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:nth-child(odd){
|
&:nth-child(odd){
|
||||||
@@ -84,5 +84,3 @@ td {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
104
src/migrate.html
104
src/migrate.html
@@ -1,104 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<title>Coriolis EDCD Edition</title>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<link rel="stylesheet" href="<%= htmlWebpackPlugin.files.css[0] %>" />
|
|
||||||
<!-- Standard headers -->
|
|
||||||
<meta
|
|
||||||
name="description"
|
|
||||||
content="A ship builder, outfitting and comparison
|
|
||||||
tool for Elite Dangerous"
|
|
||||||
/>
|
|
||||||
<meta name="mobile-web-app-capable" content="yes" />
|
|
||||||
<meta
|
|
||||||
name="viewport"
|
|
||||||
content="width=device-width, initial-scale=1.0,
|
|
||||||
maximum-scale=1.0, user-scalable=0"
|
|
||||||
/>
|
|
||||||
<link rel="manifest" href="/manifest.json" />
|
|
||||||
<link rel="shortcut icon" href=/favicon2.ico>
|
|
||||||
<link
|
|
||||||
rel="icon"
|
|
||||||
sizes="152x152 192x192"
|
|
||||||
type="image/png"
|
|
||||||
href="/192x192.png"
|
|
||||||
/>
|
|
||||||
<!-- Bugsnag -->
|
|
||||||
<script src="https://d2wy8f7a9ursnm.cloudfront.net/v5.0.0/bugsnag.min.js"></script>
|
|
||||||
<script>
|
|
||||||
window.bugsnagClient = bugsnag('ba9fae819372850fb660755341fa6ef5', {appVersion: window.BUGSNAG_VERSION || undefined})
|
|
||||||
window.Bugsnag = window.bugsnagClient
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<!-- Apple/iOS headers -->
|
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
|
||||||
<meta name="apple-mobile-web-app-title" content="Coriolis" />
|
|
||||||
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
|
|
||||||
|
|
||||||
<!-- Microsoft Windows Phone/Tablet headers -->
|
|
||||||
<meta name="msapplication-TileColor" content="#000000" />
|
|
||||||
<meta name="msapplication-TileImage" content="/mstile-144x144.png" />
|
|
||||||
<meta name="msapplication-config" content="/browserconfig.xml" />
|
|
||||||
<meta name="theme-color" content="#000000" />
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<body style="background-color:#000;">
|
|
||||||
<section id="coriolis">
|
|
||||||
<div class="modal">
|
|
||||||
<h2>
|
|
||||||
Please migrate to <a href="https://coriolis.io">coriolis.io</a>
|
|
||||||
</h2>
|
|
||||||
You are currently on coriolis.<strong>.edcd</strong>.io This domain is
|
|
||||||
considered deprecated. To migrate your builds, copy the below text and
|
|
||||||
go to
|
|
||||||
<a
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
href="https://coriolis.io"
|
|
||||||
>this link</a
|
|
||||||
>, press ctrl + i and then paste in the data. (If you are on mobile,
|
|
||||||
you can go to the settings and hit import)
|
|
||||||
<div>
|
|
||||||
<textarea id="data" class="cb json"></textarea>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</body>
|
|
||||||
<script>
|
|
||||||
const LS = localStorage;
|
|
||||||
/**
|
|
||||||
* Safe localstorage get string
|
|
||||||
* @param {String} key key
|
|
||||||
* @return {String} The stored string
|
|
||||||
*/
|
|
||||||
function _getString(key) {
|
|
||||||
return LS ? LS.getItem(key) : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Safe localstorage get
|
|
||||||
* @param {String} key key
|
|
||||||
* @return {object | number} The stored data
|
|
||||||
*/
|
|
||||||
function _get(key) {
|
|
||||||
let str = _getString(key);
|
|
||||||
try {
|
|
||||||
return str ? JSON.parse(str) : null;
|
|
||||||
} catch (e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const textarea = document.querySelector("#data");
|
|
||||||
const data = {
|
|
||||||
builds: _get("builds") || {},
|
|
||||||
comparisons: _get("comparisons") || {},
|
|
||||||
insurance: _get("insurance") || "standard",
|
|
||||||
shipDiscount: _get("shipDiscount") || 0,
|
|
||||||
moduleDiscount: _get("moduleDiscount") || 0
|
|
||||||
};
|
|
||||||
textarea.textContent = JSON.stringify(data, null, 2);
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
19
src/sw.js
19
src/sw.js
@@ -7,8 +7,8 @@ if (workbox) {
|
|||||||
workbox.routing.registerNavigationRoute('/index.html');
|
workbox.routing.registerNavigationRoute('/index.html');
|
||||||
|
|
||||||
workbox.routing.registerRoute(
|
workbox.routing.registerRoute(
|
||||||
/\.(?:png|jpg|jpeg|svg|gif)$/,
|
new RegExp('/(.*?)'),
|
||||||
new workbox.strategies.CacheFirst({
|
workbox.strategies.staleWhileRevalidate({
|
||||||
plugins: [
|
plugins: [
|
||||||
new workbox.cacheableResponse.Plugin({
|
new workbox.cacheableResponse.Plugin({
|
||||||
statuses: [0, 200]
|
statuses: [0, 200]
|
||||||
@@ -17,16 +17,9 @@ if (workbox) {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
workbox.routing.registerRoute(
|
|
||||||
/\.(?:js|css)$/,
|
|
||||||
new workbox.strategies.StaleWhileRevalidate({
|
|
||||||
cacheName: 'static-resources',
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
workbox.routing.registerRoute(
|
workbox.routing.registerRoute(
|
||||||
new RegExp('https://fonts.(?:googleapis|gstatic).com/(.*)'),
|
new RegExp('https://fonts.(?:googleapis|gstatic).com/(.*)'),
|
||||||
new workbox.strategies.CacheFirst({
|
workbox.strategies.cacheFirst({
|
||||||
cacheName: 'google-fonts',
|
cacheName: 'google-fonts',
|
||||||
plugins: [
|
plugins: [
|
||||||
new workbox.expiration.Plugin({
|
new workbox.expiration.Plugin({
|
||||||
@@ -38,6 +31,12 @@ if (workbox) {
|
|||||||
]
|
]
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
workbox.googleAnalytics.initialize();
|
||||||
|
} catch (e) {
|
||||||
|
console.log('Probably an ad-blocker');
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log('Boo! Workbox didn\'t load 😬');
|
console.log('Boo! Workbox didn\'t load 😬');
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user