From 9c421796173e428f4500a45ea2c738b9f0f5be87 Mon Sep 17 00:00:00 2001 From: Cmdr McDonald Date: Wed, 12 Oct 2016 11:48:42 +0100 Subject: [PATCH 1/4] Handle fighter bays and luxury passenger cabins --- src/app/components/InternalSlotSection.jsx | 4 ++-- src/app/i18n/en.js | 5 +++++ src/app/shipyard/Constants.js | 5 +++++ src/app/shipyard/ModuleSet.js | 9 ++++++++- src/app/shipyard/Ship.js | 2 +- src/app/shipyard/ShipRoles.js | 12 ++++++------ src/app/utils/SlotFunctions.js | 11 ++++++++--- 7 files changed, 35 insertions(+), 13 deletions(-) diff --git a/src/app/components/InternalSlotSection.jsx b/src/app/components/InternalSlotSection.jsx index 9a85215d..f35d81e4 100644 --- a/src/app/components/InternalSlotSection.jsx +++ b/src/app/components/InternalSlotSection.jsx @@ -58,7 +58,7 @@ export default class InternalSlotSection extends SlotSection { let ship = this.props.ship; let chargeCap = 0; // Capacity of single activation ship.internal.forEach(function(slot) { - if ((!slot.m || (clobber && !ModuleUtils.isShieldGenerator(slot.m.grp))) && (!slot.eligible || slot.eligible.scb)) { // Check eligibility due to Orca special case + if ((!slot.m || (clobber && !ModuleUtils.isShieldGenerator(slot.m.grp))) && (!slot.eligible || slot.eligible.scb)) { // Check eligibility due to passenger ships special case ship.use(slot, ModuleUtils.findInternal('scb', slot.maxClass, 'A')); ship.setSlotEnabled(slot, chargeCap <= ship.shieldStrength); // Don't waste cell capacity on overcharge chargeCap += slot.m.recharge; @@ -108,7 +108,7 @@ export default class InternalSlotSection extends SlotSection { slots.push( availableModules.getInts(s.maxClass, s.eligible)} + availableModules={() => availableModules.getInts(ship, s.maxClass, s.eligible)} onOpen={this._openMenu.bind(this,s)} onSelect={this._selectModule.bind(this, s)} selected={currentMenu == s} diff --git a/src/app/i18n/en.js b/src/app/i18n/en.js index 7756bd1f..c29d0436 100644 --- a/src/app/i18n/en.js +++ b/src/app/i18n/en.js @@ -42,6 +42,7 @@ export const terms = { cs: 'Cargo Scanner', dc: 'Docking Computer', fc: 'Fragment Cannon', + fh: 'Fighter Hangar', fi: 'FSD Interdictor', fs: 'Fuel Scoop', fsd: 'Frame Shift Drive', @@ -58,6 +59,10 @@ export const terms = { pa: 'Plasma Accelerator', pas: 'Planetary Approach Suite', pc: 'Prospector Limpet Controller', + pce: 'Economy Class Passenger Cabin', + pci: 'Business Class Passenger Cabin', + pcm: 'First Class Passenger Cabin', + pcq: 'Luxury Passenger Cabin', pd: 'power distributor', pl: 'Pulse Laser', pp: 'Power Plant', diff --git a/src/app/shipyard/Constants.js b/src/app/shipyard/Constants.js index 19b7ac07..70688066 100755 --- a/src/app/shipyard/Constants.js +++ b/src/app/shipyard/Constants.js @@ -37,6 +37,7 @@ export const ModuleGroupToName = { am: 'Auto Field-Maintenance Unit', bsg: 'Bi-Weave Shield Generator', cr: 'Cargo Rack', + fh: 'Fighter Hangar', fi: 'Frame Shift Drive Interdictor', hb: 'Hatch Breaker Limpet Controller', hr: 'Hull Reinforcement Package', @@ -48,6 +49,10 @@ export const ModuleGroupToName = { dc: 'Docking Computer', fx: 'Fuel Transfer Limpet Controller', pc: 'Prospector Limpet Controller', + pce: 'Economy Class Passenger Cabin', + pci: 'Business Class Passenger Cabin', + pcm: 'First Class Passenger Cabin', + pcq: 'Luxury Passenger Cabin', cc: 'Collector Limpet Controller', // Hard Points diff --git a/src/app/shipyard/ModuleSet.js b/src/app/shipyard/ModuleSet.js index 601bc33b..04711cb8 100755 --- a/src/app/shipyard/ModuleSet.js +++ b/src/app/shipyard/ModuleSet.js @@ -71,16 +71,23 @@ export default class ModuleSet { /** * Determine the modules that areeligible for an internal slot + * @param {Object} ship The ship * @param {integer} c The max class module that can be mounted in the slot * @param {Object} eligible) The map of eligible internal groups * @return {object} A map of all eligible modules by group */ - getInts(c, eligible) { + getInts(ship, c, eligible) { let o = {}; for (let key in this.internal) { if (eligible && !eligible[key]) { continue; } + if (key == 'pcq' && !(ship.luxuryCabins && ship.luxuryCabins === true)) { + continue; + } + if (key == 'fh' && !(ship.fighterHangars && ship.fighterHangars === true)) { + continue; + } let data = filter(this.internal[key], c, 0, this.mass); if (data.length) { // If group is not empty o[key] = data; diff --git a/src/app/shipyard/Ship.js b/src/app/shipyard/Ship.js index 9984e358..3b006005 100755 --- a/src/app/shipyard/Ship.js +++ b/src/app/shipyard/Ship.js @@ -3,7 +3,7 @@ import * as Calc from './Calculations'; import * as ModuleUtils from './ModuleUtils'; import LZString from 'lz-string'; -const UNIQUE_MODULES = ['psg', 'sg', 'bsg', 'rf', 'fs']; +const UNIQUE_MODULES = ['psg', 'sg', 'bsg', 'rf', 'fs', 'fh']; /** * Returns the power usage type of a slot and it's particular modul diff --git a/src/app/shipyard/ShipRoles.js b/src/app/shipyard/ShipRoles.js index 7fbaefd2..fc06fbe0 100644 --- a/src/app/shipyard/ShipRoles.js +++ b/src/app/shipyard/ShipRoles.js @@ -15,7 +15,7 @@ export function multiPurpose(ship, shielded, bulkheadIndex) { if (shielded) { ship.internal.some(function(slot) { - if (canMount(slot, 'sg')) { // Assuming largest slot can hold an eligible shield + if (canMount(ship, slot, 'sg')) { // Assuming largest slot can hold an eligible shield ship.use(slot, ModuleUtils.findInternal('sg', slot.maxClass, 'A')); ship.setSlotEnabled(slot, true); return true; @@ -35,7 +35,7 @@ export function trader(ship, shielded, standardOpts) { for (let i = ship.internal.length; i--;) { let slot = ship.internal[i]; - if (sg && canMount(slot, 'sg', sg.class)) { + if (sg && canMount(ship, slot, 'sg', sg.class)) { ship.use(slot, sg); sg = null; } else { @@ -77,23 +77,23 @@ export function explorer(ship, planetary) { let slot = ship.internal[i]; let nextSlot = (i + 1) < intLength ? ship.internal[i + 1] : null; // Fit best possible Fuel Scoop - if (!fuelScoopSlot && canMount(slot, 'fs')) { + if (!fuelScoopSlot && canMount(ship, slot, 'fs')) { fuelScoopSlot = slot; ship.use(slot, ModuleUtils.findInternal('fs', slot.maxClass, 'A')); ship.setSlotEnabled(slot, true); // Mount a Shield generator if possible AND an AFM Unit has been mounted already (Guarantees at least 1 AFM Unit) - } else if (!sgSlot && shieldNext && canMount(slot, 'sg', sg.class) && !canMount(nextSlot, 'sg', sg.class)) { + } else if (!sgSlot && shieldNext && canMount(ship, slot, 'sg', sg.class) && !canMount(ship, nextSlot, 'sg', sg.class)) { sgSlot = slot; shieldNext = false; ship.use(slot, sg); ship.setSlotEnabled(slot, true); // if planetary explorer and the next slot cannot mount a PVH or the next modul to mount is a SG - } else if (planetary && !pvhSlot && canMount(slot, 'pv') && (shieldNext || !canMount(nextSlot, 'pv', 2))) { + } else if (planetary && !pvhSlot && canMount(ship, slot, 'pv') && (shieldNext || !canMount(ship, nextSlot, 'pv', 2))) { pvhSlot = slot; ship.use(slot, ModuleUtils.findInternal('pv', Math.min(Math.floor(pvhSlot.maxClass / 2) * 2, 6), 'G')); ship.setSlotEnabled(slot, false); // Disabled power for PVH shieldNext = !sgSlot; - } else if (afmUnitCount > 0 && canMount(slot, 'am')) { + } else if (afmUnitCount > 0 && canMount(ship, slot, 'am')) { afmUnitCount--; ship.use(slot, ModuleUtils.findInternal('am', slot.maxClass, 'A')); ship.setSlotEnabled(slot, false); // Disabled power for AFM Unit diff --git a/src/app/utils/SlotFunctions.js b/src/app/utils/SlotFunctions.js index ed47d4dc..d0bb60ea 100644 --- a/src/app/utils/SlotFunctions.js +++ b/src/app/utils/SlotFunctions.js @@ -5,14 +5,19 @@ import { Infinite } from '../components/SvgIcons'; import Persist from '../stores/Persist'; /** - * Determine if a slot 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 + * @param {Object} ship Ship object * @param {Object} slot Slot object * @param {String} group Module group/type abbrivation/code * @param {Integer} clazz [Optional] Module Class/Size * @return {Boolean} True if the slot can mount the module */ -export function canMount(slot, group, clazz) { - if (slot && (!slot.eligible || slot.eligible[group]) && (clazz === undefined || slot.maxClass >= clazz)) { +export function canMount(ship, slot, group, clazz) { + if (slot + && (!slot.eligible || slot.eligible[group]) + && (group != 'pcq' || (ship.luxuryCabins && ship.luxuryCabins === true)) + && (group != 'fh' || (ship.fighterHangars && ship.fighterHangars === true)) + && (clazz === undefined || slot.maxClass >= clazz)) { return true; } return false; From ed7a9ef03763e21a382a1e144dbf55302bf1c82c Mon Sep 17 00:00:00 2001 From: Cmdr McDonald Date: Fri, 14 Oct 2016 01:04:05 +0100 Subject: [PATCH 2/4] Display new-style hardpoint information --- src/app/components/HardpointSlot.jsx | 26 ++++--- src/app/components/SvgIcons.jsx | 109 ++++++++++++++++++++++++--- src/app/utils/SlotFunctions.js | 6 +- src/less/slot.less | 10 +++ 4 files changed, 131 insertions(+), 20 deletions(-) diff --git a/src/app/components/HardpointSlot.jsx b/src/app/components/HardpointSlot.jsx index 5f910b7a..5e253015 100644 --- a/src/app/components/HardpointSlot.jsx +++ b/src/app/components/HardpointSlot.jsx @@ -1,5 +1,6 @@ import React from 'react'; import Slot from './Slot'; +import { DamageKinetic, DamageThermal, DamageExplosive, MountFixed, MountGimballed, MountTurret } from './SvgIcons'; /** * Hardpoint / Utility Slot @@ -33,24 +34,31 @@ export default class HardpointSlot extends Slot { */ _getSlotDetails(m, translate, formats, u) { if (m) { - let classRating = `${m.class}${m.rating}${m.mount ? '/' + m.mount : ''}${m.missile ? m.missile : ''}`; + let classRating = `${m.class}${m.rating}${m.missile ? '/' + m.missile : ''}`; let { drag, drop } = this.props; return
-
{classRating} {translate(m.name || m.grp)}
+
+ {m.mount && m.mount == 'F' ? : ''} + {m.mount && m.mount == 'G' ? : ''} + {m.mount && m.mount == 'T' ? : ''} + {m.type && m.type == 'K' ? : ''} + {m.type && m.type == 'T' ? : ''} + {m.type && m.type == 'KT' ? : ''} + {m.type && m.type == 'E' ? : ''} + {classRating} {translate(m.name || m.grp)}
{m.mass}{u.T}
- { m.damage ?
{translate('damage')}: {m.damage} { m.ssdam ? ({formats.int(m.ssdam)} {u.MJ}) : null }
: null } - { m.dps ?
{translate('DPS')}: {m.dps} { m.mjdps ? ({formats.int(m.mjdps)} {u.MJ}) : null }
: null } - { m.thermload ?
{translate('T-Load')}: {m.thermload}
: null } - { m.type ?
{translate('type')}: {m.type}
: null } + { m.dps ?
{translate('DPS')}: {formats.int(10 * m.dps) / 10} { m.clip ? ({formats.int(10 * (m.clip * m.dps / m.rof) / ((m.clip / m.rof) + m.reload)) / 10}) : null }
: null } + { m.eps ?
{translate('EPS')}: {formats.int(10 * m.eps) / 10} { m.clip ? ({formats.int(10 * (m.clip * m.eps / m.rof) / ((m.clip / m.rof) + m.reload)) / 10}) : null }
: null } + { m.hps ?
{translate('HPS')}: {formats.int(10 * m.hps) / 10} { m.clip ? ({formats.int(10 * (m.clip * m.hps / m.rof) / ((m.clip / m.rof) + m.reload)) / 10}) : null }
: null } + { m.dps && m.eps ?
{translate('DPE')}: {formats.int( 10 * m.dps / m.eps) / 10}
: null } { m.rof ?
{translate('ROF')}: {m.rof}{u.ps}
: null } - { m.armourpen ?
{translate('pen')}: {m.armourpen}
: null } + { m.range && !m.dps ?
{translate('Range')}: {m.range/1000}{u.km}
: null } { m.shieldmul ?
+{formats.rPct(m.shieldmul)}
: null } - { m.range ?
{m.range} km
: null } - { m.ammo >= 0 ?
{translate('ammo')}: {formats.int(m.clip)}+{formats.int(m.ammo)}
: null } + { m.ammo >= 0 ?
{translate('ammo')}: {formats.int(m.clip)}/{formats.int(m.ammo)}
: null }
; } else { diff --git a/src/app/components/SvgIcons.jsx b/src/app/components/SvgIcons.jsx index 58debe2d..6e228026 100644 --- a/src/app/components/SvgIcons.jsx +++ b/src/app/components/SvgIcons.jsx @@ -319,6 +319,90 @@ export class Warning extends SvgIcon { } } +/** + * Thermal damage + */ +export class DamageThermal extends SvgIcon { + /** + * Overriden view box + * @return {String} view box + */ + viewBox() { return '0 0 200 200'; } + /** + * Generate the SVG + * @return {React.Component} SVG Contents + */ + svg() { + return + + + + ; + } +} + +/** + * Kinetic damage + */ +export class DamageKinetic extends SvgIcon { + /** + * Overriden view box + * @return {String} view box + */ + viewBox() { return '0 0 200 200'; } + /** + * Generate the SVG + * @return {React.Component} SVG Contents + */ + svg() { + return + + + + + + + + + + + + ; + } +} + +/** + * Explosive damage + */ +export class DamageExplosive extends SvgIcon { + /** + * Overriden view box + * @return {String} view box + */ + viewBox() { return '0 0 200 200'; } + /** + * Generate the SVG + * @return {React.Component} SVG Contents + */ + svg() { + return + + + + + + + + + + + + + + ; + } +} + /** * Fixed mount hardpoint */ @@ -334,11 +418,11 @@ export class MountFixed extends SvgIcon { */ svg() { return - - - - - + + + + + ; } } @@ -358,8 +442,8 @@ export class MountGimballed extends SvgIcon { */ svg() { return - - + + ; } } @@ -379,9 +463,14 @@ export class MountTurret extends SvgIcon { */ svg() { return - - - + + + + + + + + ; } } diff --git a/src/app/utils/SlotFunctions.js b/src/app/utils/SlotFunctions.js index d0bb60ea..4069a54e 100644 --- a/src/app/utils/SlotFunctions.js +++ b/src/app/utils/SlotFunctions.js @@ -127,7 +127,11 @@ const PROP_BLACKLIST = { enginecapacity: 1, enginerecharge: 1, systemcapacity: 1, - systemrecharge: 1 + systemrecharge: 1, + breachdps: 1, + breachmin: 1, + breachmax: 1, + integrity: 1 }; const TERM_LOOKUP = { diff --git a/src/less/slot.less b/src/less/slot.less index 641b876b..11d17d30 100755 --- a/src/less/slot.less +++ b/src/less/slot.less @@ -12,6 +12,8 @@ background-color: @primary-bg; border: 1px solid @primary-disabled; color: @fg; + stroke: @fg; + stroke-width: 20; fill: @fg; .details-container { @@ -54,6 +56,8 @@ font-size: 1.2em; width: 1.2em; color: @primary-disabled; + stroke: @primary-disabled; + stroke-width: 20; border-right: 1px solid @primary-disabled; box-sizing: border-box; padding-top: 0.2em; @@ -64,6 +68,8 @@ text-transform: uppercase; font-size: 1.3em; color: lighten(@primary-bg, 12%); + stroke: lighten(@primary-bg, 12%); + stroke-width: 20; text-align: center; letter-spacing: 0.1em; line-height: 1.7em; @@ -71,12 +77,16 @@ &.selected { color: @primary-bg; + stroke: @primary-bg; + stroke-width: 20; fill: @primary-bg; background-color: @primary; border: 1px solid @primary; z-index: 1; .sz { color: @primary; + stroke: @primary; + stroke-width: 20; background-color: @primary-bg; border-right: 1px solid @primary; } From e6278858b94431073381195ab8d1696fc8daadb1 Mon Sep 17 00:00:00 2001 From: Cmdr McDonald Date: Fri, 14 Oct 2016 12:09:54 +0100 Subject: [PATCH 3/4] Added drag and drop logic for special compartments --- src/app/components/SlotSection.jsx | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/app/components/SlotSection.jsx b/src/app/components/SlotSection.jsx index af88b729..29ea806e 100644 --- a/src/app/components/SlotSection.jsx +++ b/src/app/components/SlotSection.jsx @@ -1,6 +1,7 @@ import React from 'react'; import TranslatedComponent from './TranslatedComponent'; import { wrapCtxMenu } from '../utils/UtilityFunctions'; +import { canMount } from '../utils/SlotFunctions'; import { Equalizer } from '../components/SvgIcons'; import cn from 'classnames'; @@ -90,7 +91,7 @@ export default class SlotSection extends TranslatedComponent { e.stopPropagation(); let os = this.state.originSlot; if (os) { - e.dataTransfer.dropEffect = os != targetSlot && targetSlot.maxClass >= os.m.class ? 'copyMove' : 'none'; + e.dataTransfer.dropEffect = os != targetSlot && canMount(this.props.ship, targetSlot, os.m.grp, os.m.class) ? 'copyMove' : 'none'; this.setState({ targetSlot }); } else { e.dataTransfer.dropEffect = 'none'; @@ -116,9 +117,9 @@ export default class SlotSection extends TranslatedComponent { let { originSlot, targetSlot } = this.state; let m = originSlot.m; - if (targetSlot && m && targetSlot.maxClass >= m.class) { + if (targetSlot && m && canMount(this.props.ship, targetSlot, m.grp, m.class)) { // Swap modules if possible - if (targetSlot.m && originSlot.maxClass >= targetSlot.m.class) { + if (targetSlot.m && canMount(this.props.ship, originSlot, targetSlot.m.grp, targetSlot.m.class)) { this.props.ship.use(originSlot, targetSlot.m, true); } else { // Otherwise empty the origin slot this.props.ship.use(originSlot, null, true); // Empty but prevent summary update @@ -141,12 +142,12 @@ export default class SlotSection extends TranslatedComponent { return null; } if (slot === originSlot) { - if (targetSlot && targetSlot.m && originSlot.maxClass < targetSlot.m.class) { + if (targetSlot && targetSlot.m && !canMount(this.props.ship, originSlot, targetSlot.m.grp, targetSlot.m.class)) { return 'dropEmpty'; // Origin slot will be emptied } return null; } - if (originSlot.m && slot.maxClass >= originSlot.m.class) { // Eligble drop slot + if (originSlot.m && canMount(this.props.ship, slot, originSlot.m.grp, originSlot.m.class)) { // Eligble drop slot if (slot === targetSlot) { return 'drop'; // Can drop } From 33b22b82804274602f4873f59fe69a30f55e89e1 Mon Sep 17 00:00:00 2001 From: Cmdr McDonald Date: Fri, 14 Oct 2016 14:53:20 +0100 Subject: [PATCH 4/4] Use correct i18n formatting methods. Update note to 2.2 --- src/app/components/HardpointSlot.jsx | 10 +++++----- src/app/i18n/Language.jsx | 2 ++ src/app/pages/AboutPage.jsx | 2 +- src/app/pages/OutfittingPage.jsx | 2 +- src/app/pages/ShipyardPage.jsx | 2 +- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/app/components/HardpointSlot.jsx b/src/app/components/HardpointSlot.jsx index 5e253015..64807dde 100644 --- a/src/app/components/HardpointSlot.jsx +++ b/src/app/components/HardpointSlot.jsx @@ -51,12 +51,12 @@ export default class HardpointSlot extends Slot {
{m.mass}{u.T}
- { m.dps ?
{translate('DPS')}: {formats.int(10 * m.dps) / 10} { m.clip ? ({formats.int(10 * (m.clip * m.dps / m.rof) / ((m.clip / m.rof) + m.reload)) / 10}) : null }
: null } - { m.eps ?
{translate('EPS')}: {formats.int(10 * m.eps) / 10} { m.clip ? ({formats.int(10 * (m.clip * m.eps / m.rof) / ((m.clip / m.rof) + m.reload)) / 10}) : null }
: null } - { m.hps ?
{translate('HPS')}: {formats.int(10 * m.hps) / 10} { m.clip ? ({formats.int(10 * (m.clip * m.hps / m.rof) / ((m.clip / m.rof) + m.reload)) / 10}) : null }
: null } - { m.dps && m.eps ?
{translate('DPE')}: {formats.int( 10 * m.dps / m.eps) / 10}
: null } + { m.dps ?
{translate('DPS')}: {formats.round1(m.dps)} { m.clip ? ({formats.round1((m.clip * m.dps / m.rof) / ((m.clip / m.rof) + m.reload)) }) : null }
: null } + { m.eps ?
{translate('EPS')}: {formats.round1(m.eps)} { m.clip ? ({formats.round1((m.clip * m.eps / m.rof) / ((m.clip / m.rof) + m.reload)) }) : null }
: null } + { m.hps ?
{translate('HPS')}: {formats.round1(m.hps)} { m.clip ? ({formats.round1((m.clip * m.hps / m.rof) / ((m.clip / m.rof) + m.reload)) }) : null }
: null } + { m.dps && m.eps ?
{translate('DPE')}: {formats.round1(m.dps / m.eps)}
: null } { m.rof ?
{translate('ROF')}: {m.rof}{u.ps}
: null } - { m.range && !m.dps ?
{translate('Range')}: {m.range/1000}{u.km}
: null } + { m.range && !m.dps ?
{translate('Range')}: {formats.round(m.range/1000)}{u.km}
: null } { m.shieldmul ?
+{formats.rPct(m.shieldmul)}
: null } { m.ammo >= 0 ?
{translate('ammo')}: {formats.int(m.clip)}/{formats.int(m.ammo)}
: null }
diff --git a/src/app/i18n/Language.jsx b/src/app/i18n/Language.jsx index dc237c24..6d4d21a8 100644 --- a/src/app/i18n/Language.jsx +++ b/src/app/i18n/Language.jsx @@ -41,12 +41,14 @@ export function getLanguage(langCode) { formats: { gen, // General number format (.e.g 1,001,001.1234) int: d3Locale.numberFormat(',.0f'), // Fixed to 0 decimal places (.e.g 1,001) + f1: d3Locale.numberFormat(',.1f'), // Fixed to 1 decimal place (.e.g 1,001.1) f2: d3Locale.numberFormat(',.2f'), // Fixed to 2 decimal places (.e.g 1,001.10) s2: d3Locale.numberFormat('.2s'), // SI Format to 2 decimal places (.e.g 1.1k) pct: d3Locale.numberFormat('.2%'), // % to 2 decimal places (.e.g 5.40%) pct1: d3Locale.numberFormat('.1%'), // % to 1 decimal places (.e.g 5.4%) r2: d3Locale.numberFormat('.2r'), // Rounded to 2 significant numbers (.e.g 512 => 510, 4.122 => 4.1) rPct: d3.format('%'), // % to 0 decimal places (.e.g 5%) + round1: (d) => gen(d3.round(d, 1)), // Rounded to 0-1 decimal places (.e.g 5.1, 4) round: (d) => gen(d3.round(d, 2)), // Rounded to 0-2 decimal places (.e.g 5.12, 4.1) time: (d) => (d < 0 ? '-' : '') + Math.floor(Math.abs(d) / 60) + ':' + ('00' + Math.floor(Math.abs(d) % 60)).substr(-2, 2) }, diff --git a/src/app/pages/AboutPage.jsx b/src/app/pages/AboutPage.jsx index ed8771c9..77579786 100644 --- a/src/app/pages/AboutPage.jsx +++ b/src/app/pages/AboutPage.jsx @@ -29,7 +29,7 @@ export default class AboutPage extends Page {

This is a clone of the Coriolis project, whose original author is currently unable to maintain it. This clone is maintained by the EDCD community.

To recover your builds, go to https://coriolis.io/, backup your builds (Settings / Backup), copy the text, return here and import (Settings / Import).

The Coriolis project was inspired by E:D Shipyard and, of course, Elite Dangerous. 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.

-

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.

+

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 ED Assets

diff --git a/src/app/pages/OutfittingPage.jsx b/src/app/pages/OutfittingPage.jsx index 0ac81281..e4ee5633 100644 --- a/src/app/pages/OutfittingPage.jsx +++ b/src/app/pages/OutfittingPage.jsx @@ -293,7 +293,7 @@ export default class OutfittingPage extends Page {