mirror of
https://github.com/EDCD/coriolis.git
synced 2025-12-09 14:45:35 +00:00
Compare commits
6 Commits
b31de9c37a
...
feature/fi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
59b6945fee | ||
|
|
4613e7ca7a | ||
|
|
3315570edf | ||
|
|
1fd545ba1f | ||
|
|
25839de1fe | ||
|
|
15feff9344 |
6
.babelrc
6
.babelrc
@@ -7,8 +7,6 @@
|
|||||||
"@babel/plugin-syntax-dynamic-import",
|
"@babel/plugin-syntax-dynamic-import",
|
||||||
"@babel/plugin-syntax-import-meta",
|
"@babel/plugin-syntax-import-meta",
|
||||||
["@babel/plugin-proposal-class-properties", { "loose": true }],
|
["@babel/plugin-proposal-class-properties", { "loose": true }],
|
||||||
"@babel/plugin-proposal-do-expressions",
|
|
||||||
"@babel/plugin-proposal-function-bind",
|
|
||||||
"@babel/plugin-proposal-json-strings",
|
"@babel/plugin-proposal-json-strings",
|
||||||
[
|
[
|
||||||
"@babel/plugin-proposal-decorators",
|
"@babel/plugin-proposal-decorators",
|
||||||
@@ -30,7 +28,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"@babel/plugin-proposal-nullish-coalescing-operator",
|
"@babel/plugin-proposal-nullish-coalescing-operator",
|
||||||
["@babel/plugin-proposal-private-methods", { "loose": true }],
|
"@babel/plugin-proposal-do-expressions",
|
||||||
["@babel/plugin-proposal-private-property-in-object", { "loose": true }]
|
"@babel/plugin-proposal-function-bind"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
2
.docker/.dockerignore
Normal file
2
.docker/.dockerignore
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
node_modules
|
||||||
|
npm-debug.log
|
||||||
35
.docker/Dockerfile
Normal file
35
.docker/Dockerfile
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
### 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
|
||||||
|
|
||||||
|
COPY ./coriolis/ /src/app/coriolis
|
||||||
|
COPY ./coriolis-data/ /src/app/coriolis-data
|
||||||
|
|
||||||
|
RUN apk update
|
||||||
|
RUN apk add git
|
||||||
|
|
||||||
|
RUN npm i -g npm
|
||||||
|
|
||||||
|
# Set up coriolis-data
|
||||||
|
WORKDIR /src/app/coriolis-data
|
||||||
|
RUN git fetch --all
|
||||||
|
RUN npm install --no-package-lock
|
||||||
|
RUN npm start
|
||||||
|
|
||||||
|
WORKDIR /src/app/coriolis
|
||||||
|
RUN git fetch --all
|
||||||
|
RUN npm install --no-package-lock
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
|
||||||
|
### STAGE 2: Production Environment ###
|
||||||
|
FROM nginx:1.13.12-alpine as web
|
||||||
|
COPY coriolis/.docker/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;"]
|
||||||
34
.docker/docker-compose.yml
Normal file
34
.docker/docker-compose.yml
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
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"
|
||||||
|
|
||||||
|
networks:
|
||||||
|
web:
|
||||||
|
external: true
|
||||||
45
.docker/nginx.conf
Normal file
45
.docker/nginx.conf
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
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;
|
||||||
|
|
||||||
|
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)$ {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
Dockerfile
|
|
||||||
.dockerignore
|
|
||||||
.gitignore
|
|
||||||
README.md
|
|
||||||
|
|
||||||
build
|
|
||||||
node_modules
|
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
"title": "Coriolis",
|
"title": "Coriolis",
|
||||||
"description": "Coriolis Shipyard for Elite Dangerous",
|
"description": "Coriolis Shipyard for Elite Dangerous",
|
||||||
"repository": "https://github.com/EDCD/coriolis",
|
"repository": "https://github.com/EDCD/coriolis",
|
||||||
"site": "https://coriolis.io",
|
"site": "https://coriolis.edcd.io",
|
||||||
"author": "https://github.com/edcd",
|
"author": "https://github.com/edcd",
|
||||||
"image": "./src/images/logo/192x192.png"
|
"image": "./src/images/logo/192x192.png"
|
||||||
}
|
}
|
||||||
@@ -81,7 +81,7 @@
|
|||||||
"title": "Coriolis",
|
"title": "Coriolis",
|
||||||
"description": "Coriolis Shipyard for Elite Dangerous",
|
"description": "Coriolis Shipyard for Elite Dangerous",
|
||||||
"repository": "https://github.com/EDCD/coriolis",
|
"repository": "https://github.com/EDCD/coriolis",
|
||||||
"site": "https://coriolis.io",
|
"site": "https://coriolis.edcd.io",
|
||||||
"author": "https://github.com/edcd",
|
"author": "https://github.com/edcd",
|
||||||
"image": "./src/images/logo/192x192.png"
|
"image": "./src/images/logo/192x192.png"
|
||||||
}
|
}
|
||||||
|
|||||||
14
.gitattributes
vendored
14
.gitattributes
vendored
@@ -1,14 +0,0 @@
|
|||||||
# Set the default behavior, in case people don't have core.autocrlf set, in order to prevent line ending inconsistency.
|
|
||||||
* text=auto
|
|
||||||
|
|
||||||
# Explicitly declare text files you want to always be normalized and converted
|
|
||||||
# to native line endings on checkout.
|
|
||||||
*.jsx text
|
|
||||||
*.js text
|
|
||||||
|
|
||||||
# Declare files that will always have CRLF line endings on checkout.
|
|
||||||
# *.sln text eol=crlf
|
|
||||||
|
|
||||||
# Denote all files that are truly binary and should not be modified.
|
|
||||||
*.png binary
|
|
||||||
*.jpg binary
|
|
||||||
28
.github/workflows/autodeploy.yml
vendored
28
.github/workflows/autodeploy.yml
vendored
@@ -1,28 +0,0 @@
|
|||||||
# This is a basic deployment workflow triggered by pushes to the alpha branch.
|
|
||||||
|
|
||||||
name: Auto-Deploy
|
|
||||||
|
|
||||||
# Controls when the action will run. Workflow runs when the alpha branch receives a push event
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- alpha
|
|
||||||
|
|
||||||
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
|
|
||||||
jobs:
|
|
||||||
downloadcode:
|
|
||||||
runs-on: self-hosted
|
|
||||||
steps:
|
|
||||||
- shell: bash
|
|
||||||
run: |
|
|
||||||
rm -Rf ./coriolis
|
|
||||||
rm -Rf ./coriolis-data
|
|
||||||
git clone https://github.com/alex-williams/coriolis.git --single-branch --branch alpha
|
|
||||||
git clone https://github.com/alex-williams/coriolis-data.git --single-branch --branch alpha
|
|
||||||
cd coriolis-data
|
|
||||||
npm install
|
|
||||||
cd ../coriolis
|
|
||||||
npm install
|
|
||||||
npm run build
|
|
||||||
sudo -u www-data cp -r ./build/* /var/www/newdisk/coriolis.brighter-applications.co.uk/
|
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -10,3 +10,4 @@ env
|
|||||||
.project
|
.project
|
||||||
.vscode/
|
.vscode/
|
||||||
docs/
|
docs/
|
||||||
|
package-lock.json
|
||||||
|
|||||||
16
.travis.yml
Normal file
16
.travis.yml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
language: node_js
|
||||||
|
notifications:
|
||||||
|
email: false
|
||||||
|
sudo: false
|
||||||
|
node_js:
|
||||||
|
- "4.8.1"
|
||||||
|
cache:
|
||||||
|
directories:
|
||||||
|
- node_modules
|
||||||
|
|
||||||
|
before_install:
|
||||||
|
- git clone https://github.com/EDCD/coriolis-data.git ../coriolis-data
|
||||||
|
|
||||||
|
script:
|
||||||
|
- npm run lint
|
||||||
|
- npm test
|
||||||
25
Dockerfile
25
Dockerfile
@@ -1,25 +0,0 @@
|
|||||||
#syntax=docker/dockerfile:1.4
|
|
||||||
# Run this from within this directory. Change the location of coriolis-data repo and image name/tag as needed.
|
|
||||||
# docker buildx build --build-context data=../coriolis-data --tag coriolis .
|
|
||||||
|
|
||||||
FROM node:18-alpine
|
|
||||||
|
|
||||||
# TODO: For a production build, we may want to just build the bundle and copy that in. No need for local copy of source.
|
|
||||||
WORKDIR /app
|
|
||||||
ADD . .
|
|
||||||
COPY --from=data . /coriolis-data/
|
|
||||||
|
|
||||||
# Git is required before install if any modules (like coriolis-data) are loaded from github
|
|
||||||
RUN apk update
|
|
||||||
RUN apk add git
|
|
||||||
|
|
||||||
WORKDIR /app/coriolis-data
|
|
||||||
RUN npm install
|
|
||||||
WORKDIR /app
|
|
||||||
RUN npm install
|
|
||||||
# Bundle for production config with webpack & log
|
|
||||||
RUN npm run build > >(tee -a stdout.log) 2> >(tee -a stderr.log >&2)
|
|
||||||
|
|
||||||
# Optimally, this will start a static asset server like nginx/apache. Currently, this will start dev webpack server.
|
|
||||||
CMD ["npm", "start"]
|
|
||||||
EXPOSE 3300
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
#syntax=docker/dockerfile:1.4
|
|
||||||
# Run this from within this directory. Change the location of coriolis-data repo and image name/tag as needed.
|
|
||||||
# docker buildx build --build-context data=../coriolis-data --tag coriolis -f ./Dockerfile-dev .
|
|
||||||
|
|
||||||
FROM node:18-alpine
|
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
ADD . .
|
|
||||||
COPY --from=data . /coriolis-data/
|
|
||||||
|
|
||||||
# Install git & any other desired in-container dev tools
|
|
||||||
# Git is required before install if any modules (like coriolis-data) are loaded from github
|
|
||||||
RUN apk update
|
|
||||||
RUN apk add git
|
|
||||||
|
|
||||||
WORKDIR /app/coriolis-data
|
|
||||||
RUN npm install
|
|
||||||
WORKDIR /app
|
|
||||||
RUN npm install
|
|
||||||
|
|
||||||
|
|
||||||
CMD ["npm", "start"]
|
|
||||||
EXPOSE 3300
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
#syntax=docker/dockerfile:1.4
|
|
||||||
# Run this from within this directory. Change the location of coriolis-data repo and image name/tag as needed.
|
|
||||||
# docker buildx build --build-context data=../coriolis-data --tag coriolis:0.0.7-local-prod -f Dockerfile-local-prod .
|
|
||||||
# docker run -d -p 80:8080 coriolis:0.0.7-local-prod
|
|
||||||
|
|
||||||
FROM node:18-alpine
|
|
||||||
|
|
||||||
# TODO: For a production build, we may want to just build the bundle and copy that in. No need for local copy of source.
|
|
||||||
WORKDIR /app
|
|
||||||
ADD . .
|
|
||||||
# COPY --from=data . /coriolis-data/
|
|
||||||
|
|
||||||
# Git is required before install if any modules (like coriolis-data is now referenced in the package.json) are loaded from github
|
|
||||||
RUN apk update
|
|
||||||
RUN apk add git
|
|
||||||
|
|
||||||
# WORKDIR /app/coriolis-data
|
|
||||||
# RUN npm install
|
|
||||||
# WORKDIR /app
|
|
||||||
# RUN npm install
|
|
||||||
# Bundle for production config with webpack & log
|
|
||||||
# In this version of the dockerfile, I'm deferring automated webpack build so I can monitor a manual build
|
|
||||||
# RUN npm run build > >(tee -a stdout.log) 2> >(tee -a stderr.log >&2)
|
|
||||||
|
|
||||||
RUN npm install -g http-server
|
|
||||||
|
|
||||||
# Optimally, this will start a static asset server like nginx/apache. Currently, this will start dev webpack server.
|
|
||||||
# CMD ["http-server", "/app/build", "-c-1"]
|
|
||||||
CMD ["/bin/ash"]
|
|
||||||
# CMD [""]
|
|
||||||
|
|
||||||
EXPOSE 8080
|
|
||||||
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.
|
|
||||||
73
README.md
73
README.md
@@ -1,4 +1,4 @@
|
|||||||
[](https://discord.gg/0uwCh6R62aPRjk9w)
|
 [](https://travis-ci.org/EDCD/coriolis) [](https://discord.gg/0uwCh6R62aPRjk9w)
|
||||||
|
|
||||||
## About
|
## About
|
||||||
|
|
||||||
@@ -8,50 +8,51 @@ Coriolis was created using assets and imagery from Elite: Dangerous, with the pe
|
|||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
- [Submit issues](https://github.com/EDCD/coriolis/issues)
|
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.
|
||||||
- [Submit pull requests](https://github.com/EDCD/coriolis/pulls) targetting `develop` branch
|
|
||||||
- Chat to us on [Discord](https://discord.gg/0uwCh6R62aPRjk9w)!
|
### 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
|
||||||
|
|
||||||
|
Chat to us on [Discord](https://discord.gg/0uwCh6R62aPRjk9w)!
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
This release includes the ability to run the app as a Docker container.
|
See the [Developer's Guide](https://github.com/EDCD/coriolis/wiki/Developing-for-Coriolis) in the wiki.
|
||||||
```sh
|
|
||||||
> git clone https://github.com/EDCD/coriolis.git
|
|
||||||
> git clone https://github.com/EDCD/coriolis-data.git
|
|
||||||
> cd coriolis
|
|
||||||
> docker buildx build --build-context data=../coriolis-data --tag coriolis .
|
|
||||||
> docker run -d -p 3300:3300 coriolis
|
|
||||||
```
|
|
||||||
|
|
||||||
Or to run an instance of coriolis without Docker Desktop, perform the following steps in a shell:
|
Also see [the documentation site.](https://coriolis.willb.info/)
|
||||||
```sh
|
|
||||||
> git clone https://github.com/EDCD/coriolis.git
|
|
||||||
> git clone https://github.com/EDCD/coriolis-data.git
|
|
||||||
> cd ./coriolis-data
|
|
||||||
> npm install
|
|
||||||
> cd ../coriolis
|
|
||||||
> npm install
|
|
||||||
> npm start
|
|
||||||
```
|
|
||||||
|
|
||||||
You will then have a development server running on `localhost:3300`.
|
|
||||||
|
|
||||||
### Ship and Module Database
|
### Ship and Module Database
|
||||||
|
|
||||||
See the [Data wiki](https://github.com/EDCD/coriolis-data/wiki) for details on structure, etc.
|
See the [Data wiki](https://github.com/cmmcleod/coriolis-data/wiki) for details on structure, etc.
|
||||||
|
|
||||||
## Deployment
|
|
||||||
|
|
||||||
Follow the steps for [Development](#development) as above, but instead
|
## License
|
||||||
of `npm start` you'll want to:
|
|
||||||
|
|
||||||
```sh
|
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
|
||||||
> npm run build
|
[terms and conditions](https://www.frontierstore.net/terms-and-conditions/).
|
||||||
```
|
|
||||||
|
|
||||||
this will result in a `build/` directory being created containing all the necessary files.
|
The code (Javascript, CSS, HTML, and SVG files only) specificially for Coriolis.io is released under the MIT License.
|
||||||
|
|
||||||
After this you need to serve the files in some manner.
|
Copyright (c) 2015 Coriolis.io, Colin McLeod
|
||||||
Either configure your webserver to make the actual `build/` directory
|
|
||||||
visible on the web, or alternatively copy it to somewhere to serve it
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
from.
|
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.
|
||||||
|
|||||||
@@ -275,11 +275,11 @@
|
|||||||
"totalCost": 882362060,
|
"totalCost": 882362060,
|
||||||
"unladenMass": 1179.2,
|
"unladenMass": 1179.2,
|
||||||
"totalDps": 29,
|
"totalDps": 29,
|
||||||
|
"passengerCapacity": 0,
|
||||||
"powerAvailable": 36,
|
"powerAvailable": 36,
|
||||||
"powerRetracted": 23.33,
|
"powerRetracted": 23.33,
|
||||||
"powerDeployed": 34.76,
|
"powerDeployed": 34.76,
|
||||||
"unladenRange": 18.49,
|
"unladenRange": 18.49,
|
||||||
"fullTankRange": 18.12,
|
|
||||||
"ladenRange": 16.39,
|
"ladenRange": 16.39,
|
||||||
"unladenFastestRange": 73.21,
|
"unladenFastestRange": 73.21,
|
||||||
"ladenFastestRange": 66.15,
|
"ladenFastestRange": 66.15,
|
||||||
|
|||||||
@@ -287,6 +287,7 @@
|
|||||||
"totalThermSDps": 58.64,
|
"totalThermSDps": 58.64,
|
||||||
"baseShieldStrength": 350,
|
"baseShieldStrength": 350,
|
||||||
"baseArmour": 945,
|
"baseArmour": 945,
|
||||||
|
"hullCausRes": 0,
|
||||||
"hullExplRes": 0.22,
|
"hullExplRes": 0.22,
|
||||||
"hullKinRes": 0.27,
|
"hullKinRes": 0.27,
|
||||||
"hullMass": 400,
|
"hullMass": 400,
|
||||||
@@ -303,13 +304,13 @@
|
|||||||
"armour": 2227.5,
|
"armour": 2227.5,
|
||||||
"baseArmour": 525,
|
"baseArmour": 525,
|
||||||
"unladenMass": 1163.2,
|
"unladenMass": 1163.2,
|
||||||
|
"passengerCapacity": 0,
|
||||||
"powerAvailable": 39.6,
|
"powerAvailable": 39.6,
|
||||||
"powerRetracted": 23.33,
|
"powerRetracted": 23.33,
|
||||||
"powerDeployed": 34.13,
|
"powerDeployed": 34.13,
|
||||||
"roll": 60,
|
"roll": 60,
|
||||||
"unladenRange": 18.74,
|
"unladenRange": 18.74,
|
||||||
"yaw": 10,
|
"yaw": 10,
|
||||||
"fullTankRange": 18.36,
|
|
||||||
"hardness": 65,
|
"hardness": 65,
|
||||||
"ladenRange": 16.59,
|
"ladenRange": 16.59,
|
||||||
"unladenFastestRange": 74.2,
|
"unladenFastestRange": 74.2,
|
||||||
|
|||||||
@@ -237,14 +237,15 @@
|
|||||||
"shieldExplRes": 0.5,
|
"shieldExplRes": 0.5,
|
||||||
"shieldKinRes": 0.6,
|
"shieldKinRes": 0.6,
|
||||||
"shieldThermRes": 1.2,
|
"shieldThermRes": 1.2,
|
||||||
|
"hullCausRes": 0,
|
||||||
"hullExplRes": 1.4,
|
"hullExplRes": 1.4,
|
||||||
"hullKinRes": 1.2,
|
"hullKinRes": 1.2,
|
||||||
"hullThermRes": 1,
|
"hullThermRes": 1,
|
||||||
|
"passengerCapacity": 0,
|
||||||
"powerAvailable": 20.41,
|
"powerAvailable": 20.41,
|
||||||
"powerRetracted": 11.91,
|
"powerRetracted": 11.91,
|
||||||
"powerDeployed": 11.91,
|
"powerDeployed": 11.91,
|
||||||
"unladenRange": 50.45,
|
"unladenRange": 50.45,
|
||||||
"fullTankRange": 47.03,
|
|
||||||
"ladenRange": 42.71,
|
"ladenRange": 42.71,
|
||||||
"unladenFastestRange": 317.24,
|
"unladenFastestRange": 317.24,
|
||||||
"ladenFastestRange": 287.02,
|
"ladenFastestRange": 287.02,
|
||||||
|
|||||||
@@ -309,14 +309,15 @@
|
|||||||
"shieldExplRes": 0.48,
|
"shieldExplRes": 0.48,
|
||||||
"shieldKinRes": 0.55,
|
"shieldKinRes": 0.55,
|
||||||
"shieldThermRes": 1.09,
|
"shieldThermRes": 1.09,
|
||||||
|
"hullCausRes": 0,
|
||||||
"hullExplRes": 1.4,
|
"hullExplRes": 1.4,
|
||||||
"hullKinRes": 1.2,
|
"hullKinRes": 1.2,
|
||||||
"hullThermRes": 1,
|
"hullThermRes": 1,
|
||||||
|
"passengerCapacity": 0,
|
||||||
"powerAvailable": 17.24,
|
"powerAvailable": 17.24,
|
||||||
"powerRetracted": 11.3,
|
"powerRetracted": 11.3,
|
||||||
"powerDeployed": 16.41,
|
"powerDeployed": 16.41,
|
||||||
"unladenRange": 25.57,
|
"unladenRange": 25.57,
|
||||||
"fullTankRange": 23.92,
|
|
||||||
"ladenRange": 22.09,
|
"ladenRange": 22.09,
|
||||||
"unladenFastestRange": 116.23,
|
"unladenFastestRange": 116.23,
|
||||||
"ladenFastestRange": 107,
|
"ladenFastestRange": 107,
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
@@ -115,7 +115,6 @@
|
|||||||
"powerRetracted": 7.21,
|
"powerRetracted": 7.21,
|
||||||
"powerDeployed": 7.21,
|
"powerDeployed": 7.21,
|
||||||
"unladenRange": 32.48,
|
"unladenRange": 32.48,
|
||||||
"fullTankRange": 30.27,
|
|
||||||
"ladenRange": 19.61,
|
"ladenRange": 19.61,
|
||||||
"unladenFastestRange": 176.71,
|
"unladenFastestRange": 176.71,
|
||||||
"ladenFastestRange": 112.92,
|
"ladenFastestRange": 112.92,
|
||||||
@@ -249,7 +248,6 @@
|
|||||||
"powerRetracted": 9.33,
|
"powerRetracted": 9.33,
|
||||||
"powerDeployed": 10.33,
|
"powerDeployed": 10.33,
|
||||||
"unladenRange": 30.24,
|
"unladenRange": 30.24,
|
||||||
"fullTankRange": 28.32,
|
|
||||||
"ladenRange": 19.8,
|
"ladenRange": 19.8,
|
||||||
"unladenFastestRange": 164.89,
|
"unladenFastestRange": 164.89,
|
||||||
"ladenFastestRange": 114.03,
|
"ladenFastestRange": 114.03,
|
||||||
@@ -379,7 +377,6 @@
|
|||||||
"powerRetracted": 7.28,
|
"powerRetracted": 7.28,
|
||||||
"powerDeployed": 8.06,
|
"powerDeployed": 8.06,
|
||||||
"unladenRange": 31.71,
|
"unladenRange": 31.71,
|
||||||
"fullTankRange": 29.61,
|
|
||||||
"ladenRange": 23.58,
|
"ladenRange": 23.58,
|
||||||
"unladenFastestRange": 172.68,
|
"unladenFastestRange": 172.68,
|
||||||
"ladenFastestRange": 136.46,
|
"ladenFastestRange": 136.46,
|
||||||
@@ -511,7 +508,6 @@
|
|||||||
"powerRetracted": 8.81,
|
"powerRetracted": 8.81,
|
||||||
"powerDeployed": 8.81,
|
"powerDeployed": 8.81,
|
||||||
"unladenRange": 26.41,
|
"unladenRange": 26.41,
|
||||||
"fullTankRange": 24.97,
|
|
||||||
"ladenRange": 17.36,
|
"ladenRange": 17.36,
|
||||||
"unladenFastestRange": 172.04,
|
"unladenFastestRange": 172.04,
|
||||||
"ladenFastestRange": 118.55,
|
"ladenFastestRange": 118.55,
|
||||||
@@ -653,7 +649,6 @@
|
|||||||
"powerRetracted": 10.66,
|
"powerRetracted": 10.66,
|
||||||
"powerDeployed": 11.66,
|
"powerDeployed": 11.66,
|
||||||
"unladenRange": 25.77,
|
"unladenRange": 25.77,
|
||||||
"fullTankRange": 24.39,
|
|
||||||
"ladenRange": 17.98,
|
"ladenRange": 17.98,
|
||||||
"unladenFastestRange": 167.93,
|
"unladenFastestRange": 167.93,
|
||||||
"ladenFastestRange": 122.84,
|
"ladenFastestRange": 122.84,
|
||||||
@@ -791,7 +786,6 @@
|
|||||||
"powerRetracted": 8.95,
|
"powerRetracted": 8.95,
|
||||||
"powerDeployed": 9.73,
|
"powerDeployed": 9.73,
|
||||||
"unladenRange": 19.27,
|
"unladenRange": 19.27,
|
||||||
"fullTankRange": 18.95,
|
|
||||||
"ladenRange": 15.43,
|
"ladenRange": 15.43,
|
||||||
"unladenFastestRange": 67.34,
|
"unladenFastestRange": 67.34,
|
||||||
"ladenFastestRange": 54.75,
|
"ladenFastestRange": 54.75,
|
||||||
@@ -954,7 +948,6 @@
|
|||||||
"powerRetracted": 15.49,
|
"powerRetracted": 15.49,
|
||||||
"powerDeployed": 19.43,
|
"powerDeployed": 19.43,
|
||||||
"unladenRange": 27.1,
|
"unladenRange": 27.1,
|
||||||
"fullTankRange": 25.58,
|
|
||||||
"ladenRange": 21.94,
|
"ladenRange": 21.94,
|
||||||
"unladenFastestRange": 176.39,
|
"unladenFastestRange": 176.39,
|
||||||
"ladenFastestRange": 150.58,
|
"ladenFastestRange": 150.58,
|
||||||
@@ -1096,7 +1089,6 @@
|
|||||||
"powerRetracted": 10.38,
|
"powerRetracted": 10.38,
|
||||||
"powerDeployed": 12.58,
|
"powerDeployed": 12.58,
|
||||||
"unladenRange": 26.01,
|
"unladenRange": 26.01,
|
||||||
"fullTankRange": 25.42,
|
|
||||||
"ladenRange": 17.19,
|
"ladenRange": 17.19,
|
||||||
"unladenFastestRange": 90.67,
|
"unladenFastestRange": 90.67,
|
||||||
"ladenFastestRange": 61.04,
|
"ladenFastestRange": 61.04,
|
||||||
@@ -1260,7 +1252,6 @@
|
|||||||
"powerRetracted": 19.35,
|
"powerRetracted": 19.35,
|
||||||
"powerDeployed": 25.31,
|
"powerDeployed": 25.31,
|
||||||
"unladenRange": 15.19,
|
"unladenRange": 15.19,
|
||||||
"fullTankRange": 14.99,
|
|
||||||
"ladenRange": 14.99,
|
"ladenRange": 14.99,
|
||||||
"unladenFastestRange": 53.15,
|
"unladenFastestRange": 53.15,
|
||||||
"ladenFastestRange": 53.15,
|
"ladenFastestRange": 53.15,
|
||||||
@@ -1360,7 +1351,6 @@
|
|||||||
"powerRetracted": 10.7,
|
"powerRetracted": 10.7,
|
||||||
"powerDeployed": 10.7,
|
"powerDeployed": 10.7,
|
||||||
"unladenRange": 24.25,
|
"unladenRange": 24.25,
|
||||||
"fullTankRange": 23.73,
|
|
||||||
"ladenRange": 23.73,
|
"ladenRange": 23.73,
|
||||||
"unladenFastestRange": 84.56,
|
"unladenFastestRange": 84.56,
|
||||||
"ladenFastestRange": 84.56,
|
"ladenFastestRange": 84.56,
|
||||||
@@ -1499,7 +1489,6 @@
|
|||||||
"powerRetracted": 13.13,
|
"powerRetracted": 13.13,
|
||||||
"powerDeployed": 13.13,
|
"powerDeployed": 13.13,
|
||||||
"unladenRange": 19.51,
|
"unladenRange": 19.51,
|
||||||
"fullTankRange": 18.58,
|
|
||||||
"ladenRange": 13.09,
|
"ladenRange": 13.09,
|
||||||
"unladenFastestRange": 152.32,
|
"unladenFastestRange": 152.32,
|
||||||
"ladenFastestRange": 106.49,
|
"ladenFastestRange": 106.49,
|
||||||
@@ -1637,7 +1626,6 @@
|
|||||||
"powerRetracted": 10.25,
|
"powerRetracted": 10.25,
|
||||||
"powerDeployed": 10.25,
|
"powerDeployed": 10.25,
|
||||||
"unladenRange": 28.25,
|
"unladenRange": 28.25,
|
||||||
"fullTankRange": 26.6,
|
|
||||||
"ladenRange": 16.67,
|
"ladenRange": 16.67,
|
||||||
"unladenFastestRange": 183.67,
|
"unladenFastestRange": 183.67,
|
||||||
"ladenFastestRange": 113.69,
|
"ladenFastestRange": 113.69,
|
||||||
@@ -1808,7 +1796,6 @@
|
|||||||
"powerRetracted": 19.34,
|
"powerRetracted": 19.34,
|
||||||
"powerDeployed": 26.18,
|
"powerDeployed": 26.18,
|
||||||
"unladenRange": 20.32,
|
"unladenRange": 20.32,
|
||||||
"fullTankRange": 19.46,
|
|
||||||
"ladenRange": 14.65,
|
"ladenRange": 14.65,
|
||||||
"unladenFastestRange": 133.17,
|
"unladenFastestRange": 133.17,
|
||||||
"ladenFastestRange": 99.65,
|
"ladenFastestRange": 99.65,
|
||||||
@@ -1987,7 +1974,6 @@
|
|||||||
"powerRetracted": 22.61,
|
"powerRetracted": 22.61,
|
||||||
"powerDeployed": 29.63,
|
"powerDeployed": 29.63,
|
||||||
"unladenRange": 14.32,
|
"unladenRange": 14.32,
|
||||||
"fullTankRange": 13.89,
|
|
||||||
"ladenRange": 13.46,
|
"ladenRange": 13.46,
|
||||||
"unladenFastestRange": 94.42,
|
"unladenFastestRange": 94.42,
|
||||||
"ladenFastestRange": 91.49,
|
"ladenFastestRange": 91.49,
|
||||||
@@ -2217,7 +2203,6 @@
|
|||||||
"powerRetracted": 25.88,
|
"powerRetracted": 25.88,
|
||||||
"powerDeployed": 37.51,
|
"powerDeployed": 37.51,
|
||||||
"unladenRange": 16.99,
|
"unladenRange": 16.99,
|
||||||
"fullTankRange": 16.68,
|
|
||||||
"ladenRange": 15.91,
|
"ladenRange": 15.91,
|
||||||
"unladenFastestRange": 67.35,
|
"unladenFastestRange": 67.35,
|
||||||
"ladenFastestRange": 64.2,
|
"ladenFastestRange": 64.2,
|
||||||
@@ -2372,7 +2357,6 @@
|
|||||||
"powerRetracted": 11.92,
|
"powerRetracted": 11.92,
|
||||||
"powerDeployed": 11.92,
|
"powerDeployed": 11.92,
|
||||||
"unladenRange": 39.26,
|
"unladenRange": 39.26,
|
||||||
"fullTankRange": 37.65,
|
|
||||||
"ladenRange": 21.21,
|
"ladenRange": 21.21,
|
||||||
"unladenFastestRange": 153.79,
|
"unladenFastestRange": 153.79,
|
||||||
"ladenFastestRange": 85.82,
|
"ladenFastestRange": 85.82,
|
||||||
@@ -2528,7 +2512,6 @@
|
|||||||
"powerRetracted": 12.49,
|
"powerRetracted": 12.49,
|
||||||
"powerDeployed": 12.49,
|
"powerDeployed": 12.49,
|
||||||
"unladenRange": 38.44,
|
"unladenRange": 38.44,
|
||||||
"fullTankRange": 36.89,
|
|
||||||
"ladenRange": 21.04,
|
"ladenRange": 21.04,
|
||||||
"unladenFastestRange": 150.62,
|
"unladenFastestRange": 150.62,
|
||||||
"ladenFastestRange": 85.16,
|
"ladenFastestRange": 85.16,
|
||||||
@@ -2696,7 +2679,6 @@
|
|||||||
"powerRetracted": 13,
|
"powerRetracted": 13,
|
||||||
"powerDeployed": 12.4,
|
"powerDeployed": 12.4,
|
||||||
"unladenRange": 38.04,
|
"unladenRange": 38.04,
|
||||||
"fullTankRange": 30.11,
|
|
||||||
"ladenRange": 23.03,
|
"ladenRange": 23.03,
|
||||||
"unladenFastestRange": 675.7,
|
"unladenFastestRange": 675.7,
|
||||||
"ladenFastestRange": 501.97,
|
"ladenFastestRange": 501.97,
|
||||||
@@ -2914,7 +2896,6 @@
|
|||||||
"powerRetracted": 23.93,
|
"powerRetracted": 23.93,
|
||||||
"powerDeployed": 35.56,
|
"powerDeployed": 35.56,
|
||||||
"unladenRange": 18.49,
|
"unladenRange": 18.49,
|
||||||
"fullTankRange": 18.12,
|
|
||||||
"ladenRange": 16.39,
|
"ladenRange": 16.39,
|
||||||
"unladenFastestRange": 73.21,
|
"unladenFastestRange": 73.21,
|
||||||
"ladenFastestRange": 66.15,
|
"ladenFastestRange": 66.15,
|
||||||
@@ -3042,7 +3023,6 @@
|
|||||||
"powerRetracted": 8.48,
|
"powerRetracted": 8.48,
|
||||||
"powerDeployed": 7.88,
|
"powerDeployed": 7.88,
|
||||||
"unladenRange": 35.99,
|
"unladenRange": 35.99,
|
||||||
"fullTankRange": 33.36,
|
|
||||||
"ladenRange": 33.36,
|
"ladenRange": 33.36,
|
||||||
"unladenFastestRange": 232.28,
|
"unladenFastestRange": 232.28,
|
||||||
"ladenFastestRange": 232.28,
|
"ladenFastestRange": 232.28,
|
||||||
@@ -3179,7 +3159,6 @@
|
|||||||
"powerRetracted": 14.87,
|
"powerRetracted": 14.87,
|
||||||
"powerDeployed": 17.51,
|
"powerDeployed": 17.51,
|
||||||
"unladenRange": 15.06,
|
"unladenRange": 15.06,
|
||||||
"fullTankRange": 14.86,
|
|
||||||
"ladenRange": 14.86,
|
"ladenRange": 14.86,
|
||||||
"unladenFastestRange": 42.5,
|
"unladenFastestRange": 42.5,
|
||||||
"ladenFastestRange": 42.5,
|
"ladenFastestRange": 42.5,
|
||||||
@@ -3333,7 +3312,6 @@
|
|||||||
"powerRetracted": 17.71,
|
"powerRetracted": 17.71,
|
||||||
"powerDeployed": 23.14,
|
"powerDeployed": 23.14,
|
||||||
"unladenRange": 12.51,
|
"unladenRange": 12.51,
|
||||||
"fullTankRange": 12.38,
|
|
||||||
"ladenRange": 12.38,
|
"ladenRange": 12.38,
|
||||||
"unladenFastestRange": 35.35,
|
"unladenFastestRange": 35.35,
|
||||||
"ladenFastestRange": 35.35,
|
"ladenFastestRange": 35.35,
|
||||||
@@ -3452,7 +3430,6 @@
|
|||||||
"powerRetracted": 9.46,
|
"powerRetracted": 9.46,
|
||||||
"powerDeployed": 11.17,
|
"powerDeployed": 11.17,
|
||||||
"unladenRange": 17.12,
|
"unladenRange": 17.12,
|
||||||
"fullTankRange": 16.71,
|
|
||||||
"ladenRange": 16.71,
|
"ladenRange": 16.71,
|
||||||
"unladenFastestRange": 42.4,
|
"unladenFastestRange": 42.4,
|
||||||
"ladenFastestRange": 42.4,
|
"ladenFastestRange": 42.4,
|
||||||
@@ -3610,7 +3587,6 @@
|
|||||||
"powerRetracted": 9.31,
|
"powerRetracted": 9.31,
|
||||||
"powerDeployed": 13.91,
|
"powerDeployed": 13.91,
|
||||||
"unladenRange": 8.43,
|
"unladenRange": 8.43,
|
||||||
"fullTankRange": 8.09,
|
|
||||||
"ladenRange": 7.25,
|
"ladenRange": 7.25,
|
||||||
"unladenFastestRange": 81.5,
|
"unladenFastestRange": 81.5,
|
||||||
"ladenFastestRange": 72.9,
|
"ladenFastestRange": 72.9,
|
||||||
|
|||||||
@@ -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]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -6,41 +6,70 @@ import TU from 'react-testutils-additions';
|
|||||||
|
|
||||||
let origAddEventListener = window.addEventListener;
|
let origAddEventListener = window.addEventListener;
|
||||||
let storageListener;
|
let storageListener;
|
||||||
let ls = {};
|
|
||||||
|
|
||||||
// Implment mock localStorage
|
/**
|
||||||
let localStorage = {
|
* Mock local storage
|
||||||
getItem: function(key) {
|
*/
|
||||||
return ls[key];
|
class LocalStorage {
|
||||||
},
|
/**
|
||||||
setItem: function(key, value) {
|
* Sets up storage variable
|
||||||
ls[key] = value;
|
*/
|
||||||
},
|
constructor() {
|
||||||
removeItem: function(key) {
|
this.ls = {};
|
||||||
delete ls[key];
|
}
|
||||||
},
|
|
||||||
clear: function() {
|
/**
|
||||||
ls = {};
|
* Retrieves a value from local storage
|
||||||
|
* @param {String} key Storage key
|
||||||
|
* @return {*} Storage value
|
||||||
|
*/
|
||||||
|
getItem(key) {
|
||||||
|
return this.ls[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes a value to local storage
|
||||||
|
* @param {String} key Storage key
|
||||||
|
* @param {*} value Storage value
|
||||||
|
*/
|
||||||
|
setItem(key, value) {
|
||||||
|
this.ls[key] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears a value from local storage
|
||||||
|
* @param {String} key Storage key
|
||||||
|
*/
|
||||||
|
removeItem(key) {
|
||||||
|
delete this.ls[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears local storage
|
||||||
|
*/
|
||||||
|
clear() {
|
||||||
|
this.ls = {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener = function(eventName, listener) {
|
const LOCAL_STORAGE = new LocalStorage();
|
||||||
|
|
||||||
|
window.addEventListener = function(eventName, listener) {
|
||||||
if(eventName == 'storage') {
|
if(eventName == 'storage') {
|
||||||
storageListener = listener; // Keep track of latest storage listener
|
storageListener = listener; // Keep track of latest storage listener
|
||||||
} else {
|
} else {
|
||||||
origAddEventListener.apply(arguments);
|
origAddEventListener.apply(arguments);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
describe('Persist', function() {
|
describe('Persist', function() {
|
||||||
|
|
||||||
const Persist = require('../src/app/stores/Persist').Persist;
|
const Persist = require('../src/app/stores/Persist').Persist;
|
||||||
|
|
||||||
describe('Multi tab/window', function() {
|
describe('Multi tab/window', function() {
|
||||||
it("syncs builds", function() {
|
it("syncs builds", function() {
|
||||||
window.localStorage = localStorage;
|
window.localStorage = localStorage;
|
||||||
ls = {};
|
localStorage.clear();
|
||||||
|
|
||||||
let p = new Persist();
|
let p = new Persist();
|
||||||
let newBuilds = {
|
let newBuilds = {
|
||||||
anaconda: { test: '1234' }
|
anaconda: { test: '1234' }
|
||||||
@@ -54,7 +83,8 @@ describe('Persist', function() {
|
|||||||
describe('General and Settings', function() {
|
describe('General and Settings', function() {
|
||||||
it("has defaults", function() {
|
it("has defaults", function() {
|
||||||
window.localStorage = localStorage;
|
window.localStorage = localStorage;
|
||||||
ls = {};
|
localStorage.clear();
|
||||||
|
|
||||||
let p = new Persist();
|
let p = new Persist();
|
||||||
expect(p.getLangCode()).toBe('en');
|
expect(p.getLangCode()).toBe('en');
|
||||||
expect(p.showTooltips()).toBe(true);
|
expect(p.showTooltips()).toBe(true);
|
||||||
@@ -65,14 +95,14 @@ describe('Persist', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("loads from localStorage correctly", function() {
|
it("loads from localStorage correctly", function() {
|
||||||
window.localStorage = localStorage;
|
window.localStorage = LOCAL_STORAGE;
|
||||||
let savedData = require('./fixtures/valid-backup');
|
let savedData = require('./fixtures/valid-backup');
|
||||||
ls = {};
|
LOCAL_STORAGE.clear();
|
||||||
ls.builds = JSON.stringify(savedData.builds);
|
LOCAL_STORAGE.setItem('builds', JSON.stringify(savedData.builds));
|
||||||
ls.NG_TRANSLATE_LANG_KEY = 'de';
|
LOCAL_STORAGE.setItem('NG_TRANSLATE_LANG_KEY', 'de');
|
||||||
ls.insurance = 'Standard';
|
LOCAL_STORAGE.setItem('insurance', 'Standard');
|
||||||
ls.shipDiscount = 0.25;
|
LOCAL_STORAGE.setItem('shipDiscount', 0.25);
|
||||||
ls.moduleDiscount = 0.15;
|
LOCAL_STORAGE.setItem('moduleDiscount', 0.15);
|
||||||
let p = new Persist();
|
let p = new Persist();
|
||||||
|
|
||||||
expect(p.getInsurance()).toBe('standard');
|
expect(p.getInsurance()).toBe('standard');
|
||||||
@@ -86,13 +116,13 @@ describe('Persist', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("uses defaults from a corrupted localStorage", function() {
|
it("uses defaults from a corrupted localStorage", function() {
|
||||||
window.localStorage = localStorage;
|
window.localStorage = LOCAL_STORAGE;
|
||||||
ls = {};
|
LOCAL_STORAGE.clear();
|
||||||
ls.builds = "not valid json";
|
LOCAL_STORAGE.setItem('builds', 'not valid json');
|
||||||
ls.comparisons = "1, 3, 4";
|
LOCAL_STORAGE.setItem('comparisons', '1, 3, 4');
|
||||||
ls.insurance = 'this insurance does not exist';
|
LOCAL_STORAGE.setItem('insurance', 'this insurance does not exist');
|
||||||
ls.shipDiscount = 'this is not a number';
|
LOCAL_STORAGE.setItem('shipDiscount', 'this is not a number');
|
||||||
ls.moduleDiscount = 10; // Way to big
|
LOCAL_STORAGE.setItem('moduleDiscount', 10); // Way to big
|
||||||
|
|
||||||
let p = new Persist();
|
let p = new Persist();
|
||||||
expect(p.getLangCode()).toBe('en');
|
expect(p.getLangCode()).toBe('en');
|
||||||
@@ -122,13 +152,13 @@ describe('Persist', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("generates the backup", function() {
|
it("generates the backup", function() {
|
||||||
window.localStorage = localStorage;
|
window.localStorage = LOCAL_STORAGE;
|
||||||
let savedData = require('./fixtures/valid-backup');
|
let savedData = require('./fixtures/valid-backup');
|
||||||
ls = {};
|
LOCAL_STORAGE.clear();
|
||||||
ls.builds = JSON.stringify(savedData.builds);
|
LOCAL_STORAGE.setItem('builds', JSON.stringify(savedData.builds));
|
||||||
ls.insurance = 'Beta';
|
LOCAL_STORAGE.setItem('insurance', 'Beta');
|
||||||
ls.shipDiscount = 0.25;
|
LOCAL_STORAGE.setItem('shipDiscount', 0.25);
|
||||||
ls.moduleDiscount = 0.15;
|
LOCAL_STORAGE.setItem('moduleDiscount', 0.15);
|
||||||
|
|
||||||
let p = new Persist();
|
let p = new Persist();
|
||||||
let backup = p.getAll();
|
let backup = p.getAll();
|
||||||
@@ -140,4 +170,4 @@ describe('Persist', function() {
|
|||||||
expect(backup.comparisons).toEqual({});
|
expect(backup.comparisons).toEqual({});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
});
|
||||||
|
|||||||
@@ -3,32 +3,31 @@ import { Ships } from 'coriolis-data/dist';
|
|||||||
import * as ModuleUtils from '../src/app/shipyard/ModuleUtils';
|
import * as ModuleUtils from '../src/app/shipyard/ModuleUtils';
|
||||||
|
|
||||||
describe("Ship", function() {
|
describe("Ship", function() {
|
||||||
|
for (let s in Ships) {
|
||||||
it("can build all ships", function() {
|
it("can build " + s, function() {
|
||||||
for (let s in Ships) {
|
|
||||||
let shipData = Ships[s];
|
let shipData = Ships[s];
|
||||||
let ship = new Ship(s, shipData.properties, shipData.slots);
|
let ship = new Ship(s, shipData.properties, shipData.slots);
|
||||||
|
|
||||||
for (let p in shipData.properties) {
|
for (let p in shipData.properties) {
|
||||||
expect(ship[p]).toEqual(shipData.properties[p], s + ' property [' + p + '] does not match when built');
|
expect(ship[p]).toEqual(shipData.properties[p]);
|
||||||
}
|
}
|
||||||
|
|
||||||
ship.buildWith(shipData.defaults);
|
ship.buildWith(shipData.defaults);
|
||||||
|
|
||||||
expect(ship.totalCost).toEqual(shipData.retailCost, s + ' retail cost does not match default build cost');
|
expect(ship.totalCost).toEqual(shipData.retailCost);
|
||||||
expect(ship.cargoCapacity).toBeDefined();
|
expect(ship.cargoCapacity).toBeDefined();
|
||||||
expect(ship.priorityBands[0].retracted).toBeGreaterThan(0, s + ' priorityBands');
|
expect(ship.priorityBands[0].retracted).toBeGreaterThan(0);
|
||||||
expect(ship.powerAvailable).toBeGreaterThan(0, s + ' powerAvailable');
|
expect(ship.powerAvailable).toBeGreaterThan(0);
|
||||||
expect(ship.unladenRange).toBeGreaterThan(0, s + ' unladenRange');
|
expect(ship.unladenRange).toBeGreaterThan(0);
|
||||||
expect(ship.ladenRange).toBeGreaterThan(0, s + ' ladenRange');
|
expect(ship.ladenRange).toBeGreaterThan(0);
|
||||||
expect(ship.fuelCapacity).toBeGreaterThan(0, s + ' fuelCapacity');
|
expect(ship.fuelCapacity).toBeGreaterThan(0);
|
||||||
expect(ship.unladenFastestRange).toBeGreaterThan(0, s + ' unladenFastestRange');
|
expect(ship.unladenFastestRange).toBeGreaterThan(0);
|
||||||
expect(ship.ladenFastestRange).toBeGreaterThan(0, s + ' ladenFastestRange');
|
expect(ship.ladenFastestRange).toBeGreaterThan(0);
|
||||||
expect(ship.shield).toBeGreaterThan(0, s + ' shield');
|
expect(ship.shield).toBeGreaterThan(0);
|
||||||
expect(ship.armour).toBeGreaterThan(0, s + ' armour');
|
expect(ship.armour).toBeGreaterThan(0);
|
||||||
expect(ship.topSpeed).toBeGreaterThan(0, s + ' topSpeed');
|
expect(ship.topSpeed).toBeGreaterThan(0);
|
||||||
}
|
});
|
||||||
});
|
}
|
||||||
|
|
||||||
it("resets and rebuilds properly", function() {
|
it("resets and rebuilds properly", function() {
|
||||||
var id = 'cobra_mk_iii';
|
var id = 'cobra_mk_iii';
|
||||||
|
|||||||
11
devServer.js
11
devServer.js
@@ -3,13 +3,24 @@ var WebpackDevServer = require("webpack-dev-server");
|
|||||||
var config = require('./webpack.config.dev');
|
var config = require('./webpack.config.dev');
|
||||||
|
|
||||||
new WebpackDevServer(webpack(config), {
|
new WebpackDevServer(webpack(config), {
|
||||||
|
publicPath: config.output.publicPath,
|
||||||
hot: true,
|
hot: true,
|
||||||
|
disableHostCheck: true,
|
||||||
headers: { "Access-Control-Allow-Origin": "*" },
|
headers: { "Access-Control-Allow-Origin": "*" },
|
||||||
historyApiFallback: {
|
historyApiFallback: {
|
||||||
rewrites: [
|
rewrites: [
|
||||||
// For some reason connect-history-api-fallback does not allow '.' in the URL for history fallback...
|
// For some reason connect-history-api-fallback does not allow '.' in the URL for history fallback...
|
||||||
{ from: /\/outfit\//, to: '/index.html' }
|
{ from: /\/outfit\//, to: '/index.html' }
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
stats: {
|
||||||
|
assets: true,
|
||||||
|
colors: true,
|
||||||
|
version: false,
|
||||||
|
hash: false,
|
||||||
|
timings: true,
|
||||||
|
chunks: false,
|
||||||
|
chunkModules: false
|
||||||
}
|
}
|
||||||
}).listen(3300, "0.0.0.0", function (err, result) {
|
}).listen(3300, "0.0.0.0", function (err, result) {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|||||||
59
nginx.conf
Normal file
59
nginx.conf
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
worker_processes 2;
|
||||||
|
error_log ./nginx.error.log;
|
||||||
|
worker_rlimit_nofile 8192;
|
||||||
|
pid nginx.pid;
|
||||||
|
|
||||||
|
events {
|
||||||
|
worker_connections 1024;
|
||||||
|
multi_accept on;
|
||||||
|
}
|
||||||
|
|
||||||
|
http {
|
||||||
|
|
||||||
|
access_log off;
|
||||||
|
charset UTF-8;
|
||||||
|
|
||||||
|
types {
|
||||||
|
text/html html htm shtml;
|
||||||
|
text/css css;
|
||||||
|
text/xml xml rss;
|
||||||
|
image/gif gif;
|
||||||
|
image/jpeg jpeg jpg;
|
||||||
|
application/x-javascript js;
|
||||||
|
text/plain txt;
|
||||||
|
image/png png;
|
||||||
|
image/svg+xml svg;
|
||||||
|
image/x-icon ico;
|
||||||
|
application/pdf pdf;
|
||||||
|
text/cache-manifest appcache;
|
||||||
|
}
|
||||||
|
|
||||||
|
gzip on;
|
||||||
|
gzip_vary on;
|
||||||
|
gzip_proxied any;
|
||||||
|
gzip_comp_level 6;
|
||||||
|
gzip_buffers 16 8k;
|
||||||
|
gzip_http_version 1.1;
|
||||||
|
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 3301;
|
||||||
|
server_name localhost;
|
||||||
|
root ./build/;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
location ~* \.(?:manifest|appcache|html?|xml|json|css|js|map|jpg|jpeg|gif|png|ico|svg|eot|ttf|woff|woff2)$ {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
12992
package-lock.json
generated
12992
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
99
package.json
99
package.json
@@ -1,19 +1,14 @@
|
|||||||
{
|
{
|
||||||
"name": "coriolis_shipyard",
|
"name": "coriolis_shipyard",
|
||||||
"version": "3.0.1",
|
"version": "3.0.0",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/EDCD/coriolis"
|
"url": "https://github.com/EDCD/coriolis"
|
||||||
},
|
},
|
||||||
"homepage": "https://coriolis.io",
|
"homepage": "https://coriolis.edcd.io",
|
||||||
"bugs": "https://github.com/EDCD/coriolis/issues",
|
"bugs": "https://github.com/EDCD/coriolis/issues",
|
||||||
"contributors": [
|
|
||||||
{ "name": "cmdrmcdonald" },
|
|
||||||
{ "name": "willb321" },
|
|
||||||
{ "name": "felixlinker" }
|
|
||||||
],
|
|
||||||
"private": true,
|
"private": true,
|
||||||
"engine": "node >= 10.13.0",
|
"engine": "node >= 4.8.1",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"extract-translations": "grep -hroE \"(translate\\('[^']+'\\))|(tip.bind\\(null, '[^']+')\" src/* | grep -oE \"'[^']+'\" | grep -oE \"[^']+\" | sort -u -f",
|
"extract-translations": "grep -hroE \"(translate\\('[^']+'\\))|(tip.bind\\(null, '[^']+')\" src/* | grep -oE \"'[^']+'\" | grep -oE \"[^']+\" | sort -u -f",
|
||||||
@@ -23,8 +18,7 @@
|
|||||||
"test": "jest",
|
"test": "jest",
|
||||||
"prod-serve": "nginx -p $(pwd) -c nginx.conf",
|
"prod-serve": "nginx -p $(pwd) -c nginx.conf",
|
||||||
"prod-stop": "kill -QUIT $(cat nginx.pid)",
|
"prod-stop": "kill -QUIT $(cat nginx.pid)",
|
||||||
"buildfresh": "rimraf node_modules && rm package-lock.json && npm install && npm run build > >(tee -a stdout.log) 2> >(tee -a stderr.log >&2)",
|
"build": "npm run clean && cross-env NODE_ENV=production webpack -p --config webpack.config.prod.js",
|
||||||
"build": "npm run clean && cross-env NODE_ENV=production webpack --config webpack.config.prod.js",
|
|
||||||
"rsync": "rsync -ae \"ssh -i $CORIOLIS_PEM\" --delete build/ $CORIOLIS_USER@$CORIOLIS_HOST:~/wwws",
|
"rsync": "rsync -ae \"ssh -i $CORIOLIS_PEM\" --delete build/ $CORIOLIS_USER@$CORIOLIS_HOST:~/wwws",
|
||||||
"deploy": "npm run lint && npm test && npm run build && npm run rsync"
|
"deploy": "npm run lint && npm test && npm run build && npm run rsync"
|
||||||
},
|
},
|
||||||
@@ -61,7 +55,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.20.12",
|
"@babel/core": "^7.0.0",
|
||||||
"@babel/plugin-proposal-class-properties": "^7.0.0",
|
"@babel/plugin-proposal-class-properties": "^7.0.0",
|
||||||
"@babel/plugin-proposal-decorators": "^7.0.0",
|
"@babel/plugin-proposal-decorators": "^7.0.0",
|
||||||
"@babel/plugin-proposal-do-expressions": "^7.0.0",
|
"@babel/plugin-proposal-do-expressions": "^7.0.0",
|
||||||
@@ -80,12 +74,15 @@
|
|||||||
"@babel/plugin-syntax-import-meta": "^7.0.0",
|
"@babel/plugin-syntax-import-meta": "^7.0.0",
|
||||||
"@babel/preset-env": "^7.0.0",
|
"@babel/preset-env": "^7.0.0",
|
||||||
"@babel/preset-react": "^7.0.0",
|
"@babel/preset-react": "^7.0.0",
|
||||||
"@rollup/plugin-node-resolve": "^15.0.1",
|
"appcache-webpack-plugin": "^1.4.0",
|
||||||
|
"babel-core": "^7.0.0-bridge.0",
|
||||||
|
"babel-eslint": "^10.0.1",
|
||||||
|
"babel-jest": "^23.6.0",
|
||||||
"babel-loader": "^8.0.0",
|
"babel-loader": "^8.0.0",
|
||||||
"copy-webpack-plugin": "^10.2.4",
|
"copy-webpack-plugin": "^4.5.2",
|
||||||
"create-react-class": "^15.6.3",
|
"create-react-class": "^15.6.3",
|
||||||
"cross-env": "^5.2.0",
|
"cross-env": "^5.2.0",
|
||||||
"css-loader": "^6.7.3",
|
"css-loader": "^1.0.0",
|
||||||
"d3-selection": "^1.3.2",
|
"d3-selection": "^1.3.2",
|
||||||
"esdoc": "^1.1.0",
|
"esdoc": "^1.1.0",
|
||||||
"esdoc-custom-theme": "^1.4.2",
|
"esdoc-custom-theme": "^1.4.2",
|
||||||
@@ -96,66 +93,52 @@
|
|||||||
"esdoc-standard-plugin": "^1.0.0",
|
"esdoc-standard-plugin": "^1.0.0",
|
||||||
"eslint": "^5.6.0",
|
"eslint": "^5.6.0",
|
||||||
"eslint-plugin-react": "^7.11.1",
|
"eslint-plugin-react": "^7.11.1",
|
||||||
"expose-loader": "^3.1.0",
|
"expose-loader": "^0.7.5",
|
||||||
"express": "^4.18.2",
|
"express": "^4.16.3",
|
||||||
"html-webpack-plugin": "^5.5.0",
|
"extract-text-webpack-plugin": "^4.0.0-beta.0",
|
||||||
"jsen": "^0.6.6",
|
"file-loader": "^2.0.0",
|
||||||
|
"html-webpack-plugin": "^3.0.7",
|
||||||
|
"jest-cli": "^23.6.0",
|
||||||
|
"jsen": "^0.6.4",
|
||||||
"json-loader": "^0.5.4",
|
"json-loader": "^0.5.4",
|
||||||
"less": "^3.8.1",
|
"less": "^3.8.1",
|
||||||
"less-loader": "^11.1.0",
|
"less-loader": "^4.1.0",
|
||||||
"mini-css-extract-plugin": "^2.7.2",
|
"react-addons-perf": "^15.4.2",
|
||||||
"react-container-dimensions": "^1.4.1",
|
"react-container-dimensions": "^1.4.1",
|
||||||
"react-testutils-additions": "^15.0.0",
|
"react-testutils-additions": "^16.0.0",
|
||||||
"react-transition-group": "^2.5.0",
|
"react-transition-group": "^2.5.0",
|
||||||
"rimraf": "^4.1.2",
|
"rimraf": "^2.6.1",
|
||||||
"rollup": "^3.17.2",
|
"rollup": "^0.66.2",
|
||||||
"style-loader": "^3.3.1",
|
"rollup-plugin-node-resolve": "^3.4.0",
|
||||||
"uglify-js": "^3.17.4",
|
"style-loader": "^0.23.0",
|
||||||
"webpack": "^5.75.0",
|
"uglify-js": "^3.4.9",
|
||||||
"webpack-cli": "^5.0.1",
|
"url-loader": "^1.1.1",
|
||||||
"webpack-dev-server": "^4.11.1",
|
"webpack": "^4.20.2",
|
||||||
"webpack-merge": "^5.8.0",
|
"webpack-bugsnag-plugins": "^1.2.2",
|
||||||
"webpack-notifier": "^1.15.0",
|
"webpack-cli": "^3.1.1",
|
||||||
"workbox-cacheable-response": "^6.5.4",
|
"webpack-dev-server": "^3.1.9",
|
||||||
"workbox-expiration": "^6.5.4",
|
"webpack-notifier": "^1.6.0",
|
||||||
"workbox-precaching": "^6.5.4",
|
"workbox-webpack-plugin": "^3.6.1"
|
||||||
"workbox-routing": "^6.5.4",
|
|
||||||
"workbox-strategies": "^6.5.4",
|
|
||||||
"workbox-webpack-plugin": "^6.5.4"
|
|
||||||
},
|
},
|
||||||
"sideEffects": false,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"assert": "^1.5.0",
|
"@babel/polyfill": "^7.0.0",
|
||||||
"auto-bind": "^5.0.1",
|
|
||||||
"base64url": "^3.0.1",
|
|
||||||
"browserify-zlib-next": "^1.0.1",
|
"browserify-zlib-next": "^1.0.1",
|
||||||
"buffer": "^5.7.0",
|
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
"constants-browserify": "^1.0.0",
|
|
||||||
"core-js": "^3.28.0",
|
|
||||||
"coriolis-data": "../coriolis-data",
|
"coriolis-data": "../coriolis-data",
|
||||||
"crypto-browserify": "^3.12.0",
|
|
||||||
"d3": "^5.7.0",
|
"d3": "^5.7.0",
|
||||||
"detect-browser": "^3.0.1",
|
"detect-browser": "^3.0.1",
|
||||||
"fbemitter": "^2.1.1",
|
"fbemitter": "^2.1.1",
|
||||||
"https-browserify": "^1.0.0",
|
|
||||||
"lodash": "^4.17.11",
|
"lodash": "^4.17.11",
|
||||||
"lz-string": "^1.4.4",
|
"lz-string": "^1.4.4",
|
||||||
"os-browserify": "^0.3.0",
|
"pako": "^1.0.6",
|
||||||
"pako": "^2.1.0",
|
|
||||||
"path-browserify": "^1.0.1",
|
|
||||||
"prop-types": "^15.6.2",
|
"prop-types": "^15.6.2",
|
||||||
"react": "^15.6.2",
|
"react": "^15.5.4",
|
||||||
"react-dom": "^15.6.2",
|
"react-dom": "^15.5.4",
|
||||||
"react-fuzzy": "^0.5.2",
|
"react-extras": "^0.7.1",
|
||||||
"react-ga": "^2.5.3",
|
"react-ga": "^2.5.3",
|
||||||
"react-number-editor": "^4.0.3",
|
"react-number-editor": "Athanasius/react-number-editor.git#miggy",
|
||||||
"recharts": "^1.2.0",
|
"recharts": "^1.2.0",
|
||||||
"register-service-worker": "^1.7.2",
|
"register-service-worker": "^1.5.2",
|
||||||
"stream-browserify": "^3.0.0",
|
"superagent": "^3.8.3"
|
||||||
"stream-http": "^3.2.0",
|
|
||||||
"superagent": "^3.8.3",
|
|
||||||
"url": "^0.11.0",
|
|
||||||
"vm-browserify": "^1.1.2"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import nodeResolve from "@rollup/plugin-node-resolve";
|
import nodeResolve from "rollup-plugin-node-resolve";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
entry: "d3-funcs.js",
|
entry: "d3-funcs.js",
|
||||||
|
|||||||
@@ -214,7 +214,7 @@ Options -MultiViews
|
|||||||
# </Files>
|
# </Files>
|
||||||
|
|
||||||
AddType application/x-web-app-manifest+json webapp
|
AddType application/x-web-app-manifest+json webapp
|
||||||
# AddType text/cache-manifest appcache manifest
|
AddType text/cache-manifest appcache manifest
|
||||||
|
|
||||||
# Media files
|
# Media files
|
||||||
AddType audio/mp4 f4a f4b m4a
|
AddType audio/mp4 f4a f4b m4a
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import Router from './Router';
|
import Router from './Router';
|
||||||
import { register } from 'register-service-worker';
|
import { register } from 'register-service-worker'
|
||||||
import { EventEmitter } from 'fbemitter';
|
import { EventEmitter } from 'fbemitter';
|
||||||
import { getLanguage } from './i18n/Language';
|
import { getLanguage } from './i18n/Language';
|
||||||
import Persist from './stores/Persist';
|
import Persist from './stores/Persist';
|
||||||
|
|
||||||
import Announcement from './components/Announcement';
|
|
||||||
import Header from './components/Header';
|
import Header from './components/Header';
|
||||||
import Tooltip from './components/Tooltip';
|
import Tooltip from './components/Tooltip';
|
||||||
import ModalExport from './components/ModalExport';
|
import ModalExport from './components/ModalExport';
|
||||||
@@ -15,6 +14,7 @@ import ModalImport from './components/ModalImport';
|
|||||||
import ModalPermalink from './components/ModalPermalink';
|
import ModalPermalink from './components/ModalPermalink';
|
||||||
import * as CompanionApiUtils from './utils/CompanionApiUtils';
|
import * as CompanionApiUtils from './utils/CompanionApiUtils';
|
||||||
import * as JournalUtils from './utils/JournalUtils';
|
import * as JournalUtils from './utils/JournalUtils';
|
||||||
|
|
||||||
import AboutPage from './pages/AboutPage';
|
import AboutPage from './pages/AboutPage';
|
||||||
import NotFoundPage from './pages/NotFoundPage';
|
import NotFoundPage from './pages/NotFoundPage';
|
||||||
import OutfittingPage from './pages/OutfittingPage';
|
import OutfittingPage from './pages/OutfittingPage';
|
||||||
@@ -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));
|
||||||
@@ -93,39 +93,32 @@ export default class Coriolis extends React.Component {
|
|||||||
_importBuild(r) {
|
_importBuild(r) {
|
||||||
try {
|
try {
|
||||||
// Need to decode and gunzip the data, then build the ship
|
// Need to decode and gunzip the data, then build the ship
|
||||||
const data = zlib.inflate(new Buffer.from(r.params.data, 'base64'), { to: 'string' });
|
const data = zlib.inflate(new Buffer(r.params.data, 'base64'), { to: 'string' });
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_getAnnouncements() {
|
||||||
|
return request.get('https://orbis.zone/api/announcement')
|
||||||
|
.query({showInCoriolis: true})
|
||||||
|
.then(announces => {
|
||||||
|
this.setState({ announcements: announces.body })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
@@ -149,6 +142,13 @@ export default class Coriolis extends React.Component {
|
|||||||
*/
|
*/
|
||||||
_onError(msg, scriptUrl, line, col, errObj) {
|
_onError(msg, scriptUrl, line, col, errObj) {
|
||||||
console && console.error && console.error(arguments); // eslint-disable-line no-console
|
console && console.error && console.error(arguments); // eslint-disable-line no-console
|
||||||
|
if (errObj) {
|
||||||
|
if (errObj instanceof Error) {
|
||||||
|
bugsnagClient.notify(errObj); // eslint-disable-line
|
||||||
|
} else if (errObj instanceof String) {
|
||||||
|
bugsnagClient.notify(msg, errObj); // eslint-disable-line
|
||||||
|
}
|
||||||
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
error: <ErrorDetails error={{ message: msg, details: { scriptUrl, line, col, error: JSON.stringify(errObj) } }}/>,
|
error: <ErrorDetails error={{ message: msg, details: { scriptUrl, line, col, error: JSON.stringify(errObj) } }}/>,
|
||||||
page: null,
|
page: null,
|
||||||
@@ -344,37 +344,37 @@ export default class Coriolis extends React.Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
if ('serviceWorker' in navigator) {
|
if ('serviceWorker' in navigator) {
|
||||||
// Your service-worker.js *must* be located at the top-level directory relative to your site.
|
window.addEventListener('load', () => {
|
||||||
// It won't be able to control pages unless it's located at the same level or higher than them.
|
// Your service-worker.js *must* be located at the top-level directory relative to your site.
|
||||||
// *Don't* register service worker file in, e.g., a scripts/ sub-directory!
|
// It won't be able to control pages unless it's located at the same level or higher than them.
|
||||||
// See https://github.com/slightlyoff/ServiceWorker/issues/468
|
// *Don't* register service worker file in, e.g., a scripts/ sub-directory!
|
||||||
const self = this;
|
// See https://github.com/slightlyoff/ServiceWorker/issues/468
|
||||||
if (process.env.NODE_ENV === 'production') {
|
const self = this;
|
||||||
register('/service-worker.js', {
|
register('/service-worker.js', {
|
||||||
ready(registration) {
|
ready (registration) {
|
||||||
console.log('Service worker is active.');
|
console.log('Service worker is active.')
|
||||||
},
|
},
|
||||||
registered(registration) {
|
registered (registration) {
|
||||||
console.log('Service worker has been registered.');
|
console.log('Service worker has been registered.')
|
||||||
},
|
},
|
||||||
cached(registration) {
|
cached (registration) {
|
||||||
console.log('Content has been cached for offline use.');
|
console.log('Content has been cached for offline use.')
|
||||||
},
|
},
|
||||||
updatefound(registration) {
|
updatefound (registration) {
|
||||||
console.log('New content is downloading.');
|
console.log('New content is downloading.')
|
||||||
},
|
},
|
||||||
updated(registration) {
|
updated (registration) {
|
||||||
self.setState({ appCacheUpdate: true });
|
self.setState({ appCacheUpdate: true });
|
||||||
console.log('New content is available; please refresh.');
|
console.log('New content is available; please refresh.')
|
||||||
},
|
},
|
||||||
offline() {
|
offline () {
|
||||||
console.log('No internet connection found. App is running in offline mode.');
|
console.log('No internet connection found. App is running in offline mode.')
|
||||||
},
|
},
|
||||||
error(error) {
|
error (error) {
|
||||||
console.error('Error during service worker registration:', error);
|
console.error('Error during service worker registration:', error)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
window.onerror = this._onError.bind(this);
|
window.onerror = this._onError.bind(this);
|
||||||
window.addEventListener('resize', () => this.emitter.emit('windowResize'));
|
window.addEventListener('resize', () => this.emitter.emit('windowResize'));
|
||||||
@@ -392,26 +392,22 @@ 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
|
|
||||||
text={a.text}/>)}</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"
|
||||||
title="Coriolis Github Project">{window.CORIOLIS_VERSION} - {window.CORIOLIS_DATE}</a>
|
title="Coriolis Github Project">{window.CORIOLIS_VERSION} - {window.CORIOLIS_DATE}</a>
|
||||||
<br/>
|
<br/>
|
||||||
<a
|
<a
|
||||||
href={'https://github.com/EDCD/coriolis/compare/edcd:develop@{' + window.CORIOLIS_DATE + '}...edcd:develop'}
|
href={'https://github.com/EDCD/coriolis/compare/edcd:develop@{' + window.CORIOLIS_DATE + '}...edcd:develop'}
|
||||||
target="_blank" rel="noopener noreferrer" title={'Coriolis Commits since' + window.CORIOLIS_DATE}>Commits
|
target="_blank" title={'Coriolis Commits since' + window.CORIOLIS_DATE}>Commits since last release
|
||||||
since last release
|
|
||||||
({window.CORIOLIS_DATE})</a>
|
({window.CORIOLIS_DATE})</a>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
|||||||
@@ -1,5 +1,13 @@
|
|||||||
import Persist from './stores/Persist';
|
// Check whether a test is run because then we need to
|
||||||
|
// initialize ReactGA in test mode
|
||||||
|
let isTest = false;
|
||||||
|
try {
|
||||||
|
isTest = process.env.node_env === 'test';
|
||||||
|
} catch (e) {}
|
||||||
|
|
||||||
|
import Persist from './stores/Persist';
|
||||||
|
import ReactGA from 'react-ga';
|
||||||
|
ReactGA.initialize('UA-55840909-18', { testMode: isTest });
|
||||||
let standalone = undefined;
|
let standalone = undefined;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -72,7 +80,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 +265,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import autoBind from 'auto-bind';
|
import { autoBind } from 'react-extras';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Announcement component
|
* Announcement component
|
||||||
@@ -25,7 +25,7 @@ export default class Announcement extends React.Component {
|
|||||||
* @return {React.Component} A href element
|
* @return {React.Component} A href element
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
return <div className="announcement" >{this.props.text}</div>;
|
return <p>{this.props.text}</p>;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,7 @@ import * as ModuleUtils from '../shipyard/ModuleUtils';
|
|||||||
import TranslatedComponent from './TranslatedComponent';
|
import TranslatedComponent from './TranslatedComponent';
|
||||||
import { stopCtxPropagation } from '../utils/UtilityFunctions';
|
import { stopCtxPropagation } from '../utils/UtilityFunctions';
|
||||||
import cn from 'classnames';
|
import cn from 'classnames';
|
||||||
import { CoriolisLogo, MountFixed, MountGimballed, MountTurret } from './SvgIcons';
|
import { MountFixed, MountGimballed, MountTurret } from './SvgIcons';
|
||||||
import FuzzySearch from 'react-fuzzy';
|
|
||||||
|
|
||||||
const PRESS_THRESHOLD = 500; // mouse/touch down threshold
|
const PRESS_THRESHOLD = 500; // mouse/touch down threshold
|
||||||
|
|
||||||
@@ -20,7 +19,6 @@ const GRPCAT = {
|
|||||||
'cc': 'limpet controllers',
|
'cc': 'limpet controllers',
|
||||||
'fx': 'limpet controllers',
|
'fx': 'limpet controllers',
|
||||||
'hb': 'limpet controllers',
|
'hb': 'limpet controllers',
|
||||||
'mlc': 'limpet controllers',
|
|
||||||
'pc': 'limpet controllers',
|
'pc': 'limpet controllers',
|
||||||
'rpl': 'limpet controllers',
|
'rpl': 'limpet controllers',
|
||||||
'pce': 'passenger cabins',
|
'pce': 'passenger cabins',
|
||||||
@@ -39,17 +37,13 @@ const GRPCAT = {
|
|||||||
'ml': 'lasers',
|
'ml': 'lasers',
|
||||||
'c': 'projectiles',
|
'c': 'projectiles',
|
||||||
'mc': 'projectiles',
|
'mc': 'projectiles',
|
||||||
'advmc': 'projectiles',
|
|
||||||
'axmc': 'experimental',
|
'axmc': 'experimental',
|
||||||
'axmce': 'experimental',
|
|
||||||
'ntp': 'experimental',
|
|
||||||
'fc': 'projectiles',
|
'fc': 'projectiles',
|
||||||
'rfl': 'experimental',
|
'rfl': 'experimental',
|
||||||
'pa': 'projectiles',
|
'pa': 'projectiles',
|
||||||
'rg': 'projectiles',
|
'rg': 'projectiles',
|
||||||
'mr': 'ordnance',
|
'mr': 'ordnance',
|
||||||
'axmr': 'experimental',
|
'axmr': 'experimental',
|
||||||
'axmre': 'experimental',
|
|
||||||
'rcpl': 'experimental',
|
'rcpl': 'experimental',
|
||||||
'dtl': 'experimental',
|
'dtl': 'experimental',
|
||||||
'tbsc': 'experimental',
|
'tbsc': 'experimental',
|
||||||
@@ -78,18 +72,7 @@ const GRPCAT = {
|
|||||||
'gfsb': 'guardian',
|
'gfsb': 'guardian',
|
||||||
'gmrp': 'guardian',
|
'gmrp': 'guardian',
|
||||||
'gsc': 'guardian',
|
'gsc': 'guardian',
|
||||||
'ghrp': 'guardian',
|
'ghrp': 'guardian'
|
||||||
|
|
||||||
// Mining
|
|
||||||
'scl': 'mining',
|
|
||||||
'pwa': 'mining',
|
|
||||||
'sdm': 'mining',
|
|
||||||
|
|
||||||
// Assists
|
|
||||||
'dc': 'flight assists',
|
|
||||||
'sua': 'flight assists',
|
|
||||||
// Stabilizers
|
|
||||||
'ews': 'weapon stabilizers',
|
|
||||||
};
|
};
|
||||||
// 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 = {
|
||||||
@@ -99,30 +82,26 @@ const CATEGORIES = {
|
|||||||
'fi': ['fi'],
|
'fi': ['fi'],
|
||||||
'fuel': ['ft', 'fs'],
|
'fuel': ['ft', 'fs'],
|
||||||
'hangars': ['fh', 'pv'],
|
'hangars': ['fh', 'pv'],
|
||||||
'limpet controllers': ['cc', 'fx', 'hb', 'pc', 'rpl', 'mlc'],
|
'limpet controllers': ['cc', 'fx', 'hb', 'pc', 'rpl'],
|
||||||
'passenger cabins': ['pce', 'pci', 'pcm', 'pcq'],
|
'passenger cabins': ['pce', 'pci', 'pcm', 'pcq'],
|
||||||
'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', 'ml'],
|
||||||
'projectiles': ['mc', 'advmc', 'c', 'fc', 'pa', 'rg'],
|
'projectiles': ['mc', 'c', 'fc', 'pa', 'rg'],
|
||||||
'ordnance': ['mr', 'tp', 'nl'],
|
'ordnance': ['mr', 'tp', 'nl'],
|
||||||
// Utilities
|
// Utilities
|
||||||
'sb': ['sb'],
|
'sb': ['sb'],
|
||||||
'hs': ['hs'],
|
'hs': ['hs'],
|
||||||
'csl': ['csl'],
|
|
||||||
'defence': ['ch', 'po', 'ec'],
|
'defence': ['ch', 'po', 'ec'],
|
||||||
'scanners': ['sc', 'ss', 'cs', 'kw', 'ws'], // Overloaded with internal scanners
|
'scanners': ['sc', 'ss', 'cs', 'kw', 'ws'], // Overloaded with internal scanners
|
||||||
// Experimental
|
// Experimental
|
||||||
'experimental': ['axmc', 'axmce', 'axmr', 'axmre', 'ntp','rfl', 'tbrfl', 'tbsc', 'tbem', 'xs', 'sfn', 'rcpl', 'dtl', 'rsl', 'mahr',],
|
'experimental': ['axmc', 'axmr', 'rfl', 'tbrfl', 'tbsc', 'tbem', 'xs', 'sfn', 'rcpl', 'dtl', 'rsl', 'mahr',],
|
||||||
'weapon stabilizers': ['ews'],
|
|
||||||
// Guardian
|
|
||||||
'guardian': ['gpp', 'gpd', 'gpc', 'ggc', 'gsrp', 'gfsb', 'ghrp', 'gmrp', 'gsc'],
|
|
||||||
|
|
||||||
'mining': ['ml', 'scl', 'pwa', 'sdm', 'abl'],
|
// Guardian
|
||||||
|
'guardian': ['gpp', 'gpd', 'gpc', 'ggc', 'gsrp', 'gfsb', 'ghrp', 'gmrp', 'gsc']
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -134,7 +113,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,
|
||||||
@@ -142,6 +121,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
|
||||||
@@ -150,7 +133,6 @@ export default class AvailableModulesMenu extends TranslatedComponent {
|
|||||||
constructor(props, context) {
|
constructor(props, context) {
|
||||||
super(props);
|
super(props);
|
||||||
this._hideDiff = this._hideDiff.bind(this);
|
this._hideDiff = this._hideDiff.bind(this);
|
||||||
this._showSearch = this._showSearch.bind(this);
|
|
||||||
this.state = this._initState(props, context);
|
this.state = this._initState(props, context);
|
||||||
this.slotItems = [];// Array to hold <li> refs.
|
this.slotItems = [];// Array to hold <li> refs.
|
||||||
}
|
}
|
||||||
@@ -163,21 +145,21 @@ 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);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
let fuzzy = [];
|
|
||||||
if (modules instanceof Array) {
|
if (modules instanceof Array) {
|
||||||
list = buildGroup(modules[0].grp, modules);
|
list = buildGroup(modules[0].grp, modules);
|
||||||
} else {
|
} else {
|
||||||
@@ -185,11 +167,9 @@ export default class AvailableModulesMenu extends TranslatedComponent {
|
|||||||
// At present time slots with grouped options (Hardpoints and Internal) can be empty
|
// At present time slots with grouped options (Hardpoints and Internal) can be empty
|
||||||
if (m) {
|
if (m) {
|
||||||
let emptyId = 'empty';
|
let emptyId = 'empty';
|
||||||
if (this.firstSlotId == null) this.firstSlotId = emptyId;
|
if(this.firstSlotId == null) this.firstSlotId = emptyId;
|
||||||
let keyDown = this._keyDown.bind(this, onSelect);
|
let keyDown = this._keyDown.bind(this, onSelect);
|
||||||
list.push(<div className='empty-c upp' key={emptyId} data-id={emptyId} onClick={onSelect.bind(null, null)}
|
list.push(<div className='empty-c upp' key={emptyId} data-id={emptyId} onClick={onSelect.bind(null, null)} onKeyDown={keyDown} tabIndex="0" ref={slotItem => this.slotItems[emptyId] = slotItem} >{translate('empty')}</div>);
|
||||||
onKeyDown={keyDown} tabIndex="0"
|
|
||||||
ref={slotItem => this.slotItems[emptyId] = slotItem}>{translate('empty')}</div>);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Need to regroup the modules by our own categorisation
|
// Need to regroup the modules by our own categorisation
|
||||||
@@ -217,124 +197,70 @@ export default class AvailableModulesMenu extends TranslatedComponent {
|
|||||||
if (categories.length === 1) {
|
if (categories.length === 1) {
|
||||||
// Show category header instead of group header
|
// Show category header instead of group header
|
||||||
if (m && grp == m.grp) {
|
if (m && grp == m.grp) {
|
||||||
// If this is a missing module/weapon, skip it
|
list.push(<div ref={(elem) => this.groupElem = elem} key={category} className={'select-category upp'}>{translate(category)}</div>);
|
||||||
if (m.grp == "mh" || m.grp == "mm"){
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
list.push(<div ref={(elem) => this.groupElem = elem} key={category}
|
|
||||||
className={'select-category upp'}>{translate(category)}</div>);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (category == "mh"){
|
list.push(<div key={category} className={'select-category upp'}>{translate(category)}</div>);
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
list.push(<div key={category} className={'select-category upp'}>{translate(category)}</div>);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Show category header as well as group header
|
// Show category header as well as group header
|
||||||
if (!categoryHeader) {
|
if (!categoryHeader) {
|
||||||
if (category == "mh"){
|
list.push(<div key={category} className={'select-category upp'}>{translate(category)}</div>);
|
||||||
continue;
|
categoryHeader = true;
|
||||||
}
|
|
||||||
else {
|
|
||||||
list.push(<div key={category} className={'select-category upp'}>{translate(category)}</div>);
|
|
||||||
categoryHeader = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (m && grp == m.grp) {
|
if (m && grp == m.grp) {
|
||||||
list.push(<div ref={(elem) => this.groupElem = elem} key={grp}
|
list.push(<div ref={(elem) => this.groupElem = elem} key={grp} className={'select-group cap'}>{translate(grp)}</div>);
|
||||||
className={'select-group cap'}>{translate(grp)}</div>);
|
|
||||||
} else {
|
} else {
|
||||||
list.push(<div key={grp} className={'select-group cap'}>{translate(grp)}</div>);
|
list.push(<div key={grp} className={'select-group cap'}>{translate(grp)}</div>);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
list.push(buildGroup(grp, modules[grp]));
|
list.push(buildGroup(grp, modules[grp]));
|
||||||
for (const i of modules[grp]) {
|
|
||||||
let mount = '';
|
|
||||||
if (i.mount === 'F') {
|
|
||||||
mount = 'Fixed';
|
|
||||||
} else if (i.mount === 'G') {
|
|
||||||
mount = 'Gimballed';
|
|
||||||
} else if (i.mount === 'T') {
|
|
||||||
mount = 'Turreted';
|
|
||||||
}
|
|
||||||
const fuzz = { grp, m: i, name: `${i.class}${i.rating}${mount ? ' ' + mount : ''} ${translate(grp)}` };
|
|
||||||
fuzzy.push(fuzz);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let trackingFocus = false;
|
let trackingFocus = false;
|
||||||
return { list, currentGroup, fuzzy, trackingFocus };
|
return { list, currentGroup, trackingFocus };
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return Is expiremental capacity reached
|
|
||||||
* @return {boolean} Is experimental capacity reached
|
|
||||||
*/
|
|
||||||
_experimentalCapacityReached() {
|
|
||||||
const ship = this.props.ship;
|
|
||||||
const ews = ship.internal.filter(o => o.m && o.m.grp === 'ews');
|
|
||||||
let expCap;
|
|
||||||
|
|
||||||
if(ews.length < 1){
|
|
||||||
expCap = 4;
|
|
||||||
} else{
|
|
||||||
expCap = ews[0].m.class == 3 ? 5 : 6;
|
|
||||||
}
|
|
||||||
|
|
||||||
return expCap <= this.props.ship.hardpoints.filter(o => o.m && o.m.experimental).length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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 = [];
|
||||||
|
|
||||||
const sortedModules = modules.sort(this._moduleOrder);
|
const sortedModules = modules.sort(this._moduleOrder);
|
||||||
|
|
||||||
|
|
||||||
// Calculate the number of items per class. Used so we don't have long lists with only a few items in each row
|
// Calculate the number of items per class. Used so we don't have long lists with only a few items in each row
|
||||||
const tmp = sortedModules.map((v, i) => v['class']).reduce((count, cls) => {
|
const tmp = sortedModules.map((v, i) => v['class']).reduce((count, cls) => { count[cls] = ++count[cls] || 1; return count; }, {});
|
||||||
count[cls] = ++count[cls] || 1;
|
|
||||||
return count;
|
|
||||||
}, {});
|
|
||||||
const itemsPerClass = Math.max.apply(null, Object.keys(tmp).map(key => tmp[key]));
|
const itemsPerClass = Math.max.apply(null, Object.keys(tmp).map(key => tmp[key]));
|
||||||
|
|
||||||
let itemsOnThisRow = 0;
|
let itemsOnThisRow = 0;
|
||||||
for (let i = 0; i < sortedModules.length; i++) {
|
for (let i = 0; i < sortedModules.length; i++) {
|
||||||
let m = sortedModules[i];
|
let m = sortedModules[i];
|
||||||
if (m.grp == 'mh' || m.grp == 'mm') {
|
|
||||||
// If this is a missing module, skip it
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let mount = null;
|
let mount = null;
|
||||||
let disabled = false;
|
let disabled = false;
|
||||||
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 = this._experimentalCapacityReached();
|
|
||||||
} else if (m.grp === 'mlc' && (!mountedModule || mountedModule.grp !== 'mlc')) {
|
|
||||||
disabled = 1 <= ship.internal.filter(o => o.m && o.m.grp === 'mlc').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', {
|
||||||
warning: !disabled && warningFunc && warningFunc(m),
|
warning: !disabled && warningFunc && warningFunc(m),
|
||||||
active,
|
active,
|
||||||
@@ -371,29 +297,22 @@ export default class AvailableModulesMenu extends TranslatedComponent {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (m.mount) {
|
switch(m.mount) {
|
||||||
case 'F':
|
case 'F': mount = <MountFixed className={'lg'} />; break;
|
||||||
mount = <MountFixed className={'lg'}/>;
|
case 'G': mount = <MountGimballed className={'lg'}/>; break;
|
||||||
break;
|
case 'T': mount = <MountTurret className={'lg'}/>; break;
|
||||||
case 'G':
|
|
||||||
mount = <MountGimballed className={'lg'}/>;
|
|
||||||
break;
|
|
||||||
case 'T':
|
|
||||||
mount = <MountTurret className={'lg'}/>;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (m.name && m.name === prevName) {
|
if (m.name && m.name === prevName) {
|
||||||
// elems.push(<br key={'b' + m.grp + i} />);
|
// elems.push(<br key={'b' + m.grp + i} />);
|
||||||
itemsOnThisRow = 0;
|
itemsOnThisRow = 0;
|
||||||
}
|
}
|
||||||
if (itemsOnThisRow == 6 || i > 0 && sortedModules.length > 3 && itemsPerClass > 2 && m.class != prevClass && (m.rating != prevRating || m.mount)) {
|
if (itemsOnThisRow == 6 || i > 0 && sortedModules.length > 3 && itemsPerClass > 2 && m.class != prevClass && (m.rating != prevRating || m.mount)) {
|
||||||
elems.push(<br key={'b' + m.grp + i}/>);
|
elems.push(<br key={'b' + m.grp + i} />);
|
||||||
itemsOnThisRow = 0;
|
itemsOnThisRow = 0;
|
||||||
}
|
}
|
||||||
let tbIdx = (classes.indexOf('disabled') < 0) ? 0 : undefined;
|
let tbIdx = (classes.indexOf('disabled') < 0) ? 0 : undefined;
|
||||||
elems.push(
|
elems.push(
|
||||||
<li key={m.id} data-id={m.id} className={classes} {...eventHandlers} tabIndex={tbIdx}
|
<li key={m.id} data-id={m.id} className={classes} {...eventHandlers} tabIndex={tbIdx} ref={slotItem => this.slotItems[m.id] = slotItem}>
|
||||||
ref={slotItem => this.slotItems[m.id] = slotItem}>
|
|
||||||
{mount}
|
{mount}
|
||||||
{(mount ? ' ' : '') + m.class + m.rating + (m.missile ? '/' + m.missile : '') + (m.name ? ' ' + translate(m.name) : '')}
|
{(mount ? ' ' : '') + m.class + m.rating + (m.missile ? '/' + m.missile : '') + (m.name ? ' ' + translate(m.name) : '')}
|
||||||
</li>
|
</li>
|
||||||
@@ -421,50 +340,6 @@ export default class AvailableModulesMenu extends TranslatedComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate tooltip content for the difference between the
|
|
||||||
* mounted module and the hovered modules
|
|
||||||
*/
|
|
||||||
_showSearch() {
|
|
||||||
if (this.props.modules instanceof Array) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const mountedModule = this.props.m;
|
|
||||||
return (
|
|
||||||
<FuzzySearch
|
|
||||||
list={this.state.fuzzy}
|
|
||||||
keys={['grp', 'name']}
|
|
||||||
tokenize={true}
|
|
||||||
className={'input'}
|
|
||||||
width={'100%'}
|
|
||||||
style={{ padding: 0 }}
|
|
||||||
onSelect={e => this.props.onSelect.bind(null, e.m)()}
|
|
||||||
resultsTemplate={(props, state, styles, clickHandler) => {
|
|
||||||
return state.results.map((val, i) => {
|
|
||||||
let disabled;
|
|
||||||
|
|
||||||
if(val.m.experimental && (!mountedModule || !mountedModule.experimental)) {
|
|
||||||
disabled = this._experimentalCapacityReached();
|
|
||||||
} else{
|
|
||||||
disabled = false;
|
|
||||||
}
|
|
||||||
const handler = disabled ? null : () => clickHandler(i);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
key={i}
|
|
||||||
className={cn('lc', {disabled})}
|
|
||||||
onClick={handler}
|
|
||||||
>
|
|
||||||
{val.name}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mouse over diff handler
|
* Mouse over diff handler
|
||||||
* @param {Function} showDiff diff tooltip callback
|
* @param {Function} showDiff diff tooltip callback
|
||||||
@@ -530,7 +405,7 @@ export default class AvailableModulesMenu extends TranslatedComponent {
|
|||||||
* @param {Function} select Select module callback
|
* @param {Function} select Select module callback
|
||||||
* @param {SytheticEvent} event Event
|
* @param {SytheticEvent} event Event
|
||||||
*/
|
*/
|
||||||
_keyUp(select, event) {
|
_keyUp(select,event) {
|
||||||
// nothing here yet
|
// nothing here yet
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -573,15 +448,6 @@ export default class AvailableModulesMenu extends TranslatedComponent {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Sort multi limpet controllers by name
|
|
||||||
if (a.grp === 'mlc') {
|
|
||||||
if (a.name[0] <= b.name[0]) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (a.name[0] > b.name[0]) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Rating ordered from highest (A) to lowest (E)
|
// Rating ordered from highest (A) to lowest (E)
|
||||||
if (a.rating < b.rating) {
|
if (a.rating < b.rating) {
|
||||||
return -1;
|
return -1;
|
||||||
@@ -609,13 +475,12 @@ export default class AvailableModulesMenu extends TranslatedComponent {
|
|||||||
this.slotItems[this.firstSlotId].focus();
|
this.slotItems[this.firstSlotId].focus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle focus if the component updates
|
* Handle focus if the component updates
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
if (this.props.slotDiv) {
|
if(this.props.slotDiv) {
|
||||||
this.props.slotDiv.focus();
|
this.props.slotDiv.focus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -636,12 +501,11 @@ export default class AvailableModulesMenu extends TranslatedComponent {
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div ref={node => this.node = node}
|
<div ref={node => this.node = node}
|
||||||
className={cn('select', this.props.className)}
|
className={cn('select', this.props.className)}
|
||||||
onScroll={this._hideDiff}
|
onScroll={this._hideDiff}
|
||||||
onClick={(e) => e.stopPropagation()}
|
onClick={(e) => e.stopPropagation() }
|
||||||
onContextMenu={stopCtxPropagation}
|
onContextMenu={stopCtxPropagation}
|
||||||
>
|
>
|
||||||
{this._showSearch()}
|
|
||||||
{this.state.list}
|
{this.state.list}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ export default class CostSection extends TranslatedComponent {
|
|||||||
this._buildRetrofitShip = this._buildRetrofitShip.bind(this);
|
this._buildRetrofitShip = this._buildRetrofitShip.bind(this);
|
||||||
this._onBaseRetrofitChange = this._onBaseRetrofitChange.bind(this);
|
this._onBaseRetrofitChange = this._onBaseRetrofitChange.bind(this);
|
||||||
this._defaultRetrofitName = this._defaultRetrofitName.bind(this);
|
this._defaultRetrofitName = this._defaultRetrofitName.bind(this);
|
||||||
this._eddbShoppingList = this._inaraShoppingList.bind(this);
|
this._eddbShoppingList = this._eddbShoppingList.bind(this);
|
||||||
|
|
||||||
let data = Ships[props.ship.id]; // Retrieve the basic ship properties, slots and defaults
|
let data = Ships[props.ship.id]; // Retrieve the basic ship properties, slots and defaults
|
||||||
let retrofitName = this._defaultRetrofitName(props.ship.id, props.buildName);
|
let retrofitName = this._defaultRetrofitName(props.ship.id, props.buildName);
|
||||||
@@ -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>
|
||||||
@@ -328,9 +328,9 @@ export default class CostSection extends TranslatedComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open up a window for inara with a shopping list of our retrofit components
|
* Open up a window for EDDB with a shopping list of our retrofit components
|
||||||
*/
|
*/
|
||||||
_inaraShoppingList() {
|
_eddbShoppingList() {
|
||||||
const { retrofitCosts } = this.state;
|
const { retrofitCosts } = this.state;
|
||||||
const { ship } = this.props;
|
const { ship } = this.props;
|
||||||
|
|
||||||
@@ -338,7 +338,7 @@ export default class CostSection extends TranslatedComponent {
|
|||||||
const modIds = retrofitCosts.filter(item => item.retroItem.incCost && item.buyId && !item.buyPp).map(item => item.buyId).filter((v, i, a) => a.indexOf(v) === i);
|
const modIds = retrofitCosts.filter(item => item.retroItem.incCost && item.buyId && !item.buyPp).map(item => item.buyId).filter((v, i, a) => a.indexOf(v) === i);
|
||||||
|
|
||||||
// Open up the relevant URL
|
// Open up the relevant URL
|
||||||
window.open('https://inara.cz/inapi/corisearch.php?m=' + modIds.join(','));
|
window.open('https://eddb.io/station?m=' + modIds.join(','));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -387,7 +387,7 @@ export default class CostSection extends TranslatedComponent {
|
|||||||
<tbody>
|
<tbody>
|
||||||
{rows}
|
{rows}
|
||||||
<tr className='ri'>
|
<tr className='ri'>
|
||||||
<td className='lbl' ><button onClick={this._inaraShoppingList} onMouseOver={termtip.bind(null, 'PHRASE_REFIT_SHOPPING_LIST')} onMouseOut={tooltip.bind(null, null)}><ShoppingIcon className='lg' style={{ fill: 'black' }}/></button></td>
|
<td className='lbl' ><button onClick={this._eddbShoppingList} onMouseOver={termtip.bind(null, 'PHRASE_REFIT_SHOPPING_LIST')} onMouseOut={tooltip.bind(null, null)}><ShoppingIcon className='lg' style={{ fill: 'black' }}/></button></td>
|
||||||
<td colSpan='3' className='lbl' >{translate('cost')}</td>
|
<td colSpan='3' className='lbl' >{translate('cost')}</td>
|
||||||
<td colSpan='2' className={cn('val', retrofitTotal > 0 ? 'warning' : 'secondary-disabled')} style={{ borderBottom:'none' }}>
|
<td colSpan='2' className={cn('val', retrofitTotal > 0 ? 'warning' : 'secondary-disabled')} style={{ borderBottom:'none' }}>
|
||||||
{int(retrofitTotal)}{units.CR}
|
{int(retrofitTotal)}{units.CR}
|
||||||
|
|||||||
@@ -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 = [];
|
||||||
|
|||||||
@@ -2,21 +2,12 @@ import React from 'react';
|
|||||||
import cn from 'classnames';
|
import cn from 'classnames';
|
||||||
import Slot from './Slot';
|
import Slot from './Slot';
|
||||||
import Persist from '../stores/Persist';
|
import Persist from '../stores/Persist';
|
||||||
import {
|
import { DamageAbsolute, DamageKinetic, DamageThermal, DamageExplosive, MountFixed, MountGimballed, MountTurret, ListModifications, Modified } from './SvgIcons';
|
||||||
DamageAbsolute,
|
|
||||||
DamageKinetic,
|
|
||||||
DamageThermal,
|
|
||||||
DamageExplosive,
|
|
||||||
MountFixed,
|
|
||||||
MountGimballed,
|
|
||||||
MountTurret,
|
|
||||||
ListModifications,
|
|
||||||
Modified
|
|
||||||
} from './SvgIcons';
|
|
||||||
import { Modifications } from 'coriolis-data/dist';
|
import { Modifications } from 'coriolis-data/dist';
|
||||||
import { stopCtxPropagation } from '../utils/UtilityFunctions';
|
import { stopCtxPropagation } from '../utils/UtilityFunctions';
|
||||||
import { blueprintTooltip } from '../utils/BlueprintFunctions';
|
import { blueprintTooltip } from '../utils/BlueprintFunctions';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hardpoint / Utility Slot
|
* Hardpoint / Utility Slot
|
||||||
*/
|
*/
|
||||||
@@ -36,7 +27,7 @@ export default class HardpointSlot extends Slot {
|
|||||||
* @return {string} Label
|
* @return {string} Label
|
||||||
*/
|
*/
|
||||||
_getMaxClassLabel(translate) {
|
_getMaxClassLabel(translate) {
|
||||||
return translate(['U', 'S', 'M', 'L', 'H'][this.props.maxClass]);
|
return translate(['U','S','M','L','H'][this.props.maxClass]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -75,77 +66,42 @@ export default class HardpointSlot extends Slot {
|
|||||||
return <div className={className} draggable='true' onDragStart={drag} onDragEnd={drop}>
|
return <div className={className} draggable='true' onDragStart={drag} onDragEnd={drop}>
|
||||||
<div className={'cb'}>
|
<div className={'cb'}>
|
||||||
<div className={'l'}>
|
<div className={'l'}>
|
||||||
{m.mount && m.mount == 'F' ? <span onMouseOver={termtip.bind(null, 'fixed')}
|
{m.mount && m.mount == 'F' ? <span onMouseOver={termtip.bind(null, 'fixed')} onMouseOut={tooltip.bind(null, null)}><MountFixed /></span> : ''}
|
||||||
onMouseOut={tooltip.bind(null, null)}><MountFixed/></span> : ''}
|
{m.mount && m.mount == 'G' ? <span onMouseOver={termtip.bind(null, 'gimballed')} onMouseOut={tooltip.bind(null, null)}><MountGimballed /></span> : ''}
|
||||||
{m.mount && m.mount == 'G' ? <span onMouseOver={termtip.bind(null, 'gimballed')}
|
{m.mount && m.mount == 'T' ? <span onMouseOver={termtip.bind(null, 'turreted')} onMouseOut={tooltip.bind(null, null)}><MountTurret /></span> : ''}
|
||||||
onMouseOut={tooltip.bind(null, null)}><MountGimballed/></span> : ''}
|
{m.getDamageDist() && m.getDamageDist().K ? <span onMouseOver={termtip.bind(null, 'kinetic')} onMouseOut={tooltip.bind(null, null)}><DamageKinetic /></span> : ''}
|
||||||
{m.mount && m.mount == 'T' ? <span onMouseOver={termtip.bind(null, 'turreted')}
|
{m.getDamageDist() && m.getDamageDist().T ? <span onMouseOver={termtip.bind(null, 'thermal')} onMouseOut={tooltip.bind(null, null)}><DamageThermal /></span> : ''}
|
||||||
onMouseOut={tooltip.bind(null, null)}><MountTurret/></span> : ''}
|
{m.getDamageDist() && m.getDamageDist().E ? <span onMouseOver={termtip.bind(null, 'explosive')} onMouseOut={tooltip.bind(null, null)}><DamageExplosive /></span> : ''}
|
||||||
{m.getDamageDist() && m.getDamageDist().K ? <span onMouseOver={termtip.bind(null, 'kinetic')}
|
{m.getDamageDist() && m.getDamageDist().A ? <span onMouseOver={termtip.bind(null, 'absolute')} onMouseOut={tooltip.bind(null, null)}><DamageAbsolute /></span> : ''}
|
||||||
onMouseOut={tooltip.bind(null, null)}><DamageKinetic/></span> : ''}
|
{classRating} {translate(m.name || m.grp)}{ m.mods && Object.keys(m.mods).length > 0 ? <span className='r' onMouseOver={termtip.bind(null, modTT)} onMouseOut={tooltip.bind(null, null)}><Modified /></span> : null }
|
||||||
{m.getDamageDist() && m.getDamageDist().T ? <span onMouseOver={termtip.bind(null, 'thermal')}
|
|
||||||
onMouseOut={tooltip.bind(null, null)}><DamageThermal/></span> : ''}
|
|
||||||
{m.getDamageDist() && m.getDamageDist().E ? <span onMouseOver={termtip.bind(null, 'explosive')}
|
|
||||||
onMouseOut={tooltip.bind(null, null)}><DamageExplosive/></span> : ''}
|
|
||||||
{m.getDamageDist() && m.getDamageDist().A ? <span onMouseOver={termtip.bind(null, 'absolute')}
|
|
||||||
onMouseOut={tooltip.bind(null, null)}><DamageAbsolute/></span> : ''}
|
|
||||||
{classRating} {translate(m.name || m.grp)}{m.mods && Object.keys(m.mods).length > 0 ? <span className='r'
|
|
||||||
onMouseOver={termtip.bind(null, modTT)}
|
|
||||||
onMouseOut={tooltip.bind(null, null)}><Modified/></span> : null}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={'r'}>{formats.round(m.getMass())}{u.T}</div>
|
<div className={'r'}>{formats.round(m.getMass())}{u.T}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={'cb'}>
|
<div className={'cb'}>
|
||||||
{m.getDps() ? <div className={'l'} onMouseOver={termtip.bind(null, m.getClip() ? 'dpssdps' : 'dps')}
|
{ m.getDps() ? <div className={'l'} onMouseOver={termtip.bind(null, m.getClip() ? 'dpssdps' : 'dps')} onMouseOut={tooltip.bind(null, null)}>{translate('DPS')}: {formats.round1(m.getDps())} { m.getClip() ? <span>({formats.round1(m.getSDps()) })</span> : null }</div> : null }
|
||||||
onMouseOut={tooltip.bind(null, null)}>{translate('DPS')}: {formats.round1(m.getDps())} {m.getClip() ?
|
{ 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() ? <span>({formats.round1((m.getClip() * m.getEps() / m.getRoF()) / ((m.getClip() / m.getRoF()) + m.getReload())) }{u.MW})</span> : null }</div> : null }
|
||||||
<span>({formats.round1(m.getSDps())})</span> : null}</div> : null}
|
{ 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() ? <span>({formats.round1((m.getClip() * m.getHps() / m.getRoF()) / ((m.getClip() / m.getRoF()) + m.getReload())) })</span> : null }</div> : null }
|
||||||
{m.getDamage() ? <div className={'l'} onMouseOver={termtip.bind(null, m.getDamage() ? 'shotdmg' : 'shotdmg')}
|
{ 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('shotdmg')}: {formats.round1(m.getDamage())}</div> : null}
|
{ m.getRoF() ? <div className={'l'} onMouseOver={termtip.bind(null, 'rof')} onMouseOut={tooltip.bind(null, null)}>{translate('ROF')}: {formats.f1(m.getRoF())}{u.ps}</div> : null }
|
||||||
{m.getEps() ? <div className={'l'} onMouseOver={termtip.bind(null, m.getClip() ? 'epsseps' : 'eps')}
|
{ m.getRange() ? <div className={'l'}>{translate('range', m.grp)} {formats.f1(m.getRange() / 1000)}{u.km}</div> : null }
|
||||||
onMouseOut={tooltip.bind(null, null)}>{translate('EPS')}: {formats.round1(m.getEps())}{u.MW} {m.getClip() ?
|
{ m.getScanTime() ? <div className={'l'}>{translate('scantime')} {formats.f1(m.getScanTime())}{u.s}</div> : null }
|
||||||
<span>({formats.round1(m.getEps() * m.getSustainedFactor())}{u.MW})</span> : null}</div> : null}
|
{ m.getFalloff() ? <div className={'l'}>{translate('falloff')} {formats.round(m.getFalloff() / 1000)}{u.km}</div> : null }
|
||||||
{m.getHps() ? <div className={'l'} onMouseOver={termtip.bind(null, m.getClip() ? 'hpsshps' : 'hps')}
|
{ m.getShieldBoost() ? <div className={'l'}>+{formats.pct1(m.getShieldBoost())}</div> : null }
|
||||||
onMouseOut={tooltip.bind(null, null)}>{translate('HPS')}: {formats.round1(m.getHps())} {m.getClip() ?
|
{ m.getAmmo() ? <div className={'l'}>{translate('ammunition')}: {formats.int(m.getClip())}/{formats.int(m.getAmmo())}</div> : null }
|
||||||
<span>({formats.round1(m.getHps() * m.getSustainedFactor())})</span> : null}</div> : null}
|
{ m.getReload() ? <div className={'l'}>{translate('reload')}: {formats.round(m.getReload())}{u.s}</div> : null }
|
||||||
{m.getDps() && m.getEps() ? <div className={'l'} onMouseOver={termtip.bind(null, 'dpe')}
|
{ m.getShotSpeed() ? <div className={'l'}>{translate('shotspeed')}: {formats.int(m.getShotSpeed())}{u.mps}</div> : null }
|
||||||
onMouseOut={tooltip.bind(null, null)}>{translate('DPE')}: {formats.f1(m.getDps() / m.getEps())}</div> : null}
|
{ m.getPiercing() ? <div className={'l'}>{translate('piercing')}: {formats.int(m.getPiercing())}</div> : null }
|
||||||
{m.getRoF() ? <div className={'l'} onMouseOver={termtip.bind(null, 'rof')}
|
{ m.getJitter() ? <div className={'l'}>{translate('jitter')}: {formats.f2(m.getJitter())}°</div> : null }
|
||||||
onMouseOut={tooltip.bind(null, null)}>{translate('ROF')}: {formats.f1(m.getRoF())}{u.ps}</div> : null}
|
{ showModuleResistances && m.getExplosiveResistance() ? <div className='l'>{translate('explres')}: {formats.pct(m.getExplosiveResistance())}</div> : null }
|
||||||
{m.getRange() ? <div
|
{ showModuleResistances && m.getKineticResistance() ? <div className='l'>{translate('kinres')}: {formats.pct(m.getKineticResistance())}</div> : null }
|
||||||
className={'l'}>{translate('range', m.grp)} {formats.f1(m.getRange() / 1000)}{u.km}</div> : null}
|
{ showModuleResistances && m.getThermalResistance() ? <div className='l'>{translate('thermres')}: {formats.pct(m.getThermalResistance())}</div> : null }
|
||||||
{m.getScanTime() ? <div
|
{ m.getIntegrity() ? <div className='l'>{translate('integrity')}: {formats.int(m.getIntegrity())}</div> : null }
|
||||||
className={'l'}>{translate('scantime')} {formats.f1(m.getScanTime())}{u.s}</div> : null}
|
{ m && validMods.length > 0 ? <div className='r' tabIndex="0" ref={ modButton => this.modButton = modButton }><button tabIndex="-1" onClick={this._toggleModifications.bind(this)} onContextMenu={stopCtxPropagation} onMouseOver={termtip.bind(null, 'modifications')} onMouseOut={tooltip.bind(null, null)}><ListModifications /></button></div> : null }
|
||||||
{m.getFalloff() ? <div
|
|
||||||
className={'l'}>{translate('falloff')} {formats.round(m.getFalloff() / 1000)}{u.km}</div> : null}
|
|
||||||
{m.getShieldBoost() ? <div className={'l'}>+{formats.pct1(m.getShieldBoost())}</div> : null}
|
|
||||||
{m.getAmmo() ? <div
|
|
||||||
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.getShotSpeed() ? <div
|
|
||||||
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.getJitter() ? <div className={'l'}>{translate('jitter')}: {formats.f2(m.getJitter())}°</div> : null}
|
|
||||||
{m.getScanAngle() ? <div className={'l'}>{translate('scan angle')}: {formats.f2(m.getScanAngle())}°</div> : null}
|
|
||||||
{m.getScanRange() ? <div className={'l'}>{translate('scan range')}: {formats.int(m.getScanRange())}{u.m}</div> : null}
|
|
||||||
{m.getMaxAngle() ? <div className={'l'}>{translate('max angle')}: {formats.f2(m.getMaxAngle())}°</div> : null}
|
|
||||||
{showModuleResistances && m.getExplosiveResistance() ? <div
|
|
||||||
className='l'>{translate('explres')}: {formats.pct(m.getExplosiveResistance())}</div> : null}
|
|
||||||
{showModuleResistances && m.getKineticResistance() ? <div
|
|
||||||
className='l'>{translate('kinres')}: {formats.pct(m.getKineticResistance())}</div> : null}
|
|
||||||
{showModuleResistances && m.getThermalResistance() ? <div
|
|
||||||
className='l'>{translate('thermres')}: {formats.pct(m.getThermalResistance())}</div> : null}
|
|
||||||
{m.getIntegrity() ? <div className='l'>{translate('integrity')}: {formats.int(m.getIntegrity())}</div> : null}
|
|
||||||
{m.getInfo() ? <div className='l'>{translate(m.getInfo())}</div> : null}
|
|
||||||
{m && validMods.length > 0 ? <div className='r' tabIndex="0" ref={modButton => this.modButton = modButton}>
|
|
||||||
<button tabIndex="-1" onClick={this._toggleModifications.bind(this)} onContextMenu={stopCtxPropagation}
|
|
||||||
onMouseOver={termtip.bind(null, 'modifications')} onMouseOut={tooltip.bind(null, null)}>
|
|
||||||
<ListModifications/></button>
|
|
||||||
</div> : null}
|
|
||||||
</div>
|
</div>
|
||||||
</div>;
|
</div>;
|
||||||
} else {
|
} else {
|
||||||
return <div className={'empty'}>{translate('empty')}</div>;
|
return <div className={'empty'}>{translate('empty')}</div>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -149,19 +149,10 @@ 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('rfl')}</div>
|
|
||||||
<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', 'T')} onKeyDown={this._keyDown} ref={smRef => this.sectionRefArr['rfl-T'] = smRef}><MountTurret className='lg'/></li>
|
|
||||||
</ul>
|
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 }
|
||||||
@@ -88,7 +89,6 @@ export default class InternalSlot extends Slot {
|
|||||||
{ m.getHullReinforcement() ? <div className='l'>{translate('armour')}: {formats.int(m.getHullReinforcement() + ship.baseArmour * m.getModValue('hullboost') / 10000)}</div> : null }
|
{ m.getHullReinforcement() ? <div className='l'>{translate('armour')}: {formats.int(m.getHullReinforcement() + ship.baseArmour * m.getModValue('hullboost') / 10000)}</div> : null }
|
||||||
{ m.getProtection() ? <div className='l'>{translate('protection')}: {formats.rPct(m.getProtection())}</div> : null }
|
{ m.getProtection() ? <div className='l'>{translate('protection')}: {formats.rPct(m.getProtection())}</div> : null }
|
||||||
{ m.getIntegrity() ? <div className='l'>{translate('integrity')}: {formats.int(m.getIntegrity())}</div> : null }
|
{ m.getIntegrity() ? <div className='l'>{translate('integrity')}: {formats.int(m.getIntegrity())}</div> : null }
|
||||||
{ m.getInfo() ? <div className='l'>{translate(m.getInfo())}</div> : null }
|
|
||||||
{ m && validMods.length > 0 ? <div className='r' tabIndex="0" ref={ modButton => this.modButton = modButton }><button tabIndex="-1" onClick={this._toggleModifications.bind(this)} onContextMenu={stopCtxPropagation} onMouseOver={termtip.bind(null, 'modifications')} onMouseOut={tooltip.bind(null, null)}><ListModifications /></button></div> : null }
|
{ m && validMods.length > 0 ? <div className='r' tabIndex="0" ref={ modButton => this.modButton = modButton }><button tabIndex="-1" onClick={this._toggleModifications.bind(this)} onContextMenu={stopCtxPropagation} onMouseOver={termtip.bind(null, 'modifications')} onMouseOut={tooltip.bind(null, null)}><ListModifications /></button></div> : null }
|
||||||
</div>
|
</div>
|
||||||
</div>;
|
</div>;
|
||||||
|
|||||||
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) {
|
||||||
|
|||||||
117
src/app/components/ModalOrbis.jsx
Normal file
117
src/app/components/ModalOrbis.jsx
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
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: '...',
|
||||||
|
authenticatedStatus: 'Checking...'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 >{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>;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,8 +3,6 @@ import PropTypes from 'prop-types';
|
|||||||
import TranslatedComponent from './TranslatedComponent';
|
import TranslatedComponent from './TranslatedComponent';
|
||||||
import request from 'superagent';
|
import request from 'superagent';
|
||||||
import Persist from '../stores/Persist';
|
import Persist from '../stores/Persist';
|
||||||
const zlib = require('zlib');
|
|
||||||
const base64url = require('base64url');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Permalink modal
|
* Permalink modal
|
||||||
@@ -58,6 +56,7 @@ export default class ModalShoppingList extends TranslatedComponent {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (module.m.blueprint.special) {
|
if (module.m.blueprint.special) {
|
||||||
|
console.log(module.m.blueprint.special);
|
||||||
blueprints.push({ uuid: module.m.blueprint.special.uuid, number: 1 });
|
blueprints.push({ uuid: module.m.blueprint.special.uuid, number: 1 });
|
||||||
}
|
}
|
||||||
for (const g in module.m.blueprint.grades) {
|
for (const g in module.m.blueprint.grades) {
|
||||||
@@ -110,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;
|
||||||
@@ -141,70 +139,12 @@ 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';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Send all blueprints to EDOMH. This is a modified copy of registerBPs because this.state.blueprints was empty when I tried to modify sendToEDEng and I couldn't figure out why
|
|
||||||
* @param {Event} event React event
|
|
||||||
*/
|
|
||||||
sendToEDOMH(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
const ship = this.props.ship;
|
|
||||||
let blueprints = [];
|
|
||||||
|
|
||||||
//create the json
|
|
||||||
for (const module of ship.costList) {
|
|
||||||
if (module.type === 'SHIP') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (module.m && module.m.blueprint) {
|
|
||||||
if (!module.m.blueprint.grade || !module.m.blueprint.grades) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (module.m.blueprint.special) {
|
|
||||||
blueprints.push({
|
|
||||||
"item": module.m.symbol,
|
|
||||||
"blueprint": module.m.blueprint.special.edname
|
|
||||||
});
|
|
||||||
}
|
|
||||||
for (const g in module.m.blueprint.grades) {
|
|
||||||
if (!module.m.blueprint.grades.hasOwnProperty(g)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (g < module.m.blueprint.grade) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
blueprints.push({
|
|
||||||
"item": module.m.symbol,
|
|
||||||
"blueprint": module.m.blueprint.fdname,
|
|
||||||
"grade": module.m.blueprint.grade,
|
|
||||||
"highestGradePercentage":1.0
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//create JSON to encode
|
|
||||||
let baseJson = {
|
|
||||||
"version":1,
|
|
||||||
"name":ship.name, // TO-DO: Import build name and put that here correctly
|
|
||||||
"items": blueprints
|
|
||||||
}
|
|
||||||
|
|
||||||
let JSONString = JSON.stringify(baseJson)
|
|
||||||
let deflated = zlib.deflateSync(JSONString)
|
|
||||||
|
|
||||||
//actually encode
|
|
||||||
let link = base64url.encode(deflated)
|
|
||||||
link = "edomh://coriolis/?" + link;
|
|
||||||
|
|
||||||
window.open(link, "_self")
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert mats object to string
|
* Convert mats object to string
|
||||||
*/
|
*/
|
||||||
@@ -236,18 +176,6 @@ export default class ModalShoppingList extends TranslatedComponent {
|
|||||||
mats[i] = module.m.blueprint.grades[g].components[i] * this.state.matsPerGrade[g];
|
mats[i] = module.m.blueprint.grades[g].components[i] * this.state.matsPerGrade[g];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (module.m.blueprint.special) {
|
|
||||||
for (const j in module.m.blueprint.special.components) {
|
|
||||||
if (!module.m.blueprint.special.components.hasOwnProperty(j)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (mats[j]) {
|
|
||||||
mats[j] += module.m.blueprint.special.components[j];
|
|
||||||
} else {
|
|
||||||
mats[j] = module.m.blueprint.special.components[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -300,36 +228,34 @@ export default class ModalShoppingList extends TranslatedComponent {
|
|||||||
const compatible = this.checkBrowserIsCompatible();
|
const compatible = this.checkBrowserIsCompatible();
|
||||||
this.cmdrChangeHandler = this.cmdrChangeHandler.bind(this);
|
this.cmdrChangeHandler = this.cmdrChangeHandler.bind(this);
|
||||||
this.sendToEDEng = this.sendToEDEng.bind(this);
|
this.sendToEDEng = this.sendToEDEng.bind(this);
|
||||||
this.sendToEDOMH = this.sendToEDOMH.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 style={{marginTop: 5}} className={'l cb dismiss cap'} disabled={!!this.state.failed} onClick={this.sendToEDOMH}>{translate('Send to EDOMH')}</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
|
||||||
@@ -44,7 +43,7 @@ export default class Modification extends TranslatedComponent {
|
|||||||
if (reCast.endsWith(value) || reCast.startsWith(value)) {
|
if (reCast.endsWith(value) || reCast.startsWith(value)) {
|
||||||
let { m, name, ship } = this.props;
|
let { m, name, ship } = this.props;
|
||||||
value = Math.max(Math.min(value, 50000), -50000);
|
value = Math.max(Math.min(value, 50000), -50000);
|
||||||
ship.setModification(m, name, value, true);
|
ship.setModification(m, name, value, true, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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>
|
||||||
|
|||||||
@@ -436,7 +436,7 @@ export default class ModificationsMenu extends TranslatedComponent {
|
|||||||
let specialLabel;
|
let specialLabel;
|
||||||
let specialTt;
|
let specialTt;
|
||||||
if (m.blueprint && m.blueprint.special) {
|
if (m.blueprint && m.blueprint.special) {
|
||||||
specialLabel = translate(m.blueprint.special.name);
|
specialLabel = m.blueprint.special.name;
|
||||||
specialTt = specialToolTip(translate, m.blueprint.grades[m.blueprint.grade], m.grp, m, m.blueprint.special.edname);
|
specialTt = specialToolTip(translate, m.blueprint.grades[m.blueprint.grade], m.grp, m, m.blueprint.special.edname);
|
||||||
} else {
|
} else {
|
||||||
specialLabel = translate('PHRASE_SELECT_SPECIAL');
|
specialLabel = translate('PHRASE_SELECT_SPECIAL');
|
||||||
@@ -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>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import React from 'react';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import TranslatedComponent from './TranslatedComponent';
|
import TranslatedComponent from './TranslatedComponent';
|
||||||
import { Pip } from './SvgIcons';
|
import { Pip } from './SvgIcons';
|
||||||
import autoBind from 'auto-bind';
|
import { autoBind } from 'react-extras';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pips displays SYS/ENG/WEP pips and allows users to change them with key presses by clicking on the relevant area.
|
* Pips displays SYS/ENG/WEP pips and allows users to change them with key presses by clicking on the relevant area.
|
||||||
|
|||||||
@@ -50,10 +50,8 @@ 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 armourMetrics = Calc.armourMetrics(ship);
|
const armourMetrics = Calc.armourMetrics(ship);
|
||||||
let shieldColour = 'blue';
|
let shieldColour = 'blue';
|
||||||
if (shieldGenerator && shieldGenerator.m.grp === 'psg') {
|
if (shieldGenerator && shieldGenerator.m.grp === 'psg') {
|
||||||
@@ -72,7 +70,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>
|
||||||
@@ -80,21 +78,20 @@ export default class ShipSummaryTable extends TranslatedComponent {
|
|||||||
<th rowSpan={2}>{translate('TTD')}</th>
|
<th rowSpan={2}>{translate('TTD')}</th>
|
||||||
{/* <th onMouseEnter={termtip.bind(null, 'heat per second')} onMouseLeave={hide} rowSpan={2}>{translate('HPS')}</th> */}
|
{/* <th onMouseEnter={termtip.bind(null, 'heat per second')} onMouseLeave={hide} rowSpan={2}>{translate('HPS')}</th> */}
|
||||||
<th rowSpan={2}>{translate('cargo')}</th>
|
<th rowSpan={2}>{translate('cargo')}</th>
|
||||||
<th rowSpan={2} onMouseEnter={termtip.bind(null, 'passenger capacity', { cap: 0 })} onMouseLeave={hide}>{translate('pax')}</th>
|
<th rowSpan={2}>{translate('pax')}</th>
|
||||||
<th rowSpan={2}>{translate('fuel')}</th>
|
<th rowSpan={2}>{translate('fuel')}</th>
|
||||||
<th colSpan={3}>{translate('mass')}</th>
|
<th colSpan={3}>{translate('mass')}</th>
|
||||||
<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>
|
|
||||||
</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 +101,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>
|
||||||
@@ -125,7 +122,6 @@ export default class ShipSummaryTable extends TranslatedComponent {
|
|||||||
<td>{ship.crew}</td>
|
<td>{ship.crew}</td>
|
||||||
<td>{ship.masslock}</td>
|
<td>{ship.masslock}</td>
|
||||||
<td>{shipBoost !== 'No Boost' ? formats.time(shipBoost) : 'No Boost'}</td>
|
<td>{shipBoost !== 'No Boost' ? formats.time(shipBoost) : 'No Boost'}</td>
|
||||||
<td>{formats.pct(restingHeat)}</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
@@ -160,10 +156,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 +194,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>
|
||||||
|
|
||||||
|
|||||||
@@ -99,7 +99,6 @@ export default class Slot extends TranslatedComponent {
|
|||||||
let translate = language.translate;
|
let translate = language.translate;
|
||||||
let { ship, m, enabled, dropClass, dragOver, onOpen, onChange, selected, eligible, onSelect, warning, availableModules } = this.props;
|
let { ship, m, enabled, dropClass, dragOver, onOpen, onChange, selected, eligible, onSelect, warning, availableModules } = this.props;
|
||||||
let slotDetails, modificationsMarker, menu;
|
let slotDetails, modificationsMarker, menu;
|
||||||
let missing = false;
|
|
||||||
|
|
||||||
if (!selected) {
|
if (!selected) {
|
||||||
// If not selected then sure that modifications flag is unset
|
// If not selected then sure that modifications flag is unset
|
||||||
@@ -109,11 +108,6 @@ export default class Slot extends TranslatedComponent {
|
|||||||
if (m) {
|
if (m) {
|
||||||
slotDetails = this._getSlotDetails(m, enabled, translate, language.formats, language.units); // Must be implemented by sub classes
|
slotDetails = this._getSlotDetails(m, enabled, translate, language.formats, language.units); // Must be implemented by sub classes
|
||||||
modificationsMarker = JSON.stringify(m);
|
modificationsMarker = JSON.stringify(m);
|
||||||
if(typeof m.grp !== 'undefined' || m.grp !== null) {
|
|
||||||
if(m.grp == "mh" || m.grp == "mm") {
|
|
||||||
missing = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
slotDetails = <div className={'empty'}>{translate(eligible ? 'emptyrestricted' : 'empty')}</div>;
|
slotDetails = <div className={'empty'}>{translate(eligible ? 'emptyrestricted' : 'empty')}</div>;
|
||||||
modificationsMarker = '';
|
modificationsMarker = '';
|
||||||
@@ -133,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)}
|
||||||
@@ -147,13 +141,10 @@ export default class Slot extends TranslatedComponent {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={cn('slot', dropClass, { selected })} onClick={onOpen} onKeyDown={this._keyDown} onContextMenu={this._contextMenu} onDragOver={dragOver} tabIndex="0" ref={slotDiv => this.slotDiv = slotDiv}>
|
<div className={cn('slot', dropClass, { selected })} onClick={onOpen} onKeyDown={this._keyDown} onContextMenu={this._contextMenu} onDragOver={dragOver} tabIndex="0" ref={slotDiv => this.slotDiv = slotDiv}>
|
||||||
{
|
<div className='details-container'>
|
||||||
// If missing module/hardpoint, set the div container to warning status.
|
|
||||||
}
|
|
||||||
<div className={ missing === true ? 'details-container warning' : 'details-container'}>
|
|
||||||
<div className='sz'>{this._getMaxClassLabel(translate)}</div>
|
<div className='sz'>{this._getMaxClassLabel(translate)}</div>
|
||||||
{slotDetails}
|
{slotDetails}
|
||||||
</div>
|
</div>
|
||||||
{menu}
|
{menu}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -93,11 +93,6 @@ export default class StandardSlot extends TranslatedComponent {
|
|||||||
this._modificationsSelected = false;
|
this._modificationsSelected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this is a missing module, therefore has the 'info' field, set the warning value on the module to be true when loaded.
|
|
||||||
if (m.info) {
|
|
||||||
warning = () => true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const modificationsMarker = JSON.stringify(m);
|
const modificationsMarker = JSON.stringify(m);
|
||||||
|
|
||||||
if (selected) {
|
if (selected) {
|
||||||
@@ -114,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)}
|
||||||
@@ -129,7 +124,7 @@ export default class StandardSlot extends TranslatedComponent {
|
|||||||
<div className={cn('details-container', { warning: warning && warning(slot.m), disabled: m.grp !== 'bh' && !slot.enabled })}>
|
<div className={cn('details-container', { warning: warning && warning(slot.m), disabled: m.grp !== 'bh' && !slot.enabled })}>
|
||||||
<div className={'sz'}>{m.grp == 'bh' ? m.name.charAt(0) : slot.maxClass}</div>
|
<div className={'sz'}>{m.grp == 'bh' ? m.name.charAt(0) : slot.maxClass}</div>
|
||||||
<div>
|
<div>
|
||||||
<div className={'l'}>{classRating} {m.getInfo() ? translate(m.ukName) : translate(m.name || m.grp)}{m.mods && Object.keys(m.mods).length > 0 ? <span className='r' onMouseOver={termtip.bind(null, modTT)} onMouseOut={tooltip.bind(null, null)}><Modified /></span> : null }</div>
|
<div className={'l'}>{classRating} {translate(m.name || m.grp)}{m.mods && Object.keys(m.mods).length > 0 ? <span className='r' onMouseOver={termtip.bind(null, modTT)} onMouseOut={tooltip.bind(null, null)}><Modified /></span> : null }</div>
|
||||||
<div className={'r'}>{formats.round(mass)}{units.T}</div>
|
<div className={'r'}>{formats.round(mass)}{units.T}</div>
|
||||||
<div/>
|
<div/>
|
||||||
<div className={'cb'}>
|
<div className={'cb'}>
|
||||||
@@ -149,8 +144,7 @@ export default class StandardSlot extends TranslatedComponent {
|
|||||||
{ showModuleResistances && m.getKineticResistance() ? <div className='l'>{translate('kinres')}: {formats.pct(m.getKineticResistance())}</div> : null }
|
{ showModuleResistances && m.getKineticResistance() ? <div className='l'>{translate('kinres')}: {formats.pct(m.getKineticResistance())}</div> : null }
|
||||||
{ showModuleResistances && m.getThermalResistance() ? <div className='l'>{translate('thermres')}: {formats.pct(m.getThermalResistance())}</div> : null }
|
{ showModuleResistances && m.getThermalResistance() ? <div className='l'>{translate('thermres')}: {formats.pct(m.getThermalResistance())}</div> : null }
|
||||||
{ m.getIntegrity() ? <div className='l'>{translate('integrity')}: {formats.int(m.getIntegrity())}</div> : null }
|
{ m.getIntegrity() ? <div className='l'>{translate('integrity')}: {formats.int(m.getIntegrity())}</div> : null }
|
||||||
{ m.getInfo() ? <div className='l'>{translate(m.getInfo())}</div> : null }
|
{ validMods.length > 0 ? <div className='r' tabIndex="0" ref={ modButton => this.modButton = modButton }><button tabIndex="-1" onClick={this._toggleModifications.bind(this)} onContextMenu={stopCtxPropagation} onMouseOver={termtip.bind(null, 'modifications')} onMouseOut={tooltip.bind(null, null)}><ListModifications /></button></div> : null }
|
||||||
{ m.getInfo() ? <div className='r'></div> : validMods.length > 0 ? <div className='r' tabIndex="0" ref={ modButton => this.modButton = modButton }><button tabIndex="-1" onClick={this._toggleModifications.bind(this)} onContextMenu={stopCtxPropagation} onMouseOver={termtip.bind(null, 'modifications')} onMouseOut={tooltip.bind(null, null)}><ListModifications /></button></div> : null }
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</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>);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import TranslatedComponent from './TranslatedComponent';
|
import TranslatedComponent from './TranslatedComponent';
|
||||||
import React, { PropTypes } from 'react';
|
import React, { PropTypes } from 'react';
|
||||||
import ContainerDimensions from 'react-container-dimensions';
|
import ContainerDimensions from 'react-container-dimensions';
|
||||||
import { BarChart, Bar, XAxis, YAxis, LabelList } from 'recharts';
|
import { BarChart, Bar, XAxis, YAxis } from 'recharts';
|
||||||
|
|
||||||
const CORIOLIS_COLOURS = ['#FF8C0D', '#1FB0FF', '#71A052', '#D5D54D'];
|
const CORIOLIS_COLOURS = ['#FF8C0D', '#1FB0FF', '#71A052', '#D5D54D'];
|
||||||
const LABEL_COLOUR = '#000000';
|
const LABEL_COLOUR = '#000000';
|
||||||
@@ -53,9 +53,7 @@ export default class VerticalBarChart extends TranslatedComponent {
|
|||||||
<BarChart width={width} height={width * ASPECT} data={this.props.data} margin={{ top: 5, right: 5, left: 5, bottom: 5 }}>
|
<BarChart width={width} height={width * ASPECT} data={this.props.data} margin={{ top: 5, right: 5, left: 5, bottom: 5 }}>
|
||||||
<XAxis interval={0} fontSize='0.8em' stroke={AXIS_COLOUR} dataKey='label' />
|
<XAxis interval={0} fontSize='0.8em' stroke={AXIS_COLOUR} dataKey='label' />
|
||||||
<YAxis interval={'preserveStart'} tickCount={11} fontSize='0.8em' stroke={AXIS_COLOUR} type='number' domain={[0, localMax]}/>
|
<YAxis interval={'preserveStart'} tickCount={11} fontSize='0.8em' stroke={AXIS_COLOUR} type='number' domain={[0, localMax]}/>
|
||||||
<Bar dataKey='value' fill={CORIOLIS_COLOURS[0]} isAnimationActive={false} onMouseOver={this._termtip} onMouseOut={tooltip.bind(null, null)}>
|
<Bar dataKey='value' label={<ValueLabel />} fill={CORIOLIS_COLOURS[0]} isAnimationActive={false} onMouseOver={this._termtip} onMouseOut={tooltip.bind(null, null)}/>
|
||||||
<LabelList dataKey='value' position='insideTop'/>
|
|
||||||
</Bar>
|
|
||||||
</BarChart>
|
</BarChart>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -78,3 +76,29 @@ export default class VerticalBarChart extends TranslatedComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A label that displays the value within the bar of the chart
|
||||||
|
*/
|
||||||
|
class ValueLabel extends React.Component {
|
||||||
|
static propTypes = {
|
||||||
|
x: PropTypes.number,
|
||||||
|
y: PropTypes.number,
|
||||||
|
payload: PropTypes.object,
|
||||||
|
value: PropTypes.number
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render offence
|
||||||
|
* @return {React.Component} contents
|
||||||
|
*/
|
||||||
|
render() {
|
||||||
|
const { x, y, payload, value } = this.props;
|
||||||
|
|
||||||
|
const em = value < 1000 ? '1em' : value < 1000 ? '0.8em' : '0.7em';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<text x={x} y={y} fill="#000000" textAnchor="middle" dy={20} style={{ fontSize: em }}>{value}</text>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
@@ -7,8 +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 KO from './ko';
|
|
||||||
import * as d3 from 'd3';
|
import * as d3 from 'd3';
|
||||||
|
|
||||||
let fallbackTerms = EN.terms;
|
let fallbackTerms = EN.terms;
|
||||||
@@ -29,8 +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;
|
|
||||||
case 'ko': lang = KO; break;
|
|
||||||
default:
|
default:
|
||||||
lang = EN;
|
lang = EN;
|
||||||
}
|
}
|
||||||
@@ -98,7 +94,5 @@ export const Languages = {
|
|||||||
fr: 'Français',
|
fr: 'Français',
|
||||||
ru: 'ру́сский',
|
ru: 'ру́сский',
|
||||||
pl: 'polski',
|
pl: 'polski',
|
||||||
pt: 'português',
|
pt: 'português'
|
||||||
cn: '中文',
|
|
||||||
ko: '한국어'
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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
File diff suppressed because one or more lines are too long
@@ -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",
|
||||||
|
|||||||
@@ -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: ['오전', '오후'],
|
|
||||||
days: ['일요일', '월요일', '화요일', '수요일', '목요일', '금요일', '토요일'],
|
|
||||||
shortDays: ['일', '월', '화', '수', '목', '금', '토'],
|
|
||||||
months: ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월'],
|
|
||||||
shortMonths: ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월']
|
|
||||||
};
|
|
||||||
|
|
||||||
export { default as terms } from './ko.json';
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -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
@@ -5,7 +5,7 @@
|
|||||||
"PHRASE_EXPORT_DESC": "Детальный JSON-экспорт вашей сборки для использования в других местах и инструментах",
|
"PHRASE_EXPORT_DESC": "Детальный JSON-экспорт вашей сборки для использования в других местах и инструментах",
|
||||||
"PHRASE_FASTEST_RANGE": "Последовательные прыжки максимальной дальности",
|
"PHRASE_FASTEST_RANGE": "Последовательные прыжки максимальной дальности",
|
||||||
"PHRASE_IMPORT": "Для импорта вставьте код в эту форму",
|
"PHRASE_IMPORT": "Для импорта вставьте код в эту форму",
|
||||||
"PHRASE_LADEN": "Масса корабля с учетом топлива и грузов",
|
"PHRASE_LADEN": "Масса корабля с учётом топлива и грузов",
|
||||||
"PHRASE_NO_BUILDS": "Нечего сравнивать",
|
"PHRASE_NO_BUILDS": "Нечего сравнивать",
|
||||||
"PHRASE_NO_RETROCH": "Нет ранних версий сборки",
|
"PHRASE_NO_RETROCH": "Нет ранних версий сборки",
|
||||||
"PHRASE_SELECT_BUILDS": "Выберите конфигурацию для сравнения",
|
"PHRASE_SELECT_BUILDS": "Выберите конфигурацию для сравнения",
|
||||||
@@ -14,20 +14,17 @@
|
|||||||
"PHRASE_UNLADEN": "Масса корабля без учета топлива и грузов",
|
"PHRASE_UNLADEN": "Масса корабля без учета топлива и грузов",
|
||||||
"PHRASE_UPDATE_RDY": "Доступна новая версия. Нажмите для обновления.",
|
"PHRASE_UPDATE_RDY": "Доступна новая версия. Нажмите для обновления.",
|
||||||
"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": "Щиты продержатся",
|
||||||
"PHRASE_TIME_TO_RECOVER_SHIELDS": "Щиты восстановятся за",
|
"PHRASE_TIME_TO_RECOVER_SHIELDS": "Щиты восстановятся за",
|
||||||
"PHRASE_TIME_TO_RECHARGE_SHIELDS": "Щиты будут заряжены за",
|
"PHRASE_TIME_TO_RECHARGE_SHIELDS": "Щиты будут заряжены за",
|
||||||
@@ -39,89 +36,76 @@
|
|||||||
"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": "Непрерывным огнём из всех орудий",
|
||||||
"PHRASE_TIME_TO_DRAIN_WEP": "Опустошит ОРУ за",
|
"PHRASE_TIME_TO_DRAIN_WEP": "Опустошит ОРУЖ за",
|
||||||
"TT_TIME_TO_DRAIN_WEP": "Время, за которое опустошится аккумулятор ОРУ при стрельбе из всех орудий",
|
"TT_TIME_TO_DRAIN_WEP": "Время, за которое опустошится аккумулятор ОРУЖ при стрельбе из всех орудий",
|
||||||
"TT_TIME_TO_LOSE_SHIELDS": "Против поддерживаемой стрельбы из всех орудий противника",
|
"TT_TIME_TO_LOSE_SHIELDS": "Против поддерживаемой стрельбы из всех орудий противника",
|
||||||
"TT_TIME_TO_LOSE_ARMOUR": "Против поддерживаемой стрельбы из всех орудий противника",
|
"TT_TIME_TO_LOSE_ARMOUR": "Против поддерживаемой стрельбы из всех орудий противника",
|
||||||
"TT_MODULE_ARMOUR": "Броня, защищающая модули от урона",
|
"TT_MODULE_ARMOUR": "Броня, защищающая модули от урона",
|
||||||
"TT_MODULE_PROTECTION_EXTERNAL": "Процент урона, перенаправленного от гнезд на наборы для усиления модулей",
|
"TT_MODULE_PROTECTION_EXTERNAL": "Процент урона, перенаправленного от гнёзд на наборы для усиления модулей",
|
||||||
"TT_MODULE_PROTECTION_INTERNAL": "Процент урона, перенаправленного от модулей вне гнёзд на наборы для усиления модулей",
|
"TT_MODULE_PROTECTION_INTERNAL": "Процент урона, перенаправленного от модулей вне гнёзд на наборы для усиления модулей",
|
||||||
"TT_EFFECTIVE_SDPS_SHIELDS": "Реальный поддерживаемый УвС пока ёмкость ОРУ не пуста",
|
"TT_EFFECTIVE_SDPS_SHIELDS": "Реальный поддерживаемый ДПС пока аккумулятор ОРУЖ не пуст",
|
||||||
"TT_EFFECTIVENESS_SHIELDS": "Эффективность в сравнении с попаданием по цели с 0-сопротивляемостью без пунктов в СИС на 0 метрах",
|
"TT_EFFECTIVENESS_SHIELDS": "Эффективность в сравнении с попаданием по цели с 0-сопротивляемостью без пунктов в СИС на 0 метрах",
|
||||||
"TT_EFFECTIVE_SDPS_ARMOUR": "Реальный поддерживаемый УвС пока аккумулятор ОРУ не пуст",
|
"TT_EFFECTIVE_SDPS_ARMOUR": "Реальный поддерживаемый ДПС пока аккумулятор ОРУЖ не пуст",
|
||||||
"TT_EFFECTIVENESS_ARMOUR": "Эффективность в сравнении с попаданием по цели с 0-сопротивляемостью на 0 метрах",
|
"TT_EFFECTIVENESS_ARMOUR": "Эффективность в сравнении с попаданием по цели с 0-сопротивляемостью на 0 метрах",
|
||||||
"PHRASE_EFFECTIVE_SDPS_SHIELDS": "ПУвС против щитов",
|
"PHRASE_EFFECTIVE_SDPS_SHIELDS": "ПДПС против щитов",
|
||||||
"PHRASE_EFFECTIVE_SDPS_ARMOUR": "ПУвС против брони",
|
"PHRASE_EFFECTIVE_SDPS_ARMOUR": "ПДПС против брони",
|
||||||
"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": "Прочность щита, включая бустеры и щитонакопители",
|
|
||||||
"TT_SUMMARY_SHIELDS_NONFUNCTIONAL": "Шитогенератор отсутствует или выключен",
|
"TT_SUMMARY_SHIELDS_NONFUNCTIONAL": "Шитогенератор отсутствует или выключен",
|
||||||
"TT_SUMMARY_INTEGRITY": "Целостность корабля, включая переборки и наборы для усиления корпуса",
|
"TT_SUMMARY_INTEGRITY": "Целостность корабля, включая переборки и наборы для усиления корпуса",
|
||||||
"TT_SUMMARY_HULL_MASS": "Масса корпуса без каких-либо модулей",
|
"TT_SUMMARY_HULL_MASS": "Масса корпуса без каких-либо модулей",
|
||||||
"TT_SUMMARY_UNLADEN_MASS": "Масса корпуса и модулей без топлива и груза",
|
"TT_SUMMARY_UNLADEN_MASS": "Масса корпуса и модулей без топлива и груза",
|
||||||
"TT_SUMMARY_LADEN_MASS": "Масса корпуса и модулей с топливом и грузом",
|
"TT_SUMMARY_LADEN_MASS": "Масса корпуса и модулей с топливом и грузом",
|
||||||
"TT_SUMMARY_DPS": "Урон в секунду при стрельбе из всех орудий",
|
"TT_SUMMARY_DPS": "Урон в секунду при стрельбе из всех орудий",
|
||||||
"TT_SUMMARY_EPS": "Расход аккумулятора ОРУ в секунду при стрельбе из всех орудий",
|
"TT_SUMMARY_EPS": "Расход аккумулятора ОРУЖ в секунду при стрельбе из всех орудий",
|
||||||
"TT_SUMMARY_TTD": "Время расхода аккумулятора ОРУ при стрельбе из всех орудий и с 4 пунктами в ОРУ",
|
"TT_SUMMARY_TTD": "Время расхода аккумулятора ОРУЖ при стрельбе из всех орудий и с 4 пунктами в ОРУЖ",
|
||||||
"TT_SUMMARY_MAX_SINGLE_JUMP": "Самый дальний возможный прыжок без груза и с топливом, достаточным только на сам прыжок",
|
"TT_SUMMARY_MAX_SINGLE_JUMP": "Самый дальний возможный прыжок без груза и с топливом, достаточным только на сам прыжок",
|
||||||
"TT_SUMMARY_UNLADEN_SINGLE_JUMP": "Самый дальний возможный прыжок без груза и с полным топливным баком",
|
"TT_SUMMARY_UNLADEN_SINGLE_JUMP": "Самый дальний возможный прыжок без груза и с полным топливным баком",
|
||||||
"TT_SUMMARY_LADEN_SINGLE_JUMP": "Самый дальний возможный прыжок с полным грузовым отсеком и с полным топливным баком",
|
"TT_SUMMARY_LADEN_SINGLE_JUMP": "Самый дальний возможный прыжок с полным грузовым отсеком и с полным топливным баком",
|
||||||
"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": "Сопротивление едк.урону",
|
"cc": "Контроллер магнитного снаряда для сбора",
|
||||||
"Caustic resistance": "Сопротивление едк.урону",
|
|
||||||
"cc": "Контроллер дронов-сборщиков",
|
|
||||||
"ch": "Разбрасыватель дипольных отражателей",
|
"ch": "Разбрасыватель дипольных отражателей",
|
||||||
"cr": "Грузовой стеллаж",
|
"cr": "Грузовой стеллаж",
|
||||||
"cs": "Сканер содержимого",
|
"cs": "Сканер содержимого",
|
||||||
"csl": "Антикор катапульта",
|
|
||||||
"dc": "Стыковочный компьютер",
|
"dc": "Стыковочный компьютер",
|
||||||
"ec": "Радиоэлектронное подавление",
|
"ec": "Электр. противодействие",
|
||||||
"fc": "Залповое орудие",
|
"fc": "Залповое орудие",
|
||||||
"fh": "Ангар для истребителя",
|
"fh": "Ангар для истребителя",
|
||||||
"fi": "FSD-перехватчик",
|
"fi": "FSD-перехватчик",
|
||||||
"fs": "Топливозаборник",
|
"fs": "Топливозаборник",
|
||||||
"fsd": "Рамочно-сместительный двигатель",
|
"fsd": "Рамочно-сместительный двигатель",
|
||||||
"ft": "Топливный бак",
|
"ft": "Топливный бак",
|
||||||
"fx": "Контроллер дронов-заправщиков",
|
"fx": "Контроллер магнитного снаряда для топлива",
|
||||||
"hb": "Контроллер дронов-взломщиков трюмов",
|
"hb": "Контроллер магнитного снаряда для взлома трюма",
|
||||||
"hr": "Набор для усиления корпуса",
|
"hr": "Набор для усиления корпуса",
|
||||||
"hs": "Теплоотводная катапульта",
|
"hs": "Теплоотводная катапульта",
|
||||||
"kw": "Сканер преступников",
|
"kw": "Сканер преступников",
|
||||||
"ls": "Система жизнеобеспечения",
|
"ls": "Система жизнеобеспечения",
|
||||||
"mc": "Многоствольное орудие",
|
"mc": "Многоствольное орудие",
|
||||||
"axmc": "Многоствольное орудие АИ",
|
|
||||||
"ml": "Проходочный лазер",
|
"ml": "Проходочный лазер",
|
||||||
"mr": "Блок ракет",
|
"mr": "Ракетный лоток",
|
||||||
"axmr": "Блок ракет АИ",
|
|
||||||
"ews": "Стабилизатор экспериментального вооружения",
|
|
||||||
"mrp": "Набор для усиления модуля",
|
"mrp": "Набор для усиления модуля",
|
||||||
"nl": "Мины",
|
"nl": "Мины",
|
||||||
"pa": "Ускоритель плазмы",
|
"pa": "Ускоритель плазмы",
|
||||||
"pas": "Комплект для сближения с планетой",
|
"pas": "Комплект для сближения с планетой",
|
||||||
"pc": "Контроллер дронов-геологоразведчиков",
|
"pc": "Контроллер магнитного снаряда для геологоразведки",
|
||||||
"pce": "Каюта пассажира эконом-класса",
|
"pce": "Каюта пассажира эконом-класса",
|
||||||
"passenger capacity": "Количество пассажиров",
|
|
||||||
"pci": "Каюта пассажира бизнес-класса",
|
"pci": "Каюта пассажира бизнес-класса",
|
||||||
"pcm": "Каюта пассажира первого класса",
|
"pcm": "Каюта пассажира первого класса",
|
||||||
"pcq": "Каюта пассажира класса люкс",
|
"pcq": "Каюта пассажира класса люкс",
|
||||||
@@ -129,65 +113,33 @@
|
|||||||
"pl": "Импульсный лазер",
|
"pl": "Импульсный лазер",
|
||||||
"po": "Точечная оборона",
|
"po": "Точечная оборона",
|
||||||
"pp": "Силовая установка",
|
"pp": "Силовая установка",
|
||||||
"gpp": "Силовая установка Стражей",
|
|
||||||
"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",
|
|
||||||
"Send To EDOMH": "Отправить в EDOMH",
|
|
||||||
"ws": "Сканер следа FSD",
|
"ws": "Сканер следа FSD",
|
||||||
"rpl": "Контроллер дронов-ремонтников",
|
|
||||||
"rcpl": "Контроллер дронов-разведчиков",
|
|
||||||
"xs": "Ксено-сканер",
|
|
||||||
"tbem": "Блок энзимных ракет",
|
|
||||||
"tbrfl": "Установка для стрельбы стреловидными снарядами с дистанционным подрывом",
|
|
||||||
"dtl": "Контроллер дронов-очистителей",
|
|
||||||
"mlc": "Мультиконтроллер",
|
|
||||||
"mahr": "Метасплавное усиление корпуса",
|
|
||||||
"emptyrestricted": "пусто (ограниченно)",
|
"emptyrestricted": "пусто (ограниченно)",
|
||||||
"damage dealt to": "Урон нанесён",
|
"damage dealt to": "Урон нанесён",
|
||||||
"damage received from": "Урон получен от",
|
"damage received from": "Урон получен от",
|
||||||
"against shields": "Против щитов",
|
"against shields": "Против щитов",
|
||||||
"against hull": "Против корпуса",
|
"against hull": "Против корпуса",
|
||||||
"total effective shield": "Общая эффективность щита",
|
"total effective shield": "Общие эффективные щиты",
|
||||||
"ammunition": "Припасы",
|
"ammunition": "Припасы",
|
||||||
"secs": "с",
|
"secs": "с",
|
||||||
"bays": "Ячейки",
|
"rebuildsperbay": "Построек за полосу",
|
||||||
"rebuildsperbay": "Истребителей в ячейке",
|
|
||||||
"mroll": "Roll",
|
|
||||||
"feature": "Свойство",
|
|
||||||
"worst": "Худшее",
|
"worst": "Худшее",
|
||||||
"average": "Среднее",
|
"average": "Среднее",
|
||||||
"random": "Случайное",
|
"random": "Случайное",
|
||||||
"best": "Лучшее",
|
"best": "Лучшее",
|
||||||
"current": "Текущее",
|
|
||||||
"extreme": "Экстремальное",
|
"extreme": "Экстремальное",
|
||||||
"reset": "Сброс",
|
"reset": "Сброс",
|
||||||
"dpe": "Урон на МДж энергии",
|
"dpe": "Урон на МДж энергии",
|
||||||
@@ -196,8 +148,6 @@
|
|||||||
"dpssdps": "Урон в секунду (поддерживаемый урон в секунду)",
|
"dpssdps": "Урон в секунду (поддерживаемый урон в секунду)",
|
||||||
"eps": "Энергия в секунду",
|
"eps": "Энергия в секунду",
|
||||||
"epsseps": "Энергия в секунду (поддерживаемая энергия в секунду)",
|
"epsseps": "Энергия в секунду (поддерживаемая энергия в секунду)",
|
||||||
"fallofffromrange": "Спад",
|
|
||||||
"falloff": "Спад",
|
|
||||||
"hps": "Нагрев в секунду",
|
"hps": "Нагрев в секунду",
|
||||||
"hpsshps": "Нагрев в секунду (поддерживаемый нагрев в секунду)",
|
"hpsshps": "Нагрев в секунду (поддерживаемый нагрев в секунду)",
|
||||||
"damage by": "Урон",
|
"damage by": "Урон",
|
||||||
@@ -205,7 +155,7 @@
|
|||||||
"shield cells": "Щитонакопители",
|
"shield cells": "Щитонакопители",
|
||||||
"recovery": "включение",
|
"recovery": "включение",
|
||||||
"recharge": "перезарядка",
|
"recharge": "перезарядка",
|
||||||
"engine pips": "Ячейки питания на ДВГ",
|
"engine pips": "Пункты в двигателе",
|
||||||
"4b": "4 пункта и Форсаж",
|
"4b": "4 пункта и Форсаж",
|
||||||
"speed": "скорость",
|
"speed": "скорость",
|
||||||
"pitch": "Тангаж",
|
"pitch": "Тангаж",
|
||||||
@@ -214,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": "Продолжительность",
|
||||||
@@ -251,16 +199,11 @@
|
|||||||
"rof": "Скорострельность",
|
"rof": "Скорострельность",
|
||||||
"angle": "Угол сканера",
|
"angle": "Угол сканера",
|
||||||
"scanrate": "Скорость сканера",
|
"scanrate": "Скорость сканера",
|
||||||
"proberadius": "Радиус зонда",
|
|
||||||
"scantime": "Время сканирования",
|
"scantime": "Время сканирования",
|
||||||
"scan range": "Дальность",
|
|
||||||
"max angle": "Макс. угол",
|
|
||||||
"shield": "Щит",
|
"shield": "Щит",
|
||||||
"armour": "Броня",
|
|
||||||
"shieldboost": "Усиление щитов",
|
"shieldboost": "Усиление щитов",
|
||||||
"shieldreinforcement": "Усилитель щита",
|
"shieldreinforcement": "Усилитель щита",
|
||||||
"shotspeed": "Скорость выстрела",
|
"shotspeed": "Скорость выстрела",
|
||||||
"shotdmg": "Урон за выстрел(DPS)",
|
|
||||||
"spinup": "Время раскрутки",
|
"spinup": "Время раскрутки",
|
||||||
"syscap": "Ресурс систем",
|
"syscap": "Ресурс систем",
|
||||||
"sysrate": "Перезарядка систем",
|
"sysrate": "Перезарядка систем",
|
||||||
@@ -291,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": "Энергия и стоимость",
|
||||||
@@ -310,7 +250,7 @@
|
|||||||
"damage to opponent's shields": "Урон щиту противника",
|
"damage to opponent's shields": "Урон щиту противника",
|
||||||
"damage to opponent's hull": "Урон корпусу противника",
|
"damage to opponent's hull": "Урон корпусу противника",
|
||||||
"offence": "Нападение",
|
"offence": "Нападение",
|
||||||
"defence": "Защита",
|
"defence": "Оборона",
|
||||||
"shield metrics": "Данные щита",
|
"shield metrics": "Данные щита",
|
||||||
"raw shield strength": "Чистая мощность щита",
|
"raw shield strength": "Чистая мощность щита",
|
||||||
"shield sources": "Ресурсы щита",
|
"shield sources": "Ресурсы щита",
|
||||||
@@ -325,70 +265,28 @@
|
|||||||
"defence metrics": "Данные обороны",
|
"defence metrics": "Данные обороны",
|
||||||
"fuel carried": "Топливо на борту",
|
"fuel carried": "Топливо на борту",
|
||||||
"cargo carried": "Груз на борту",
|
"cargo carried": "Груз на борту",
|
||||||
"ship control": "Управление кораблем",
|
"ship control": "Управление кораблём",
|
||||||
"opponent": "Противник",
|
"opponent": "Противник",
|
||||||
"opponent's shields": "Щит противника",
|
"opponent's shields": "Щит противника",
|
||||||
"opponent's armour": "Броня противника",
|
"opponent's armour": "Броня противника",
|
||||||
"overall damage": "общий урон",
|
|
||||||
"overall": "общий",
|
|
||||||
"shield damage sources": "источники урона по щиту",
|
"shield damage sources": "источники урона по щиту",
|
||||||
"armour damage sources": "источники урона по броне",
|
"armour damage sources": "источники урона по броне",
|
||||||
"never": "Никогда",
|
"never": "Никогда",
|
||||||
"stock": "базовый",
|
"stock": "базовый",
|
||||||
"boost": "форсаж",
|
"boost": "форсаж",
|
||||||
"tab_defence": "защита",
|
|
||||||
"federation rank 1": "Рекрут",
|
|
||||||
"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": "Минимальный ранг империи для покупки",
|
|
||||||
"kg": "кг",
|
|
||||||
"kg/s": "кг/с",
|
|
||||||
"km": "км",
|
|
||||||
"m": "м",
|
|
||||||
"MJ": "МДж",
|
|
||||||
"MW": "МВт",
|
|
||||||
"T": "т",
|
|
||||||
"°/s": "°/с",
|
|
||||||
"/s": "/с",
|
"/s": "/с",
|
||||||
"/min": "/мин",
|
|
||||||
"m/s": "м/с",
|
"m/s": "м/с",
|
||||||
"Ls": "Св.с",
|
"Ls": "Св.сек",
|
||||||
"LY": "Св.лет",
|
"LY": "Св.лет",
|
||||||
"CR": "КР.",
|
"CR": "кр.",
|
||||||
"S": "М",
|
"S": "M",
|
||||||
"M": "С",
|
"M": "С",
|
||||||
"L": "Б",
|
"L": "б",
|
||||||
"H": "О",
|
"H": "O",
|
||||||
"U": "В",
|
"U": "B",
|
||||||
"small": "Малый",
|
"small": "Малый",
|
||||||
"medium": "Средний",
|
"medium": "Средний",
|
||||||
"large": "Большой",
|
"large": "большой",
|
||||||
"alpha": "Альфа",
|
"alpha": "Альфа",
|
||||||
"beta": "Бета",
|
"beta": "Бета",
|
||||||
"standard": "Стандартный",
|
"standard": "Стандартный",
|
||||||
@@ -401,29 +299,28 @@
|
|||||||
"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": "внутренние отсеки",
|
||||||
"jump range": "Дальность прыжка",
|
"jump range": "Дальность прыжка",
|
||||||
"mass lock factor": "Коэффициент гравитационного захвата",
|
"mass lock factor": "Масс. блок",
|
||||||
"max mass": "Максимальная масса",
|
"max mass": "Максимальная масса",
|
||||||
"minimum mass": "Минимальная масса",
|
|
||||||
"optimal mass": "Оптимальная масса",
|
|
||||||
"net cost": "разница в цене",
|
"net cost": "разница в цене",
|
||||||
"none created": "не создано",
|
"none created": "не создано",
|
||||||
"refuel time": "Время дозаправки",
|
"refuel time": "Время дозаправки",
|
||||||
"retrofit from": "модификация от",
|
"retrofit from": "модификация от",
|
||||||
"T-Load": "Тепл.",
|
"T-Load": "Тепл.",
|
||||||
"utility mounts": "Вспомогательное оборудование",
|
"utility mounts": "Вспомогательное оборудование",
|
||||||
"about": "О сайте",
|
"about": "О ...",
|
||||||
"action": "Действие",
|
"action": "Действие",
|
||||||
"added": "Добавлено",
|
"added": "Добавлено",
|
||||||
|
"armour": "Броня",
|
||||||
"available": "доступно",
|
"available": "доступно",
|
||||||
"backup": "Резервная копия",
|
"backup": "Резервная копия",
|
||||||
"bins": "контейнеры",
|
"bins": "контейнеры",
|
||||||
"build": "сборка",
|
"build": "cборка",
|
||||||
"builds": "сборки",
|
"builds": "cборки",
|
||||||
"buy": "купить",
|
"buy": "купить",
|
||||||
"cancel": "отменить",
|
"cancel": "отменить",
|
||||||
"cargo": "Груз",
|
"cargo": "Груз",
|
||||||
@@ -439,21 +336,21 @@
|
|||||||
"deployed": "Открыты",
|
"deployed": "Открыты",
|
||||||
"disabled": "Отключено",
|
"disabled": "Отключено",
|
||||||
"discount": "Скидка",
|
"discount": "Скидка",
|
||||||
"DPS": "УвС",
|
"DPS": "УВС",
|
||||||
"efficiency": "Эффективность",
|
"efficiency": "Эффективность",
|
||||||
"empty": "пусто",
|
"empty": "пусто",
|
||||||
"ENG": "ДВГ",
|
"ENG": "ДВИ",
|
||||||
"export": "Экспорт",
|
"export": "Экспорт",
|
||||||
"forum": "Форум",
|
"forum": "Форум",
|
||||||
"fuel": "Топл.",
|
"fuel": "Топливо",
|
||||||
"hardpoints": "Орудийные порты",
|
"hardpoints": "Орудийные порты",
|
||||||
"hull": "Корпус",
|
"hull": "Корпус",
|
||||||
"import": "импортировать ",
|
"import": "импортировать ",
|
||||||
"insurance": "Страховка",
|
"insurance": "Страховка",
|
||||||
"jumps": "Прыжков",
|
"jumps": "Прыжков",
|
||||||
"laden": "Груж",
|
"laden": "Груженый",
|
||||||
"language": "Язык",
|
"language": "Язык",
|
||||||
"maneuverability": "Манёвренность",
|
"maneuverability": "Маневренность",
|
||||||
"max": "Макс",
|
"max": "Макс",
|
||||||
"no": "Нет",
|
"no": "Нет",
|
||||||
"pen": "ПБ",
|
"pen": "ПБ",
|
||||||
@@ -464,15 +361,13 @@
|
|||||||
"rate": "скорость",
|
"rate": "скорость",
|
||||||
"rename": "Переименовать",
|
"rename": "Переименовать",
|
||||||
"repair": "Починка",
|
"repair": "Починка",
|
||||||
"ret": "Убр",
|
"ret": "Убр.",
|
||||||
"retracted": "Убрано",
|
"retracted": "Убрано",
|
||||||
"ROF": "В\/с",
|
"ROF": "В/сек",
|
||||||
"save": "Сохранить",
|
"save": "Сохранить",
|
||||||
"sell": "Продать",
|
"sell": "Продать",
|
||||||
"settings": "Настройки",
|
"settings": "Настройки",
|
||||||
"shields": "Щиты",
|
"shields": "Щиты",
|
||||||
"No Shield": "Нет щита",
|
|
||||||
"Never": "Никогда",
|
|
||||||
"ship": "Корабль",
|
"ship": "Корабль",
|
||||||
"ships": "Корабли",
|
"ships": "Корабли",
|
||||||
"shortened": "Укороченный",
|
"shortened": "Укороченный",
|
||||||
@@ -482,296 +377,8 @@
|
|||||||
"SYS": "СИС",
|
"SYS": "СИС",
|
||||||
"time": "Время",
|
"time": "Время",
|
||||||
"type": "Тип",
|
"type": "Тип",
|
||||||
"unladen": "Пуст",
|
"unladen": "Пустой",
|
||||||
"URL": "Ссылка",
|
"URL": "Ссылка",
|
||||||
"WEP": "ОРУ",
|
"WEP": "ОРУЖ",
|
||||||
"yes": "Да",
|
"yes": "Да"
|
||||||
"crew": "экипаж",
|
|
||||||
"jump": "прыж",
|
|
||||||
"pax": "псж",
|
|
||||||
"RST": "СБР",
|
|
||||||
"grade": "уровень",
|
|
||||||
"total laden": "всего груж",
|
|
||||||
"total unladen": "всего пуст",
|
|
||||||
"module": "модуль",
|
|
||||||
"announcements": "объявления",
|
|
||||||
"resistance": "сопротивление",
|
|
||||||
"Lightweight Alloy": "Лёгкие сплавы",
|
|
||||||
"base": "базовые",
|
|
||||||
"core module classes": "основные модули",
|
|
||||||
"Group highlighted ships": "Сгруппировать выделенные корабли",
|
|
||||||
"tooltips": "всплывающие подсказки",
|
|
||||||
"module resistances": "сопротивление модулей",
|
|
||||||
"power plant": "силовая установка",
|
|
||||||
"thrusters": "маневровые двигатели",
|
|
||||||
"frame shift drive": "рамочно-сместительный двигатель",
|
|
||||||
"life support": "система жизнеобеспечения",
|
|
||||||
"power distributor": "распределитель питания",
|
|
||||||
"sensors": "сенсоры",
|
|
||||||
"fuel tank": "топливный бак",
|
|
||||||
"resting heat (Beta)": "тепло покоя (бета)",
|
|
||||||
"hull hardness": "Прочность корпуса",
|
|
||||||
"weapon": "оружие",
|
|
||||||
"maximum speed": "максимальная скорость",
|
|
||||||
"maximum range": "максимальная дальность",
|
|
||||||
"shortlink": "короткая ссылка",
|
|
||||||
"guardian": "Стражи",
|
|
||||||
"engineers": "инженеры",
|
|
||||||
"component": "компонент",
|
|
||||||
"amount": "кол-во",
|
|
||||||
"core internal": "основное оборуднование",
|
|
||||||
"optional internal": "доп. оборудование",
|
|
||||||
"Heat Sink Launcher": "Теплоотводная катапульта",
|
|
||||||
"scanners": "сканеры",
|
|
||||||
"experimental": "экспериментальное",
|
|
||||||
"mining": "добыча ресурсов",
|
|
||||||
"lasers": "лазеры",
|
|
||||||
"ordnance": "артиллерия",
|
|
||||||
"projectiles": "с боеприпасами",
|
|
||||||
"hangars": "ангары",
|
|
||||||
"limpet controllers": "контроллеры дронов",
|
|
||||||
"passenger cabins": "каюты пассажиров",
|
|
||||||
"structural reinforcement": "усиление конструктива",
|
|
||||||
"flight assists": "помощь в полёте",
|
|
||||||
"modifications": "модификации",
|
|
||||||
"wep_reload": "перезарядка",
|
|
||||||
"optimal multiplier": "оптимальный усилитель",
|
|
||||||
"Cargo Hatch": "Грузовой люк",
|
|
||||||
"Chaff Launcher": "Разбрасыватель дипольных отражателей",
|
|
||||||
"Point Defence": "Точечная оборона",
|
|
||||||
"Electronic Countermeasure": "Радиоэлектронное подавление",
|
|
||||||
"Xeno Scanner": "Ксено-сканер",
|
|
||||||
"Shutdown Field Neutraliser": "Нейтрализатор отключающего поля",
|
|
||||||
"Disruptor": "«Диверсант»",
|
|
||||||
"Pacifier": "«Миротворец»",
|
|
||||||
"Advanced Plasma Accelerator": "Улучшенный ускоритель плазмы",
|
|
||||||
"Cytoscrambler": "«Дезинтегратор»",
|
|
||||||
"Retributor": "«Каратель»",
|
|
||||||
"Enforcer": "«Убийца»",
|
|
||||||
"Imperial Hammer": "«Имперский молот»",
|
|
||||||
"Rocket Propelled FSD Disruptor": "Ракетный FSD-разрушитель",
|
|
||||||
"Pack-Hound": "«Гончие»",
|
|
||||||
"Shock Mine Launcher": "Установщик шоковых мин",
|
|
||||||
"Mining Lance": "«Копьё шахтера»",
|
|
||||||
"Corrosion Resistant": "Коррозийно-устойчивый стеллаж",
|
|
||||||
"Standard Docking Computer": "Стандартный стыковочный компьютер",
|
|
||||||
"Advanced Docking Computer": "Улучшенный стыковочный компьютер",
|
|
||||||
"Detailed Surface Scanner": "Подробный сканер поверхности",
|
|
||||||
"Supercruise Assist": "Помощь в гиперкрейсерском режиме",
|
|
||||||
"Guardian Power Distributor": "Рапределитель питания Стражей",
|
|
||||||
"Enhanced Performance": "Усиленные маневровые двигатели",
|
|
||||||
"Guardian Hybrid Power Plant": "Гибридная силовая установка Стражей",
|
|
||||||
"Reinforced Alloy": "Укреплённые сплавы",
|
|
||||||
"Military Grade Composite": "Композит военного класса",
|
|
||||||
"Mirrored Surface Composite": "Композит с зеркальной поверхностью",
|
|
||||||
"Reactive Surface Composite": "Композит с реактивной поверхностью",
|
|
||||||
"Proto Light Alloys": "Опытные лёгкие сплавы",
|
|
||||||
"Ammo capacity": "Вместимость магазина",
|
|
||||||
"Lightweight": "Облегчённый",
|
|
||||||
"Reinforced": "Усиленный",
|
|
||||||
"Shielded": "Защищённый",
|
|
||||||
"Fast scan": "Быстрое сканирование",
|
|
||||||
"Long range": "Дальнего действия",
|
|
||||||
"Wide angle": "Широкоугольный",
|
|
||||||
"Blast resistant": "Взрывостойкий",
|
|
||||||
"Heavy duty": "Надёжный",
|
|
||||||
"Kinetic resistant": "Противокинетический",
|
|
||||||
"Resistance augmented": "С универсальной защитой",
|
|
||||||
"Thermal resistant": "Термостойкий",
|
|
||||||
"Thermo Block": "Блокировка тепла",
|
|
||||||
"Force Block": "Усиленная блокировка",
|
|
||||||
"Blast Block": "Блокировка взрыва",
|
|
||||||
"Flow Control": "Контроль интенсивности",
|
|
||||||
"Double Braced": "Двойная прочность",
|
|
||||||
"Super Capacitors": "Суперконденсаторы",
|
|
||||||
"Efficient": "Эффективный",
|
|
||||||
"Focused": "Точный",
|
|
||||||
"Overcharged": "Усиленный",
|
|
||||||
"Rapid fire": "Скорострельный",
|
|
||||||
"Short range": "Ближнего действия",
|
|
||||||
"Sturdy": "Прочный",
|
|
||||||
"Oversized": "Сверхразмер",
|
|
||||||
"Stripped Down": "Урезанный вариант",
|
|
||||||
"Phasing sequence": "Последовательность фазирования",
|
|
||||||
"Concordant sequence": "Последовательность координации",
|
|
||||||
"Scramble spectrum": "Отключающая сетка",
|
|
||||||
"Thermal shock": "Тепловой удар",
|
|
||||||
"Emissive munitions": "Эмиссионные припасы",
|
|
||||||
"Multi-servos": "Сервосистема",
|
|
||||||
"Inertial impact": "Инерционный удар",
|
|
||||||
"Thermal vent": "Теплоотдача",
|
|
||||||
"Regeneration sequence": "Последовательность восстановления",
|
|
||||||
"Thermal conduit": "Проводник тепла",
|
|
||||||
"High capacity": "Вместительный магазин",
|
|
||||||
"Incendiary rounds": "Зажигательные припасы",
|
|
||||||
"Auto loader": "Автоматическая система заряжения",
|
|
||||||
"Smart rounds": "Умные боеприпасы",
|
|
||||||
"Corrosive shell": "Разъедающие припасы",
|
|
||||||
"Force shell": "Усиленные снаряды",
|
|
||||||
"High yield shell": "Снаряд большой мощности",
|
|
||||||
"Dispersal field": "Рассеивающее поле",
|
|
||||||
"Thermal cascade": "Термический залп",
|
|
||||||
"Double shot": "Двойной выстрел",
|
|
||||||
"Dazzle shell": "Ослепляющие снаряды",
|
|
||||||
"Screening shell": "Заслоняющие снаряды",
|
|
||||||
"Drag munitions": "Замедляющие боеприпасы",
|
|
||||||
"Target lock breaker": "Генератор помех для системы захвата цели",
|
|
||||||
"Plasma Slug": "Плазменный рельсовый снаряд",
|
|
||||||
"Feedback Cascade": "Ответный запл",
|
|
||||||
"Super Penetrator": "Модуль сверхпробития",
|
|
||||||
"Overload munitions": "Вызывающие перезагрузку боеприпасы",
|
|
||||||
"Penetrator payload": "Бронебойные снаряды",
|
|
||||||
"Penetrator Payload": "Бронебойные снаряды",
|
|
||||||
"FSD interrupt": "Помеха для FSD",
|
|
||||||
"Penetrator Munitions": "Бронебойные боеголовки",
|
|
||||||
"Mass lock munition": "Боеприпасы с гравитационным захватом",
|
|
||||||
"Mass Lock Munition": "Боеприпасы с гравитационным захватом",
|
|
||||||
"Reverberating cascade": "Отражённый залп",
|
|
||||||
"Shift-lock canister": "Рамоблокирующая кассета",
|
|
||||||
"Ion disruptor": "Ионный дестабилизатор",
|
|
||||||
"Radiant Canister": "Светящаяся кассета",
|
|
||||||
"Expanded capture arc": "Расширенная дуга захвата",
|
|
||||||
"Enhanced low power": "Улучшенное энергосбережение",
|
|
||||||
"Fast Charge": "Быстрый заряд",
|
|
||||||
"Multi-weave": "Мультипрошивка",
|
|
||||||
"Hi-Cap": "Высокая ёмкость",
|
|
||||||
"Lo-draw": "Пониженное потребление",
|
|
||||||
"Rapid charge": "Быстрая зарядка",
|
|
||||||
"Specialised": "Адаптивный",
|
|
||||||
"Boss Cells": "Босс-ячейки",
|
|
||||||
"Recycling Cell": "Рециркуляционная ячейка",
|
|
||||||
"Reflective Plating": "Отражающая броня",
|
|
||||||
"Angled Plating": "Угловая броня",
|
|
||||||
"Layered Plating": "Многослойная броня",
|
|
||||||
"Deep Plating": "Утолщённая броня",
|
|
||||||
"Expanded Probe Scanning Radius": "Увеличение радиуса сканирования зондов",
|
|
||||||
"High charge capacity": "Высокоёмкий",
|
|
||||||
"Charge enhanced": "Быстрозаряжающийся",
|
|
||||||
"Engine focused": "Фокус на двигатель",
|
|
||||||
"System focused": "Фокус на систему",
|
|
||||||
"Weapon focused": "Фокус на орудия",
|
|
||||||
"Super Conduits": "Сверхпроводники",
|
|
||||||
"Cluster Capacitors": "Кассетные конденсаторы",
|
|
||||||
"Increased range": "Увеличенная дальность",
|
|
||||||
"Faster boot sequence": "Ускорение запуска",
|
|
||||||
"Deep Charge": "Заряд повышенной мощности",
|
|
||||||
"Thermal Spread": "Рассеивание тепла",
|
|
||||||
"Mass Manager": "Распределитель гравитации",
|
|
||||||
"Dirty": "«Грязная» донастройка",
|
|
||||||
"Clean": "«Чистая» донастройка",
|
|
||||||
"Drag Drives": "Ускорители",
|
|
||||||
"Drive Distributors": "Распределители тяги",
|
|
||||||
"Armoured": "Бронированный",
|
|
||||||
"Low emissions": "Малое излучение",
|
|
||||||
"Monstered": "Монстрация",
|
|
||||||
"roles": "роли",
|
|
||||||
"Maximize Jump Range": "Максимизировать дальность прыжка",
|
|
||||||
"Multi-purpose": "Многоцелевой",
|
|
||||||
"Combat": "Боец",
|
|
||||||
"Trader": "Торговец",
|
|
||||||
"Explorer": "Исследователь",
|
|
||||||
"Planetary Explorer": "Исследователь планет",
|
|
||||||
"Miner": "Старатель",
|
|
||||||
"Racer": "Гонщик",
|
|
||||||
|
|
||||||
"Aberrant Shield Pattern Analysis": "Анализ аномального поведения щита",
|
|
||||||
"Abnormal Compact Emissions Data": "Аномальные компактные данные об излучении",
|
|
||||||
"Aerogel": "Аэрогель",
|
|
||||||
"Adaptive Encryptors Capture": "Захват адаптивного шифровальщика",
|
|
||||||
"Anomalous Bulk Scan Data": "Аномальный массив данных сканирования",
|
|
||||||
"Anomalous FSD Telemetry": "Аномальная телеметрия FSD",
|
|
||||||
"Antimony": "Сурьма",
|
|
||||||
"Arsenic": "Мышьяк",
|
|
||||||
"Atypical Disrupted Wake Echoes": "Атипичное эхо поврежденного следа",
|
|
||||||
"Atypical Encryption Archives": "Нетипичные архивы шифрования",
|
|
||||||
"Basic Conductors": "Простые проводники",
|
|
||||||
"Bio-Mechanical Conduits": "Биомеханические энергопроводники",
|
|
||||||
"Biotech Conductors": "Биотехнические проводники",
|
|
||||||
"Boron": "Бор",
|
|
||||||
"Cadmium": "Кадмий",
|
|
||||||
"Carbon": "Углерод",
|
|
||||||
"Carbon Fibre Plating": "Углеволоконная броня",
|
|
||||||
"Chemical Distillery": "Оборудование для перегонки химикатов",
|
|
||||||
"Chemical Manipulators": "Манипуляторы для работы с химикатами",
|
|
||||||
"Chemical Processors": "Оборудование для химобработки",
|
|
||||||
"Chromium": "Хром",
|
|
||||||
"Classified Scan Databanks": "Засекреченные базы данных сканирования",
|
|
||||||
"Classified Scan Fragment": "Засекреченные фрагменты данных сканирования",
|
|
||||||
"Compound Shielding": "Многоступенчатая защита",
|
|
||||||
"Conductive Ceramics": "Проводящая керамика",
|
|
||||||
"Conductive Components": "Проводящие компоненты",
|
|
||||||
"Conductive Polymers": "Проводящие полимеры",
|
|
||||||
"Configurable Components": "Настраиваемые компоненты",
|
|
||||||
"Core Dynamics Composites": "Композиты Core Dynamics",
|
|
||||||
"Cracked Industrial Firmware": "Взломанные промышленные микропрограммы",
|
|
||||||
"Datamined Wake Exceptions": "Исключения из глубинного анализа данных следа",
|
|
||||||
"Decoded Emission Data": "Расшифрованные данные об излучении",
|
|
||||||
"Distorted Shield Cycle Recordings": "Повреждённые цикличные записи щита",
|
|
||||||
"Divergent Scan Data": "Неформатные данные сканирования",
|
|
||||||
"Eccentric Hyperspace Trajectories": "Аномальные траектории в гиперпространстве",
|
|
||||||
"Electrochemical Arrays": "Электрохимические массивы",
|
|
||||||
"Exceptional Scrambled Emission Data": "Исключительные зашифрованные данные об излучении",
|
|
||||||
"Exquisite Focus Crystals": "Отборные фокусировочные кристаллы",
|
|
||||||
"Flawed Focus Crystals": "Поврежденные фокусировочные кристаллы",
|
|
||||||
"Focus Crystals": "Фокусировочные кристаллы",
|
|
||||||
"Galvanising Alloys": "Сплавы для гальванизации",
|
|
||||||
"Germanium": "Германий",
|
|
||||||
"Grid Resistors": "Наборные резисторы",
|
|
||||||
"Heat Conduction Wiring": "Теплопроводящие провода",
|
|
||||||
"Heat Dispersion Plate": "Теплорассеивающая пластина",
|
|
||||||
"Heat Exchangers": "Теплообменные агрегаты",
|
|
||||||
"Heat Vanes": "Тепловые заслонки",
|
|
||||||
"High Density Composites": "Высокоплотностные композиты",
|
|
||||||
"Hybrid Capacitors": "Гибридные конденсаторы",
|
|
||||||
"Imperial Shielding": "Имперская защита",
|
|
||||||
"Improvised Components": "Кустарные компоненты",
|
|
||||||
"Inconsistent Shield Soak Analysis": "Неполный анализ поглощения щита",
|
|
||||||
"Iron": "Железо",
|
|
||||||
"Irregular Emission Data": "Нестандартные данные об излучении",
|
|
||||||
"Manganese": "Марганец",
|
|
||||||
"Mechanical Components": "Механические компоненты",
|
|
||||||
"Mechanical Equipment": "Механическое оборудование",
|
|
||||||
"Mechanical Scrap": "Механические отходы",
|
|
||||||
"Mercury": "Ртуть",
|
|
||||||
"Military Grade Alloys": "Сплавы военного назначения",
|
|
||||||
"Military Supercapacitors": "Военные суперконденсаторы",
|
|
||||||
"Modified Consumer Firmware": "Изменённые пользовательские микропрограммы",
|
|
||||||
"Modified Embedded Firmware": "Изменённые встроенные микропрограммы",
|
|
||||||
"Molybdenum": "Молибден",
|
|
||||||
"Nickel": "Никель",
|
|
||||||
"Niobium": "Ниобий",
|
|
||||||
"Open Symmetric Keys": "Открытые симметричные ключи",
|
|
||||||
"Pharmaceutical Isolators": "Фармацевтические изоляционные материалы",
|
|
||||||
"Phase Alloys": "Фазовые сплавы",
|
|
||||||
"Phosphorus": "Фосфор",
|
|
||||||
"Polymer Capacitors": "Полимерные конденсаторы",
|
|
||||||
"Precipitated Alloys": "Осаждённые сплавы",
|
|
||||||
"Proprietary Composites": "Патентованные композиты",
|
|
||||||
"Proto Heat Radiators": "Прототипы теплоизлучателей",
|
|
||||||
"Proto Radiolic Alloys": "Сплавы для изготовления зондов",
|
|
||||||
"Refined Focus Crystals": "Обработанные фокусировочные кристаллы",
|
|
||||||
"Ruthenium": "Рутений",
|
|
||||||
"Salvaged Alloys": "Захваченные сплавы",
|
|
||||||
"Security Firmware Patch": "Обновление для защитной микропрограммы",
|
|
||||||
"Selenium": "Селен",
|
|
||||||
"Shield Emitters": "Щитоизлучатели",
|
|
||||||
"Shielding Sensors": "Сенсоры системы экранирования",
|
|
||||||
"Specialised Legacy Firmware": "Специальные микропрограммы предыдущего поколения",
|
|
||||||
"Strange Wake Solutions": "Странные расчёты следа",
|
|
||||||
"Sulphur": "Сера",
|
|
||||||
"Tagged Encryption Codes": "Меченные шифровальные коды",
|
|
||||||
"Technetium": "Технеций",
|
|
||||||
"Tellurium": "Теллур",
|
|
||||||
"Thermic Alloys": "Термические сплавы",
|
|
||||||
"Tin": "Олово",
|
|
||||||
"Tungsten": "Вольфрам",
|
|
||||||
"Unexpected Emission Data": "Неожиданные данные об излучении",
|
|
||||||
"Unidentified Scan Archives": "Неопознанные архивы сканирования",
|
|
||||||
"Untypical Shield Scans": "Нетипичные данные сканирования щитов",
|
|
||||||
"Unusual Encrypted Files": "Особые зашифрованные файлы",
|
|
||||||
"Vanadium": "Ванадий",
|
|
||||||
"Worn Shield Emitters": "Изношенные щитоизлучатели",
|
|
||||||
"Yttrium": "Иттрий",
|
|
||||||
"Zinc": "Цинк",
|
|
||||||
"Zirconium": "Цирконий"
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,12 @@
|
|||||||
|
import '@babel/polyfill';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { render } from 'react-dom';
|
import { render } from 'react-dom';
|
||||||
import '../less/app.less';
|
import '../less/app.less';
|
||||||
import Coriolis from './Coriolis';
|
import Coriolis from './Coriolis';
|
||||||
|
// import TapEventPlugin from 'react/lib/TapEventPlugin';
|
||||||
|
// import EventPluginHub from 'react/lib/EventPluginHub';
|
||||||
|
|
||||||
|
// onTouchTap not ready for primetime yet, too many issues with preventing default
|
||||||
|
// EventPluginHub.injection.injectEventPluginsByName({ TapEventPlugin });
|
||||||
|
|
||||||
render(<Coriolis />, document.getElementById('coriolis'));
|
render(<Coriolis />, document.getElementById('coriolis'));
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { CoriolisLogo, GitHub } from '../components/SvgIcons';
|
|||||||
* About Page
|
* About Page
|
||||||
*/
|
*/
|
||||||
export default class AboutPage extends Page {
|
export default class AboutPage extends Page {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
* @param {Object} props React Component properties
|
* @param {Object} props React Component properties
|
||||||
@@ -22,79 +23,33 @@ export default class AboutPage extends Page {
|
|||||||
* @return {React.Component} The page contents
|
* @return {React.Component} The page contents
|
||||||
*/
|
*/
|
||||||
renderPage() {
|
renderPage() {
|
||||||
return (
|
return <div className={'page'} style={{ textAlign: 'left', maxWidth: 800, margin: '0 auto' }}>
|
||||||
<div
|
<h1><CoriolisLogo style={{ marginRight: '0.4em' }} className='xl'/><span className='warning'>Coriolis EDCD Edition</span></h1>
|
||||||
className={'page'}
|
|
||||||
style={{ textAlign: 'left', maxWidth: 800, margin: '0 auto' }}
|
|
||||||
>
|
|
||||||
<h1>
|
|
||||||
<CoriolisLogo style={{ marginRight: '0.4em' }} className="xl" />
|
|
||||||
<span className="warning">Coriolis EDCD Edition</span>
|
|
||||||
</h1>
|
|
||||||
|
|
||||||
<p>
|
<p>This is a clone of the Coriolis project, whose original author is currently unable to maintain it. This clone is maintained by the <a href="http://edcd.github.io/">EDCD community</a>.</p>
|
||||||
This is a clone of the Coriolis project, whose original author is
|
<p>To recover your builds, go to <a href='https://coriolis.io/' target='_blank'>https://coriolis.io/</a>, backup your builds (Settings / Backup), copy the text, return here and import (Settings / Import).</p>
|
||||||
currently unable to maintain it. This clone is maintained by the{' '}
|
<p>The Coriolis project was inspired by <a href='http://www.edshipyard.com/' target='_blank'>E:D Shipyard</a> and, of course, <a href='http://www.elitedangerous.com' target='_blank'>Elite Dangerous</a>. The ultimate goal of Coriolis is to provide rich features to support in-game play and planning while engaging the E:D community to support its development.</p>
|
||||||
<a href="http://edcd.github.io/">EDCD community</a>.
|
<p>Coriolis was created using assets and imagery from Elite: Dangerous, with the permission of Frontier Developments plc, for non-commercial purposes. It is not endorsed by nor reflects the views or opinions of Frontier Developments. A number of assets were sourced from <a href='http://edassets.org' target='_blank'>ED Assets</a></p>
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
To recover your builds, go to{' '}
|
|
||||||
<a href="https://coriolis.io/" target="_blank">
|
|
||||||
https://coriolis.io/
|
|
||||||
</a>
|
|
||||||
, backup your builds (Settings / Backup), copy the text, return here
|
|
||||||
and import (Settings / Import).
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
The Coriolis project was inspired by{' '}
|
|
||||||
<a href="http://www.edshipyard.com/" target="_blank">
|
|
||||||
E:D Shipyard
|
|
||||||
</a>{' '}
|
|
||||||
and, of course,{' '}
|
|
||||||
<a href="http://www.elitedangerous.com" target="_blank">
|
|
||||||
Elite Dangerous
|
|
||||||
</a>
|
|
||||||
. The ultimate goal of Coriolis is to provide rich features to support
|
|
||||||
in-game play and planning while engaging the E:D community to support
|
|
||||||
its development.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Coriolis was created using assets and imagery from Elite: Dangerous,
|
|
||||||
with the permission of Frontier Developments plc, for non-commercial
|
|
||||||
purposes. It is not endorsed by nor reflects the views or opinions of
|
|
||||||
Frontier Developments. A number of assets were sourced from{' '}
|
|
||||||
<a href="http://edassets.org" target="_blank">
|
|
||||||
ED Assets
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<a
|
<a style={{ display: 'block', textDecoration: 'none' }} href='https://github.com/EDCD/coriolis' target='_blank' title='Coriolis Github Project'>
|
||||||
style={{ display: 'block', textDecoration: 'none' }}
|
<GitHub style={{ margin: '0.4em' }} className='l fg xl'/>
|
||||||
href="https://github.com/EDCD/coriolis"
|
<h2 style={{ margin: 0, textDecoration: 'none' }}>Github</h2>
|
||||||
target="_blank"
|
github.com/EDCD/coriolis
|
||||||
title="Coriolis Github Project"
|
</a>
|
||||||
>
|
|
||||||
<GitHub style={{ margin: '0.4em' }} className="l fg xl" />
|
|
||||||
<h2 style={{ margin: 0, textDecoration: 'none' }}>Github</h2>
|
|
||||||
github.com/EDCD/coriolis
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<p>
|
<p>Coriolis is an open source project. Checkout the list of upcoming features and to-do list on github. Any and all contributions and feedback are welcome. If you encounter any bugs please report them and provide as much detail as possible.</p>
|
||||||
Coriolis is an open source project. Checkout the list of upcoming
|
|
||||||
features and to-do list on github. Any and all contributions and
|
|
||||||
feedback are welcome. If you encounter any bugs please report them and
|
|
||||||
provide as much detail as possible.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3>Chat</h3>
|
<h3>Chat</h3>
|
||||||
<p>
|
<p>You can chat to us on our <a href='https://discord.gg/0uwCh6R62aPRjk9w' target='_blank'>EDCD Discord server</a>.</p>
|
||||||
You can chat to us on our{' '}
|
|
||||||
<a href="https://discord.gg/0uwCh6R62aPRjk9w" target="_blank">
|
<h3>Supporting Coriolis</h3>
|
||||||
EDCD Discord server
|
<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>
|
||||||
</a>
|
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_top">
|
||||||
.
|
<input type="hidden" name="cmd" value="_s-xclick"/>
|
||||||
</p>
|
<input type="hidden" name="hosted_button_id" value="SJBKT2SWEEU68" />
|
||||||
</div>
|
<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>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,14 +13,7 @@ import ModalCompare from '../components/ModalCompare';
|
|||||||
import ModalExport from '../components/ModalExport';
|
import ModalExport from '../components/ModalExport';
|
||||||
import ModalPermalink from '../components/ModalPermalink';
|
import ModalPermalink from '../components/ModalPermalink';
|
||||||
import ModalImport from '../components/ModalImport';
|
import ModalImport from '../components/ModalImport';
|
||||||
import {
|
import { FloppyDisk, Bin, Download, Embed, Rocket, LinkIcon } from '../components/SvgIcons';
|
||||||
FloppyDisk,
|
|
||||||
Bin,
|
|
||||||
Download,
|
|
||||||
Embed,
|
|
||||||
Rocket,
|
|
||||||
LinkIcon
|
|
||||||
} from '../components/SvgIcons';
|
|
||||||
import ShortenUrl from '../utils/ShortenUrl';
|
import ShortenUrl from '../utils/ShortenUrl';
|
||||||
import { comparisonBBCode } from '../utils/BBCode';
|
import { comparisonBBCode } from '../utils/BBCode';
|
||||||
const browser = require('detect-browser');
|
const browser = require('detect-browser');
|
||||||
@@ -49,6 +42,7 @@ function sortBy(predicate) {
|
|||||||
* Comparison Page
|
* Comparison Page
|
||||||
*/
|
*/
|
||||||
export default class ComparisonPage extends Page {
|
export default class ComparisonPage extends Page {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
* @param {Object} props React Component properties
|
* @param {Object} props React Component properties
|
||||||
@@ -87,13 +81,7 @@ export default class ComparisonPage extends Page {
|
|||||||
for (let shipId in allBuilds) {
|
for (let shipId in allBuilds) {
|
||||||
for (let buildName in allBuilds[shipId]) {
|
for (let buildName in allBuilds[shipId]) {
|
||||||
if (buildName && allBuilds[shipId][buildName]) {
|
if (buildName && allBuilds[shipId][buildName]) {
|
||||||
builds.push(
|
builds.push(this._createBuild(shipId, buildName, allBuilds[shipId][buildName]));
|
||||||
this._createBuild(
|
|
||||||
shipId,
|
|
||||||
buildName,
|
|
||||||
allBuilds[shipId][buildName]
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -101,9 +89,7 @@ export default class ComparisonPage extends Page {
|
|||||||
let comparisonData = Persist.getComparison(name);
|
let comparisonData = Persist.getComparison(name);
|
||||||
if (comparisonData) {
|
if (comparisonData) {
|
||||||
defaultFacets = comparisonData.facets;
|
defaultFacets = comparisonData.facets;
|
||||||
comparisonData.builds.forEach(b =>
|
comparisonData.builds.forEach((b) => builds.push(this._createBuild(b.shipId, b.buildName)));
|
||||||
builds.push(this._createBuild(b.shipId, b.buildName))
|
|
||||||
);
|
|
||||||
saved = true;
|
saved = true;
|
||||||
newName = name;
|
newName = name;
|
||||||
}
|
}
|
||||||
@@ -115,7 +101,7 @@ export default class ComparisonPage extends Page {
|
|||||||
newName = name = comparisonData.n;
|
newName = name = comparisonData.n;
|
||||||
predicate = comparisonData.p;
|
predicate = comparisonData.p;
|
||||||
desc = comparisonData.d;
|
desc = comparisonData.d;
|
||||||
comparisonData.b.forEach(build => {
|
comparisonData.b.forEach((build) => {
|
||||||
builds.push(this._createBuild(build.s, build.n, build.c));
|
builds.push(this._createBuild(build.s, build.n, build.c));
|
||||||
if (!importObj[build.s]) {
|
if (!importObj[build.s]) {
|
||||||
importObj[build.s] = {};
|
importObj[build.s] = {};
|
||||||
@@ -132,9 +118,9 @@ export default class ComparisonPage extends Page {
|
|||||||
let selectedFacets = new Array(selectedLength);
|
let selectedFacets = new Array(selectedLength);
|
||||||
|
|
||||||
for (let i = 0; i < ShipFacets.length; i++) {
|
for (let i = 0; i < ShipFacets.length; i++) {
|
||||||
let facet = Object.assign({}, ShipFacets[i]);
|
let facet = Object.assign({ }, ShipFacets[i]);
|
||||||
let defaultIndex = defaultFacets.indexOf(facet.i);
|
let defaultIndex = defaultFacets.indexOf(facet.i);
|
||||||
if (defaultIndex == -1) {
|
if(defaultIndex == -1) {
|
||||||
facets.push(facet);
|
facets.push(facet);
|
||||||
} else {
|
} else {
|
||||||
facet.active = true;
|
facet.active = true;
|
||||||
@@ -169,18 +155,17 @@ export default class ComparisonPage extends Page {
|
|||||||
_createBuild(id, name, code) {
|
_createBuild(id, name, code) {
|
||||||
code = code ? code : Persist.getBuild(id, name); // Retrieve build code if not passed
|
code = code ? code : Persist.getBuild(id, name); // Retrieve build code if not passed
|
||||||
|
|
||||||
if (!code) {
|
if (!code) { // No build found
|
||||||
// No build found
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let data = Ships[id]; // Get ship properties
|
let data = Ships[id]; // Get ship properties
|
||||||
let b = new Ship(id, data.properties, data.slots); // Create a new Ship instance
|
let b = new Ship(id, data.properties, data.slots); // Create a new Ship instance
|
||||||
b.buildFrom(code); // Populate components from code
|
b.buildFrom(code); // Populate components from code
|
||||||
b.buildName = name;
|
b.buildName = name;
|
||||||
b.applyDiscounts(Persist.getShipDiscount(), Persist.getModuleDiscount());
|
b.applyDiscounts(Persist.getShipDiscount(), Persist.getModuleDiscount());
|
||||||
return b;
|
return b;
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update state with the specified sort predicates
|
* Update state with the specified sort predicates
|
||||||
@@ -199,18 +184,13 @@ export default class ComparisonPage extends Page {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.setState({ predicate, desc });
|
this.setState({ predicate, desc });
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show selected builds modal
|
* Show selected builds modal
|
||||||
*/
|
*/
|
||||||
_selectBuilds() {
|
_selectBuilds() {
|
||||||
this.context.showModal(
|
this.context.showModal(<ModalCompare onSelect={this._buildsSelected} builds={this.state.builds} />);
|
||||||
<ModalCompare
|
|
||||||
onSelect={this._buildsSelected}
|
|
||||||
builds={this.state.builds}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -244,7 +224,7 @@ export default class ComparisonPage extends Page {
|
|||||||
_facetDrag(e) {
|
_facetDrag(e) {
|
||||||
this.nodeAfter = false;
|
this.nodeAfter = false;
|
||||||
this.dragged = e.currentTarget;
|
this.dragged = e.currentTarget;
|
||||||
let placeholder = (this.placeholder = document.createElement('li'));
|
let placeholder = this.placeholder = document.createElement('li');
|
||||||
placeholder.style.width = Math.round(this.dragged.offsetWidth) + 'px';
|
placeholder.style.width = Math.round(this.dragged.offsetWidth) + 'px';
|
||||||
placeholder.className = 'facet-placeholder';
|
placeholder.className = 'facet-placeholder';
|
||||||
if (!browser || (browser.name !== 'edge' && browser.name !== 'ie')) {
|
if (!browser || (browser.name !== 'edge' && browser.name !== 'ie')) {
|
||||||
@@ -282,7 +262,7 @@ export default class ComparisonPage extends Page {
|
|||||||
_facetDragOver(e) {
|
_facetDragOver(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
if (e.target.className == 'facet-placeholder') {
|
if(e.target.className == 'facet-placeholder') {
|
||||||
return;
|
return;
|
||||||
} else if (e.target != e.currentTarget) {
|
} else if (e.target != e.currentTarget) {
|
||||||
this.over = e.target;
|
this.over = e.target;
|
||||||
@@ -292,7 +272,7 @@ export default class ComparisonPage extends Page {
|
|||||||
let parent = e.target.parentNode;
|
let parent = e.target.parentNode;
|
||||||
|
|
||||||
if (parent == e.currentTarget) {
|
if (parent == e.currentTarget) {
|
||||||
if (relX > width && this.dragged != e.target) {
|
if(relX > width && this.dragged != e.target) {
|
||||||
this.nodeAfter = true;
|
this.nodeAfter = true;
|
||||||
parent.insertBefore(this.placeholder, e.target.nextElementSibling);
|
parent.insertBefore(this.placeholder, e.target.nextElementSibling);
|
||||||
} else {
|
} else {
|
||||||
@@ -341,7 +321,7 @@ export default class ComparisonPage extends Page {
|
|||||||
let { newName, builds, facets } = this.state;
|
let { newName, builds, facets } = this.state;
|
||||||
let selectedFacets = [];
|
let selectedFacets = [];
|
||||||
|
|
||||||
facets.forEach(f => {
|
facets.forEach((f) => {
|
||||||
if (f.active) {
|
if (f.active) {
|
||||||
selectedFacets.unshift(f.i);
|
selectedFacets.unshift(f.i);
|
||||||
}
|
}
|
||||||
@@ -368,20 +348,14 @@ export default class ComparisonPage extends Page {
|
|||||||
|
|
||||||
let code = fromComparison(name, builds, selectedFacets, predicate, desc);
|
let code = fromComparison(name, builds, selectedFacets, predicate, desc);
|
||||||
let loc = window.location;
|
let loc = window.location;
|
||||||
return (
|
return loc.protocol + '//' + loc.host + '/comparison?code=' + encodeURIComponent(code);
|
||||||
loc.protocol +
|
|
||||||
'//' +
|
|
||||||
loc.host +
|
|
||||||
'/comparison?code=' +
|
|
||||||
encodeURIComponent(code)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates the long permalink URL
|
* Generates the long permalink URL
|
||||||
*/
|
*/
|
||||||
_genPermalink() {
|
_genPermalink() {
|
||||||
this.context.showModal(<ModalPermalink url={this._buildUrl()} />);
|
this.context.showModal(<ModalPermalink url={this._buildUrl()}/>);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -391,25 +365,18 @@ export default class ComparisonPage extends Page {
|
|||||||
let { translate, formats } = this.context.language;
|
let { translate, formats } = this.context.language;
|
||||||
let { facets, builds } = this.state;
|
let { facets, builds } = this.state;
|
||||||
|
|
||||||
let generator = callback => {
|
let generator = (callback) => {
|
||||||
let url = this._buildUrl();
|
let url = this._buildUrl();
|
||||||
ShortenUrl(
|
ShortenUrl(url,
|
||||||
url,
|
(shortenedUrl) => callback(comparisonBBCode(translate, formats, facets, builds, shortenedUrl)),
|
||||||
shortenedUrl =>
|
(error) => callback(comparisonBBCode(translate, formats, facets, builds, url))
|
||||||
callback(
|
|
||||||
comparisonBBCode(translate, formats, facets, builds, shortenedUrl)
|
|
||||||
),
|
|
||||||
error =>
|
|
||||||
callback(comparisonBBCode(translate, formats, facets, builds, url))
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.context.showModal(
|
this.context.showModal(<ModalExport
|
||||||
<ModalExport
|
title={translate('forum') + ' BBCode'}
|
||||||
title={translate('forum') + ' BBCode'}
|
generator={generator}
|
||||||
generator={generator}
|
/>);
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -442,8 +409,7 @@ export default class ComparisonPage extends Page {
|
|||||||
* @param {Object} nextContext Incoming/Next conext
|
* @param {Object} nextContext Incoming/Next conext
|
||||||
*/
|
*/
|
||||||
componentWillReceiveProps(nextProps, nextContext) {
|
componentWillReceiveProps(nextProps, nextContext) {
|
||||||
if (this.context.route !== nextContext.route) {
|
if (this.context.route !== nextContext.route) { // Only reinit state if the route has changed
|
||||||
// Only reinit state if the route has changed
|
|
||||||
this.setState(this._initState(nextContext));
|
this.setState(this._initState(nextContext));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -453,10 +419,7 @@ export default class ComparisonPage extends Page {
|
|||||||
*/
|
*/
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
this.resizeListener = this.context.onWindowResize(this._updateDimensions);
|
this.resizeListener = this.context.onWindowResize(this._updateDimensions);
|
||||||
this.persistListener = Persist.addListener(
|
this.persistListener = Persist.addListener('discounts', this._updateDiscounts);
|
||||||
'discounts',
|
|
||||||
this._updateDiscounts
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -481,132 +444,65 @@ export default class ComparisonPage extends Page {
|
|||||||
renderPage() {
|
renderPage() {
|
||||||
let translate = this.context.language.translate;
|
let translate = this.context.language.translate;
|
||||||
let compareHeader;
|
let compareHeader;
|
||||||
let {
|
let { newName, name, saved, builds, facets, predicate, desc, chartWidth } = this.state;
|
||||||
newName,
|
|
||||||
name,
|
|
||||||
saved,
|
|
||||||
builds,
|
|
||||||
facets,
|
|
||||||
predicate,
|
|
||||||
desc,
|
|
||||||
chartWidth
|
|
||||||
} = this.state;
|
|
||||||
|
|
||||||
if (this.state.compareMode) {
|
if (this.state.compareMode) {
|
||||||
compareHeader = (
|
compareHeader = <tr>
|
||||||
<tr>
|
<td className='head'>{translate('comparison')}</td>
|
||||||
<td className="head">{translate('comparison')}</td>
|
<td>
|
||||||
<td>
|
<input value={newName} onChange={this._onNameChange} placeholder={translate('Enter Name')} maxLength='50' />
|
||||||
<input
|
<button onClick={this._save} disabled={!newName || newName == 'all' || saved}>
|
||||||
value={newName}
|
<FloppyDisk className='lg'/><span className='button-lbl'>{translate('save')}</span>
|
||||||
onChange={this._onNameChange}
|
</button>
|
||||||
placeholder={translate('Enter Name')}
|
<button onClick={this._delete} disabled={name == 'all' || !saved}><Bin className='lg warning'/></button>
|
||||||
maxLength="50"
|
<button onClick={this._selectBuilds}>
|
||||||
/>
|
<Rocket className='lg'/><span className='button-lbl'>{translate('builds')}</span>
|
||||||
<button
|
</button>
|
||||||
onClick={this._save}
|
<button className='r' onClick={this._genPermalink} disabled={builds.length == 0}>
|
||||||
disabled={!newName || newName == 'all' || saved}
|
<LinkIcon className='lg'/><span className='button-lbl'>{translate('permalink')}</span>
|
||||||
>
|
</button>
|
||||||
<FloppyDisk className="lg" />
|
<button className='r' onClick={this._genBBcode} disabled={builds.length == 0}>
|
||||||
<span className="button-lbl">{translate('save')}</span>
|
<Embed className='lg'/><span className='button-lbl'>{translate('forum')}</span>
|
||||||
</button>
|
</button>
|
||||||
<button onClick={this._delete} disabled={name == 'all' || !saved}>
|
</td>
|
||||||
<Bin className="lg warning" />
|
</tr>;
|
||||||
</button>
|
|
||||||
<button onClick={this._selectBuilds}>
|
|
||||||
<Rocket className="lg" />
|
|
||||||
<span className="button-lbl">{translate('builds')}</span>
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
className="r"
|
|
||||||
onClick={this._genPermalink}
|
|
||||||
disabled={builds.length == 0}
|
|
||||||
>
|
|
||||||
<LinkIcon className="lg" />
|
|
||||||
<span className="button-lbl">{translate('permalink')}</span>
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
className="r"
|
|
||||||
onClick={this._genBBcode}
|
|
||||||
disabled={builds.length == 0}
|
|
||||||
>
|
|
||||||
<Embed className="lg" />
|
|
||||||
<span className="button-lbl">{translate('forum')}</span>
|
|
||||||
</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
compareHeader = (
|
compareHeader = <tr>
|
||||||
<tr>
|
<td className='head'>{translate('comparison')}</td>
|
||||||
<td className="head">{translate('comparison')}</td>
|
<td>
|
||||||
<td>
|
<h3>{name}</h3>
|
||||||
<h3>{name}</h3>
|
<button className='r' onClick={this._import}><Download className='lg'/>{translate('import')}</button>
|
||||||
<button className="r" onClick={this._import}>
|
</td>
|
||||||
<Download className="lg" />
|
</tr>;
|
||||||
{translate('import')}
|
|
||||||
</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div className={'page'} style={{ fontSize: this.context.sizeRatio + 'em' }}>
|
||||||
className={'page'}
|
<table id='comparison'>
|
||||||
style={{ fontSize: this.context.sizeRatio + 'em' }}
|
|
||||||
>
|
|
||||||
<table id="comparison">
|
|
||||||
<tbody>
|
<tbody>
|
||||||
{compareHeader}
|
{compareHeader}
|
||||||
<tr key="facets">
|
<tr key='facets'>
|
||||||
<td className="head">{translate('compare')}</td>
|
<td className='head'>{translate('compare')}</td>
|
||||||
<td>
|
<td>
|
||||||
<ul id="facet-container" onDragOver={this._facetDragOver}>
|
<ul id='facet-container' onDragOver={this._facetDragOver}>
|
||||||
{facets.map((f, i) => (
|
{facets.map((f, i) =>
|
||||||
<li
|
<li key={f.title} data-i={i} draggable='true' onDragStart={this._facetDrag} onDragEnd={this._facetDrop} className={cn('facet', { active: f.active })} onClick={this._toggleFacet.bind(this, f)}>
|
||||||
key={f.title}
|
|
||||||
data-i={i}
|
|
||||||
draggable="true"
|
|
||||||
onDragStart={this._facetDrag}
|
|
||||||
onDragEnd={this._facetDrop}
|
|
||||||
className={cn('facet', { active: f.active })}
|
|
||||||
onClick={this._toggleFacet.bind(this, f)}
|
|
||||||
>
|
|
||||||
{'↔ ' + translate(f.title)}
|
{'↔ ' + translate(f.title)}
|
||||||
</li>
|
</li>
|
||||||
))}
|
)}
|
||||||
</ul>
|
</ul>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<ComparisonTable
|
<ComparisonTable builds={builds} facets={facets} onSort={this._sortShips} predicate={predicate} desc={desc} />
|
||||||
builds={builds}
|
|
||||||
facets={facets}
|
|
||||||
onSort={this._sortShips}
|
|
||||||
predicate={predicate}
|
|
||||||
desc={desc}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{!builds.length ? (
|
{!builds.length ?
|
||||||
<div className="chart" ref={node => (this.chartRef = node)}>
|
<div className='chart' ref={node => this.chartRef = node}>{translate('PHRASE_NO_BUILDS')}</div> :
|
||||||
{translate('PHRASE_NO_BUILDS')}
|
facets.filter((f) => f.active).map((f, i) =>
|
||||||
</div>
|
<div key={f.title} className='chart' ref={ i == 0 ? node => this.chartRef = node : null}>
|
||||||
) : (
|
<h3 className='ptr' onClick={this._sortShips.bind(this, f.props[0])}>{translate(f.title)}</h3>
|
||||||
facets.filter(f => f.active).map((f, i) => (
|
|
||||||
<div
|
|
||||||
key={f.title}
|
|
||||||
className="chart"
|
|
||||||
ref={i == 0 ? node => (this.chartRef = node) : null}
|
|
||||||
>
|
|
||||||
<h3
|
|
||||||
className="ptr"
|
|
||||||
onClick={this._sortShips.bind(this, f.props[0])}
|
|
||||||
>
|
|
||||||
{translate(f.title)}
|
|
||||||
</h3>
|
|
||||||
<BarChart
|
<BarChart
|
||||||
width={chartWidth}
|
width={chartWidth}
|
||||||
data={builds}
|
data={builds}
|
||||||
@@ -619,8 +515,8 @@ export default class ComparisonPage extends Page {
|
|||||||
desc={desc}
|
desc={desc}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
))
|
|
||||||
)}
|
)}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,9 +45,6 @@ export default class ErrorDetails extends React.Component {
|
|||||||
return <div className='error'>
|
return <div className='error'>
|
||||||
<h1>Jameson, we have a problem..</h1>
|
<h1>Jameson, we have a problem..</h1>
|
||||||
<h1><small>{error.message}</small></h1>
|
<h1><small>{error.message}</small></h1>
|
||||||
Import Error handling has been improved, but still isn't perfect. <br/>MOST Import failures are a result of missing modules in Coriolis, <br />OR incorrect import strings generated by third party apps. If you're seeing this page, we may have failed to handle the errors in your import correctly. Please see the data output below, specifically the 'scriptUrl:' section if it's there and then if you feel confident enough, please check the github issues page linked below and see if there is a similar issue already logged. If not, please create a new issue with the data below. If you're not confident, please ask for help on the Coriolis Channel of the EDCD Discord server.
|
|
||||||
<br/>
|
|
||||||
<br/>
|
|
||||||
<br/>
|
<br/>
|
||||||
{importerror ? <div>If you are attempting to import a ship from EDDI or EDMC and are seeing a 'Z_BUF_ERROR' it means that the URL has not been provided correctly. This is a common problem when using Microsoft Internet Explorer or Microsoft Edge, and you should use another browser instead.</div> : null }
|
{importerror ? <div>If you are attempting to import a ship from EDDI or EDMC and are seeing a 'Z_BUF_ERROR' it means that the URL has not been provided correctly. This is a common problem when using Microsoft Internet Explorer or Microsoft Edge, and you should use another browser instead.</div> : null }
|
||||||
<br/>
|
<br/>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import Page from './Page';
|
|||||||
* 404 Page
|
* 404 Page
|
||||||
*/
|
*/
|
||||||
export default class NotFoundPage extends Page {
|
export default class NotFoundPage extends Page {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
* @param {Object} props React Component properties
|
* @param {Object} props React Component properties
|
||||||
@@ -21,10 +22,6 @@ export default class NotFoundPage extends Page {
|
|||||||
* @return {React.Component} The page contents
|
* @return {React.Component} The page contents
|
||||||
*/
|
*/
|
||||||
renderPage() {
|
renderPage() {
|
||||||
return (
|
return <div className='page' style={{ marginTop: 30 }}>Page <small>{this.context.route.path}</small> Not Found</div>;
|
||||||
<div className="page" style={{ marginTop: 30 }}>
|
|
||||||
Page <small>{this.context.route.path}</small> Not Found
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
// import Perf from 'react-addons-perf';
|
||||||
import { Ships } from 'coriolis-data/dist';
|
import { Ships } from 'coriolis-data/dist';
|
||||||
import cn from 'classnames';
|
import cn from 'classnames';
|
||||||
import Page from './Page';
|
import Page from './Page';
|
||||||
@@ -18,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';
|
||||||
@@ -35,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
|
||||||
@@ -50,6 +53,7 @@ function getTitle(shipName, buildName) {
|
|||||||
* The Outfitting Page
|
* The Outfitting Page
|
||||||
*/
|
*/
|
||||||
export default class OutfittingPage extends Page {
|
export default class OutfittingPage extends Page {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
* @param {Object} props React Component properties
|
* @param {Object} props React Component properties
|
||||||
@@ -57,6 +61,7 @@ export default class OutfittingPage extends Page {
|
|||||||
*/
|
*/
|
||||||
constructor(props, context) {
|
constructor(props, context) {
|
||||||
super(props, context);
|
super(props, context);
|
||||||
|
// window.Perf = Perf;
|
||||||
this.state = this._initState(props, context);
|
this.state = this._initState(props, context);
|
||||||
this._keyDown = this._keyDown.bind(this);
|
this._keyDown = this._keyDown.bind(this);
|
||||||
this._exportBuild = this._exportBuild.bind(this);
|
this._exportBuild = this._exportBuild.bind(this);
|
||||||
@@ -80,38 +85,22 @@ export default class OutfittingPage extends Page {
|
|||||||
let shipId = params.ship;
|
let shipId = params.ship;
|
||||||
let code = params.code;
|
let code = params.code;
|
||||||
let buildName = params.bn;
|
let buildName = params.bn;
|
||||||
let data = Ships[shipId]; // Retrieve the basic ship properties, slots and defaults
|
let data = Ships[shipId]; // Retrieve the basic ship properties, slots and defaults
|
||||||
let savedCode = Persist.getBuild(shipId, buildName);
|
let savedCode = Persist.getBuild(shipId, buildName);
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return { error: { message: 'Ship not found: ' + shipId } };
|
return { error: { message: 'Ship not found: ' + shipId } };
|
||||||
}
|
}
|
||||||
let ship = new Ship(shipId, data.properties, data.slots); // Create a new Ship instance
|
let ship = new Ship(shipId, data.properties, data.slots); // Create a new Ship instance
|
||||||
if (code) {
|
if (code) {
|
||||||
ship.buildFrom(code); // Populate modules from serialized 'code' URL param
|
ship.buildFrom(code); // Populate modules from serialized 'code' URL param
|
||||||
} else {
|
} else {
|
||||||
ship.buildWith(data.defaults); // Populate with default components
|
ship.buildWith(data.defaults); // Populate with default components
|
||||||
}
|
}
|
||||||
|
|
||||||
this._getTitle = getTitle.bind(this, data.properties.name);
|
this._getTitle = getTitle.bind(this, data.properties.name);
|
||||||
|
|
||||||
// Obtain ship control from code
|
// Obtain ship control from code
|
||||||
const {
|
const { sys, eng, wep, mcSys, mcEng, mcWep, boost, fuel, cargo, opponent, opponentBuild, opponentSys, opponentEng, opponentWep, engagementRange } = this._obtainControlFromCode(ship, code);
|
||||||
sys,
|
|
||||||
eng,
|
|
||||||
wep,
|
|
||||||
mcSys,
|
|
||||||
mcEng,
|
|
||||||
mcWep,
|
|
||||||
boost,
|
|
||||||
fuel,
|
|
||||||
cargo,
|
|
||||||
opponent,
|
|
||||||
opponentBuild,
|
|
||||||
opponentSys,
|
|
||||||
opponentEng,
|
|
||||||
opponentWep,
|
|
||||||
engagementRange
|
|
||||||
} = this._obtainControlFromCode(ship, code);
|
|
||||||
return {
|
return {
|
||||||
error: null,
|
error: null,
|
||||||
title: this._getTitle(buildName),
|
title: this._getTitle(buildName),
|
||||||
@@ -150,10 +139,7 @@ export default class OutfittingPage extends Page {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (Persist.hasBuild(this.state.shipId, stateChanges.newBuildName)) {
|
if (Persist.hasBuild(this.state.shipId, stateChanges.newBuildName)) {
|
||||||
stateChanges.savedCode = Persist.getBuild(
|
stateChanges.savedCode = Persist.getBuild(this.state.shipId, stateChanges.newBuildName);
|
||||||
this.state.shipId,
|
|
||||||
stateChanges.newBuildName
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
stateChanges.savedCode = null;
|
stateChanges.savedCode = null;
|
||||||
}
|
}
|
||||||
@@ -179,9 +165,7 @@ export default class OutfittingPage extends Page {
|
|||||||
* @returns {string} the code for this ship
|
* @returns {string} the code for this ship
|
||||||
*/
|
*/
|
||||||
_fullCode(ship, fuel, cargo) {
|
_fullCode(ship, fuel, cargo) {
|
||||||
return `${ship.toString()}.${LZString.compressToBase64(
|
return `${ship.toString()}.${LZString.compressToBase64(this._controlCode(fuel, cargo))}`;
|
||||||
this._controlCode(fuel, cargo)
|
|
||||||
)}`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -201,11 +185,7 @@ export default class OutfittingPage extends Page {
|
|||||||
let boost = false;
|
let boost = false;
|
||||||
let fuel = ship.fuelCapacity;
|
let fuel = ship.fuelCapacity;
|
||||||
let cargo = ship.cargoCapacity;
|
let cargo = ship.cargoCapacity;
|
||||||
let opponent = new Ship(
|
let opponent = new Ship('eagle', Ships['eagle'].properties, Ships['eagle'].slots).buildWith(Ships['eagle'].defaults);
|
||||||
'eagle',
|
|
||||||
Ships['eagle'].properties,
|
|
||||||
Ships['eagle'].slots
|
|
||||||
).buildWith(Ships['eagle'].defaults);
|
|
||||||
let opponentSys = 2;
|
let opponentSys = 2;
|
||||||
let opponentEng = 2;
|
let opponentEng = 2;
|
||||||
let opponentWep = 2;
|
let opponentWep = 2;
|
||||||
@@ -217,25 +197,16 @@ export default class OutfittingPage extends Page {
|
|||||||
const parts = code.split('.');
|
const parts = code.split('.');
|
||||||
if (parts.length >= 5) {
|
if (parts.length >= 5) {
|
||||||
// We have control information in the code
|
// We have control information in the code
|
||||||
const control = LZString.decompressFromBase64(
|
const control = LZString.decompressFromBase64(Utils.fromUrlSafe(parts[4])).split('/');
|
||||||
Utils.fromUrlSafe(parts[4])
|
sys = parseFloat(control[0]) || sys;
|
||||||
).split('/');
|
eng = parseFloat(control[1]) || eng;
|
||||||
sys = parseFloat(control[0]);
|
wep = parseFloat(control[2]) || wep;
|
||||||
eng = parseFloat(control[1]);
|
|
||||||
wep = parseFloat(control[2]);
|
|
||||||
if (sys + eng + wep > 6) {
|
|
||||||
sys = eng = wep = 2;
|
|
||||||
}
|
|
||||||
boost = control[3] == 1 ? true : false;
|
boost = control[3] == 1 ? true : false;
|
||||||
fuel = parseFloat(control[4]) || fuel;
|
fuel = parseFloat(control[4]) || fuel;
|
||||||
cargo = parseInt(control[5]) || cargo;
|
cargo = parseInt(control[5]) || cargo;
|
||||||
if (control[6]) {
|
if (control[6]) {
|
||||||
const shipId = control[6];
|
const shipId = control[6];
|
||||||
opponent = new Ship(
|
opponent = new Ship(shipId, Ships[shipId].properties, Ships[shipId].slots);
|
||||||
shipId,
|
|
||||||
Ships[shipId].properties,
|
|
||||||
Ships[shipId].slots
|
|
||||||
);
|
|
||||||
if (control[7] && Persist.getBuild(shipId, control[7])) {
|
if (control[7] && Persist.getBuild(shipId, control[7])) {
|
||||||
// Ship is a particular build
|
// Ship is a particular build
|
||||||
const opponentCode = Persist.getBuild(shipId, control[7]);
|
const opponentCode = Persist.getBuild(shipId, control[7]);
|
||||||
@@ -245,9 +216,7 @@ export default class OutfittingPage extends Page {
|
|||||||
// Obtain opponent's sys/eng/wep pips from their code
|
// Obtain opponent's sys/eng/wep pips from their code
|
||||||
const opponentParts = opponentCode.split('.');
|
const opponentParts = opponentCode.split('.');
|
||||||
if (opponentParts.length >= 5) {
|
if (opponentParts.length >= 5) {
|
||||||
const opponentControl = LZString.decompressFromBase64(
|
const opponentControl = LZString.decompressFromBase64(Utils.fromUrlSafe(opponentParts[4])).split('/');
|
||||||
Utils.fromUrlSafe(opponentParts[4])
|
|
||||||
).split('/');
|
|
||||||
opponentSys = parseFloat(opponentControl[0]) || opponentSys;
|
opponentSys = parseFloat(opponentControl[0]) || opponentSys;
|
||||||
opponentEng = parseFloat(opponentControl[1]) || opponentEng;
|
opponentEng = parseFloat(opponentControl[1]) || opponentEng;
|
||||||
opponentWep = parseFloat(opponentControl[2]) || opponentWep;
|
opponentWep = parseFloat(opponentControl[2]) || opponentWep;
|
||||||
@@ -268,23 +237,7 @@ export default class OutfittingPage extends Page {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return { sys, eng, wep, mcSys, mcEng, mcWep, boost, fuel, cargo, opponent, opponentBuild, opponentSys, opponentEng, opponentWep, engagementRange };
|
||||||
sys,
|
|
||||||
eng,
|
|
||||||
wep,
|
|
||||||
mcSys,
|
|
||||||
mcEng,
|
|
||||||
mcWep,
|
|
||||||
boost,
|
|
||||||
fuel,
|
|
||||||
cargo,
|
|
||||||
opponent,
|
|
||||||
opponentBuild,
|
|
||||||
opponentSys,
|
|
||||||
opponentEng,
|
|
||||||
opponentWep,
|
|
||||||
engagementRange
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -299,9 +252,7 @@ export default class OutfittingPage extends Page {
|
|||||||
* @param {number} mcWep WEP pips from multi-crew
|
* @param {number} mcWep WEP pips from multi-crew
|
||||||
*/
|
*/
|
||||||
_pipsUpdated(sys, eng, wep, mcSys, mcEng, mcWep) {
|
_pipsUpdated(sys, eng, wep, mcSys, mcEng, mcWep) {
|
||||||
this.setState({ sys, eng, wep, mcSys, mcEng, mcWep }, () =>
|
this.setState({ sys, eng, wep, mcSys, mcEng, mcWep }, () => this._updateRouteOnControlChange());
|
||||||
this._updateRouteOnControlChange()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -309,7 +260,7 @@ export default class OutfittingPage extends Page {
|
|||||||
* @param {boolean} boost true if boosting
|
* @param {boolean} boost true if boosting
|
||||||
*/
|
*/
|
||||||
_boostUpdated(boost) {
|
_boostUpdated(boost) {
|
||||||
this.setState({ boost }, () => this._updateRouteOnControlChange());
|
this.setState({ boost }, () => this._updateRouteOnControlChange());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -317,7 +268,7 @@ export default class OutfittingPage extends Page {
|
|||||||
* @param {number} fuel the amount of fuel, in T
|
* @param {number} fuel the amount of fuel, in T
|
||||||
*/
|
*/
|
||||||
_fuelUpdated(fuel) {
|
_fuelUpdated(fuel) {
|
||||||
this.setState({ fuel }, () => this._updateRouteOnControlChange());
|
this.setState({ fuel }, () => this._updateRouteOnControlChange());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -325,7 +276,7 @@ export default class OutfittingPage extends Page {
|
|||||||
* @param {number} cargo the amount of cargo, in T
|
* @param {number} cargo the amount of cargo, in T
|
||||||
*/
|
*/
|
||||||
_cargoUpdated(cargo) {
|
_cargoUpdated(cargo) {
|
||||||
this.setState({ cargo }, () => this._updateRouteOnControlChange());
|
this.setState({ cargo }, () => this._updateRouteOnControlChange());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -333,9 +284,7 @@ export default class OutfittingPage extends Page {
|
|||||||
* @param {number} engagementRange the engagement range, in m
|
* @param {number} engagementRange the engagement range, in m
|
||||||
*/
|
*/
|
||||||
_engagementRangeUpdated(engagementRange) {
|
_engagementRangeUpdated(engagementRange) {
|
||||||
this.setState({ engagementRange }, () =>
|
this.setState({ engagementRange }, () => this._updateRouteOnControlChange());
|
||||||
this._updateRouteOnControlChange()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -344,11 +293,7 @@ export default class OutfittingPage extends Page {
|
|||||||
* @param {string} opponentBuild the name of the opponent's build
|
* @param {string} opponentBuild the name of the opponent's build
|
||||||
*/
|
*/
|
||||||
_opponentUpdated(opponent, opponentBuild) {
|
_opponentUpdated(opponent, opponentBuild) {
|
||||||
const opponentShip = new Ship(
|
const opponentShip = new Ship(opponent, Ships[opponent].properties, Ships[opponent].slots);
|
||||||
opponent,
|
|
||||||
Ships[opponent].properties,
|
|
||||||
Ships[opponent].slots
|
|
||||||
);
|
|
||||||
let opponentSys = this.state.opponentSys;
|
let opponentSys = this.state.opponentSys;
|
||||||
let opponentEng = this.state.opponentEng;
|
let opponentEng = this.state.opponentEng;
|
||||||
let opponentWep = this.state.opponentWep;
|
let opponentWep = this.state.opponentWep;
|
||||||
@@ -356,13 +301,9 @@ export default class OutfittingPage extends Page {
|
|||||||
// Ship is a particular build
|
// Ship is a particular build
|
||||||
opponentShip.buildFrom(Persist.getBuild(opponent, opponentBuild));
|
opponentShip.buildFrom(Persist.getBuild(opponent, opponentBuild));
|
||||||
// Set pips for opponent
|
// Set pips for opponent
|
||||||
const opponentParts = Persist.getBuild(opponent, opponentBuild).split(
|
const opponentParts = Persist.getBuild(opponent, opponentBuild).split('.');
|
||||||
'.'
|
|
||||||
);
|
|
||||||
if (opponentParts.length >= 5) {
|
if (opponentParts.length >= 5) {
|
||||||
const opponentControl = LZString.decompressFromBase64(
|
const opponentControl = LZString.decompressFromBase64(Utils.fromUrlSafe(opponentParts[4])).split('/');
|
||||||
Utils.fromUrlSafe(opponentParts[4])
|
|
||||||
).split('/');
|
|
||||||
opponentSys = parseFloat(opponentControl[0]);
|
opponentSys = parseFloat(opponentControl[0]);
|
||||||
opponentEng = parseFloat(opponentControl[1]);
|
opponentEng = parseFloat(opponentControl[1]);
|
||||||
opponentWep = parseFloat(opponentControl[2]);
|
opponentWep = parseFloat(opponentControl[2]);
|
||||||
@@ -375,16 +316,7 @@ export default class OutfittingPage extends Page {
|
|||||||
opponentWep = 2;
|
opponentWep = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState(
|
this.setState({ opponent: opponentShip, opponentBuild, opponentSys, opponentEng, opponentWep }, () => this._updateRouteOnControlChange());
|
||||||
{
|
|
||||||
opponent: opponentShip,
|
|
||||||
opponentBuild,
|
|
||||||
opponentSys,
|
|
||||||
opponentEng,
|
|
||||||
opponentWep
|
|
||||||
},
|
|
||||||
() => this._updateRouteOnControlChange()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -394,22 +326,8 @@ export default class OutfittingPage extends Page {
|
|||||||
* @returns {string} The control code
|
* @returns {string} The control code
|
||||||
*/
|
*/
|
||||||
_controlCode(fuel, cargo) {
|
_controlCode(fuel, cargo) {
|
||||||
const {
|
const { sys, eng, wep, mcSys, mcEng, mcWep, boost, opponent, opponentBuild, engagementRange } = this.state;
|
||||||
sys,
|
const code = `${sys}/${eng}/${wep}/${boost ? 1 : 0}/${fuel || this.state.fuel}/${cargo || this.state.cargo}/${opponent.id}/${opponentBuild ? opponentBuild : ''}/${engagementRange}/${mcSys}/${mcEng}/${mcWep}`;
|
||||||
eng,
|
|
||||||
wep,
|
|
||||||
mcSys,
|
|
||||||
mcEng,
|
|
||||||
mcWep,
|
|
||||||
boost,
|
|
||||||
opponent,
|
|
||||||
opponentBuild,
|
|
||||||
engagementRange
|
|
||||||
} = this.state;
|
|
||||||
const code = `${sys}/${eng}/${wep}/${boost ? 1 : 0}/${fuel ||
|
|
||||||
this.state.fuel}/${cargo || this.state.cargo}/${opponent.id}/${
|
|
||||||
opponentBuild ? opponentBuild : ''
|
|
||||||
}/${engagementRange}/${mcSys}/${mcEng}/${mcWep}`;
|
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -420,44 +338,27 @@ export default class OutfittingPage extends Page {
|
|||||||
const { ship, buildName, newBuildName, shipId } = this.state;
|
const { ship, buildName, newBuildName, shipId } = this.state;
|
||||||
|
|
||||||
// If this is a stock ship the code won't be set, so ensure that we have it
|
// If this is a stock ship the code won't be set, so ensure that we have it
|
||||||
const code = this.state.code || ship.toString();
|
const code = this.state.code || ship.toString();
|
||||||
|
|
||||||
Persist.saveBuild(shipId, newBuildName, code);
|
Persist.saveBuild(shipId, newBuildName, code);
|
||||||
this._updateRoute(shipId, newBuildName, code);
|
this._updateRoute(shipId, newBuildName, code);
|
||||||
|
|
||||||
let opponent, opponentBuild, opponentSys, opponentEng, opponentWep;
|
let opponent, opponentBuild, opponentSys, opponentEng, opponentWep;
|
||||||
if (
|
if (shipId === this.state.opponent.id && buildName === this.state.opponentBuild) {
|
||||||
shipId === this.state.opponent.id &&
|
|
||||||
buildName === this.state.opponentBuild
|
|
||||||
) {
|
|
||||||
// This is a save of our current opponent build; update it
|
// This is a save of our current opponent build; update it
|
||||||
opponentBuild = newBuildName;
|
opponentBuild = newBuildName;
|
||||||
opponent = new Ship(
|
opponent = new Ship(shipId, Ships[shipId].properties, Ships[shipId].slots).buildFrom(code);
|
||||||
shipId,
|
|
||||||
Ships[shipId].properties,
|
|
||||||
Ships[shipId].slots
|
|
||||||
).buildFrom(code);
|
|
||||||
opponentSys = this.state.sys;
|
opponentSys = this.state.sys;
|
||||||
opponentEng = this.state.eng;
|
opponentEng = this.state.eng;
|
||||||
opponentWep = this.state.wep;
|
opponentWep = this.state.wep;
|
||||||
} else {
|
} else {
|
||||||
opponentBuild = this.state.opponentBuild;
|
opponentBuild = this.state.opponentBuild;
|
||||||
opponent = this.state.opponent;
|
opponent = this.state.opponent;
|
||||||
opponentSys = this.state.opponentSys;
|
opponentSys = this.state.opponentSys;
|
||||||
opponentEng = this.state.opponentEng;
|
opponentEng = this.state.opponentEng;
|
||||||
opponentWep = this.state.opponentWep;
|
opponentWep = this.state.opponentWep;
|
||||||
}
|
}
|
||||||
this.setState({
|
this.setState({ buildName: newBuildName, code, savedCode: code, opponent, opponentBuild, opponentSys, opponentEng, opponentWep, title: this._getTitle(newBuildName) });
|
||||||
buildName: newBuildName,
|
|
||||||
code,
|
|
||||||
savedCode: code,
|
|
||||||
opponent,
|
|
||||||
opponentBuild,
|
|
||||||
opponentSys,
|
|
||||||
opponentEng,
|
|
||||||
opponentWep,
|
|
||||||
title: this._getTitle(newBuildName)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -469,12 +370,7 @@ export default class OutfittingPage extends Page {
|
|||||||
Persist.deleteBuild(shipId, buildName);
|
Persist.deleteBuild(shipId, buildName);
|
||||||
Persist.saveBuild(shipId, newBuildName, code);
|
Persist.saveBuild(shipId, newBuildName, code);
|
||||||
this._updateRoute(shipId, newBuildName, code);
|
this._updateRoute(shipId, newBuildName, code);
|
||||||
this.setState({
|
this.setState({ buildName: newBuildName, code, savedCode: code, opponentBuild: newBuildName });
|
||||||
buildName: newBuildName,
|
|
||||||
code,
|
|
||||||
savedCode: code,
|
|
||||||
opponentBuild: newBuildName
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -494,7 +390,9 @@ export default class OutfittingPage extends Page {
|
|||||||
ship.buildWith(Ships[shipId].defaults);
|
ship.buildWith(Ships[shipId].defaults);
|
||||||
// Reset controls
|
// Reset controls
|
||||||
const code = ship.toString();
|
const code = ship.toString();
|
||||||
const {
|
const { sys, eng, wep, mcSys, mcEng, mcWep, boost, fuel, cargo, opponent, opponentBuild, engagementRange } = this._obtainControlFromCode(ship, code);
|
||||||
|
// Update state, and refresh the ship
|
||||||
|
this.setState({
|
||||||
sys,
|
sys,
|
||||||
eng,
|
eng,
|
||||||
wep,
|
wep,
|
||||||
@@ -507,25 +405,7 @@ export default class OutfittingPage extends Page {
|
|||||||
opponent,
|
opponent,
|
||||||
opponentBuild,
|
opponentBuild,
|
||||||
engagementRange
|
engagementRange
|
||||||
} = this._obtainControlFromCode(ship, code);
|
}, () => this._updateRoute(shipId, buildName, code));
|
||||||
// Update state, and refresh the ship
|
|
||||||
this.setState(
|
|
||||||
{
|
|
||||||
sys,
|
|
||||||
eng,
|
|
||||||
wep,
|
|
||||||
mcSys,
|
|
||||||
mcEng,
|
|
||||||
mcWep,
|
|
||||||
boost,
|
|
||||||
fuel,
|
|
||||||
cargo,
|
|
||||||
opponent,
|
|
||||||
opponentBuild,
|
|
||||||
engagementRange
|
|
||||||
},
|
|
||||||
() => this._updateRoute(shipId, buildName, code)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -536,10 +416,7 @@ export default class OutfittingPage extends Page {
|
|||||||
Persist.deleteBuild(shipId, buildName);
|
Persist.deleteBuild(shipId, buildName);
|
||||||
|
|
||||||
let opponentBuild;
|
let opponentBuild;
|
||||||
if (
|
if (shipId === this.state.opponent.id && buildName === this.state.opponentBuild) {
|
||||||
shipId === this.state.opponent.id &&
|
|
||||||
buildName === this.state.opponentBuild
|
|
||||||
) {
|
|
||||||
// Our current opponent has been deleted; revert to stock
|
// Our current opponent has been deleted; revert to stock
|
||||||
opponentBuild = null;
|
opponentBuild = null;
|
||||||
} else {
|
} else {
|
||||||
@@ -556,13 +433,11 @@ export default class OutfittingPage extends Page {
|
|||||||
_exportBuild() {
|
_exportBuild() {
|
||||||
let translate = this.context.language.translate;
|
let translate = this.context.language.translate;
|
||||||
let { buildName, ship } = this.state;
|
let { buildName, ship } = this.state;
|
||||||
this.context.showModal(
|
this.context.showModal(<ModalExport
|
||||||
<ModalExport
|
title={(buildName || ship.name) + ' ' + translate('export')}
|
||||||
title={(buildName || ship.name) + ' ' + translate('export')}
|
description={translate('PHRASE_EXPORT_DESC')}
|
||||||
description={translate('PHRASE_EXPORT_DESC')}
|
data={toDetailedBuild(buildName, ship, ship.toString())}
|
||||||
data={toDetailedBuild(buildName, ship, ship.toString())}
|
/>);
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -575,7 +450,9 @@ export default class OutfittingPage extends Page {
|
|||||||
this.state.ship.buildFrom(code);
|
this.state.ship.buildFrom(code);
|
||||||
|
|
||||||
// Obtain controls from the code
|
// Obtain controls from the code
|
||||||
const {
|
const { sys, eng, wep, mcSys, mcEng, mcWep, boost, fuel, cargo, opponent, opponentBuild, engagementRange } = this._obtainControlFromCode(ship, code);
|
||||||
|
// Update state, and refresh the route when complete
|
||||||
|
this.setState({
|
||||||
sys,
|
sys,
|
||||||
eng,
|
eng,
|
||||||
wep,
|
wep,
|
||||||
@@ -588,25 +465,7 @@ export default class OutfittingPage extends Page {
|
|||||||
opponent,
|
opponent,
|
||||||
opponentBuild,
|
opponentBuild,
|
||||||
engagementRange
|
engagementRange
|
||||||
} = this._obtainControlFromCode(ship, code);
|
}, () => this._updateRoute(shipId, buildName, code));
|
||||||
// Update state, and refresh the route when complete
|
|
||||||
this.setState(
|
|
||||||
{
|
|
||||||
sys,
|
|
||||||
eng,
|
|
||||||
wep,
|
|
||||||
mcSys,
|
|
||||||
mcEng,
|
|
||||||
mcWep,
|
|
||||||
boost,
|
|
||||||
fuel,
|
|
||||||
cargo,
|
|
||||||
opponent,
|
|
||||||
opponentBuild,
|
|
||||||
engagementRange
|
|
||||||
},
|
|
||||||
() => this._updateRoute(shipId, buildName, code)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -622,14 +481,8 @@ export default class OutfittingPage extends Page {
|
|||||||
}
|
}
|
||||||
const code = this._fullCode(ship, fuel, cargo);
|
const code = this._fullCode(ship, fuel, cargo);
|
||||||
// Only update the state if this really has been updated
|
// Only update the state if this really has been updated
|
||||||
if (
|
if (this.state.code != code || this.state.cargo != cargo || this.state.fuel != fuel) {
|
||||||
this.state.code != code ||
|
this.setState({ code, cargo, fuel }, () => this._updateRoute(shipId, buildName, code));
|
||||||
this.state.cargo != cargo ||
|
|
||||||
this.state.fuel != fuel
|
|
||||||
) {
|
|
||||||
this.setState({ code, cargo, fuel }, () =>
|
|
||||||
this._updateRoute(shipId, buildName, code)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -649,8 +502,7 @@ export default class OutfittingPage extends Page {
|
|||||||
* @param {Object} nextContext Incoming/Next conext
|
* @param {Object} nextContext Incoming/Next conext
|
||||||
*/
|
*/
|
||||||
componentWillReceiveProps(nextProps, nextContext) {
|
componentWillReceiveProps(nextProps, nextContext) {
|
||||||
if (this.context.route !== nextContext.route) {
|
if (this.context.route !== nextContext.route) { // Only reinit state if the route has changed
|
||||||
// Only reinit state if the route has changed
|
|
||||||
this.setState(this._initState(nextProps, nextContext));
|
this.setState(this._initState(nextProps, nextContext));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -673,34 +525,45 @@ export default class OutfittingPage extends Page {
|
|||||||
* Generates the short URL
|
* Generates the short URL
|
||||||
*/
|
*/
|
||||||
_genShortlink() {
|
_genShortlink() {
|
||||||
this.context.showModal(<ModalPermalink url={window.location.href} />);
|
this.context.showModal(<ModalPermalink url={window.location.href}/>);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open up a window for inara with a shopping list of our components
|
* Generate Orbis link
|
||||||
*/
|
*/
|
||||||
_inaraShoppingList() {
|
_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
|
||||||
|
*/
|
||||||
|
_eddbShoppingList() {
|
||||||
const ship = this.state.ship;
|
const ship = this.state.ship;
|
||||||
|
|
||||||
const shipId = Ships[ship.id].eddbID;
|
const shipId = Ships[ship.id].eddbID;
|
||||||
// Provide unique list of non-PP module EDDB IDs
|
// Provide unique list of non-PP module EDDB IDs
|
||||||
const modIds = ship.internal
|
const modIds = ship.internal.concat(ship.bulkheads, ship.standard, ship.hardpoints).filter(slot => slot !== null && slot.m !== null && !slot.m.pp).map(slot => slot.m.eddbID).filter((v, i, a) => a.indexOf(v) === i);
|
||||||
.concat(ship.bulkheads, ship.standard, ship.hardpoints)
|
|
||||||
.filter(slot => slot !== null && slot.m !== null && !slot.m.pp)
|
|
||||||
.map(slot => slot.m.eddbID)
|
|
||||||
.filter((v, i, a) => a.indexOf(v) === i);
|
|
||||||
|
|
||||||
// Open up the relevant URL
|
// Open up the relevant URL
|
||||||
window.open(
|
window.open('https://eddb.io/station?s=' + shipId + '&m=' + modIds.join(','));
|
||||||
'https://inara.cz/inapi/corisearch.php?s=' + shipId + '&m=' + modIds.join(',')
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates the shopping list
|
* Generates the shopping list
|
||||||
*/
|
*/
|
||||||
_genShoppingList() {
|
_genShoppingList() {
|
||||||
this.context.showModal(<ModalShoppingList ship={this.state.ship} />);
|
this.context.showModal(<ModalShoppingList ship={this.state.ship}/>);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -710,9 +573,8 @@ export default class OutfittingPage extends Page {
|
|||||||
_keyDown(e) {
|
_keyDown(e) {
|
||||||
// .keyCode will eventually be replaced with .key
|
// .keyCode will eventually be replaced with .key
|
||||||
switch (e.keyCode) {
|
switch (e.keyCode) {
|
||||||
case 69: // 'e'
|
case 69: // 'e'
|
||||||
if (e.ctrlKey || e.metaKey) {
|
if (e.ctrlKey || e.metaKey) { // CTRL/CMD + e
|
||||||
// CTRL/CMD + e
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this._exportBuild();
|
this._exportBuild();
|
||||||
}
|
}
|
||||||
@@ -728,28 +590,7 @@ export default class OutfittingPage extends Page {
|
|||||||
let state = this.state,
|
let state = this.state,
|
||||||
{ language, termtip, tooltip, sizeRatio, onWindowResize } = this.context,
|
{ language, termtip, tooltip, sizeRatio, onWindowResize } = this.context,
|
||||||
{ translate, units, formats } = language,
|
{ translate, units, formats } = language,
|
||||||
{
|
{ ship, code, savedCode, buildName, newBuildName, sys, eng, wep, mcSys, mcEng, mcWep, boost, fuel, cargo, opponent, opponentBuild, opponentSys, opponentEng, opponentWep, engagementRange } = state,
|
||||||
ship,
|
|
||||||
code,
|
|
||||||
savedCode,
|
|
||||||
buildName,
|
|
||||||
newBuildName,
|
|
||||||
sys,
|
|
||||||
eng,
|
|
||||||
wep,
|
|
||||||
mcSys,
|
|
||||||
mcEng,
|
|
||||||
mcWep,
|
|
||||||
boost,
|
|
||||||
fuel,
|
|
||||||
cargo,
|
|
||||||
opponent,
|
|
||||||
opponentBuild,
|
|
||||||
opponentSys,
|
|
||||||
opponentEng,
|
|
||||||
opponentWep,
|
|
||||||
engagementRange
|
|
||||||
} = state,
|
|
||||||
hide = tooltip.bind(null, null),
|
hide = tooltip.bind(null, null),
|
||||||
menu = this.props.currentMenu,
|
menu = this.props.currentMenu,
|
||||||
shipUpdated = this._shipUpdated,
|
shipUpdated = this._shipUpdated,
|
||||||
@@ -767,15 +608,11 @@ export default class OutfittingPage extends Page {
|
|||||||
const _pStr = `${ship.getPowerEnabledString()}${ship.getPowerPrioritiesString()}`;
|
const _pStr = `${ship.getPowerEnabledString()}${ship.getPowerPrioritiesString()}`;
|
||||||
const _mStr = ship.getModificationsString();
|
const _mStr = ship.getModificationsString();
|
||||||
|
|
||||||
const standardSlotMarker = `${ship.name}${_sStr}${_pStr}${_mStr}${
|
const standardSlotMarker = `${ship.name}${_sStr}${_pStr}${_mStr}${ship.ladenMass}${cargo}${fuel}`;
|
||||||
ship.ladenMass
|
|
||||||
}${cargo}${fuel}`;
|
|
||||||
const internalSlotMarker = `${ship.name}${_iStr}${_pStr}${_mStr}`;
|
const internalSlotMarker = `${ship.name}${_iStr}${_pStr}${_mStr}`;
|
||||||
const hardpointsSlotMarker = `${ship.name}${_hStr}${_pStr}${_mStr}`;
|
const hardpointsSlotMarker = `${ship.name}${_hStr}${_pStr}${_mStr}`;
|
||||||
const boostMarker = `${ship.canBoost(cargo, fuel)}`;
|
const boostMarker = `${ship.canBoost(cargo, fuel)}`;
|
||||||
const shipSummaryMarker = `${
|
const shipSummaryMarker = `${ship.name}${_sStr}${_iStr}${_hStr}${_pStr}${_mStr}${ship.ladenMass}${cargo}${fuel}`;
|
||||||
ship.name
|
|
||||||
}${_sStr}${_iStr}${_hStr}${_pStr}${_mStr}${ship.ladenMass}${cargo}${fuel}`;
|
|
||||||
|
|
||||||
const requirements = Ships[ship.id].requirements;
|
const requirements = Ships[ship.id].requirements;
|
||||||
let requirementElements = [];
|
let requirementElements = [];
|
||||||
@@ -787,268 +624,94 @@ export default class OutfittingPage extends Page {
|
|||||||
*/
|
*/
|
||||||
function renderRequirement(className, textKey, tooltipTextKey) {
|
function renderRequirement(className, textKey, tooltipTextKey) {
|
||||||
if (textKey.startsWith('empire') || textKey.startsWith('federation')) {
|
if (textKey.startsWith('empire') || textKey.startsWith('federation')) {
|
||||||
requirementElements.push(
|
requirementElements.push(<div key={textKey} className={className} onMouseEnter={termtip.bind(null, tooltipTextKey)} onMouseLeave={hide}><a href={textKey.startsWith('empire') ? 'http://elite-dangerous.wikia.com/wiki/Empire/Ranks' : 'http://elite-dangerous.wikia.com/wiki/Federation/Ranks'} target="_blank" rel="noopener">{translate(textKey)}</a></div>);
|
||||||
<div
|
|
||||||
key={textKey}
|
|
||||||
className={className}
|
|
||||||
onMouseEnter={termtip.bind(null, tooltipTextKey)}
|
|
||||||
onMouseLeave={hide}
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
href={
|
|
||||||
textKey.startsWith('empire') ?
|
|
||||||
'http://elite-dangerous.wikia.com/wiki/Empire/Ranks' :
|
|
||||||
'http://elite-dangerous.wikia.com/wiki/Federation/Ranks'
|
|
||||||
}
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener"
|
|
||||||
>
|
|
||||||
{translate(textKey)}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
requirementElements.push(
|
requirementElements.push(<div key={textKey} className={className} onMouseEnter={termtip.bind(null, tooltipTextKey)} onMouseLeave={hide}>{translate(textKey)}</div>);
|
||||||
<div
|
|
||||||
key={textKey}
|
|
||||||
className={className}
|
|
||||||
onMouseEnter={termtip.bind(null, tooltipTextKey)}
|
|
||||||
onMouseLeave={hide}
|
|
||||||
>
|
|
||||||
{translate(textKey)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (requirements) {
|
if (requirements) {
|
||||||
requirements.federationRank &&
|
requirements.federationRank && renderRequirement('federation', 'federation rank ' + requirements.federationRank, 'federation rank required');
|
||||||
renderRequirement(
|
requirements.empireRank && renderRequirement('empire', 'empire rank ' + requirements.empireRank, 'empire rank required');
|
||||||
'federation',
|
requirements.horizons && renderRequirement('horizons', 'horizons', 'horizons required');
|
||||||
'federation rank ' + requirements.federationRank,
|
requirements.horizonsEarlyAdoption && renderRequirement('horizons', 'horizons early adoption', 'horizons early adoption required');
|
||||||
'federation rank required'
|
|
||||||
);
|
|
||||||
requirements.empireRank &&
|
|
||||||
renderRequirement(
|
|
||||||
'empire',
|
|
||||||
'empire rank ' + requirements.empireRank,
|
|
||||||
'empire rank required'
|
|
||||||
);
|
|
||||||
requirements.horizons &&
|
|
||||||
renderRequirement('horizons', 'horizons', 'horizons required');
|
|
||||||
requirements.horizonsEarlyAdoption &&
|
|
||||||
renderRequirement(
|
|
||||||
'horizons',
|
|
||||||
'horizons early adoption',
|
|
||||||
'horizons early adoption required'
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div id='outfit' className={'page'} style={{ fontSize: (sizeRatio * 0.9) + 'em' }}>
|
||||||
id="outfit"
|
<div id='overview'>
|
||||||
className={'page'}
|
|
||||||
style={{ fontSize: sizeRatio * 0.9 + 'em' }}
|
|
||||||
>
|
|
||||||
<div id="overview">
|
|
||||||
<h1>{ship.name}</h1>
|
<h1>{ship.name}</h1>
|
||||||
<div id="requirements">{requirementElements}</div>
|
<div id='requirements'>{requirementElements}</div>
|
||||||
<div id="build">
|
<div id='build'>
|
||||||
<input
|
<input value={newBuildName || ''} onChange={this._buildNameChange} placeholder={translate('Enter Name')} maxLength={50} />
|
||||||
value={newBuildName || ''}
|
<button onClick={canSave && this._saveBuild} disabled={!canSave} onMouseOver={termtip.bind(null, 'save')} onMouseOut={hide}>
|
||||||
onChange={this._buildNameChange}
|
<FloppyDisk className='lg' />
|
||||||
placeholder={translate('Enter Name')}
|
|
||||||
maxLength={50}
|
|
||||||
/>
|
|
||||||
<button
|
|
||||||
onClick={canSave && this._saveBuild}
|
|
||||||
disabled={!canSave}
|
|
||||||
onMouseOver={termtip.bind(null, 'save')}
|
|
||||||
onMouseOut={hide}
|
|
||||||
>
|
|
||||||
<FloppyDisk className="lg" />
|
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button onClick={canRename && this._renameBuild} disabled={!canRename} onMouseOver={termtip.bind(null, 'rename')} onMouseOut={hide}>
|
||||||
onClick={canRename && this._renameBuild}
|
<span style={{ textTransform: 'none', fontSize: '1.8em' }}>a|</span>
|
||||||
disabled={!canRename}
|
|
||||||
onMouseOver={termtip.bind(null, 'rename')}
|
|
||||||
onMouseOut={hide}
|
|
||||||
>
|
|
||||||
<span style={{ textTransform: 'none', fontSize: '1.8em' }}>
|
|
||||||
a|
|
|
||||||
</span>
|
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button onClick={canReload && this._reloadBuild} disabled={!canReload} onMouseOver={termtip.bind(null, 'reload')} onMouseOut={hide}>
|
||||||
onClick={canReload && this._reloadBuild}
|
<Reload className='lg'/>
|
||||||
disabled={!canReload}
|
|
||||||
onMouseOver={termtip.bind(null, 'reload')}
|
|
||||||
onMouseOut={hide}
|
|
||||||
>
|
|
||||||
<Reload className="lg" />
|
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button className={'danger'} onClick={savedCode && this._deleteBuild} disabled={!savedCode} onMouseOver={termtip.bind(null, 'delete')} onMouseOut={hide}>
|
||||||
className={'danger'}
|
<Bin className='lg'/>
|
||||||
onClick={savedCode && this._deleteBuild}
|
|
||||||
disabled={!savedCode}
|
|
||||||
onMouseOver={termtip.bind(null, 'delete')}
|
|
||||||
onMouseOut={hide}
|
|
||||||
>
|
|
||||||
<Bin className="lg" />
|
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button onClick={code && this._resetBuild} disabled={!code} onMouseOver={termtip.bind(null, 'reset')} onMouseOut={hide}>
|
||||||
onClick={code && this._resetBuild}
|
<Switch className='lg'/>
|
||||||
disabled={!code}
|
|
||||||
onMouseOver={termtip.bind(null, 'reset')}
|
|
||||||
onMouseOut={hide}
|
|
||||||
>
|
|
||||||
<Switch className="lg" />
|
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button onClick={buildName && this._exportBuild} disabled={!buildName} onMouseOver={termtip.bind(null, 'export')} onMouseOut={hide}>
|
||||||
onClick={buildName && this._exportBuild}
|
<Download className='lg'/>
|
||||||
disabled={!buildName}
|
|
||||||
onMouseOver={termtip.bind(null, 'export')}
|
|
||||||
onMouseOut={hide}
|
|
||||||
>
|
|
||||||
<Download className="lg" />
|
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button onClick={this._eddbShoppingList} onMouseOver={termtip.bind(null, 'PHRASE_SHOPPING_LIST')} onMouseOut={hide}>
|
||||||
onClick={this._inaraShoppingList}
|
<ShoppingIcon className='lg' />
|
||||||
onMouseOver={termtip.bind(null, 'PHRASE_SHOPPING_LIST')}
|
|
||||||
onMouseOut={hide}
|
|
||||||
>
|
|
||||||
<ShoppingIcon className="lg" />
|
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button onClick={this._genShortlink} onMouseOver={termtip.bind(null, 'shortlink')} onMouseOut={hide}>
|
||||||
onClick={this._genShortlink}
|
<LinkIcon className='lg' />
|
||||||
onMouseOver={termtip.bind(null, 'shortlink')}
|
|
||||||
onMouseOut={hide}
|
|
||||||
>
|
|
||||||
<LinkIcon className="lg" />
|
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button onClick={this._genOrbis} onMouseOver={termtip.bind(null, 'PHASE_UPLOAD_ORBIS')} onMouseOut={hide}>
|
||||||
onClick={this._genShoppingList}
|
<OrbisIcon className='lg' />
|
||||||
onMouseOver={termtip.bind(null, 'PHRASE_SHOPPING_MATS')}
|
</button>
|
||||||
onMouseOut={hide}
|
<button onClick={this._genShoppingList} onMouseOver={termtip.bind(null, 'PHRASE_SHOPPING_MATS')} onMouseOut={hide}>
|
||||||
>
|
<MatIcon className='lg' />
|
||||||
<MatIcon className="lg" />
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Main tables */}
|
{/* Main tables */}
|
||||||
<ShipSummaryTable
|
<ShipSummaryTable ship={ship} fuel={fuel} cargo={cargo} marker={shipSummaryMarker} pips={{ sys: this.state.sys, wep: this.state.wep, eng: this.state.eng }} />
|
||||||
ship={ship}
|
<StandardSlotSection ship={ship} fuel={fuel} cargo={cargo} code={standardSlotMarker} onChange={shipUpdated} onCargoChange={this._cargoUpdated} onFuelChange={this._fuelUpdated} currentMenu={menu} sectionMenuRefs={this._sectionMenuRefs}/>
|
||||||
fuel={fuel}
|
<InternalSlotSection ship={ship} code={internalSlotMarker} onChange={shipUpdated} onCargoChange={this._cargoUpdated} onFuelChange={this._fuelUpdated} currentMenu={menu} sectionMenuRefs={this._sectionMenuRefs}/>
|
||||||
cargo={cargo}
|
<HardpointSlotSection ship={ship} code={hardpointsSlotMarker} onChange={shipUpdated} onCargoChange={this._cargoUpdated} onFuelChange={this._fuelUpdated} currentMenu={menu} sectionMenuRefs={this._sectionMenuRefs}/>
|
||||||
marker={shipSummaryMarker}
|
<UtilitySlotSection ship={ship} code={hardpointsSlotMarker} onChange={shipUpdated} onCargoChange={this._cargoUpdated} onFuelChange={this._fuelUpdated} currentMenu={menu} sectionMenuRefs={this._sectionMenuRefs}/>
|
||||||
pips={{
|
|
||||||
sys: this.state.sys,
|
|
||||||
wep: this.state.wep,
|
|
||||||
eng: this.state.eng
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<StandardSlotSection
|
|
||||||
ship={ship}
|
|
||||||
fuel={fuel}
|
|
||||||
cargo={cargo}
|
|
||||||
code={standardSlotMarker}
|
|
||||||
onChange={shipUpdated}
|
|
||||||
onCargoChange={this._cargoUpdated}
|
|
||||||
onFuelChange={this._fuelUpdated}
|
|
||||||
currentMenu={menu}
|
|
||||||
sectionMenuRefs={this._sectionMenuRefs}
|
|
||||||
/>
|
|
||||||
<InternalSlotSection
|
|
||||||
ship={ship}
|
|
||||||
code={internalSlotMarker}
|
|
||||||
onChange={shipUpdated}
|
|
||||||
onCargoChange={this._cargoUpdated}
|
|
||||||
onFuelChange={this._fuelUpdated}
|
|
||||||
currentMenu={menu}
|
|
||||||
sectionMenuRefs={this._sectionMenuRefs}
|
|
||||||
/>
|
|
||||||
<HardpointSlotSection
|
|
||||||
ship={ship}
|
|
||||||
code={hardpointsSlotMarker}
|
|
||||||
onChange={shipUpdated}
|
|
||||||
onCargoChange={this._cargoUpdated}
|
|
||||||
onFuelChange={this._fuelUpdated}
|
|
||||||
currentMenu={menu}
|
|
||||||
sectionMenuRefs={this._sectionMenuRefs}
|
|
||||||
/>
|
|
||||||
<UtilitySlotSection
|
|
||||||
ship={ship}
|
|
||||||
code={hardpointsSlotMarker}
|
|
||||||
onChange={shipUpdated}
|
|
||||||
onCargoChange={this._cargoUpdated}
|
|
||||||
onFuelChange={this._fuelUpdated}
|
|
||||||
currentMenu={menu}
|
|
||||||
sectionMenuRefs={this._sectionMenuRefs}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* Control of ship and opponent */}
|
{/* Control of ship and opponent */}
|
||||||
<div className="group quarter">
|
<div className='group quarter'>
|
||||||
<div className="group half">
|
<div className='group half'>
|
||||||
<h2 style={{ verticalAlign: 'middle', textAlign: 'left' }}>
|
<h2 style={{ verticalAlign: 'middle', textAlign: 'left' }}>{translate('ship control')}</h2>
|
||||||
{translate('ship control')}
|
|
||||||
</h2>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="group half">
|
<div className='group half'>
|
||||||
<Boost
|
<Boost marker={boostMarker} ship={ship} boost={boost} onChange={this._boostUpdated} />
|
||||||
marker={boostMarker}
|
|
||||||
ship={ship}
|
|
||||||
boost={boost}
|
|
||||||
onChange={this._boostUpdated}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="group quarter">
|
<div className='group quarter'>
|
||||||
<Pips
|
<Pips sys={sys} eng={eng} wep={wep} mcSys={mcSys} mcEng={mcEng} mcWep={mcWep} onChange={this._pipsUpdated} />
|
||||||
sys={sys}
|
|
||||||
eng={eng}
|
|
||||||
wep={wep}
|
|
||||||
mcSys={mcSys}
|
|
||||||
mcEng={mcEng}
|
|
||||||
mcWep={mcWep}
|
|
||||||
onChange={this._pipsUpdated}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="group quarter">
|
<div className='group quarter'>
|
||||||
<Fuel
|
<Fuel fuelCapacity={ship.fuelCapacity} fuel={fuel} onChange={this._fuelUpdated}/>
|
||||||
fuelCapacity={ship.fuelCapacity}
|
|
||||||
fuel={fuel}
|
|
||||||
onChange={this._fuelUpdated}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="group quarter">
|
<div className='group quarter'>
|
||||||
{ship.cargoCapacity > 0 ? (
|
{ ship.cargoCapacity > 0 ? <Cargo cargoCapacity={ship.cargoCapacity} cargo={cargo} onChange={this._cargoUpdated}/> : null }
|
||||||
<Cargo
|
|
||||||
cargoCapacity={ship.cargoCapacity}
|
|
||||||
cargo={cargo}
|
|
||||||
onChange={this._cargoUpdated}
|
|
||||||
/>
|
|
||||||
) : null}
|
|
||||||
</div>
|
</div>
|
||||||
<div className="group half">
|
<div className='group half'>
|
||||||
<div className="group quarter">
|
<div className='group quarter'>
|
||||||
<h2 style={{ verticalAlign: 'middle', textAlign: 'left' }}>
|
<h2 style={{ verticalAlign: 'middle', textAlign: 'left' }}>{translate('opponent')}</h2>
|
||||||
{translate('opponent')}
|
|
||||||
</h2>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="group threequarters">
|
<div className='group threequarters'>
|
||||||
<ShipPicker
|
<ShipPicker ship={opponent.id} build={opponentBuild} onChange={this._opponentUpdated}/>
|
||||||
ship={opponent.id}
|
|
||||||
build={opponentBuild}
|
|
||||||
onChange={this._opponentUpdated}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="group half">
|
<div className='group half'>
|
||||||
<EngagementRange
|
<EngagementRange ship={ship} engagementRange={engagementRange} onChange={this._engagementRangeUpdated}/>
|
||||||
ship={ship}
|
|
||||||
engagementRange={engagementRange}
|
|
||||||
onChange={this._engagementRangeUpdated}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Tabbed subpages */}
|
{/* Tabbed subpages */}
|
||||||
|
|||||||
@@ -51,25 +51,23 @@ export default class Page extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the window title upon mount
|
* 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
|
||||||
*/
|
*/
|
||||||
componentWillMount() {
|
shouldComponentUpdate(np, ns, nc) {
|
||||||
document.title = this.state.title || 'Coriolis';
|
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
|
||||||
*/
|
*/
|
||||||
componentDidMount() {
|
componentWillMount() {
|
||||||
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) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -22,11 +22,9 @@ function countHp(slot) {
|
|||||||
*/
|
*/
|
||||||
function countInt(slot) {
|
function countInt(slot) {
|
||||||
let crEligible = !slot.eligible || slot.eligible.cr;
|
let crEligible = !slot.eligible || slot.eligible.cr;
|
||||||
this.int[slot.maxClass - 1]++; // Subtract 1 since there is no Class 0 Internal compartment
|
this.int[slot.maxClass - 1]++; // Subtract 1 since there is no Class 0 Internal compartment
|
||||||
this.intCount++;
|
this.intCount++;
|
||||||
this.maxCargo += crEligible ?
|
this.maxCargo += crEligible ? ModuleUtils.findInternal('cr', slot.maxClass, 'E').cargo : 0;
|
||||||
ModuleUtils.findInternal('cr', slot.maxClass, 'E').cargo :
|
|
||||||
0;
|
|
||||||
|
|
||||||
// if no eligiblity, then assume pce
|
// if no eligiblity, then assume pce
|
||||||
let passSlotType = null;
|
let passSlotType = null;
|
||||||
@@ -44,9 +42,7 @@ function countInt(slot) {
|
|||||||
passSlotType = 'pcq';
|
passSlotType = 'pcq';
|
||||||
passSlotRating = 'B';
|
passSlotRating = 'B';
|
||||||
}
|
}
|
||||||
let passengerBay = passSlotType ?
|
let passengerBay = passSlotType ? ModuleUtils.findMaxInternal(passSlotType, slot.maxClass, passSlotRating) : null;
|
||||||
ModuleUtils.findMaxInternal(passSlotType, slot.maxClass, passSlotRating) :
|
|
||||||
null;
|
|
||||||
this.maxPassengers += passengerBay ? passengerBay.passengers : 0;
|
this.maxPassengers += passengerBay ? passengerBay.passengers : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,27 +57,23 @@ function shipSummary(shipId, shipData) {
|
|||||||
id: shipId,
|
id: shipId,
|
||||||
hpCount: 0,
|
hpCount: 0,
|
||||||
intCount: 0,
|
intCount: 0,
|
||||||
beta: shipData.beta,
|
|
||||||
maxCargo: 0,
|
maxCargo: 0,
|
||||||
maxPassengers: 0,
|
maxPassengers: 0,
|
||||||
hp: [0, 0, 0, 0, 0], // Utility, Small, Medium, Large, Huge
|
hp: [0, 0, 0, 0, 0], // Utility, Small, Medium, Large, Huge
|
||||||
int: [0, 0, 0, 0, 0, 0, 0, 0], // Sizes 1 - 8
|
int: [0, 0, 0, 0, 0, 0, 0, 0], // Sizes 1 - 8
|
||||||
standard: shipData.slots.standard,
|
standard: shipData.slots.standard,
|
||||||
agility:
|
agility: shipData.properties.pitch + shipData.properties.yaw + shipData.properties.roll
|
||||||
shipData.properties.pitch +
|
|
||||||
shipData.properties.yaw +
|
|
||||||
shipData.properties.roll
|
|
||||||
};
|
};
|
||||||
Object.assign(summary, shipData.properties);
|
Object.assign(summary, shipData.properties);
|
||||||
let ship = new Ship(shipId, shipData.properties, shipData.slots);
|
let ship = new Ship(shipId, shipData.properties, shipData.slots);
|
||||||
|
|
||||||
// Build Ship
|
// Build Ship
|
||||||
ship.buildWith(shipData.defaults); // Populate with stock/default components
|
ship.buildWith(shipData.defaults); // Populate with stock/default components
|
||||||
ship.hardpoints.forEach(countHp.bind(summary)); // Count Hardpoints by class
|
ship.hardpoints.forEach(countHp.bind(summary)); // Count Hardpoints by class
|
||||||
ship.internal.forEach(countInt.bind(summary)); // Count Internal Compartments by class
|
ship.internal.forEach(countInt.bind(summary)); // Count Internal Compartments by class
|
||||||
summary.retailCost = ship.totalCost; // Record Stock/Default/retail cost
|
summary.retailCost = ship.totalCost; // Record Stock/Default/retail cost
|
||||||
ship.optimizeMass({ pd: '1D' }); // Optimize Mass with 1D PD for maximum possible jump range
|
ship.optimizeMass({ pd: '1D' }); // Optimize Mass with 1D PD for maximum possible jump range
|
||||||
summary.maxJumpRange = ship.unladenRange; // Record Jump Range
|
summary.maxJumpRange = ship.unladenRange; // Record Jump Range
|
||||||
|
|
||||||
// Best thrusters
|
// Best thrusters
|
||||||
let th;
|
let th;
|
||||||
@@ -105,6 +97,7 @@ function shipSummary(shipId, shipData) {
|
|||||||
* The Shipyard summary page
|
* The Shipyard summary page
|
||||||
*/
|
*/
|
||||||
export default class ShipyardPage extends Page {
|
export default class ShipyardPage extends Page {
|
||||||
|
|
||||||
static cachedShipSummaries = null;
|
static cachedShipSummaries = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -126,14 +119,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 +133,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
|
||||||
@@ -172,15 +145,12 @@ export default class ShipyardPage extends Page {
|
|||||||
shipPredicateIndex = undefined;
|
shipPredicateIndex = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (this.state.shipPredicate == shipPredicate && this.state.shipPredicateIndex == shipPredicateIndex) {
|
||||||
this.state.shipPredicate == shipPredicate &&
|
|
||||||
this.state.shipPredicateIndex == shipPredicateIndex
|
|
||||||
) {
|
|
||||||
shipDesc = !shipDesc;
|
shipDesc = !shipDesc;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({ shipPredicate, shipDesc, shipPredicateIndex });
|
this.setState({ shipPredicate, shipDesc, shipPredicateIndex });
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate the table row summary for the ship
|
* Generate the table row summary for the ship
|
||||||
@@ -189,60 +159,56 @@ export default class ShipyardPage extends Page {
|
|||||||
* @param {Object} u Localized unit map
|
* @param {Object} u Localized unit map
|
||||||
* @param {Function} fInt Localized integer formatter
|
* @param {Function} fInt Localized integer formatter
|
||||||
* @param {Function} fRound Localized round formatter
|
* @param {Function} fRound Localized round formatter
|
||||||
|
* @param {Boolean} highlight Should this row be highlighted
|
||||||
* @return {React.Component} Table Row
|
* @return {React.Component} Table Row
|
||||||
*/
|
*/
|
||||||
_shipRowElement(s, translate, u, fInt, fRound) {
|
_shipRowElement(s, translate, u, fInt, fRound, highlight) {
|
||||||
let noTouch = this.context.noTouch;
|
let noTouch = this.context.noTouch;
|
||||||
|
|
||||||
return (
|
return <tr
|
||||||
<tr
|
|
||||||
key={s.id}
|
key={s.id}
|
||||||
style={{ height: '1.5em' }}
|
style={{ height: '1.5em' }}
|
||||||
className={cn({
|
className={cn({ highlighted: noTouch && this.state.shipId === s.id, alt: highlight })}
|
||||||
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">{fInt(s.retailCost)}</td>
|
<td className='ri'>{s.manufacturer}</td>
|
||||||
<td className="ri cap">{translate(SizeMap[s.class])}</td>
|
<td className='ri'>{fInt(s.retailCost)}</td>
|
||||||
<td className="ri">{fInt(s.crew)}</td>
|
<td className='ri cap'>{translate(SizeMap[s.class])}</td>
|
||||||
<td className="ri">{s.masslock}</td>
|
<td className='ri'>{fInt(s.crew)}</td>
|
||||||
<td className="ri">{fInt(s.agility)}</td>
|
<td className='ri'>{s.masslock}</td>
|
||||||
<td className="ri">{fInt(s.hardness)}</td>
|
<td className='ri'>{fInt(s.agility)}</td>
|
||||||
<td className="ri">{fInt(s.hullMass)}</td>
|
<td className='ri'>{fInt(s.hardness)}</td>
|
||||||
<td className="ri">{fInt(s.speed)}</td>
|
<td className='ri'>{fInt(s.hullMass)}</td>
|
||||||
<td className="ri">{fInt(s.boost)}</td>
|
<td className='ri'>{fInt(s.speed)}</td>
|
||||||
<td className="ri">{fInt(s.baseArmour)}</td>
|
<td className='ri'>{fInt(s.boost)}</td>
|
||||||
<td className="ri">{fInt(s.baseShieldStrength)}</td>
|
<td className='ri'>{fInt(s.baseArmour)}</td>
|
||||||
<td className="ri">{fInt(s.topSpeed)}</td>
|
<td className='ri'>{fInt(s.baseShieldStrength)}</td>
|
||||||
<td className="ri">{fInt(s.topBoost)}</td>
|
<td className='ri'>{fInt(s.topSpeed)}</td>
|
||||||
<td className="ri">{fRound(s.maxJumpRange)}</td>
|
<td className='ri'>{fInt(s.topBoost)}</td>
|
||||||
<td className="ri">{fInt(s.maxCargo)}</td>
|
<td className='ri'>{fRound(s.maxJumpRange)}</td>
|
||||||
<td className="ri">{fInt(s.maxPassengers)}</td>
|
<td className='ri'>{fInt(s.maxCargo)}</td>
|
||||||
<td className="cn">{s.standard[0]}</td>
|
<td className='ri'>{fInt(s.maxPassengers)}</td>
|
||||||
<td className="cn">{s.standard[1]}</td>
|
<td className='cn'>{s.standard[0]}</td>
|
||||||
<td className="cn">{s.standard[2]}</td>
|
<td className='cn'>{s.standard[1]}</td>
|
||||||
<td className="cn">{s.standard[3]}</td>
|
<td className='cn'>{s.standard[2]}</td>
|
||||||
<td className="cn">{s.standard[4]}</td>
|
<td className='cn'>{s.standard[3]}</td>
|
||||||
<td className="cn">{s.standard[5]}</td>
|
<td className='cn'>{s.standard[4]}</td>
|
||||||
<td className="cn">{s.standard[6]}</td>
|
<td className='cn'>{s.standard[5]}</td>
|
||||||
<td className={cn({ disabled: !s.hp[1] })}>{s.hp[1]}</td>
|
<td className='cn'>{s.standard[6]}</td>
|
||||||
<td className={cn({ disabled: !s.hp[2] })}>{s.hp[2]}</td>
|
<td className={cn({ disabled: !s.hp[1] })}>{s.hp[1]}</td>
|
||||||
<td className={cn({ disabled: !s.hp[3] })}>{s.hp[3]}</td>
|
<td className={cn({ disabled: !s.hp[2] })}>{s.hp[2]}</td>
|
||||||
<td className={cn({ disabled: !s.hp[4] })}>{s.hp[4]}</td>
|
<td className={cn({ disabled: !s.hp[3] })}>{s.hp[3]}</td>
|
||||||
<td className={cn({ disabled: !s.hp[0] })}>{s.hp[0]}</td>
|
<td className={cn({ disabled: !s.hp[4] })}>{s.hp[4]}</td>
|
||||||
<td className={cn({ disabled: !s.int[0] })}>{s.int[0]}</td>
|
<td className={cn({ disabled: !s.hp[0] })}>{s.hp[0]}</td>
|
||||||
<td className={cn({ disabled: !s.int[1] })}>{s.int[1]}</td>
|
<td className={cn({ disabled: !s.int[0] })}>{s.int[0]}</td>
|
||||||
<td className={cn({ disabled: !s.int[2] })}>{s.int[2]}</td>
|
<td className={cn({ disabled: !s.int[1] })}>{s.int[1]}</td>
|
||||||
<td className={cn({ disabled: !s.int[3] })}>{s.int[3]}</td>
|
<td className={cn({ disabled: !s.int[2] })}>{s.int[2]}</td>
|
||||||
<td className={cn({ disabled: !s.int[4] })}>{s.int[4]}</td>
|
<td className={cn({ disabled: !s.int[3] })}>{s.int[3]}</td>
|
||||||
<td className={cn({ disabled: !s.int[5] })}>{s.int[5]}</td>
|
<td className={cn({ disabled: !s.int[4] })}>{s.int[4]}</td>
|
||||||
<td className={cn({ disabled: !s.int[6] })}>{s.int[6]}</td>
|
<td className={cn({ disabled: !s.int[5] })}>{s.int[5]}</td>
|
||||||
<td className={cn({ disabled: !s.int[7] })}>{s.int[7]}</td>
|
<td className={cn({ disabled: !s.int[6] })}>{s.int[6]}</td>
|
||||||
</tr>
|
<td className={cn({ disabled: !s.int[7] })}>{s.int[7]}</td>
|
||||||
);
|
</tr>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -255,9 +221,8 @@ 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);
|
|
||||||
|
|
||||||
let filters = {
|
let filters = {
|
||||||
// 'class': { 1: 1, 2: 1}
|
// 'class': { 1: 1, 2: 1}
|
||||||
@@ -274,8 +239,7 @@ export default class ShipyardPage extends Page {
|
|||||||
|
|
||||||
// Sort shipsOverview
|
// Sort shipsOverview
|
||||||
shipSummaries.sort((a, b) => {
|
shipSummaries.sort((a, b) => {
|
||||||
let valA = a[shipPredicate],
|
let valA = a[shipPredicate], valB = b[shipPredicate];
|
||||||
valB = b[shipPredicate];
|
|
||||||
|
|
||||||
if (shipPredicateIndex != undefined) {
|
if (shipPredicateIndex != undefined) {
|
||||||
valA = valA[shipPredicateIndex];
|
valA = valA[shipPredicateIndex];
|
||||||
@@ -288,16 +252,7 @@ export default class ShipyardPage extends Page {
|
|||||||
valB = val;
|
valB = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (groupCompared) {
|
if(valA == valB) {
|
||||||
if (compare[a.id] && !compare[b.id]) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (!compare[a.id] && compare[b.id]) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (valA == valB) {
|
|
||||||
if (a.name > b.name) {
|
if (a.name > b.name) {
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
@@ -314,310 +269,130 @@ export default class ShipyardPage extends Page {
|
|||||||
let shipRows = new Array(shipSummaries.length);
|
let shipRows = new Array(shipSummaries.length);
|
||||||
let detailRows = new Array(shipSummaries.length);
|
let detailRows = new Array(shipSummaries.length);
|
||||||
|
|
||||||
|
let lastShipSortValue = null;
|
||||||
|
let backgroundHighlight = false;
|
||||||
|
|
||||||
for (let s of shipSummaries) {
|
for (let s of shipSummaries) {
|
||||||
detailRows[i] = this._shipRowElement(
|
let shipSortValue = s[shipPredicate];
|
||||||
s,
|
if(shipPredicateIndex != undefined) {
|
||||||
translate,
|
shipSortValue = shipSortValue[shipPredicateIndex];
|
||||||
units,
|
}
|
||||||
fInt,
|
|
||||||
formats.f1,
|
if(shipSortValue != lastShipSortValue) {
|
||||||
);
|
backgroundHighlight = !backgroundHighlight;
|
||||||
|
lastShipSortValue = shipSortValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
detailRows[i] = this._shipRowElement(s, translate, units, fInt, formats.f1, backgroundHighlight);
|
||||||
shipRows[i] = (
|
shipRows[i] = (
|
||||||
<tr
|
<tr
|
||||||
key={i}
|
key={i}
|
||||||
style={{ height: '1.5em' }}
|
style={{ height: '1.5em' }}
|
||||||
className={cn({
|
className={cn({ highlighted: noTouch && this.state.shipId === s.id, alt: backgroundHighlight })}
|
||||||
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}</Link></td>
|
||||||
<Link href={'/outfit/' + s.id}>{s.name} {s.beta === true ? '(Beta)' : null}</Link>
|
|
||||||
</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="page" style={{fontSize: sizeRatio + 'em'}}>
|
<div className='page' style={{ fontSize: sizeRatio + 'em' }}>
|
||||||
<div className="content-wrapper">
|
<div style={{ whiteSpace: 'nowrap', margin: '0 auto', fontSize: '0.8em', position: 'relative', display: 'inline-block', maxWidth: '100%' }}>
|
||||||
<div className="shipyard-table-wrapper">
|
<table style={{ width: '12em', position: 'absolute', zIndex: 1 }}>
|
||||||
<table style={{width: '12em', position: 'absolute', zIndex: 1}} className="shipyard-table">
|
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th className="le rgt"> </th>
|
<th className='le rgt'> </th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr className="main">
|
<tr className='main'>
|
||||||
<th className="sortable le rgt" onClick={sortShips('name')}>
|
<th className='sortable le rgt' onClick={sortShips('name')}>{translate('ship')}</th>
|
||||||
{translate('ship')}
|
|
||||||
</th>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th className="le rgt invisible">{units['m/s']}</th>
|
<th className='le rgt invisible'>{units['m/s']}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody onMouseLeave={this._highlightShip.bind(this, null)}>
|
<tbody onMouseLeave={this._highlightShip.bind(this, null)}>
|
||||||
{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> </th>
|
<th rowSpan={3} className='sortable' onClick={sortShips('manufacturer')}>{translate('manufacturer')}</th>
|
||||||
<th
|
<th> </th>
|
||||||
rowSpan={3}
|
<th rowSpan={3} className='sortable' onClick={sortShips('class')}>{translate('size')}</th>
|
||||||
className="sortable"
|
<th rowSpan={3} className='sortable' onClick={sortShips('crew')}>{translate('crew')}</th>
|
||||||
onClick={sortShips('class')}
|
<th rowSpan={3} className='sortable' onMouseEnter={termtip.bind(null, 'mass lock factor')} onMouseLeave={hide} onClick={sortShips('masslock')} >{translate('MLF')}</th>
|
||||||
>
|
<th rowSpan={3} className='sortable' onClick={sortShips('agility')}>{translate('agility')}</th>
|
||||||
{translate('size')}
|
<th rowSpan={3} className='sortable' onMouseEnter={termtip.bind(null, 'hardness')} onMouseLeave={hide} onClick={sortShips('hardness')}>{translate('hrd')}</th>
|
||||||
</th>
|
<th> </th>
|
||||||
<th
|
<th colSpan={4}>{translate('base')}</th>
|
||||||
rowSpan={3}
|
<th colSpan={5}>{translate('max')}</th>
|
||||||
className="sortable"
|
<th className='lft' colSpan={7}></th>
|
||||||
onClick={sortShips('crew')}
|
<th className='lft' colSpan={5}></th>
|
||||||
>
|
<th className='lft' colSpan={8}></th>
|
||||||
{translate('crew')}
|
</tr>
|
||||||
</th>
|
<tr>
|
||||||
<th
|
<th className='sortable lft' onClick={sortShips('retailCost')}>{translate('cost')}</th>
|
||||||
rowSpan={3}
|
<th className='sortable lft' onClick={sortShips('hullMass')}>{translate('hull')}</th>
|
||||||
className="sortable"
|
<th className='sortable lft' onClick={sortShips('speed')}>{translate('speed')}</th>
|
||||||
onMouseEnter={termtip.bind(null, 'mass lock factor')}
|
<th className='sortable' onClick={sortShips('boost')}>{translate('boost')}</th>
|
||||||
onMouseLeave={hide}
|
<th className='sortable' onClick={sortShips('baseArmour')}>{translate('armour')}</th>
|
||||||
onClick={sortShips('masslock')}
|
<th className='sortable' onClick={sortShips('baseShieldStrength')}>{translate('shields')}</th>
|
||||||
>
|
|
||||||
{translate('MLF')}
|
|
||||||
</th>
|
|
||||||
<th
|
|
||||||
rowSpan={3}
|
|
||||||
className="sortable"
|
|
||||||
onClick={sortShips('agility')}
|
|
||||||
>
|
|
||||||
{translate('agility')}
|
|
||||||
</th>
|
|
||||||
<th
|
|
||||||
rowSpan={3}
|
|
||||||
className="sortable"
|
|
||||||
onMouseEnter={termtip.bind(null, 'hardness')}
|
|
||||||
onMouseLeave={hide}
|
|
||||||
onClick={sortShips('hardness')}
|
|
||||||
>
|
|
||||||
{translate('hrd')}
|
|
||||||
</th>
|
|
||||||
<th> </th>
|
|
||||||
<th colSpan={4}>{translate('base')}</th>
|
|
||||||
<th colSpan={5}>{translate('max')}</th>
|
|
||||||
<th className="lft" colSpan={7} />
|
|
||||||
<th className="lft" colSpan={5} />
|
|
||||||
<th className="lft" colSpan={8} />
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th
|
|
||||||
className="sortable lft"
|
|
||||||
onClick={sortShips('retailCost')}
|
|
||||||
>
|
|
||||||
{translate('cost')}
|
|
||||||
</th>
|
|
||||||
<th className="sortable lft" onClick={sortShips('hullMass')}>
|
|
||||||
{translate('hull')}
|
|
||||||
</th>
|
|
||||||
<th className="sortable lft" onClick={sortShips('speed')}>
|
|
||||||
{translate('speed')}
|
|
||||||
</th>
|
|
||||||
<th className="sortable" onClick={sortShips('boost')}>
|
|
||||||
{translate('boost')}
|
|
||||||
</th>
|
|
||||||
<th className="sortable" onClick={sortShips('baseArmour')}>
|
|
||||||
{translate('armour')}
|
|
||||||
</th>
|
|
||||||
<th
|
|
||||||
className="sortable"
|
|
||||||
onClick={sortShips('baseShieldStrength')}
|
|
||||||
>
|
|
||||||
{translate('shields')}
|
|
||||||
</th>
|
|
||||||
|
|
||||||
<th className="sortable lft" onClick={sortShips('topSpeed')}>
|
<th className='sortable lft' onClick={sortShips('topSpeed')}>{translate('speed')}</th>
|
||||||
{translate('speed')}
|
<th className='sortable' onClick={sortShips('topBoost')}>{translate('boost')}</th>
|
||||||
</th>
|
<th className='sortable' onClick={sortShips('maxJumpRange')}>{translate('jump')}</th>
|
||||||
<th className="sortable" onClick={sortShips('topBoost')}>
|
<th className='sortable' onClick={sortShips('maxCargo')}>{translate('cargo')}</th>
|
||||||
{translate('boost')}
|
<th className='sortable' onClick={sortShips('maxPassengers')}>{translate('pax')}</th>
|
||||||
</th>
|
|
||||||
<th className="sortable" onClick={sortShips('maxJumpRange')}>
|
|
||||||
{translate('jump')}
|
|
||||||
</th>
|
|
||||||
<th className="sortable" onClick={sortShips('maxCargo')}>
|
|
||||||
{translate('cargo')}
|
|
||||||
</th>
|
|
||||||
<th className="sortable" onClick={sortShips('maxPassengers')} onMouseEnter={termtip.bind(null, 'passenger capacity')}
|
|
||||||
onMouseLeave={hide}>
|
|
||||||
{translate('pax')}
|
|
||||||
</th>
|
|
||||||
<th className="lft" colSpan={7}>
|
|
||||||
{translate('core module classes')}
|
|
||||||
</th>
|
|
||||||
<th
|
|
||||||
colSpan={5}
|
|
||||||
className="sortable lft"
|
|
||||||
onClick={sortShips('hpCount')}
|
|
||||||
>
|
|
||||||
{translate('hardpoints')}
|
|
||||||
</th>
|
|
||||||
<th
|
|
||||||
colSpan={8}
|
|
||||||
className="sortable lft"
|
|
||||||
onClick={sortShips('intCount')}
|
|
||||||
>
|
|
||||||
{translate('internal compartments')}
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th
|
|
||||||
className="sortable lft"
|
|
||||||
onClick={sortShips('retailCost')}
|
|
||||||
>
|
|
||||||
{units.CR}
|
|
||||||
</th>
|
|
||||||
<th className="sortable lft" onClick={sortShips('hullMass')}>
|
|
||||||
{units.T}
|
|
||||||
</th>
|
|
||||||
<th className="sortable lft" onClick={sortShips('speed')}>
|
|
||||||
{units['m/s']}
|
|
||||||
</th>
|
|
||||||
<th className="sortable" onClick={sortShips('boost')}>
|
|
||||||
{units['m/s']}
|
|
||||||
</th>
|
|
||||||
<th> </th>
|
|
||||||
<th
|
|
||||||
className="sortable"
|
|
||||||
onClick={sortShips('baseShieldStrength')}
|
|
||||||
>
|
|
||||||
{units.MJ}
|
|
||||||
</th>
|
|
||||||
<th className="sortable lft" onClick={sortShips('topSpeed')}>
|
|
||||||
{units['m/s']}
|
|
||||||
</th>
|
|
||||||
<th className="sortable" onClick={sortShips('topBoost')}>
|
|
||||||
{units['m/s']}
|
|
||||||
</th>
|
|
||||||
<th className="sortable" onClick={sortShips('maxJumpRange')}>
|
|
||||||
{units.LY}
|
|
||||||
</th>
|
|
||||||
<th className="sortable" onClick={sortShips('maxCargo')}>
|
|
||||||
{units.T}
|
|
||||||
</th>
|
|
||||||
<th> </th>
|
|
||||||
<th
|
|
||||||
className="sortable lft"
|
|
||||||
onMouseEnter={termtip.bind(null, 'power plant')}
|
|
||||||
onMouseLeave={hide}
|
|
||||||
onClick={sortShips('standard', 0)}
|
|
||||||
>
|
|
||||||
{'pp'}
|
|
||||||
</th>
|
|
||||||
<th
|
|
||||||
className="sortable"
|
|
||||||
onMouseEnter={termtip.bind(null, 'thrusters')}
|
|
||||||
onMouseLeave={hide}
|
|
||||||
onClick={sortShips('standard', 1)}
|
|
||||||
>
|
|
||||||
{'th'}
|
|
||||||
</th>
|
|
||||||
<th
|
|
||||||
className="sortable"
|
|
||||||
onMouseEnter={termtip.bind(null, 'frame shift drive')}
|
|
||||||
onMouseLeave={hide}
|
|
||||||
onClick={sortShips('standard', 2)}
|
|
||||||
>
|
|
||||||
{'fsd'}
|
|
||||||
</th>
|
|
||||||
<th
|
|
||||||
className="sortable"
|
|
||||||
onMouseEnter={termtip.bind(null, 'life support')}
|
|
||||||
onMouseLeave={hide}
|
|
||||||
onClick={sortShips('standard', 3)}
|
|
||||||
>
|
|
||||||
{'ls'}
|
|
||||||
</th>
|
|
||||||
<th
|
|
||||||
className="sortable"
|
|
||||||
onMouseEnter={termtip.bind(null, 'power distributor')}
|
|
||||||
onMouseLeave={hide}
|
|
||||||
onClick={sortShips('standard', 4)}
|
|
||||||
>
|
|
||||||
{'pd'}
|
|
||||||
</th>
|
|
||||||
<th
|
|
||||||
className="sortable"
|
|
||||||
onMouseEnter={termtip.bind(null, 'sensors')}
|
|
||||||
onMouseLeave={hide}
|
|
||||||
onClick={sortShips('standard', 5)}
|
|
||||||
>
|
|
||||||
{'s'}
|
|
||||||
</th>
|
|
||||||
<th
|
|
||||||
className="sortable"
|
|
||||||
onMouseEnter={termtip.bind(null, 'fuel tank')}
|
|
||||||
onMouseLeave={hide}
|
|
||||||
onClick={sortShips('standard', 6)}
|
|
||||||
>
|
|
||||||
{'ft'}
|
|
||||||
</th>
|
|
||||||
<th className="sortable lft" onClick={sortShips('hp', 1)}>
|
|
||||||
{translate('S')}
|
|
||||||
</th>
|
|
||||||
<th className="sortable" onClick={sortShips('hp', 2)}>
|
|
||||||
{translate('M')}
|
|
||||||
</th>
|
|
||||||
<th className="sortable" onClick={sortShips('hp', 3)}>
|
|
||||||
{translate('L')}
|
|
||||||
</th>
|
|
||||||
<th className="sortable" onClick={sortShips('hp', 4)}>
|
|
||||||
{translate('H')}
|
|
||||||
</th>
|
|
||||||
<th className="sortable" onClick={sortShips('hp', 0)}>
|
|
||||||
{translate('U')}
|
|
||||||
</th>
|
|
||||||
|
|
||||||
<th className="sortable lft" onClick={sortShips('int', 0)}>
|
<th className='lft' colSpan={7}>{translate('core module classes')}</th>
|
||||||
1
|
<th colSpan={5} className='sortable lft' onClick={sortShips('hpCount')}>{translate('hardpoints')}</th>
|
||||||
</th>
|
<th colSpan={8} className='sortable lft' onClick={sortShips('intCount')}>{translate('internal compartments')}</th>
|
||||||
<th className="sortable" onClick={sortShips('int', 1)}>
|
</tr>
|
||||||
2
|
<tr>
|
||||||
</th>
|
<th className='sortable lft' onClick={sortShips('retailCost')}>{units.CR}</th>
|
||||||
<th className="sortable" onClick={sortShips('int', 2)}>
|
<th className='sortable lft' onClick={sortShips('hullMass')}>{units.T}</th>
|
||||||
3
|
<th className='sortable lft' onClick={sortShips('speed')}>{units['m/s']}</th>
|
||||||
</th>
|
<th className='sortable' onClick={sortShips('boost')}>{units['m/s']}</th>
|
||||||
<th className="sortable" onClick={sortShips('int', 3)}>
|
<th> </th>
|
||||||
4
|
<th className='sortable' onClick={sortShips('baseShieldStrength')}>{units.MJ}</th>
|
||||||
</th>
|
<th className='sortable lft' onClick={sortShips('topSpeed')}>{units['m/s']}</th>
|
||||||
<th className="sortable" onClick={sortShips('int', 4)}>
|
<th className='sortable' onClick={sortShips('topBoost')}>{units['m/s']}</th>
|
||||||
5
|
<th className='sortable' onClick={sortShips('maxJumpRange')}>{units.LY}</th>
|
||||||
</th>
|
<th className='sortable' onClick={sortShips('maxCargo')}>{units.T}</th>
|
||||||
<th className="sortable" onClick={sortShips('int', 5)}>
|
<th> </th>
|
||||||
6
|
<th className='sortable lft' onMouseEnter={termtip.bind(null, 'power plant')} onMouseLeave={hide} onClick={sortShips('standard', 0)}>{'pp'}</th>
|
||||||
</th>
|
<th className='sortable' onMouseEnter={termtip.bind(null, 'thrusters')} onMouseLeave={hide} onClick={sortShips('standard', 1)}>{'th'}</th>
|
||||||
<th className="sortable" onClick={sortShips('int', 6)}>
|
<th className='sortable' onMouseEnter={termtip.bind(null, 'frame shift drive')} onMouseLeave={hide} onClick={sortShips('standard', 2)}>{'fsd'}</th>
|
||||||
7
|
<th className='sortable' onMouseEnter={termtip.bind(null, 'life support')} onMouseLeave={hide} onClick={sortShips('standard', 3)}>{'ls'}</th>
|
||||||
</th>
|
<th className='sortable' onMouseEnter={termtip.bind(null, 'power distriubtor')} onMouseLeave={hide} onClick={sortShips('standard', 4)}>{'pd'}</th>
|
||||||
<th className="sortable" onClick={sortShips('int', 7)}>
|
<th className='sortable' onMouseEnter={termtip.bind(null, 'sensors')} onMouseLeave={hide} onClick={sortShips('standard', 5)}>{'s'}</th>
|
||||||
8
|
<th className='sortable' onMouseEnter={termtip.bind(null, 'fuel tank')} onMouseLeave={hide} onClick={sortShips('standard', 6)}>{'ft'}</th>
|
||||||
</th>
|
<th className='sortable lft' onClick={sortShips('hp',1)}>{translate('S')}</th>
|
||||||
</tr>
|
<th className='sortable' onClick={sortShips('hp', 2)}>{translate('M')}</th>
|
||||||
</thead>
|
<th className='sortable' onClick={sortShips('hp', 3)}>{translate('L')}</th>
|
||||||
<tbody onMouseLeave={this._highlightShip.bind(this, null)}>
|
<th className='sortable' onClick={sortShips('hp', 4)}>{translate('H')}</th>
|
||||||
{detailRows}
|
<th className='sortable' onClick={sortShips('hp', 0)}>{translate('U')}</th>
|
||||||
</tbody>
|
|
||||||
</table>
|
<th className='sortable lft' onClick={sortShips('int', 0)} >1</th>
|
||||||
|
<th className='sortable' onClick={sortShips('int', 1)} >2</th>
|
||||||
|
<th className='sortable' onClick={sortShips('int', 2)} >3</th>
|
||||||
|
<th className='sortable' onClick={sortShips('int', 3)} >4</th>
|
||||||
|
<th className='sortable' onClick={sortShips('int', 4)} >5</th>
|
||||||
|
<th className='sortable' onClick={sortShips('int', 5)} >6</th>
|
||||||
|
<th className='sortable' onClick={sortShips('int', 6)} >7</th>
|
||||||
|
<th className='sortable' onClick={sortShips('int', 7)} >8</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody onMouseLeave={this._highlightShip.bind(this, null)}>
|
||||||
|
{detailRows}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="table-tools" >
|
|
||||||
<label><input type="checkbox" checked={this.state.groupCompared} onClick={() => this._toggleGroupCompared()}/>{translate('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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -383,8 +415,7 @@ export function shieldMetrics(ship, sys) {
|
|||||||
|
|
||||||
// Our initial regeneration comes from the SYS capacitor store, which is replenished as it goes
|
// Our initial regeneration comes from the SYS capacitor store, which is replenished as it goes
|
||||||
// 0.6 is a magic number from FD: each 0.6 MW of energy from the power distributor recharges 1 MJ/s of regeneration
|
// 0.6 is a magic number from FD: each 0.6 MW of energy from the power distributor recharges 1 MJ/s of regeneration
|
||||||
let capacitorDrain = (shieldGenerator.getBrokenRegenerationRate() * shieldGenerator.getDistDraw()) - sysRechargeRate;
|
let capacitorDrain = (shieldGenerator.getBrokenRegenerationRate() * 0.6) - sysRechargeRate;
|
||||||
|
|
||||||
let capacitorLifetime = powerDistributor.getSystemsCapacity() / capacitorDrain;
|
let capacitorLifetime = powerDistributor.getSystemsCapacity() / capacitorDrain;
|
||||||
|
|
||||||
let recover = 16;
|
let recover = 16;
|
||||||
@@ -400,7 +431,7 @@ export function shieldMetrics(ship, sys) {
|
|||||||
recover = Math.Infinity;
|
recover = Math.Infinity;
|
||||||
} else {
|
} else {
|
||||||
// Recover remaining shields at the rate of the power distributor's recharge
|
// Recover remaining shields at the rate of the power distributor's recharge
|
||||||
recover += remainingShieldToRecover / (sysRechargeRate / shieldGenerator.getDistDraw());
|
recover += remainingShieldToRecover / (sysRechargeRate / 0.6);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -409,7 +440,7 @@ export function shieldMetrics(ship, sys) {
|
|||||||
|
|
||||||
// Our initial regeneration comes from the SYS capacitor store, which is replenished as it goes
|
// Our initial regeneration comes from the SYS capacitor store, which is replenished as it goes
|
||||||
// 0.6 is a magic number from FD: each 0.6 MW of energy from the power distributor recharges 1 MJ/s of regeneration
|
// 0.6 is a magic number from FD: each 0.6 MW of energy from the power distributor recharges 1 MJ/s of regeneration
|
||||||
capacitorDrain = (shieldGenerator.getRegenerationRate() * shieldGenerator.getDistDraw()) - sysRechargeRate;
|
capacitorDrain = (shieldGenerator.getRegenerationRate() * 0.6) - sysRechargeRate;
|
||||||
capacitorLifetime = powerDistributor.getSystemsCapacity() / capacitorDrain;
|
capacitorLifetime = powerDistributor.getSystemsCapacity() / capacitorDrain;
|
||||||
|
|
||||||
let recharge = 0;
|
let recharge = 0;
|
||||||
@@ -425,7 +456,7 @@ export function shieldMetrics(ship, sys) {
|
|||||||
recharge = Math.Inf;
|
recharge = Math.Inf;
|
||||||
} else {
|
} else {
|
||||||
// Recharge remaining shields at the rate of the power distributor's recharge
|
// Recharge remaining shields at the rate of the power distributor's recharge
|
||||||
recharge += remainingShieldToRecharge / (sysRechargeRate / shieldGenerator.getDistDraw());
|
recharge += remainingShieldToRecharge / (sysRechargeRate / 0.6);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -434,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,
|
||||||
@@ -467,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,
|
||||||
@@ -479,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,
|
||||||
@@ -491,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,
|
||||||
@@ -531,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,
|
||||||
@@ -569,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,
|
||||||
@@ -578,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,
|
||||||
@@ -587,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,
|
||||||
@@ -596,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,
|
||||||
@@ -843,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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -910,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() / m.getSustainedFactor();
|
|
||||||
weapon.effectiveness.armour.dpe = weapon.damage.armour.total / m.getEps() / m.getSustainedFactor();
|
|
||||||
|
|
||||||
|
|
||||||
return weapon;
|
return weapon;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -964,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 {
|
||||||
@@ -986,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,9 +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',
|
|
||||||
mlc: "Multi Limpet Controller",
|
|
||||||
rpl: "Repair Limpet Controller",
|
|
||||||
|
|
||||||
// Hard Points
|
// Hard Points
|
||||||
bl: 'Beam Laser',
|
bl: 'Beam Laser',
|
||||||
@@ -97,10 +94,6 @@ export const ModuleGroupToName = {
|
|||||||
gsc: 'Guardian Shard Cannon',
|
gsc: 'Guardian Shard Cannon',
|
||||||
tbem: 'Enzyme Missile Rack',
|
tbem: 'Enzyme Missile Rack',
|
||||||
tbrfl: 'Remote Release Flechette Launcher',
|
tbrfl: 'Remote Release Flechette Launcher',
|
||||||
pwa: 'Pulse Wave Analyser',
|
|
||||||
abl: 'Abrasion Blaster',
|
|
||||||
scl: 'Seismic Charge Launcher',
|
|
||||||
sdm: 'Sub-Surface Displacement Missile',
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let GrpNameToCodeMap = {};
|
let GrpNameToCodeMap = {};
|
||||||
@@ -209,7 +202,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',
|
||||||
|
|||||||
@@ -41,7 +41,6 @@ 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 baseVal = this[name];
|
|
||||||
let result = this.mods && this.mods[name] ? this.mods[name] : null;
|
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) {
|
||||||
@@ -52,25 +51,46 @@ export default class Module {
|
|||||||
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 (name === 'explres' || name === 'kinres' || name === 'thermres' || name === 'causres') {
|
||||||
// Apply resistance modding mechanisms to special effects subsequently
|
// Resistance modifications in itself are additive, however their
|
||||||
result = result + modifierActions[name] * (1 - (this[name] + result / multiplier)) * 100;
|
// special effects are multiplicative. They affect the overall result
|
||||||
|
// by (special effect resistance) * (damage mult after modification),
|
||||||
|
// i. e. we need to apply the special effect as a multiplier to the
|
||||||
|
// overall result and then calculate the difference.
|
||||||
|
let baseMult = this[name] ? 1 - this[name] : 1;
|
||||||
|
result = (baseMult - (baseMult - result / multiplier) * (1 - modifierActions[name] / 100)) * multiplier;
|
||||||
} else if (modification.method === 'additive') {
|
} else if (modification.method === 'additive') {
|
||||||
result = result + modifierActions[name] * 100;
|
result = result + modifierActions[name] * 100;
|
||||||
} else if (modification.method === 'overwrite') {
|
} else if (modification.method === 'overwrite') {
|
||||||
result = modifierActions[name];
|
result = modifierActions[name];
|
||||||
} else {
|
} else {
|
||||||
result = (((1 + result / multiplier) * (1 + modifierActions[name])) - 1) * 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Resistance modding for hull reinforcement packages has additional
|
||||||
|
// diminishing returns implemented. The mod value gets lowered by
|
||||||
|
// the amount of base resistance the hrp has.
|
||||||
|
if (!isNaN(result) && this.grp === 'hr' &&
|
||||||
|
(name === 'kinres' || name === 'thermres' || name === 'explres')) {
|
||||||
|
let baseRes = this[name];
|
||||||
|
result = result * (1 - baseRes);
|
||||||
|
}
|
||||||
|
|
||||||
// Sanitise the resultant value to 4dp equivalent
|
// Sanitise the resultant value to 4dp equivalent
|
||||||
return isNaN(result) ? result : Math.round(result);
|
return isNaN(result) ? result : Math.round(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a value for a given modification ID
|
* Set a value for a given modification ID
|
||||||
* @param {String} name The name of the modification
|
* @param {Number} name The name of the modification
|
||||||
* @param {object} value The value of the modification. If it is a numeric value then it should be an integer scaled so that -2.34% == -234
|
* @param {object} value The value of the modification. If it is a numeric value then it should be an integer scaled so that -2.34% == -234
|
||||||
* @param {Boolean} valueiswithspecial true if the value includes the special effect (when coming from a UI component)
|
* @param {Boolean} valueiswithspecial true if the value includes the special effect (when coming from a UI component)
|
||||||
*/
|
*/
|
||||||
@@ -81,30 +101,31 @@ export default class Module {
|
|||||||
if (!this.origVals) {
|
if (!this.origVals) {
|
||||||
this.origVals = {};
|
this.origVals = {};
|
||||||
}
|
}
|
||||||
if (!valueiswithspecial) {
|
if (valueiswithspecial && this.blueprint && this.blueprint.special) {
|
||||||
// Resistance modifiers scale with the base value.
|
|
||||||
if (name === 'kinres' || name === 'thermres' || name === 'causres' || name === 'explres') {
|
|
||||||
let baseValue = this.get(name, false);
|
|
||||||
value = (1 - baseValue) * value;
|
|
||||||
}
|
|
||||||
} else if (valueiswithspecial && this.blueprint && this.blueprint.special) {
|
|
||||||
// This module has a special effect, see if we need to alter the stored value
|
// This module has a special effect, see if we need to alter the stored value
|
||||||
const modifierActions = Modifications.modifierActions[this.blueprint.special.edname];
|
const modifierActions = Modifications.modifierActions[this.blueprint.special.edname];
|
||||||
if (modifierActions && modifierActions[name]) {
|
if (modifierActions && modifierActions[name]) {
|
||||||
// This special effect modifies the value being set, so we need to revert it prior to storing the value
|
// This special effect modifies the value being set, so we need to revert it prior to storing the value
|
||||||
const modification = Modifications.modifications[name];
|
const modification = Modifications.modifications[name];
|
||||||
if (name === 'explres' || name === 'kinres' || name === 'thermres' || name === 'causres') {
|
if (name === 'explres' || name === 'kinres' || name === 'thermres' || name === 'causres') {
|
||||||
let res = (this[name] ? this[name] : 0) + value / 10000;
|
// Resistance modifications in itself are additive but their
|
||||||
let experimental = modifierActions[name] / 100;
|
// experimentals are applied multiplicatively therefor we must handle
|
||||||
value = (experimental - res) / (experimental - 1) - this[name];
|
// them differently here (cf. documentation in getModValue).
|
||||||
value *= 10000;
|
let baseMult = (this[name] ? 1 - this[name] : 1);
|
||||||
// value = ((baseMult - value / 10000) / (1 - modifierActions[name] / 100) - baseMult) * -10000;
|
value = ((baseMult - value / 10000) / (1 - modifierActions[name] / 100) - baseMult) * -10000;
|
||||||
} else if (modification.method === 'additive') {
|
} else if (modification.method === 'additive') {
|
||||||
value = value - modifierActions[name];
|
value = value - modifierActions[name];
|
||||||
} 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -119,17 +140,10 @@ export default class Module {
|
|||||||
/**
|
/**
|
||||||
* Helper to obtain a module's value.
|
* Helper to obtain a module's value.
|
||||||
* @param {String} name The name of the modifier to obtain
|
* @param {String} name The name of the modifier to obtain
|
||||||
* @param {Boolean} modified Whether to return the raw or modified value
|
* @param {Number} modified Whether to return the raw or modified value
|
||||||
* @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);
|
||||||
@@ -163,22 +177,20 @@ export default class Module {
|
|||||||
baseValue = 0;
|
baseValue = 0;
|
||||||
}
|
}
|
||||||
modValue = value - baseValue;
|
modValue = value - baseValue;
|
||||||
|
if (this.grp === 'hr' &&
|
||||||
|
(name === 'kinres' || name === 'thermres' || name === 'explres')) {
|
||||||
|
modValue = modValue / (1 - 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,14 +208,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;
|
||||||
}
|
}
|
||||||
@@ -262,17 +267,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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -294,7 +294,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;
|
||||||
@@ -364,18 +368,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;
|
||||||
}
|
}
|
||||||
@@ -439,15 +439,6 @@ export default class Module {
|
|||||||
return this.get('integrity', modified);
|
return this.get('integrity', modified);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the info of this module
|
|
||||||
* @param {Boolean} [modified=false] Whether to take modifications into account
|
|
||||||
* @return {String} the info of this module
|
|
||||||
*/
|
|
||||||
getInfo(modified = false) {
|
|
||||||
return (modified && this.getModValue('info')) || this.info;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the mass of this module
|
* Get the mass of this module
|
||||||
* @param {Boolean} [modified=true] Whether to take modifications into account
|
* @param {Boolean} [modified=true] Whether to take modifications into account
|
||||||
@@ -598,9 +589,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();
|
||||||
@@ -654,6 +656,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
|
||||||
@@ -709,7 +720,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); }
|
||||||
}
|
}
|
||||||
@@ -798,6 +810,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
|
||||||
@@ -821,39 +851,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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -877,7 +893,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;
|
||||||
|
|
||||||
@@ -914,6 +930,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
|
||||||
@@ -924,8 +958,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);
|
||||||
@@ -1056,31 +1090,4 @@ export default class Module {
|
|||||||
getHackTime(modified = true) {
|
getHackTime(modified = true) {
|
||||||
return this.get('hacktime', modified);
|
return this.get('hacktime', modified);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the scan range for this module
|
|
||||||
* @param {Boolean} [modified=true] Whether to take modifications into account
|
|
||||||
* @return {string} the time for this module
|
|
||||||
*/
|
|
||||||
getScanRange(modified = true) {
|
|
||||||
return this.get('scanrange', modified);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the scan angle for this module
|
|
||||||
* @param {Boolean} [modified=true] Whether to take modifications into account
|
|
||||||
* @return {string} the time for this module
|
|
||||||
*/
|
|
||||||
getScanAngle(modified = true) {
|
|
||||||
return this.get('scanangle', modified);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the max angle for this module
|
|
||||||
* @param {Boolean} [modified=true] Whether to take modifications into account
|
|
||||||
* @return {string} the time for this module
|
|
||||||
*/
|
|
||||||
getMaxAngle(modified = true) {
|
|
||||||
return this.get('maxangle', modified);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,19 +13,6 @@ function filter(arr, maxClass, minClass, mass) {
|
|||||||
return arr.filter(m => m.class <= maxClass && m.class >= minClass && (m.maxmass === undefined || mass <= m.maxmass));
|
return arr.filter(m => m.class <= maxClass && m.class >= minClass && (m.maxmass === undefined || mass <= m.maxmass));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Filter SCO Modules to only return legal size.
|
|
||||||
* @param {Array} arr Array of available FSD modules.
|
|
||||||
* @param {number} maxSize Maximum allowable size for SCO modules.
|
|
||||||
* @return {Array} Subset of modules filtered based on legal size amd type.
|
|
||||||
*/
|
|
||||||
function sco_filter(arr, maxSize) {
|
|
||||||
return arr.filter(module => {
|
|
||||||
return !(module.hasOwnProperty('name') && module['name'] === "Frame Shift Drive (SCO)" && module['class'] < maxSize);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The available module set for a specific ship
|
* The available module set for a specific ship
|
||||||
*/
|
*/
|
||||||
@@ -54,7 +41,6 @@ export default class ModuleSet {
|
|||||||
|
|
||||||
this.standard[0] = filter(stnd.pp, maxStandardArr[0], 0, mass); // Power Plant
|
this.standard[0] = filter(stnd.pp, maxStandardArr[0], 0, mass); // Power Plant
|
||||||
this.standard[2] = filter(stnd.fsd, maxStandardArr[2], 0, mass); // FSD
|
this.standard[2] = filter(stnd.fsd, maxStandardArr[2], 0, mass); // FSD
|
||||||
this.standard[2] = sco_filter(this.standard[2], maxStandardArr[2]) // FSD - Filter SCO Modules
|
|
||||||
this.standard[4] = filter(stnd.pd, maxStandardArr[4], 0, mass); // Power Distributor
|
this.standard[4] = filter(stnd.pd, maxStandardArr[4], 0, mass); // Power Distributor
|
||||||
this.standard[6] = filter(stnd.ft, maxStandardArr[6], 0, mass); // Fuel Tank
|
this.standard[6] = filter(stnd.ft, maxStandardArr[6], 0, mass); // Fuel Tank
|
||||||
// Thrusters, filter modules by class only (to show full list of ratings for that class)
|
// Thrusters, filter modules by class only (to show full list of ratings for that class)
|
||||||
|
|||||||
@@ -63,10 +63,7 @@ export function standard(type, id) {
|
|||||||
if (!isNaN(type)) {
|
if (!isNaN(type)) {
|
||||||
type = StandardArray[type];
|
type = StandardArray[type];
|
||||||
}
|
}
|
||||||
let s = Modules.standard[type].find(e => e.id === id);
|
let s = Modules.standard[type].find(e => e.id == id || (e.class == id.charAt(0) && e.rating == id.charAt(1)));
|
||||||
if (!s) {
|
|
||||||
s = Modules.standard[type].find(e => (e.class == id.charAt(0) && e.rating == id.charAt(1)));
|
|
||||||
}
|
|
||||||
if (s) {
|
if (s) {
|
||||||
s = new Module({ template: s });
|
s = new Module({ template: s });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,12 +85,12 @@ export function toDetailedBuild(buildName, ship) {
|
|||||||
code = ship.toString();
|
code = ship.toString();
|
||||||
|
|
||||||
let data = {
|
let data = {
|
||||||
$schema: 'https://coriolis.io/schemas/ship-loadout/4.json#',
|
$schema: 'https://coriolis.edcd.io/schemas/ship-loadout/4.json#',
|
||||||
name: buildName,
|
name: buildName,
|
||||||
ship: ship.name,
|
ship: ship.name,
|
||||||
references: [{
|
references: [{
|
||||||
name: 'Coriolis.io',
|
name: 'Coriolis.io',
|
||||||
url: 'https://coriolis.io' + outfitURL(ship.id, code, buildName),
|
url: 'https://coriolis.edcd.io' + outfitURL(ship.id, code, buildName),
|
||||||
code,
|
code,
|
||||||
shipId: ship.id
|
shipId: ship.id
|
||||||
}],
|
}],
|
||||||
|
|||||||
@@ -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', 'ews'];
|
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;
|
||||||
@@ -492,18 +492,20 @@ export default class Ship {
|
|||||||
* @param {Object} m The module to change
|
* @param {Object} m The module to change
|
||||||
* @param {Object} name The name of the modification to change
|
* @param {Object} name The name of the modification to change
|
||||||
* @param {Number} value The new value of the modification. The value of the modification is scaled to provide two decimal places of precision in an integer. For example 1.23% is stored as 123
|
* @param {Number} value The new value of the modification. The value of the modification is scaled to provide two decimal places of precision in an integer. For example 1.23% is stored as 123
|
||||||
* @param {boolean} isAbsolute True if value is an absolute value and not a modification value
|
* @param {bool} sentfromui True if this update was sent from the UI
|
||||||
|
* @param {bool} isAbsolute True if value is an absolute value and not a
|
||||||
|
* modification value
|
||||||
*/
|
*/
|
||||||
setModification(m, name, value, isAbsolute = false) {
|
setModification(m, name, value, sentfromui, isAbsolute) {
|
||||||
if (isNaN(value)) {
|
if (isNaN(value)) {
|
||||||
// Value passed is invalid; reset it to 0
|
// Value passed is invalid; reset it to 0
|
||||||
value = 0;
|
value = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isAbsolute) {
|
if (isAbsolute) {
|
||||||
m.setPretty(name, value, isAbsolute);
|
m.setPretty(name, value, sentfromui);
|
||||||
} else {
|
} else {
|
||||||
m.setModValue(name, value, false);
|
m.setModValue(name, value, sentfromui);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle special cases
|
// Handle special cases
|
||||||
@@ -536,7 +538,7 @@ export default class Ship {
|
|||||||
this.recalculateArmour();
|
this.recalculateArmour();
|
||||||
} else if (name === 'shieldreinforcement') {
|
} else if (name === 'shieldreinforcement') {
|
||||||
this.recalculateShieldCells();
|
this.recalculateShieldCells();
|
||||||
} else if (name === 'burst' || name === 'burstrof' || name === 'clip' || name === 'damage' || name === 'distdraw' || name === 'jitter' || name === 'piercing' || name === 'range' || name === 'reload' || name === 'rof' || name === 'thermload') {
|
} else if (name === 'burst' || name == 'burstrof' || name === 'clip' || name === 'damage' || name === 'distdraw' || name === 'jitter' || name === 'piercing' || name === 'range' || name === 'reload' || name === 'rof' || name === 'thermload') {
|
||||||
this.recalculateDps();
|
this.recalculateDps();
|
||||||
this.recalculateHps();
|
this.recalculateHps();
|
||||||
this.recalculateEps();
|
this.recalculateEps();
|
||||||
@@ -1301,7 +1303,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);
|
||||||
@@ -1499,7 +1501,7 @@ export default class Ship {
|
|||||||
} else {
|
} else {
|
||||||
buffer.writeInt32LE(slotMod.value, curpos);
|
buffer.writeInt32LE(slotMod.value, curpos);
|
||||||
}
|
}
|
||||||
const modification = _.find(Modifications.modifications, function(o) { return o.id === slotMod.id; });
|
// const modification = _.find(Modifications.modifications, function(o) { return o.id === slotMod.id; });
|
||||||
// console.log('ENCODE Slot ' + i + ': ' + modification.name + ' = ' + slotMod.value);
|
// console.log('ENCODE Slot ' + i + ': ' + modification.name + ' = ' + slotMod.value);
|
||||||
curpos += 4;
|
curpos += 4;
|
||||||
}
|
}
|
||||||
@@ -1512,7 +1514,6 @@ export default class Ship {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.serialized.modifications = zlib.gzipSync(buffer).toString('base64');
|
this.serialized.modifications = zlib.gzipSync(buffer).toString('base64');
|
||||||
// console.log(this.serialized.modifications)
|
|
||||||
} else {
|
} else {
|
||||||
this.serialized.modifications = null;
|
this.serialized.modifications = null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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' },
|
||||||
@@ -78,6 +78,5 @@ export const STATS_FORMATTING = {
|
|||||||
'thermres': { 'format': 'pct' },
|
'thermres': { 'format': 'pct' },
|
||||||
'wepcap': { 'format': 'round1', 'unit': 'MJ' },
|
'wepcap': { 'format': 'round1', 'unit': 'MJ' },
|
||||||
'weprate': { 'format': 'round1', 'unit': 'MW' },
|
'weprate': { 'format': 'round1', 'unit': 'MW' },
|
||||||
'jumpboost': { 'format': 'round1', 'unit': 'LY' },
|
'jumpboost': { 'format': 'round1', 'unit': 'LY' }
|
||||||
'proberadius': { 'format': 'pct1', 'unit': 'pct' },
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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,6 +1,5 @@
|
|||||||
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
|
||||||
@@ -281,25 +280,6 @@ export function isValueBeneficial(feature, value) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Is the change as shown beneficial?
|
|
||||||
* @param {string} feature The name of the feature
|
|
||||||
* @param {number} value The value of the feature as percentage change
|
|
||||||
* @returns True if the value is beneficial
|
|
||||||
*/
|
|
||||||
export function isChangeValueBeneficial(feature, value) {
|
|
||||||
let changeHigherBetter = STATS_FORMATTING[feature].higherbetter;
|
|
||||||
if (changeHigherBetter === undefined) {
|
|
||||||
return isValueBeneficial(feature, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changeHigherBetter) {
|
|
||||||
return value > 0;
|
|
||||||
} else {
|
|
||||||
return value < 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a blueprint with a given name and an optional module
|
* Get a blueprint with a given name and an optional module
|
||||||
* @param {string} name The name of the blueprint
|
* @param {string} name The name of the blueprint
|
||||||
@@ -327,43 +307,26 @@ export function setPercent(ship, m, percent) {
|
|||||||
ship.clearModifications(m);
|
ship.clearModifications(m);
|
||||||
// Pick given value as multiplier
|
// Pick given value as multiplier
|
||||||
const mult = percent / 100;
|
const mult = percent / 100;
|
||||||
setQualityCB(m.blueprint, mult, (featureName, value) => ship.setModification(m, featureName, value));
|
const features = m.blueprint.grades[m.blueprint.grade].features;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the blueprint quality and fires a callback for each property affected.
|
|
||||||
* @param {Object} blueprint The ship for which to perform the modifications
|
|
||||||
* @param {Number} quality The quality to apply - float number 0 to 1.
|
|
||||||
* @param {Function} cb The Callback to run for each property. Function (featureName, value)
|
|
||||||
*/
|
|
||||||
export function setQualityCB(blueprint, quality, cb) {
|
|
||||||
// Pick given value as multiplier
|
|
||||||
const features = blueprint.grades[blueprint.grade].features;
|
|
||||||
for (const featureName in features) {
|
for (const featureName in features) {
|
||||||
let value;
|
let value;
|
||||||
if (Modifications.modifications[featureName].higherbetter) {
|
if (Modifications.modifications[featureName].higherbetter) {
|
||||||
// Higher is better, but is this making it better or worse?
|
// Higher is better, but is this making it better or worse?
|
||||||
if (features[featureName][0] < 0 || (features[featureName][0] === 0 && features[featureName][1] < 0)) {
|
if (features[featureName][0] < 0 || (features[featureName][0] === 0 && features[featureName][1] < 0)) {
|
||||||
value = features[featureName][1] + ((features[featureName][0] - features[featureName][1]) * quality);
|
value = features[featureName][1] + ((features[featureName][0] - features[featureName][1]) * mult);
|
||||||
} else {
|
} else {
|
||||||
value = features[featureName][0] + ((features[featureName][1] - features[featureName][0]) * quality);
|
value = features[featureName][0] + ((features[featureName][1] - features[featureName][0]) * mult);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Higher is worse, but is this making it better or worse?
|
// Higher is worse, but is this making it better or worse?
|
||||||
if (features[featureName][0] < 0 || (features[featureName][0] === 0 && features[featureName][1] < 0)) {
|
if (features[featureName][0] < 0 || (features[featureName][0] === 0 && features[featureName][1] < 0)) {
|
||||||
value = features[featureName][0] + ((features[featureName][1] - features[featureName][0]) * quality);
|
value = features[featureName][0] + ((features[featureName][1] - features[featureName][0]) * mult);
|
||||||
} else {
|
} else {
|
||||||
value = features[featureName][1] + ((features[featureName][0] - features[featureName][1]) * quality);
|
value = features[featureName][1] + ((features[featureName][0] - features[featureName][1]) * mult);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Modifications.modifications[featureName].type == 'percentage') {
|
_setValue(ship, m, featureName, value);
|
||||||
value = value * 10000;
|
|
||||||
} else if (Modifications.modifications[featureName].type == 'numeric') {
|
|
||||||
value = value * 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
cb(featureName, value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -377,6 +340,23 @@ export function setRandom(ship, m) {
|
|||||||
setPercent(ship, m, Math.random() * 100);
|
setPercent(ship, m, Math.random() * 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a modification feature value
|
||||||
|
* @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
|
||||||
|
*/
|
||||||
|
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') {
|
||||||
|
ship.setModification(m, featureName, value * 100);
|
||||||
|
} else {
|
||||||
|
ship.setModification(m, featureName, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provide 'percent' primary query
|
* Provide 'percent' primary query
|
||||||
* @param {Object} m The module for which to perform the query
|
* @param {Object} m The module for which to perform the query
|
||||||
@@ -392,7 +372,9 @@ export function getPercent(m) {
|
|||||||
|
|
||||||
let value = _getValue(m, featureName);
|
let value = _getValue(m, featureName);
|
||||||
let mult;
|
let mult;
|
||||||
if (Modifications.modifications[featureName].higherbetter) {
|
if (featureName == 'shieldboost') {
|
||||||
|
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?
|
// Higher is better, but is this making it better or worse?
|
||||||
if (features[featureName][0] < 0 || (features[featureName][0] === 0 && features[featureName][1] < 0)) {
|
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);
|
mult = Math.round((value - features[featureName][1]) / (features[featureName][0] - features[featureName][1]) * 100);
|
||||||
|
|||||||
@@ -30,11 +30,8 @@ export const SHIP_FD_NAME_TO_CORIOLIS_NAME = {
|
|||||||
'Hauler': 'hauler',
|
'Hauler': 'hauler',
|
||||||
'Independant_Trader': 'keelback',
|
'Independant_Trader': 'keelback',
|
||||||
'Krait_MkII': 'krait_mkii',
|
'Krait_MkII': 'krait_mkii',
|
||||||
'Mamba': 'mamba',
|
|
||||||
'Krait_Light': 'krait_phantom',
|
|
||||||
'Orca': 'orca',
|
'Orca': 'orca',
|
||||||
'Python': 'python',
|
'Python': 'python',
|
||||||
'Python_nx': 'python_nx',
|
|
||||||
'SideWinder': 'sidewinder',
|
'SideWinder': 'sidewinder',
|
||||||
'Type6': 'type_6_transporter',
|
'Type6': 'type_6_transporter',
|
||||||
'Type7': 'type_7_transport',
|
'Type7': 'type_7_transport',
|
||||||
|
|||||||
@@ -4,23 +4,7 @@ import { Ships } from 'coriolis-data/dist';
|
|||||||
import Module from '../shipyard/Module';
|
import Module from '../shipyard/Module';
|
||||||
import { Modules } from 'coriolis-data/dist';
|
import { Modules } from 'coriolis-data/dist';
|
||||||
import { Modifications } from 'coriolis-data/dist';
|
import { Modifications } from 'coriolis-data/dist';
|
||||||
import { getBlueprint, setQualityCB } from './BlueprintFunctions';
|
import { getBlueprint } from './BlueprintFunctions';
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if an imported module is valid
|
|
||||||
* @param {Object} module the module to check
|
|
||||||
* @param {Object} moduleType the type of module to check
|
|
||||||
* @return {boolean} true if the module is valid
|
|
||||||
*/
|
|
||||||
function _isValidImportedModule(module, moduleType) {
|
|
||||||
// First of all, has the _moduleFromFdName function returned 'null'?
|
|
||||||
if (!module){
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Obtain a module given its FD Name
|
* Obtain a module given its FD Name
|
||||||
@@ -111,93 +95,52 @@ export function shipFromLoadoutJSON(json) {
|
|||||||
throw 'Unknown bulkheads "' + module.Item + '"';
|
throw 'Unknown bulkheads "' + module.Item + '"';
|
||||||
}
|
}
|
||||||
ship.bulkheads.enabled = true;
|
ship.bulkheads.enabled = true;
|
||||||
if (module.Engineering) _addModifications(ship.bulkheads.m, module.Engineering.Modifiers, module.Engineering.Quality, module.Engineering.BlueprintName, module.Engineering.Level, module.Engineering.ExperimentalEffect);
|
if (module.Engineering) _addModifications(ship.bulkheads.m, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level, module.Engineering.ExperimentalEffect);
|
||||||
break;
|
break;
|
||||||
case 'powerplant':
|
case 'powerplant':
|
||||||
let powerplant = _moduleFromFdName(module.Item);
|
const powerplant = _moduleFromFdName(module.Item);
|
||||||
// Check the powerplant returned is valid
|
|
||||||
if (!_isValidImportedModule(powerplant, 'powerplant'))
|
|
||||||
{
|
|
||||||
powerplant = _moduleFromFdName('Int_Missing_Powerplant');
|
|
||||||
module.Engineering = null;
|
|
||||||
}
|
|
||||||
ship.use(ship.standard[0], powerplant, true);
|
ship.use(ship.standard[0], powerplant, true);
|
||||||
ship.standard[0].enabled = module.On;
|
ship.standard[0].enabled = module.On;
|
||||||
ship.standard[0].priority = module.Priority;
|
ship.standard[0].priority = module.Priority;
|
||||||
if (module.Engineering) _addModifications(powerplant, module.Engineering.Modifiers, module.Engineering.Quality, module.Engineering.BlueprintName, module.Engineering.Level, module.Engineering.ExperimentalEffect);
|
if (module.Engineering) _addModifications(powerplant, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level, module.Engineering.ExperimentalEffect);
|
||||||
break;
|
break;
|
||||||
case 'mainengines':
|
case 'mainengines':
|
||||||
let thrusters = _moduleFromFdName(module.Item);
|
const thrusters = _moduleFromFdName(module.Item);
|
||||||
// Check the thrusters returned is valid
|
|
||||||
if (!_isValidImportedModule(thrusters, 'thrusters'))
|
|
||||||
{
|
|
||||||
thrusters = _moduleFromFdName('Int_Missing_Engine');
|
|
||||||
module.Engineering = null;
|
|
||||||
}
|
|
||||||
ship.use(ship.standard[1], thrusters, true);
|
ship.use(ship.standard[1], thrusters, true);
|
||||||
ship.standard[1].enabled = module.On;
|
ship.standard[1].enabled = module.On;
|
||||||
ship.standard[1].priority = module.Priority;
|
ship.standard[1].priority = module.Priority;
|
||||||
if (module.Engineering) _addModifications(thrusters, module.Engineering.Modifiers, module.Engineering.Quality, module.Engineering.BlueprintName, module.Engineering.Level, module.Engineering.ExperimentalEffect);
|
if (module.Engineering) _addModifications(thrusters, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level, module.Engineering.ExperimentalEffect);
|
||||||
break;
|
break;
|
||||||
case 'frameshiftdrive':
|
case 'frameshiftdrive':
|
||||||
let frameshiftdrive = _moduleFromFdName(module.Item);
|
const frameshiftdrive = _moduleFromFdName(module.Item);
|
||||||
// Check the frameshiftdrive returned is valid
|
|
||||||
if (!_isValidImportedModule(frameshiftdrive, 'frameshiftdrive'))
|
|
||||||
{
|
|
||||||
frameshiftdrive = _moduleFromFdName('Int_Missing_Hyperdrive');
|
|
||||||
module.Engineering = null;
|
|
||||||
}
|
|
||||||
ship.use(ship.standard[2], frameshiftdrive, true);
|
ship.use(ship.standard[2], frameshiftdrive, true);
|
||||||
ship.standard[2].enabled = module.On;
|
ship.standard[2].enabled = module.On;
|
||||||
ship.standard[2].priority = module.Priority;
|
ship.standard[2].priority = module.Priority;
|
||||||
if (module.Engineering) _addModifications(frameshiftdrive, module.Engineering.Modifiers, module.Engineering.Quality, module.Engineering.BlueprintName, module.Engineering.Level, module.Engineering.ExperimentalEffect);
|
if (module.Engineering) _addModifications(frameshiftdrive, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level, module.Engineering.ExperimentalEffect);
|
||||||
break;
|
break;
|
||||||
case 'lifesupport':
|
case 'lifesupport':
|
||||||
let lifesupport = _moduleFromFdName(module.Item);
|
const lifesupport = _moduleFromFdName(module.Item);
|
||||||
// Check the lifesupport returned is valid
|
|
||||||
if (!_isValidImportedModule(lifesupport, 'lifesupport'))
|
|
||||||
{
|
|
||||||
lifesupport = _moduleFromFdName('Int_Missing_LifeSupport');
|
|
||||||
module.Engineering = null;
|
|
||||||
}
|
|
||||||
ship.use(ship.standard[3], lifesupport, true);
|
ship.use(ship.standard[3], lifesupport, true);
|
||||||
ship.standard[3].enabled = module.On === true;
|
ship.standard[3].enabled = module.On === true;
|
||||||
ship.standard[3].priority = module.Priority;
|
ship.standard[3].priority = module.Priority;
|
||||||
if (module.Engineering) _addModifications(lifesupport, module.Engineering.Modifiers, module.Engineering.Quality, module.Engineering.BlueprintName, module.Engineering.Level, module.Engineering.ExperimentalEffect);
|
if (module.Engineering) _addModifications(lifesupport, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level, module.Engineering.ExperimentalEffect);
|
||||||
break;
|
break;
|
||||||
case 'powerdistributor':
|
case 'powerdistributor':
|
||||||
let powerdistributor = _moduleFromFdName(module.Item);
|
const powerdistributor = _moduleFromFdName(module.Item);
|
||||||
// Check the powerdistributor returned is valid
|
|
||||||
if (!_isValidImportedModule(powerdistributor, 'powerdistributor'))
|
|
||||||
{
|
|
||||||
powerdistributor = _moduleFromFdName('Int_Missing_PowerDistributor');
|
|
||||||
module.Engineering = null;
|
|
||||||
}
|
|
||||||
ship.use(ship.standard[4], powerdistributor, true);
|
ship.use(ship.standard[4], powerdistributor, true);
|
||||||
ship.standard[4].enabled = module.On;
|
ship.standard[4].enabled = module.On;
|
||||||
ship.standard[4].priority = module.Priority;
|
ship.standard[4].priority = module.Priority;
|
||||||
if (module.Engineering) _addModifications(powerdistributor, module.Engineering.Modifiers, module.Engineering.Quality, module.Engineering.BlueprintName, module.Engineering.Level, module.Engineering.ExperimentalEffect);
|
if (module.Engineering) _addModifications(powerdistributor, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level, module.Engineering.ExperimentalEffect);
|
||||||
break;
|
break;
|
||||||
case 'radar':
|
case 'radar':
|
||||||
let sensors = _moduleFromFdName(module.Item);
|
const sensors = _moduleFromFdName(module.Item);
|
||||||
// Check the sensors returned is valid
|
|
||||||
if (!_isValidImportedModule(sensors, 'sensors'))
|
|
||||||
{
|
|
||||||
sensors = _moduleFromFdName('Int_Missing_Sensors');
|
|
||||||
module.Engineering = null;
|
|
||||||
}
|
|
||||||
ship.use(ship.standard[5], sensors, true);
|
ship.use(ship.standard[5], sensors, true);
|
||||||
ship.standard[5].enabled = module.On;
|
ship.standard[5].enabled = module.On;
|
||||||
ship.standard[5].priority = module.Priority;
|
ship.standard[5].priority = module.Priority;
|
||||||
if (module.Engineering) _addModifications(sensors, module.Engineering.Modifiers, module.Engineering.Quality, module.Engineering.BlueprintName, module.Engineering.Level, module.Engineering.ExperimentalEffect);
|
if (module.Engineering) _addModifications(sensors, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level, module.Engineering.ExperimentalEffect);
|
||||||
break;
|
break;
|
||||||
case 'fueltank':
|
case 'fueltank':
|
||||||
let fueltank = _moduleFromFdName(module.Item);
|
const fueltank = _moduleFromFdName(module.Item);
|
||||||
// Check the fueltank returned is valid
|
|
||||||
if (!_isValidImportedModule(fueltank, 'fueltank'))
|
|
||||||
{
|
|
||||||
fueltank = _moduleFromFdName('Int_Missing_FuelTank');
|
|
||||||
}
|
|
||||||
ship.use(ship.standard[6], fueltank, true);
|
ship.use(ship.standard[6], fueltank, true);
|
||||||
ship.standard[6].enabled = true;
|
ship.standard[6].enabled = true;
|
||||||
ship.standard[6].priority = 0;
|
ship.standard[6].priority = 0;
|
||||||
@@ -225,29 +168,14 @@ export function shipFromLoadoutJSON(json) {
|
|||||||
const hardpointSlot = json.Modules.find(elem => elem.Slot.toLowerCase() === hardpointName.toLowerCase());
|
const hardpointSlot = json.Modules.find(elem => elem.Slot.toLowerCase() === hardpointName.toLowerCase());
|
||||||
if (!hardpointSlot) {
|
if (!hardpointSlot) {
|
||||||
// This can happen with old imports that don't contain new hardpoints
|
// This can happen with old imports that don't contain new hardpoints
|
||||||
|
} else if (!hardpointSlot) {
|
||||||
|
// No module
|
||||||
} else {
|
} else {
|
||||||
hardpoint = _moduleFromFdName(hardpointSlot.Item);
|
hardpoint = _moduleFromFdName(hardpointSlot.Item);
|
||||||
// Check the hardpoint module returned is valid
|
ship.use(ship.hardpoints[hardpointArrayNum], hardpoint, true);
|
||||||
if (!_isValidImportedModule(hardpoint, 'hardpoint')){
|
ship.hardpoints[hardpointArrayNum].enabled = hardpointSlot.On;
|
||||||
// Check if it's a Utility or Hardpoint
|
ship.hardpoints[hardpointArrayNum].priority = hardpointSlot.Priority;
|
||||||
if (hardpointSlot.Slot.toLowerCase().search(/tiny/))
|
modsToAdd.push({ coriolisMod: hardpoint, json: hardpointSlot });
|
||||||
{
|
|
||||||
// Use the missing_hardpoint module 'Missing Hardpoint' which will inform the user that the module is missing
|
|
||||||
hardpoint = _moduleFromFdName('Hpt_Missing_Hardpoint');
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Use the missing_hardpoint module 'Missing Utility' which will inform the user that the module is missing
|
|
||||||
hardpoint = _moduleFromFdName('Hpt_Missing_Utility');
|
|
||||||
}
|
|
||||||
ship.use(ship.hardpoints[hardpointArrayNum], hardpoint, true);
|
|
||||||
ship.hardpoints[hardpointArrayNum].enabled = hardpointSlot.On;
|
|
||||||
ship.hardpoints[hardpointArrayNum].priority = hardpointSlot.Priority;
|
|
||||||
} else {
|
|
||||||
ship.use(ship.hardpoints[hardpointArrayNum], hardpoint, true);
|
|
||||||
ship.hardpoints[hardpointArrayNum].enabled = hardpointSlot.On;
|
|
||||||
ship.hardpoints[hardpointArrayNum].priority = hardpointSlot.Priority;
|
|
||||||
modsToAdd.push({ coriolisMod: hardpoint, json: hardpointSlot });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
hardpointArrayNum++;
|
hardpointArrayNum++;
|
||||||
}
|
}
|
||||||
@@ -261,17 +189,13 @@ export function shipFromLoadoutJSON(json) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const isMilitary = isNaN(shipTemplate.slots.internal[i]) ? shipTemplate.slots.internal[i].name == 'Military' : false;
|
const isMilitary = isNaN(shipTemplate.slots.internal[i]) ? shipTemplate.slots.internal[i].name == 'Military' : false;
|
||||||
const isPlanetary = isNaN(shipTemplate.slots.internal[i]) ? shipTemplate.slots.internal[i].name == 'PlanetaryApproachSuite' : false;
|
|
||||||
|
|
||||||
// The internal slot might be a standard or a military slot, or a planetary slot. Military and Planetary slots have a different naming system
|
// The internal slot might be a standard or a military slot. Military slots have a different naming system
|
||||||
let internalSlot = null;
|
let internalSlot = null;
|
||||||
if (isMilitary) {
|
if (isMilitary) {
|
||||||
const internalName = 'Military0' + militarySlotNum;
|
const internalName = 'Military0' + militarySlotNum;
|
||||||
internalSlot = json.Modules.find(elem => elem.Slot.toLowerCase() === internalName.toLowerCase());
|
internalSlot = json.Modules.find(elem => elem.Slot.toLowerCase() === internalName.toLowerCase());
|
||||||
militarySlotNum++;
|
militarySlotNum++;
|
||||||
} else if (isPlanetary) {
|
|
||||||
const internalName = 'PlanetaryApproachSuite';
|
|
||||||
internalSlot = json.Modules.find(elem => elem.Slot.toLowerCase() === internalName.toLowerCase());
|
|
||||||
} else {
|
} else {
|
||||||
// Slot numbers are not contiguous so handle skips.
|
// Slot numbers are not contiguous so handle skips.
|
||||||
for (; internalSlot === null && internalSlotNum < 99; internalSlotNum++) {
|
for (; internalSlot === null && internalSlotNum < 99; internalSlotNum++) {
|
||||||
@@ -290,28 +214,17 @@ export function shipFromLoadoutJSON(json) {
|
|||||||
// This can happen with old imports that don't contain new slots
|
// This can happen with old imports that don't contain new slots
|
||||||
} else {
|
} else {
|
||||||
const internalJson = internalSlot;
|
const internalJson = internalSlot;
|
||||||
let internal = _moduleFromFdName(internalJson.Item);
|
const internal = _moduleFromFdName(internalJson.Item);
|
||||||
// Check the internal module returned is valid
|
ship.use(ship.internal[i], internal, true);
|
||||||
if (!_isValidImportedModule(internal, 'internal'))
|
ship.internal[i].enabled = internalJson.On === true;
|
||||||
{
|
ship.internal[i].priority = internalJson.Priority;
|
||||||
internal = _moduleFromFdName('Int_Missing_Module');
|
modsToAdd.push({ coriolisMod: internal, json: internalSlot });
|
||||||
ship.use(ship.internal[i], internal, true);
|
|
||||||
ship.internal[i].enabled = internalJson.On === true;
|
|
||||||
ship.internal[i].priority = internalJson.Priority;
|
|
||||||
//throw 'Unknown internal module: "' + module.Item + '"';
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ship.use(ship.internal[i], internal, true);
|
|
||||||
ship.internal[i].enabled = internalJson.On === true;
|
|
||||||
ship.internal[i].priority = internalJson.Priority;
|
|
||||||
modsToAdd.push({ coriolisMod: internal, json: internalSlot });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const i of modsToAdd) {
|
for (const i of modsToAdd) {
|
||||||
if (i.json.Engineering) {
|
if (i.json.Engineering) {
|
||||||
_addModifications(i.coriolisMod, i.json.Engineering.Modifiers, i.json.Engineering.Quality, i.json.Engineering.BlueprintName, i.json.Engineering.Level, i.json.Engineering.ExperimentalEffect);
|
_addModifications(i.coriolisMod, i.json.Engineering.Modifiers, i.json.Engineering.BlueprintName, i.json.Engineering.Level, i.json.Engineering.ExperimentalEffect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// We don't have any information on it so guess it's priority 5 and disabled
|
// We don't have any information on it so guess it's priority 5 and disabled
|
||||||
@@ -328,22 +241,14 @@ export function shipFromLoadoutJSON(json) {
|
|||||||
* Add the modifications for a module
|
* Add the modifications for a module
|
||||||
* @param {Module} module the module
|
* @param {Module} module the module
|
||||||
* @param {Object} modifiers the modifiers
|
* @param {Object} modifiers the modifiers
|
||||||
* @param {float} quality quality of the modifiers 0 to 1
|
|
||||||
* @param {Object} blueprint the blueprint of the modification
|
* @param {Object} blueprint the blueprint of the modification
|
||||||
* @param {Object} grade the grade of the modification
|
* @param {Object} grade the grade of the modification
|
||||||
* @param {Object} specialModifications special modification
|
* @param {Object} specialModifications special modification
|
||||||
*/
|
*/
|
||||||
function _addModifications(module, modifiers, quality, blueprint, grade, specialModifications) {
|
function _addModifications(module, modifiers, blueprint, grade, specialModifications) {
|
||||||
if (!modifiers && !quality) 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
|
||||||
@@ -356,40 +261,33 @@ function _addModifications(module, modifiers, quality, blueprint, grade, special
|
|||||||
module.blueprint.special = special;
|
module.blueprint.special = special;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (modifiers) {
|
for (const i in modifiers) {
|
||||||
for (const i in modifiers) {
|
// Some special modifications
|
||||||
// Some special modifications
|
// Look up the modifiers to find what we need to do
|
||||||
// Look up the modifiers to find what we need to do
|
const findMod = val => Object.keys(Modifications.modifierActions).find(elem => elem.toString().toLowerCase().replace(/(outfittingfieldtype_|persecond)/igm, '') === val.toString().toLowerCase().replace(/(outfittingfieldtype_|persecond)/igm, ''));
|
||||||
const findMod = val => Object.keys(Modifications.modifierActions).find(elem => elem.toString().toLowerCase().replace(/(outfittingfieldtype_|persecond)/igm, '') === val.toString().toLowerCase().replace(/(outfittingfieldtype_|persecond)/igm, ''));
|
const modifierActions = Modifications.modifierActions[findMod(modifiers[i].Label)];
|
||||||
const modifierActions = Modifications.modifierActions[findMod(modifiers[i].Label)];
|
// TODO: Figure out how to scale this value.
|
||||||
// TODO: Figure out how to scale this value.
|
if (!!modifiers[i].LessIsGood) {
|
||||||
if (!!modifiers[i].LessIsGood) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
let value = (modifiers[i].Value / modifiers[i].OriginalValue * 100 - 100) * 100;
|
let value = (modifiers[i].Value / modifiers[i].OriginalValue * 100 - 100) * 100;
|
||||||
if (value === Infinity) {
|
if (value === Infinity) {
|
||||||
value = modifiers[i].Value * 100;
|
value = modifiers[i].Value * 100;
|
||||||
}
|
}
|
||||||
if (modifiers[i].Label.search('DamageFalloffRange') >= 0) {
|
if (modifiers[i].Label.search('Resistance') >= 0) {
|
||||||
value = (modifiers[i].Value / module.range - 1) * 100;
|
value = (modifiers[i].Value * 100) - (modifiers[i].OriginalValue * 100);
|
||||||
}
|
}
|
||||||
if (modifiers[i].Label.search('Resistance') >= 0) {
|
if (modifiers[i].Label.search('ShieldMultiplier') >= 0 || modifiers[i].Label.search('DefenceModifierHealthMultiplier') >= 0) {
|
||||||
value = (modifiers[i].Value * 100) - (modifiers[i].OriginalValue * 100);
|
value = ((100 + modifiers[i].Value) / (100 + modifiers[i].OriginalValue) * 100 - 100) * 100;
|
||||||
}
|
}
|
||||||
if (modifiers[i].Label.search('ShieldMultiplier') >= 0 || modifiers[i].Label.search('DefenceModifierHealthMultiplier') >= 0) {
|
|
||||||
value = ((100 + modifiers[i].Value) / (100 + modifiers[i].OriginalValue) * 100 - 100) * 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Carry out the required changes
|
// Carry out the required changes
|
||||||
for (const action in modifierActions) {
|
for (const action in modifierActions) {
|
||||||
if (isNaN(modifierActions[action])) {
|
if (isNaN(modifierActions[action])) {
|
||||||
module.setModValue(action, modifierActions[action]);
|
module.setModValue(action, modifierActions[action]);
|
||||||
} else {
|
} else {
|
||||||
module.setModValue(action, value, true);
|
module.setModValue(action, value, true);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (quality) {
|
|
||||||
setQualityCB(module.blueprint, quality, (featureName, value) => module.setModValue(featureName, value, false));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>);
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<script src="xdLocalStoragePostMessageApi.min.js"></script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
This is the magical iframe
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,21 +1,16 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html manifest="/">
|
||||||
<head>
|
<head>
|
||||||
<title>Coriolis EDCD Edition</title>
|
<title>Coriolis EDCD Edition</title>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<link rel="stylesheet" href="<%= htmlWebpackPlugin.files.css[0] %>">
|
<link rel="stylesheet" href="<%= htmlWebpackPlugin.files.css[0] %>">
|
||||||
<!-- Standard headers -->
|
<!-- Standard headers -->
|
||||||
<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, maximum-scale=1.0, user-scalable=0">
|
||||||
|
|
||||||
<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="manifest" href="/manifest.json">
|
||||||
<link rel="shortcut icon" href=/favicon2.ico>
|
<link rel="shortcut icon" href=/favicon2.ico>
|
||||||
<link rel="icon" sizes="152x152 192x192" type="image/png"
|
<link rel="icon" sizes="152x152 192x192" type="image/png" href="/192x192.png">
|
||||||
href="/192x192.png">
|
|
||||||
|
|
||||||
<!-- Apple/iOS headers -->
|
<!-- Apple/iOS headers -->
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||||
@@ -27,25 +22,49 @@
|
|||||||
<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.dataLayer = window.dataLayer || [];
|
window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
|
||||||
function gtag(){dataLayer.push(arguments);}
|
ga('create', '<%- htmlWebpackPlugin.options.uaTracking %>', 'auto');
|
||||||
gtag('js', new Date());
|
ga('send', 'pageview');
|
||||||
gtag('config', 'UA-55840909-18');
|
</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 -->
|
||||||
|
<script src="//d2wy8f7a9ursnm.cloudfront.net/v4/bugsnag.min.js"></script>
|
||||||
|
<script src="//d2wy8f7a9ursnm.cloudfront.net/bugsnag-plugins/v1/bugsnag-react.min.js"></script>
|
||||||
|
<script>
|
||||||
|
window.bugsnagClient = bugsnag('ba9fae819372850fb660755341fa6ef5', {appVersion: window.BUGSNAG_VERSION || undefined})
|
||||||
|
window.Bugsnag = window.bugsnagClient
|
||||||
</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>
|
||||||
|
|||||||
@@ -171,16 +171,3 @@ footer {
|
|||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.announcement-container {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding-top: 10px;
|
|
||||||
justify-content: center;
|
|
||||||
flex-flow: row wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.announcement {
|
|
||||||
border: 1px @secondary solid;
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user