diff --git a/__tests__/fixtures/expected-builds.json b/__tests__/fixtures/expected-builds.json
index 6cfc0f68..2e5498a6 100644
--- a/__tests__/fixtures/expected-builds.json
+++ b/__tests__/fixtures/expected-builds.json
@@ -36,7 +36,7 @@
"Test": "A4putkFklkdzsuf52c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04---0303326b.Iw18ZVA=.Aw18ZVA=."
},
"diamondback_explorer": {
- "Explorer": "A0p0tdFfldddsdf5---0202--320p432i2f.AwRj4zTI.AwiMIypI."
+ "Explorer": "A0p0tdFfldddsdf5---0202--320p432i2f-.AwRj4zTYg===.AwiMIyoo."
},
"vulture": {
"Bounty Hunter": "A3patcFalddksff31e1e0404-0l4a-5d27662j.AwRj4z2I.MwBhBYy6oJmAjLIA."
diff --git a/src/app/components/BattleCentre.jsx b/src/app/components/BattleCentre.jsx
deleted file mode 100644
index 2ffdfd59..00000000
--- a/src/app/components/BattleCentre.jsx
+++ /dev/null
@@ -1,144 +0,0 @@
-import React from 'react';
-import TranslatedComponent from './TranslatedComponent';
-import Ship from '../shipyard/Ship';
-import { Ships } from 'coriolis-data/dist';
-import Slider from './Slider';
-import Pips from './Pips';
-import Fuel from './Fuel';
-import Cargo from './Cargo';
-import Movement from './Movement';
-import EngagementRange from './EngagementRange';
-import ShipPicker from './ShipPicker';
-import Defence from './Defence';
-
-/**
- * Battle centre allows you to pit your current build against another ship,
- * adjust pips and engagement range, and see a wide variety of information
- */
-export default class BattleCentre extends TranslatedComponent {
- static propTypes = {
- ship: React.PropTypes.object.isRequired
- };
-
- /**
- * Constructor
- * @param {Object} props React Component properties
- * @param {Object} context React Component context
- */
- constructor(props, context) {
- super(props);
-
- const { ship } = this.props;
-
- this._cargoUpdated = this._cargoUpdated.bind(this);
- this._fuelUpdated = this._fuelUpdated.bind(this);
- this._pipsUpdated = this._pipsUpdated.bind(this);
- this._engagementRangeUpdated = this._engagementRangeUpdated.bind(this);
- this._opponentUpdated = this._opponentUpdated.bind(this);
-
- this.state = {
- sys: 2,
- eng: 2,
- wep: 2,
- fuel: ship.fuelCapacity,
- cargo: ship.cargoCapacity,
- boost: false,
- engagementRange: 1500,
- opponent: new Ship('anaconda', Ships['anaconda'].properties, Ships['anaconda'].slots).buildWith(Ships['anaconda'].defaults)
- };
- }
-
- /**
- * Update state based on property and context changes
- * @param {Object} nextProps Incoming/Next properties
- * @returns {boolean} true if an update is required
- */
- componentWillReceiveProps(nextProps) {
- // Rather than try to keep track of what changes our children require we force an update and let them work it out
- this.forceUpdate();
- return true;
- }
-
- /**
- * Triggered when pips have been updated
- * @param {number} sys SYS pips
- * @param {number} eng ENG pips
- * @param {number} wep WEP pips
- * @param {boolean} boost true if boosting
- */
- _pipsUpdated(sys, eng, wep, boost) {
- this.setState({ sys, eng, wep, boost });
- }
-
- /**
- * Triggered when fuel has been updated
- * @param {number} fuel the amount of fuel, in T
- */
- _fuelUpdated(fuel) {
- this.setState({ fuel });
- }
-
- /**
- * Triggered when cargo has been updated
- * @param {number} cargo the amount of cargo, in T
- */
- _cargoUpdated(cargo) {
- this.setState({ cargo });
- }
-
- /**
- * Triggered when engagement range has been updated
- * @param {number} engagementRange the engagement range, in m
- */
- _engagementRangeUpdated(engagementRange) {
- this.setState({ engagementRange });
- }
-
- /**
- * Triggered when target ship has been updated
- * @param {object} opponent the opponent's ship
- * @param {string} opponentBuild the name of the opponent's build
- */
- _opponentUpdated(opponent, opponentBuild) {
- this.setState({ opponent, opponentBuild });
- }
-
- /**
- * Render
- * @return {React.Component} contents
- */
- render() {
- const { language, onWindowResize, sizeRatio, tooltip, termtip } = this.context;
- const { formats, translate, units } = language;
- const { sys, eng, wep, cargo, fuel, boost, engagementRange, opponent, opponentBuild } = this.state;
- const { ship } = this.props;
-
- // Markers are used to propagate state changes without requiring a deep comparison of the ship, as that takes a long time
- const pipsMarker = '' + ship.canBoost();
- const movementMarker = '' + ship.topSpeed + ':' + ship.pitch + ':' + ship.roll + ':' + ship.yaw + ':' + ship.canBoost();
- const shieldMarker = '' + ship.shield + ':' + ship.shieldCells + ':' + ship.shieldExplRes + ':' + ship.shieldKinRes + ':' + ship.shieldThermRes + ':' + ship.armour + ship.standard[4].m.getSystemsCapacity() + ':' + ship.standard[4].m.getSystemsRechargeRate() + ':' + opponent.name + ':' + opponentBuild + ':' + engagementRange;
-
- return (
-
- {translate('battle centre')}
-
-
{translate('ship management')}
-
-
- { ship.cargoCapacity > 0 ? : null }
- {translate('opponent')}
-
-
-
-
-
{translate('movement')}
-
-
-
-
{translate('defence')}
-
-
-
- );
- }
-}
diff --git a/src/app/components/Boost.jsx b/src/app/components/Boost.jsx
new file mode 100644
index 00000000..cc39d28e
--- /dev/null
+++ b/src/app/components/Boost.jsx
@@ -0,0 +1,116 @@
+import React from 'react';
+import TranslatedComponent from './TranslatedComponent';
+import { Ships } from 'coriolis-data/dist';
+import ShipSelector from './ShipSelector';
+import { nameComparator } from '../utils/SlotFunctions';
+import { Pip } from './SvgIcons';
+import LineChart from '../components/LineChart';
+import Slider from '../components/Slider';
+import * as ModuleUtils from '../shipyard/ModuleUtils';
+import Module from '../shipyard/Module';
+
+/**
+ * Boost displays a boost button that toggles bosot
+ * Requires an onChange() function of the form onChange(boost) which is triggered whenever the boost changes.
+ */
+export default class Boost extends TranslatedComponent {
+ static propTypes = {
+ marker: React.PropTypes.string.isRequired,
+ ship: React.PropTypes.object.isRequired,
+ onChange: React.PropTypes.func.isRequired
+ };
+
+ /**
+ * Constructor
+ * @param {Object} props React Component properties
+ * @param {Object} context React Component context
+ */
+ constructor(props, context) {
+ super(props);
+ const ship = props.ship;
+
+ this._keyDown = this._keyDown.bind(this);
+ this._toggleBoost = this._toggleBoost.bind(this);
+
+ this.state = {
+ boost: false
+ };
+ }
+
+ /**
+ * Add listeners after mounting
+ */
+ componentDidMount() {
+ document.addEventListener('keydown', this._keyDown);
+ }
+
+ /**
+ * Remove listeners before unmounting
+ */
+ componentWillUnmount() {
+ document.removeEventListener('keydown', this._keyDown);
+ }
+
+ /**
+ * Update values if we change ship
+ * @param {Object} nextProps Incoming/Next properties
+ * @returns {boolean} Returns true if the component should be rerendered
+ */
+ componentWillReceiveProps(nextProps) {
+ const { boost } = this.state;
+ const nextShip = nextProps.ship;
+
+ const nextBoost = nextShip.canBoost() ? boost : false;
+ if (nextBoost != boost) {
+ this.setState({
+ boost: nextBoost
+ });
+ }
+
+ return true;
+ }
+
+ /**
+ * Handle Key Down
+ * @param {Event} e Keyboard Event
+ */
+ _keyDown(e) {
+ if (e.ctrlKey || e.metaKey) { // CTRL/CMD
+ switch (e.keyCode) {
+ case 66: // b == boost
+ if (this.props.ship.canBoost()) {
+ e.preventDefault();
+ this._toggleBoost();
+ }
+ break;
+ }
+ }
+ }
+
+ /**
+ * Toggle the boost feature
+ */
+ _toggleBoost() {
+ let { boost } = this.state;
+ boost = !boost;
+ this.setState({ boost });
+ this.props.onChange(boost);
+ }
+
+ /**
+ * Render boost
+ * @return {React.Component} contents
+ */
+ render() {
+ const { formats, translate, units } = this.context.language;
+ const { ship } = this.props;
+ const { boost } = this.state;
+
+ // TODO disable if ship cannot boost
+ return (
+
+
+
+ );
+ }
+}
diff --git a/src/app/components/Defence.jsx b/src/app/components/Defence.jsx
index 7531a91b..9a32f290 100644
--- a/src/app/components/Defence.jsx
+++ b/src/app/components/Defence.jsx
@@ -182,10 +182,10 @@ export default class Defence extends TranslatedComponent {
if (sys === 0) {
// No system pips so will never recover shields
recover = Math.Inf;
- } else {
- // Recover remaining shields at the rate of the power distributor's recharge
+ } else {
+ // Recover remaining shields at the rate of the power distributor's recharge
recover += remainingShieldToRecover / (sysRechargeRate / 0.6);
- }
+ }
}
// Recharge time is the time taken to go from 50% to 100%
@@ -207,10 +207,10 @@ export default class Defence extends TranslatedComponent {
if (sys === 0) {
// No system pips so will never recharge shields
recharge = Math.Inf;
- } else {
- // Recharge remaining shields at the rate of the power distributor's recharge
+ } else {
+ // Recharge remaining shields at the rate of the power distributor's recharge
recharge += remainingShieldToRecharge / (sysRechargeRate / 0.6);
- }
+ }
}
shield = {
diff --git a/src/app/components/EngineProfile.jsx b/src/app/components/EngineProfile.jsx
index 0ff10850..fef2a5f5 100644
--- a/src/app/components/EngineProfile.jsx
+++ b/src/app/components/EngineProfile.jsx
@@ -16,7 +16,11 @@ export default class EngineProfile extends TranslatedComponent {
static propTypes = {
ship: React.PropTypes.object.isRequired,
chartWidth: React.PropTypes.number.isRequired,
- code: React.PropTypes.string.isRequired
+ cargo: React.PropTypes.number.isRequired,
+ fuel: React.PropTypes.number.isRequired,
+ eng: React.PropTypes.number.isRequired,
+ boost: React.PropTypes.bool.isRequired,
+ marker: React.PropTypes.string.isRequired
};
/**
@@ -30,8 +34,7 @@ export default class EngineProfile extends TranslatedComponent {
const ship = this.props.ship;
this.state = {
- cargo: ship.cargoCapacity,
- calcMaxSpeedFunc: this._calcMaxSpeed.bind(this, ship)
+ calcMaxSpeedFunc: this.calcMaxSpeed.bind(this, ship, this.props.eng, this.props.boost)
};
}
@@ -42,36 +45,23 @@ export default class EngineProfile extends TranslatedComponent {
* @return {boolean} Returns true if the component should be rerendered
*/
componentWillReceiveProps(nextProps, nextContext) {
- if (nextProps.code != this.props.code) {
- this.setState({ cargo: nextProps.ship.cargoCapacity, calcMaxSpeedFunc: this._calcMaxSpeed.bind(this, nextProps.ship) });
+ if (nextProps.marker != this.props.marker) {
+ this.setState({ calcMaxSpeedFunc: this.calcMaxSpeed.bind(this, nextProps.ship, nextProps.eng, nextProps.boost) });
}
return true;
}
/**
- * Calculate the maximum speed for this ship across its applicable mass
+ * Calculate the top speed for this ship given thrusters, mass and pips to ENG
* @param {Object} ship The ship
+ * @param {Object} eng The number of pips to ENG
+ * @param {Object} boost If boost is enabled
* @param {Object} mass The mass at which to calculate the top speed
* @return {number} The maximum speed
*/
- _calcMaxSpeed(ship, mass) {
- // Obtain the thrusters for this ship
- const thrusters = ship.standard[1].m;
-
+ calcMaxSpeed(ship, eng, boost, mass) {
// Obtain the top speed
- return Calc.speed(mass, ship.speed, thrusters, ship.engpip)[4];
- }
-
- /**
- * Update cargo level
- * @param {number} cargoLevel Cargo level 0 - 1
- */
- _cargoChange(cargoLevel) {
- let ship = this.props.ship;
- let cargo = Math.round(ship.cargoCapacity * cargoLevel);
- this.setState({
- cargo
- });
+ return Calc.calcSpeed(mass, ship.speed, ship.standard[1].m, ship.pipSpeed, eng, ship.boost / ship.speed, boost);
}
/**
@@ -81,24 +71,21 @@ export default class EngineProfile extends TranslatedComponent {
render() {
const { language, onWindowResize, sizeRatio, tooltip, termtip } = this.context;
const { formats, translate, units } = language;
- const { ship } = this.props;
- const { cargo } = this.state;
+ const { ship, cargo, eng, fuel, boost } = this.props;
// Calculate bounds for our line chart
const thrusters = ship.standard[1].m;
const minMass = ship.calcLowestPossibleMass({ th: thrusters });
const maxMass = thrusters.getMaxMass();
- let mass = ship.unladenMass + ship.fuelCapacity + cargo;
- const minSpeed = Calc.speed(maxMass, ship.speed, thrusters, ship.engpip)[4];
- const maxSpeed = Calc.speed(minMass, ship.speed, thrusters, ship.engpip)[4];
+ const mass = ship.unladenMass + fuel + cargo;
+ const minSpeed = Calc.calcSpeed(maxMass, ship.speed, thrusters, ship.pipSpeed, 0, ship.boost / ship.speed, false);
+ const maxSpeed = Calc.calcSpeed(minMass, ship.speed, thrusters, ship.pipSpeed, 4, ship.boost / ship.speed, true);
// Add a mark at our current mass
const mark = Math.min(mass, maxMass);
- const cargoPercent = cargo / ship.cargoCapacity;
+ const code = `${ship.toString()}:${cargo}:${fuel}:${eng}:${boost}`;
- const code = ship.toString() + '.' + ship.getModificationsString() + '.' + ship.getPowerEnabledString();
-
- // This graph has a precipitous fall-off so we use lots of points to make it look a little smoother
+ // This graph can have a precipitous fall-off so we use lots of points to make it look a little smoother
return (
{translate('engine profile')}
@@ -117,27 +104,6 @@ export default class EngineProfile extends TranslatedComponent {
points={1000}
code={code}
/>
- {ship.cargoCapacity ?
-
- {translate('cargo carried')}: {formats.int(cargo)}{units.T}
-
- : '' }
);
}
diff --git a/src/app/components/FSDProfile.jsx b/src/app/components/FSDProfile.jsx
index b5138f9c..2db23b1d 100644
--- a/src/app/components/FSDProfile.jsx
+++ b/src/app/components/FSDProfile.jsx
@@ -16,7 +16,9 @@ export default class FSDProfile extends TranslatedComponent {
static propTypes = {
ship: React.PropTypes.object.isRequired,
chartWidth: React.PropTypes.number.isRequired,
- code: React.PropTypes.string.isRequired
+ cargo: React.PropTypes.number.isRequired,
+ fuel: React.PropTypes.number.isRequired,
+ marker: React.PropTypes.string.isRequired
};
/**
@@ -30,8 +32,7 @@ export default class FSDProfile extends TranslatedComponent {
const ship = this.props.ship;
this.state = {
- cargo: ship.cargoCapacity,
- calcMaxRangeFunc: this._calcMaxRange.bind(this, ship)
+ calcMaxRangeFunc: this._calcMaxRange.bind(this, ship, this.props.fuel)
};
}
@@ -42,8 +43,8 @@ export default class FSDProfile extends TranslatedComponent {
* @return {boolean} Returns true if the component should be rerendered
*/
componentWillReceiveProps(nextProps, nextContext) {
- if (nextProps.code != this.props.code) {
- this.setState({ cargo: nextProps.ship.cargoCapacity, calcMaxRangeFunc: this._calcMaxRange.bind(this, nextProps.ship) });
+ if (nextProps.marker != this.props.marker) {
+ this.setState({ calcMaxRangeFunc: this._calcMaxRange.bind(this, nextProps.ship, nextProps.fuel) });
}
return true;
}
@@ -51,38 +52,23 @@ export default class FSDProfile extends TranslatedComponent {
/**
* Calculate the maximum range for this ship across its applicable mass
* @param {Object} ship The ship
+ * @param {Object} fuel The fuel on the ship
* @param {Object} mass The mass at which to calculate the maximum range
* @return {number} The maximum range
*/
- _calcMaxRange(ship, mass) {
- // Obtain the FSD for this ship
- const fsd = ship.standard[2].m;
-
+ _calcMaxRange(ship, fuel, mass) {
// Obtain the maximum range
- return Calc.jumpRange(mass, fsd, fsd.getMaxFuelPerJump());
+ return Calc.jumpRange(mass, ship.standard[2].m, Math.min(fuel, ship.standard[2].m.getMaxFuelPerJump()));
}
/**
- * Update cargo level
- * @param {number} cargoLevel Cargo level 0 - 1
- */
- _cargoChange(cargoLevel) {
- let ship = this.props.ship;
- let cargo = Math.round(ship.cargoCapacity * cargoLevel);
- this.setState({
- cargo
- });
- }
-
- /**
- * Render engine profile
+ * Render FSD profile
* @return {React.Component} contents
*/
render() {
const { language, onWindowResize, sizeRatio, tooltip, termtip } = this.context;
const { formats, translate, units } = language;
- const { ship } = this.props;
- const { cargo } = this.state;
+ const { ship, cargo, fuel } = this.props;
// Calculate bounds for our line chart - use thruster info for X
@@ -90,15 +76,13 @@ export default class FSDProfile extends TranslatedComponent {
const fsd = ship.standard[2].m;
const minMass = ship.calcLowestPossibleMass({ th: thrusters });
const maxMass = thrusters.getMaxMass();
- let mass = ship.unladenMass + ship.fuelCapacity + cargo;
- const minRange = Calc.jumpRange(maxMass, fsd, ship.fuelCapacity);
+ const mass = ship.unladenMass + fuel + cargo;
+ const minRange = 0;
const maxRange = Calc.jumpRange(minMass + fsd.getMaxFuelPerJump(), fsd, fsd.getMaxFuelPerJump());
// Add a mark at our current mass
const mark = Math.min(mass, maxMass);
- const cargoPercent = cargo / ship.cargoCapacity;
-
- const code = ship.name + ship.toString() + '.' + ship.getModificationsString() + '.' + ship.getPowerEnabledString();
+ const code = ship.name + ship.toString() + '.' + fuel;
return (
@@ -118,27 +102,6 @@ export default class FSDProfile extends TranslatedComponent {
points={200}
code={code}
/>
- {ship.cargoCapacity ?
-
- {translate('cargo carried')}: {formats.int(cargo)}{units.T}
-
- : '' }
);
}
diff --git a/src/app/components/LineChart.jsx b/src/app/components/LineChart.jsx
index dbd18b16..38fc1c81 100644
--- a/src/app/components/LineChart.jsx
+++ b/src/app/components/LineChart.jsx
@@ -116,7 +116,7 @@ export default class LineChart extends TranslatedComponent {
_updateDimensions(props, scale) {
let { width, xMax, xMin, yMin, yMax } = props;
let innerWidth = width - MARGIN.left - MARGIN.right;
- let outerHeight = Math.round(width * 0.5 * scale);
+ let outerHeight = Math.round(width * 0.8 * scale);
let innerHeight = outerHeight - MARGIN.top - MARGIN.bottom;
this.state.xScale.range([0, innerWidth]).domain([xMin, xMax || 1]).clamp(true);
diff --git a/src/app/components/Movement.jsx b/src/app/components/Movement.jsx
index e03f32c7..6f84a052 100644
--- a/src/app/components/Movement.jsx
+++ b/src/app/components/Movement.jsx
@@ -33,6 +33,7 @@ export default class Movement extends TranslatedComponent {
return (
+ {translate('movement profile')}
);
}
}
diff --git a/src/app/components/ShipPicker.jsx b/src/app/components/ShipPicker.jsx
index 5b0529a5..cebfa173 100644
--- a/src/app/components/ShipPicker.jsx
+++ b/src/app/components/ShipPicker.jsx
@@ -128,12 +128,13 @@ export default class ShipPicker extends TranslatedComponent {
const { formats, translate, units } = language;
const { menuOpen, ship, build } = this.state;
- const shipString = ship.name + ': ' + (build ? build : 'stock');
+ const shipString = ship.name + ': ' + (build ? build : translate('stock'));
return (
e.stopPropagation() }>
- {shipString}
+
+ {shipString}
{ menuOpen ?
e.stopPropagation() }>
diff --git a/src/app/pages/OutfittingPage.jsx b/src/app/pages/OutfittingPage.jsx
index 35c43532..7ad4b5d4 100644
--- a/src/app/pages/OutfittingPage.jsx
+++ b/src/app/pages/OutfittingPage.jsx
@@ -17,12 +17,13 @@ import UtilitySlotSection from '../components/UtilitySlotSection';
import OffenceSummary from '../components/OffenceSummary';
import DefenceSummary from '../components/DefenceSummary';
import MovementSummary from '../components/MovementSummary';
-import EngineProfile from '../components/EngineProfile';
-import FSDProfile from '../components/FSDProfile';
-import JumpRange from '../components/JumpRange';
-import BattleCentre from '../components/BattleCentre';
-import PowerManagement from '../components/PowerManagement';
-import CostSection from '../components/CostSection';
+import Pips from '../components/Pips';
+import Boost from '../components/Boost';
+import Fuel from '../components/Fuel';
+import Cargo from '../components/Cargo';
+import ShipPicker from '../components/ShipPicker';
+import EngagementRange from '../components/EngagementRange';
+import OutfittingSubpages from '../components/OutfittingSubpages';
import ModalExport from '../components/ModalExport';
import ModalPermalink from '../components/ModalPermalink';
@@ -51,6 +52,12 @@ export default class OutfittingPage extends Page {
this.state = this._initState(context);
this._keyDown = this._keyDown.bind(this);
this._exportBuild = this._exportBuild.bind(this);
+ this._pipsUpdated = this._pipsUpdated.bind(this);
+ this._boostUpdated = this._boostUpdated.bind(this);
+ this._cargoUpdated = this._cargoUpdated.bind(this);
+ this._fuelUpdated = this._fuelUpdated.bind(this);
+ this._opponentUpdated = this._opponentUpdated.bind(this);
+ this._engagementRangeUpdated = this._engagementRangeUpdated.bind(this);
}
/**
@@ -90,7 +97,15 @@ export default class OutfittingPage extends Page {
shipId,
ship,
code,
- savedCode
+ savedCode,
+ sys: 2,
+ eng: 2,
+ wep: 2,
+ fuel: ship.fuelCapacity,
+ cargo: 0,
+ boost: false,
+ engagementRange: 1500,
+ opponent: new Ship('anaconda', Ships['anaconda'].properties, Ships['anaconda'].slots).buildWith(Ships['anaconda'].defaults)
};
}
@@ -112,6 +127,57 @@ export default class OutfittingPage extends Page {
this.setState(stateChanges);
}
+ /**
+ * Triggered when pips have been updated
+ * @param {number} sys SYS pips
+ * @param {number} eng ENG pips
+ * @param {number} wep WEP pips
+ */
+ _pipsUpdated(sys, eng, wep) {
+ this.setState({ sys, eng, wep });
+ }
+
+ /**
+ * Triggered when boost has been updated
+ * @param {boolean} boost true if boosting
+ */
+ _boostUpdated(boost) {
+ this.setState({ boost });
+ }
+
+ /**
+ * Triggered when fuel has been updated
+ * @param {number} fuel the amount of fuel, in T
+ */
+ _fuelUpdated(fuel) {
+ this.setState({ fuel });
+ }
+
+ /**
+ * Triggered when cargo has been updated
+ * @param {number} cargo the amount of cargo, in T
+ */
+ _cargoUpdated(cargo) {
+ this.setState({ cargo });
+ }
+
+ /**
+ * Triggered when engagement range has been updated
+ * @param {number} engagementRange the engagement range, in m
+ */
+ _engagementRangeUpdated(engagementRange) {
+ this.setState({ engagementRange });
+ }
+
+ /**
+ * Triggered when target ship has been updated
+ * @param {object} opponent the opponent's ship
+ * @param {string} opponentBuild the name of the opponent's build
+ */
+ _opponentUpdated(opponent, opponentBuild) {
+ this.setState({ opponent, opponentBuild });
+ }
+
/**
* Save the current build
*/
@@ -294,7 +360,7 @@ export default class OutfittingPage extends Page {
let state = this.state,
{ language, termtip, tooltip, sizeRatio, onWindowResize } = this.context,
{ translate, units, formats } = language,
- { ship, code, savedCode, buildName, newBuildName, halfChartWidth, thirdChartWidth } = state,
+ { ship, code, savedCode, buildName, newBuildName, halfChartWidth, thirdChartWidth, sys, eng, wep, boost, fuel, cargo, opponent, opponentBuild, engagementRange } = state,
hide = tooltip.bind(null, null),
menu = this.props.currentMenu,
shipUpdated = this._shipUpdated,
@@ -307,6 +373,9 @@ export default class OutfittingPage extends Page {
// Code can be blank for a default loadout. Prefix it with the ship name to ensure that changes in default ships is picked up
code = ship.name + (code || '');
+ // Markers are used to propagate state changes without requiring a deep comparison of the ship, as that takes a long time
+ const boostMarker = `${ship.canBoost()}`;
+
return (
@@ -340,40 +409,59 @@ export default class OutfittingPage extends Page {
+ {/* Main tables */}
-
-
+ {/* Control of ship and opponent */}
+
+
+
{translate('ship control')}
+
+
+
+
-
-
+
-
-
+
+
-
-
-
-
-
-
+
+ { ship.cargoCapacity > 0 ? : null }
-
-
-
+
+
+
{translate('opponent')}
+
+
+
+
-
-
-
-
-
-
-
+
+
+ {/* Tabbed subpages */}
+
);
diff --git a/src/less/app.less b/src/less/app.less
index 3dc03d2d..f1234db6 100755
--- a/src/less/app.less
+++ b/src/less/app.less
@@ -20,6 +20,7 @@
@import 'sortable';
@import 'loader';
@import 'pips';
+@import 'boost';
@import 'movement';
@import 'shippicker';
@import 'defence';
diff --git a/src/less/boost.less b/src/less/boost.less
new file mode 100755
index 00000000..75db11be
--- /dev/null
+++ b/src/less/boost.less
@@ -0,0 +1,14 @@
+#boost {
+ button {
+ font-size: 1.2em;
+ background: @primary-bg;
+ color: @primary;
+ border: 1px solid @primary;
+ &.selected {
+ // Shown when button is selected
+ background: @primary;
+ color: @primary-bg;
+ }
+ }
+}
+
diff --git a/src/less/outfit.less b/src/less/outfit.less
index bccd47f8..092fd499 100755
--- a/src/less/outfit.less
+++ b/src/less/outfit.less
@@ -220,6 +220,14 @@
});
}
+ &.threequarters {
+ width: 75%;
+
+ .smallTablet({
+ width: 100% !important;
+ });
+ }
+
&.full {
width: 100%;
diff --git a/src/less/pips.less b/src/less/pips.less
index 1db973ae..2d3dccbd 100755
--- a/src/less/pips.less
+++ b/src/less/pips.less
@@ -12,19 +12,6 @@
cursor: pointer;
}
- button {
- font-size: 1.2em;
- background: @primary-bg;
- color: @primary;
- border: 1px solid @primary;
- margin: 20px;
- &.selected {
- // Shown when button is selected
- background: @primary;
- color: @primary-bg;
- }
- }
-
// A full pip
.full {
stroke: @primary;
diff --git a/src/less/shippicker.less b/src/less/shippicker.less
index 11726fff..8c7658c1 100755
--- a/src/less/shippicker.less
+++ b/src/less/shippicker.less
@@ -1,12 +1,11 @@
.shippicker {
background-color: @bgBlack;
margin: 0;
- padding: 0 0 0 1em;
height: 3em;
- line-height: 3em;
font-family: @fTitle;
vertical-align: middle;
position: relative;
+ display: block;
.user-select-none();
@@ -34,7 +33,6 @@
cursor: pointer;
color: @warning;
text-transform: uppercase;
- // Less than 600px screen width: hide text
&.disabled {
color: @warning-disabled;
@@ -47,7 +45,6 @@
.menu-item-label {
margin-left: 1em;
- display: inline-block;
.smallTablet({
display: none;