mirror of
https://github.com/EDCD/coriolis.git
synced 2025-12-08 22:33:24 +00:00
Make various components stateless
This commit is contained in:
@@ -320,7 +320,6 @@
|
||||
"shieldExplRes": 0.5,
|
||||
"shieldKinRes": 0.4,
|
||||
"shieldThermRes": -0.2,
|
||||
"timeToDrain": 7.04,
|
||||
"crew": 3
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,6 +76,7 @@
|
||||
"json-loader": "^0.5.3",
|
||||
"less": "^2.5.3",
|
||||
"less-loader": "^2.2.1",
|
||||
"react-addons-perf": "^15.4.2",
|
||||
"react-addons-test-utils": "^15.0.1",
|
||||
"react-measure": "^1.4.6",
|
||||
"react-testutils-additions": "^15.1.0",
|
||||
|
||||
@@ -17,6 +17,7 @@ export default class Boost extends TranslatedComponent {
|
||||
static propTypes = {
|
||||
marker: React.PropTypes.string.isRequired,
|
||||
ship: React.PropTypes.object.isRequired,
|
||||
boost: React.PropTypes.bool.isRequired,
|
||||
onChange: React.PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
@@ -27,14 +28,10 @@ export default class Boost extends TranslatedComponent {
|
||||
*/
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
const ship = props.ship;
|
||||
const { ship, boost } = props;
|
||||
|
||||
this._keyDown = this._keyDown.bind(this);
|
||||
this._toggleBoost = this._toggleBoost.bind(this);
|
||||
|
||||
this.state = {
|
||||
boost: false
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -51,25 +48,6 @@ export default class Boost extends TranslatedComponent {
|
||||
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
|
||||
@@ -91,10 +69,7 @@ export default class Boost extends TranslatedComponent {
|
||||
* Toggle the boost feature
|
||||
*/
|
||||
_toggleBoost() {
|
||||
let { boost } = this.state;
|
||||
boost = !boost;
|
||||
this.setState({ boost });
|
||||
this.props.onChange(boost);
|
||||
this.props.onChange(!this.props.boost);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -103,8 +78,7 @@ export default class Boost extends TranslatedComponent {
|
||||
*/
|
||||
render() {
|
||||
const { formats, translate, units } = this.context.language;
|
||||
const { ship } = this.props;
|
||||
const { boost } = this.state;
|
||||
const { ship, boost } = this.props;
|
||||
|
||||
// TODO disable if ship cannot boost
|
||||
return (
|
||||
|
||||
@@ -9,7 +9,8 @@ import Slider from '../components/Slider';
|
||||
*/
|
||||
export default class Cargo extends TranslatedComponent {
|
||||
static propTypes = {
|
||||
ship: React.PropTypes.object.isRequired,
|
||||
cargo: React.PropTypes.number.isRequired,
|
||||
cargoCapacity: React.PropTypes.number.isRequired,
|
||||
onChange: React.PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
@@ -21,35 +22,7 @@ export default class Cargo extends TranslatedComponent {
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
const ship = this.props.ship;
|
||||
|
||||
this.state = {
|
||||
cargoCapacity: ship.cargoCapacity,
|
||||
cargoLevel: 0,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the state if our ship changes
|
||||
* @param {Object} nextProps Incoming/Next properties
|
||||
* @return {boolean} Returns true if the component should be rerendered
|
||||
*/
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const { cargoLevel, cargoCapacity } = this.state;
|
||||
const nextCargoCapacity = nextProps.ship.cargoCapacity;
|
||||
|
||||
if (nextCargoCapacity != cargoCapacity) {
|
||||
// We keep the absolute cargo amount the same if possible so recalculate the relative level
|
||||
const nextCargoLevel = Math.min((cargoLevel * cargoCapacity) / nextCargoCapacity, 1);
|
||||
|
||||
this.setState({ cargoLevel: nextCargoLevel, cargoCapacity: nextCargoCapacity });
|
||||
|
||||
// Notify if appropriate
|
||||
if (nextCargoLevel * nextCargoCapacity != cargoLevel * cargoCapacity) {
|
||||
this.props.onChange(Math.round(nextCargoLevel * nextCargoCapacity));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
this._cargoChange = this._cargoChange.bind(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -57,14 +30,12 @@ export default class Cargo extends TranslatedComponent {
|
||||
* @param {number} cargoLevel percentage level from 0 to 1
|
||||
*/
|
||||
_cargoChange(cargoLevel) {
|
||||
const { cargoCapacity } = this.state;
|
||||
const { cargo, cargoCapacity } = this.props;
|
||||
if (cargoCapacity > 0) {
|
||||
// We round the cargo level to a suitable value given the capacity
|
||||
cargoLevel = Math.round(cargoLevel * cargoCapacity) / cargoCapacity;
|
||||
|
||||
if (cargoLevel != this.state.cargoLevel) {
|
||||
this.setState({ cargoLevel });
|
||||
this.props.onChange(Math.round(cargoLevel * cargoCapacity));
|
||||
// We round the cargo to whole number of tonnes
|
||||
const newCargo = Math.round(cargoLevel * cargoCapacity);
|
||||
if (newCargo != cargo) {
|
||||
this.props.onChange(newCargo);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -76,20 +47,20 @@ export default class Cargo extends TranslatedComponent {
|
||||
render() {
|
||||
const { language, onWindowResize, sizeRatio, tooltip, termtip } = this.context;
|
||||
const { formats, translate, units } = language;
|
||||
const { cargoLevel, cargoCapacity } = this.state;
|
||||
const { cargo, cargoCapacity } = this.props;
|
||||
|
||||
return (
|
||||
<span>
|
||||
<h3>{translate('cargo carried')}: {formats.int(cargoLevel * cargoCapacity)}{units.T}</h3>
|
||||
<h3>{translate('cargo carried')}: {formats.int(cargo)}{units.T}</h3>
|
||||
<table style={{ width: '100%', lineHeight: '1em', backgroundColor: 'transparent' }}>
|
||||
<tbody >
|
||||
<tr>
|
||||
<td>
|
||||
<Slider
|
||||
axis={true}
|
||||
onChange={this._cargoChange.bind(this)}
|
||||
onChange={this._cargoChange}
|
||||
axisUnit={translate('T')}
|
||||
percent={cargoLevel}
|
||||
percent={cargo / cargoCapacity}
|
||||
max={cargoCapacity}
|
||||
scale={sizeRatio}
|
||||
onResize={onWindowResize}
|
||||
|
||||
@@ -7,9 +7,10 @@ import Slider from '../components/Slider';
|
||||
* Engagement range slider
|
||||
* Requires an onChange() function of the form onChange(range), providing the range in metres, which is triggered on range change
|
||||
*/
|
||||
export default class Range extends TranslatedComponent {
|
||||
export default class EngagementRange extends TranslatedComponent {
|
||||
static propTypes = {
|
||||
ship: React.PropTypes.object.isRequired,
|
||||
engagementRange: React.PropTypes.number.isRequired,
|
||||
onChange: React.PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
@@ -21,47 +22,15 @@ export default class Range extends TranslatedComponent {
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
const ship = this.props.ship;
|
||||
const { ship } = props;
|
||||
|
||||
const maxRange = this._calcMaxRange(ship);
|
||||
|
||||
this.state = {
|
||||
maxRange,
|
||||
rangeLevel: 1000 / maxRange,
|
||||
maxRange
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
componentWillMount() {
|
||||
// Pass initial state
|
||||
this.props.onChange(this.state.maxRange * this.state.rangeLevel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the state if our ship changes
|
||||
* @param {Object} nextProps Incoming/Next properties
|
||||
* @return {boolean} Returns true if the component should be rerendered
|
||||
*/
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const { rangeLevel, maxRange } = this.state;
|
||||
const nextMaxRange = this._calcMaxRange(nextProps.ship);
|
||||
|
||||
if (nextMaxRange != maxRange) {
|
||||
// We keep the absolute range amount the same if possible so recalculate the relative level
|
||||
const nextRangeLevel = Math.min((rangeLevel * maxRange) / nextMaxRange, 1);
|
||||
|
||||
this.setState({ rangeLevel: nextRangeLevel, maxRange: nextMaxRange });
|
||||
|
||||
// Notify if appropriate
|
||||
if (nextRangeLevel * nextMaxRange != rangeLevel * maxRange) {
|
||||
this.props.onChange(Math.round(nextRangeLevel * nextMaxRange));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the maximum range of a ship's weapons
|
||||
* @param {Object} ship The ship
|
||||
@@ -87,12 +56,12 @@ export default class Range extends TranslatedComponent {
|
||||
*/
|
||||
_rangeChange(rangeLevel) {
|
||||
const { maxRange } = this.state;
|
||||
// We round the range to an integer value
|
||||
rangeLevel = Math.round(rangeLevel * maxRange) / maxRange;
|
||||
|
||||
if (rangeLevel != this.state.rangeLevel) {
|
||||
this.setState({ rangeLevel });
|
||||
this.props.onChange(Math.round(rangeLevel * maxRange));
|
||||
// We round the range to an integer value
|
||||
const range = Math.round(rangeLevel * maxRange);
|
||||
|
||||
if (range !== this.props.engagementRange) {
|
||||
this.props.onChange(range);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,11 +72,12 @@ export default class Range extends TranslatedComponent {
|
||||
render() {
|
||||
const { language, onWindowResize, sizeRatio, tooltip, termtip } = this.context;
|
||||
const { formats, translate, units } = language;
|
||||
const { rangeLevel, maxRange } = this.state;
|
||||
const { engagementRange } = this.props;
|
||||
const { maxRange } = this.state;
|
||||
|
||||
return (
|
||||
<span>
|
||||
<h3>{translate('engagement range')}: {formats.int(rangeLevel * maxRange)}{translate('m')}</h3>
|
||||
<h3>{translate('engagement range')}: {formats.int(engagementRange)}{translate('m')}</h3>
|
||||
<table style={{ width: '100%', lineHeight: '1em', backgroundColor: 'transparent' }}>
|
||||
<tbody >
|
||||
<tr>
|
||||
@@ -116,7 +86,7 @@ export default class Range extends TranslatedComponent {
|
||||
axis={true}
|
||||
onChange={this._rangeChange.bind(this)}
|
||||
axisUnit={translate('m')}
|
||||
percent={rangeLevel}
|
||||
percent={engagementRange / maxRange}
|
||||
max={maxRange}
|
||||
scale={sizeRatio}
|
||||
onResize={onWindowResize}
|
||||
|
||||
@@ -9,7 +9,8 @@ import Slider from '../components/Slider';
|
||||
*/
|
||||
export default class Fuel extends TranslatedComponent {
|
||||
static propTypes = {
|
||||
ship: React.PropTypes.object.isRequired,
|
||||
fuel: React.PropTypes.number.isRequired,
|
||||
fuelCapacity: React.PropTypes.number.isRequired,
|
||||
onChange: React.PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
@@ -21,35 +22,7 @@ export default class Fuel extends TranslatedComponent {
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
const ship = this.props.ship;
|
||||
|
||||
this.state = {
|
||||
fuelCapacity: ship.fuelCapacity,
|
||||
fuelLevel: 1,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the state if our ship changes
|
||||
* @param {Object} nextProps Incoming/Next properties
|
||||
* @return {boolean} Returns true if the component should be rerendered
|
||||
*/
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const { fuelLevel, fuelCapacity } = this.state;
|
||||
const nextFuelCapacity = nextProps.ship.fuelCapacity;
|
||||
|
||||
if (nextFuelCapacity != fuelCapacity) {
|
||||
// We keep the absolute fuel amount the same if possible so recalculate the relative level
|
||||
const nextFuelLevel = Math.min((fuelLevel * fuelCapacity) / nextFuelCapacity, 1);
|
||||
|
||||
this.setState({ fuelLevel: nextFuelLevel, fuelCapacity: nextFuelCapacity });
|
||||
|
||||
// Notify if appropriate
|
||||
if (nextFuelLevel * nextFuelCapacity != fuelLevel * fuelCapacity) {
|
||||
this.props.onChange(nextFuelLevel * nextFuelCapacity);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
this._fuelChange = this._fuelChange.bind(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -57,8 +30,13 @@ export default class Fuel extends TranslatedComponent {
|
||||
* @param {number} fuelLevel percentage level from 0 to 1
|
||||
*/
|
||||
_fuelChange(fuelLevel) {
|
||||
this.setState({ fuelLevel });
|
||||
this.props.onChange(fuelLevel * this.state.fuelCapacity);
|
||||
const { fuel, fuelCapacity } = this.props;
|
||||
|
||||
const newFuel = fuelLevel * fuelCapacity;
|
||||
// Only send an update if the fuel has changed significantly
|
||||
if (Math.round(fuel * 10) != Math.round(newFuel * 10)) {
|
||||
this.props.onChange(Math.round(newFuel * 10) / 10);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -68,20 +46,20 @@ export default class Fuel extends TranslatedComponent {
|
||||
render() {
|
||||
const { language, onWindowResize, sizeRatio, tooltip, termtip } = this.context;
|
||||
const { formats, translate, units } = language;
|
||||
const { fuelLevel, fuelCapacity } = this.state;
|
||||
const { fuel, fuelCapacity } = this.props;
|
||||
|
||||
return (
|
||||
<span>
|
||||
<h3>{translate('fuel carried')}: {formats.f2(fuelLevel * fuelCapacity)}{units.T}</h3>
|
||||
<h3>{translate('fuel carried')}: {formats.f1(fuel)}{units.T}</h3>
|
||||
<table style={{ width: '100%', lineHeight: '1em', backgroundColor: 'transparent' }}>
|
||||
<tbody >
|
||||
<tr>
|
||||
<td>
|
||||
<Slider
|
||||
axis={true}
|
||||
onChange={this._fuelChange.bind(this)}
|
||||
onChange={this._fuelChange}
|
||||
axisUnit={translate('T')}
|
||||
percent={fuelLevel}
|
||||
percent={fuel / fuelCapacity}
|
||||
max={fuelCapacity}
|
||||
scale={sizeRatio}
|
||||
onResize={onWindowResize}
|
||||
|
||||
@@ -66,9 +66,12 @@ export default class OutfittingSubpages extends TranslatedComponent {
|
||||
let { ship, buildName, code, onChange } = this.props;
|
||||
Persist.setOutfittingTab('power');
|
||||
|
||||
const powerMarker = `${ship.toString()}`;
|
||||
const costMarker = `${ship.toString().split('.')[0]}`;
|
||||
|
||||
return <div>
|
||||
<PowerManagement ship={ship} code={code} onChange={onChange} />
|
||||
<CostSection ship={ship} buildName={buildName} code={code} />
|
||||
<PowerManagement ship={ship} code={powerMarker} onChange={onChange} />
|
||||
<CostSection ship={ship} buildName={buildName} code={costMarker} />
|
||||
</div>;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,9 @@ import Module from '../shipyard/Module';
|
||||
*/
|
||||
export default class Pips extends TranslatedComponent {
|
||||
static propTypes = {
|
||||
ship: React.PropTypes.object.isRequired,
|
||||
sys: React.PropTypes.number.isRequired,
|
||||
eng: React.PropTypes.number.isRequired,
|
||||
wep: React.PropTypes.number.isRequired,
|
||||
onChange: React.PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
@@ -26,24 +28,9 @@ export default class Pips extends TranslatedComponent {
|
||||
*/
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
const ship = props.ship;
|
||||
const pd = ship.standard[4].m;
|
||||
const { sys, eng, wep } = props;
|
||||
|
||||
this._keyDown = this._keyDown.bind(this);
|
||||
|
||||
let pipsSvg = this._renderPips(2, 2, 2);
|
||||
this.state = {
|
||||
sys: 2,
|
||||
eng: 2,
|
||||
wep: 2,
|
||||
sysCap: pd.getSystemsCapacity(),
|
||||
engCap: pd.getEnginesCapacity(),
|
||||
wepCap: pd.getWeaponsCapacity(),
|
||||
sysRate: pd.getSystemsRechargeRate(),
|
||||
engRate: pd.getEnginesRechargeRate(),
|
||||
wepRate: pd.getWeaponsRechargeRate(),
|
||||
pipsSvg
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,41 +47,6 @@ export default class Pips extends TranslatedComponent {
|
||||
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 { sysCap, engCap, wepCap, sysRate, engRate, wepRate } = this.state;
|
||||
const nextShip = nextProps.ship;
|
||||
const pd = nextShip.standard[4].m;
|
||||
|
||||
const nextSysCap = pd.getSystemsCapacity();
|
||||
const nextEngCap = pd.getEnginesCapacity();
|
||||
const nextWepCap = pd.getWeaponsCapacity();
|
||||
const nextSysRate = pd.getSystemsRechargeRate();
|
||||
const nextEngRate = pd.getEnginesRechargeRate();
|
||||
const nextWepRate = pd.getWeaponsRechargeRate();
|
||||
if (nextSysCap != sysCap ||
|
||||
nextEngCap != engCap ||
|
||||
nextWepCap != wepCap ||
|
||||
nextSysRate != sysRate ||
|
||||
nextEngRate != engRate ||
|
||||
nextWepRate != wepRate) {
|
||||
this.setState({
|
||||
sysCap: nextSysCap,
|
||||
engCap: nextEngCap,
|
||||
wepCap: nextWepCap,
|
||||
sysRate: nextSysRate,
|
||||
engRate: nextEngRate,
|
||||
wepRate: nextWepRate
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Key Down
|
||||
* @param {Event} e Keyboard Event
|
||||
@@ -142,10 +94,9 @@ export default class Pips extends TranslatedComponent {
|
||||
* Reset the capacitor
|
||||
*/
|
||||
_reset() {
|
||||
let { sys, eng, wep } = this.state;
|
||||
let { sys, eng, wep } = this.props;
|
||||
if (sys != 2 || eng != 2 || wep != 2) {
|
||||
sys = eng = wep = 2;
|
||||
this.setState({ sys, eng, wep, pipsSvg: this._renderPips(sys, eng, wep) });
|
||||
this.props.onChange(sys, eng, wep);
|
||||
}
|
||||
}
|
||||
@@ -154,7 +105,7 @@ export default class Pips extends TranslatedComponent {
|
||||
* Increment the SYS capacitor
|
||||
*/
|
||||
_incSys() {
|
||||
let { sys, eng, wep } = this.state;
|
||||
let { sys, eng, wep } = this.props;
|
||||
|
||||
const required = Math.min(1, 4 - sys);
|
||||
if (required > 0) {
|
||||
@@ -181,7 +132,6 @@ export default class Pips extends TranslatedComponent {
|
||||
sys += 1;
|
||||
}
|
||||
}
|
||||
this.setState({ sys, eng, wep, pipsSvg: this._renderPips(sys, eng, wep) });
|
||||
this.props.onChange(sys, eng, wep);
|
||||
}
|
||||
}
|
||||
@@ -190,7 +140,7 @@ export default class Pips extends TranslatedComponent {
|
||||
* Increment the ENG capacitor
|
||||
*/
|
||||
_incEng() {
|
||||
let { sys, eng, wep } = this.state;
|
||||
let { sys, eng, wep } = this.props;
|
||||
|
||||
const required = Math.min(1, 4 - eng);
|
||||
if (required > 0) {
|
||||
@@ -217,7 +167,6 @@ export default class Pips extends TranslatedComponent {
|
||||
eng += 1;
|
||||
}
|
||||
}
|
||||
this.setState({ sys, eng, wep, pipsSvg: this._renderPips(sys, eng, wep) });
|
||||
this.props.onChange(sys, eng, wep);
|
||||
}
|
||||
}
|
||||
@@ -226,7 +175,7 @@ export default class Pips extends TranslatedComponent {
|
||||
* Increment the WEP capacitor
|
||||
*/
|
||||
_incWep() {
|
||||
let { sys, eng, wep } = this.state;
|
||||
let { sys, eng, wep } = this.props;
|
||||
|
||||
const required = Math.min(1, 4 - wep);
|
||||
if (required > 0) {
|
||||
@@ -253,7 +202,6 @@ export default class Pips extends TranslatedComponent {
|
||||
wep += 1;
|
||||
}
|
||||
}
|
||||
this.setState({ sys, eng, wep, pipsSvg: this._renderPips(sys, eng, wep) });
|
||||
this.props.onChange(sys, eng, wep);
|
||||
}
|
||||
}
|
||||
@@ -313,14 +261,14 @@ export default class Pips extends TranslatedComponent {
|
||||
*/
|
||||
render() {
|
||||
const { formats, translate, units } = this.context.language;
|
||||
const { ship } = this.props;
|
||||
const { sys, eng, wep, sysCap, engCap, wepCap, sysRate, engRate, wepRate, pipsSvg } = this.state;
|
||||
const { sys, eng, wep } = this.props;
|
||||
|
||||
const onSysClicked = this.onClick.bind(this, 'SYS');
|
||||
const onEngClicked = this.onClick.bind(this, 'ENG');
|
||||
const onWepClicked = this.onClick.bind(this, 'WEP');
|
||||
const onRstClicked = this.onClick.bind(this, 'RST');
|
||||
|
||||
const pipsSvg = this._renderPips(sys, eng, wep);
|
||||
return (
|
||||
<span id='pips'>
|
||||
<table>
|
||||
@@ -349,15 +297,3 @@ export default class Pips extends TranslatedComponent {
|
||||
);
|
||||
}
|
||||
}
|
||||
// <tr>
|
||||
// <td>{translate('capacity')} ({units.MJ})</td>
|
||||
// <td>{formats.f1(sysCap)}</td>
|
||||
// <td>{formats.f1(engCap)}</td>
|
||||
// <td>{formats.f1(wepCap)}</td>
|
||||
// </tr>
|
||||
// <tr>
|
||||
// <td>{translate('recharge')} ({units.MW})</td>
|
||||
// <td>{formats.f1(sysRate * (sys / 4))}</td>
|
||||
// <td>{formats.f1(engRate * (eng / 4))}</td>
|
||||
// <td>{formats.f1(wepRate * (wep / 4))}</td>
|
||||
// </tr>
|
||||
|
||||
@@ -13,12 +13,12 @@ import cn from 'classnames';
|
||||
export default class ShipPicker extends TranslatedComponent {
|
||||
static propTypes = {
|
||||
onChange: React.PropTypes.func.isRequired,
|
||||
ship: React.PropTypes.object,
|
||||
ship: React.PropTypes.string.isRequired,
|
||||
build: React.PropTypes.string
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
ship: new Ship('anaconda', Ships['anaconda'].properties, Ships['anaconda'].slots).buildWith(Ships['anaconda'].defaults)
|
||||
ship: 'eagle'
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -33,44 +33,21 @@ export default class ShipPicker extends TranslatedComponent {
|
||||
this._toggleMenu = this._toggleMenu.bind(this);
|
||||
this._closeMenu = this._closeMenu.bind(this);
|
||||
|
||||
this.state = {
|
||||
ship: props.ship,
|
||||
build: props.build
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the state if our ship changes
|
||||
* @param {Object} nextProps Incoming/Next properties
|
||||
* @return {boolean} Returns true if the component should be rerendered
|
||||
*/
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const { ship, build } = this.state;
|
||||
const { nextShip, nextBuild } = nextProps;
|
||||
|
||||
if (nextShip != undefined && nextShip != ship && nextBuild != build) {
|
||||
this.setState({ ship: nextShip, build: nextBuild });
|
||||
}
|
||||
return true;
|
||||
this.state = { menuOpen: false };
|
||||
}
|
||||
|
||||
/**
|
||||
* Update ship
|
||||
* @param {object} shipId the ship
|
||||
* @param {object} ship the ship
|
||||
* @param {string} build the build, if present
|
||||
*/
|
||||
_shipChange(shipId, build) {
|
||||
const ship = new Ship(shipId, Ships[shipId].properties, Ships[shipId].slots);
|
||||
if (build) {
|
||||
// Ship is a particular build
|
||||
ship.buildFrom(Persist.getBuild(shipId, build));
|
||||
} else {
|
||||
// Ship is a stock build
|
||||
ship.buildWith(Ships[shipId].defaults);
|
||||
}
|
||||
_shipChange(ship, build) {
|
||||
this._closeMenu();
|
||||
this.setState({ ship, build });
|
||||
this.props.onChange(ship, build);
|
||||
|
||||
// Ensure that the ship has changed
|
||||
if (ship !== this.props.ship || this.build !== this.props.build) {
|
||||
this.props.onChange(ship, build);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -78,7 +55,7 @@ export default class ShipPicker extends TranslatedComponent {
|
||||
* @returns {object} the picker menu
|
||||
*/
|
||||
_renderPickerMenu() {
|
||||
const { ship, build } = this.state;
|
||||
const { ship, build } = this.props;
|
||||
const _shipChange = this._shipChange;
|
||||
|
||||
const builds = Persist.getBuilds();
|
||||
@@ -86,7 +63,7 @@ export default class ShipPicker extends TranslatedComponent {
|
||||
for (let shipId of this.shipOrder) {
|
||||
const shipBuilds = [];
|
||||
// Add stock build
|
||||
const stockSelected = (ship.id == shipId && !build);
|
||||
const stockSelected = (ship == shipId && !build);
|
||||
shipBuilds.push(<li key={shipId} className={ cn({ 'selected': stockSelected })} onClick={_shipChange.bind(this, shipId, null)}>Stock</li>);
|
||||
if (builds[shipId]) {
|
||||
let buildNameOrder = Object.keys(builds[shipId]).sort();
|
||||
@@ -126,9 +103,10 @@ export default class ShipPicker extends TranslatedComponent {
|
||||
render() {
|
||||
const { language, onWindowResize, sizeRatio, tooltip, termtip } = this.context;
|
||||
const { formats, translate, units } = language;
|
||||
const { menuOpen, ship, build } = this.state;
|
||||
const { ship, build } = this.props;
|
||||
const { menuOpen } = this.state;
|
||||
|
||||
const shipString = ship.name + ': ' + (build ? build : translate('stock'));
|
||||
const shipString = ship + ': ' + (build ? build : translate('stock'));
|
||||
return (
|
||||
<div className='shippicker' onClick={ (e) => e.stopPropagation() }>
|
||||
<div className='menu'>
|
||||
|
||||
@@ -30,24 +30,20 @@ export default class ShipSummaryTable extends TranslatedComponent {
|
||||
let u = language.units;
|
||||
let formats = language.formats;
|
||||
let { time, int, round, f1, f2 } = formats;
|
||||
let sgClassNames = cn({ warning: ship.findInternalByGroup('sg') && !ship.shield, muted: !ship.findInternalByGroup('sg') });
|
||||
let sgRecover = '-';
|
||||
let sgRecharge = '-';
|
||||
let hide = tooltip.bind(null, null);
|
||||
|
||||
if (ship.shield) {
|
||||
sgRecover = time(ship.calcShieldRecovery());
|
||||
sgRecharge = time(ship.calcShieldRecharge());
|
||||
}
|
||||
|
||||
const shieldGenerator = ship.findInternalByGroup('sg');
|
||||
const sgClassNames = cn({ warning: shieldGenerator && !ship.shield, muted: !shieldGenerator });
|
||||
const timeToDrain = Calc.timeToDrainWep(ship, wep);
|
||||
const canThrust = ship.canThrust();
|
||||
const canBoost = ship.canBoost();
|
||||
|
||||
return <div id='summary'>
|
||||
<table id='summaryTable'>
|
||||
<thead>
|
||||
<tr className='main'>
|
||||
<th rowSpan={2} className={ cn({ 'bg-warning-disabled': !ship.canThrust() }) }>{translate('speed')}</th>
|
||||
<th rowSpan={2} className={ cn({ 'bg-warning-disabled': !ship.canBoost() }) }>{translate('boost')}</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 onMouseEnter={termtip.bind(null, 'damage per second')} onMouseLeave={hide} rowSpan={2}>{translate('DPS')}</th>
|
||||
<th onMouseEnter={termtip.bind(null, 'energy per second')} onMouseLeave={hide} rowSpan={2}>{translate('EPS')}</th>
|
||||
<th onMouseEnter={termtip.bind(null, 'time to drain WEP capacitor')} onMouseLeave={hide} rowSpan={2}>{translate('TTD')}</th>
|
||||
@@ -72,8 +68,8 @@ export default class ShipSummaryTable extends TranslatedComponent {
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{ ship.canThrust() ? <span>{int(ship.calcSpeed(eng, fuel, cargo, false))}{u['m/s']}</span> : <span className='warning'>0 <Warning/></span> }</td>
|
||||
<td>{ ship.canBoost() ? <span>{int(ship.calcSpeed(eng, fuel, cargo, true))}{u['m/s']}</span> : <span className='warning'>0 <Warning/></span> }</td>
|
||||
<td>{ canThrust ? <span>{int(ship.calcSpeed(eng, fuel, cargo, false))}{u['m/s']}</span> : <span className='warning'>0 <Warning/></span> }</td>
|
||||
<td>{ canBoost ? <span>{int(ship.calcSpeed(eng, fuel, cargo, true))}{u['m/s']}</span> : <span className='warning'>0 <Warning/></span> }</td>
|
||||
<td>{f1(ship.totalDps)}</td>
|
||||
<td>{f1(ship.totalEps)}</td>
|
||||
<td>{timeToDrain === Infinity ? '∞' : time(timeToDrain)}</td>
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
import React from 'react';
|
||||
// import Perf from 'react-addons-perf';
|
||||
import { findDOMNode } from 'react-dom';
|
||||
import { Ships } from 'coriolis-data/dist';
|
||||
import cn from 'classnames';
|
||||
import Page from './Page';
|
||||
import Router from '../Router';
|
||||
import Persist from '../stores/Persist';
|
||||
import * as Utils from '../utils/UtilityFunctions';
|
||||
import Ship from '../shipyard/Ship';
|
||||
import { toDetailedBuild } from '../shipyard/Serializer';
|
||||
import { outfitURL } from '../utils/UrlGenerators';
|
||||
import { FloppyDisk, Bin, Switch, Download, Reload, LinkIcon, ShoppingIcon } from '../components/SvgIcons';
|
||||
import LZString from 'lz-string';
|
||||
import ShipSummaryTable from '../components/ShipSummaryTable';
|
||||
import StandardSlotSection from '../components/StandardSlotSection';
|
||||
import HardpointsSlotSection from '../components/HardpointsSlotSection';
|
||||
@@ -46,7 +49,8 @@ export default class OutfittingPage extends Page {
|
||||
*/
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
this.state = this._initState(context);
|
||||
// window.Perf = Perf;
|
||||
this.state = this._initState(props, context);
|
||||
this._keyDown = this._keyDown.bind(this);
|
||||
this._exportBuild = this._exportBuild.bind(this);
|
||||
this._pipsUpdated = this._pipsUpdated.bind(this);
|
||||
@@ -59,10 +63,11 @@ export default class OutfittingPage extends Page {
|
||||
|
||||
/**
|
||||
* [Re]Create initial state from context
|
||||
* @param {Object} props React component properties
|
||||
* @param {context} context React component context
|
||||
* @return {Object} New state object
|
||||
*/
|
||||
_initState(context) {
|
||||
_initState(props, context) {
|
||||
let params = context.route.params;
|
||||
let shipId = params.ship;
|
||||
let code = params.code;
|
||||
@@ -84,6 +89,8 @@ export default class OutfittingPage extends Page {
|
||||
|
||||
this._getTitle = getTitle.bind(this, data.properties.name);
|
||||
|
||||
// Obtain ship control from code
|
||||
const { sys, eng, wep, boost, fuel, cargo, opponent, opponentBuild, engagementRange } = this._obtainControlFromCode(ship, code);
|
||||
return {
|
||||
error: null,
|
||||
title: this._getTitle(buildName),
|
||||
@@ -94,14 +101,15 @@ export default class OutfittingPage extends Page {
|
||||
ship,
|
||||
code,
|
||||
savedCode,
|
||||
sys: 2,
|
||||
eng: 2,
|
||||
wep: 2,
|
||||
fuel: ship.fuelCapacity,
|
||||
cargo: 0,
|
||||
boost: false,
|
||||
engagementRange: 1000,
|
||||
opponent: new Ship('anaconda', Ships['anaconda'].properties, Ships['anaconda'].slots).buildWith(Ships['anaconda'].defaults)
|
||||
sys,
|
||||
eng,
|
||||
wep,
|
||||
boost,
|
||||
fuel,
|
||||
cargo,
|
||||
opponent,
|
||||
opponentBuild,
|
||||
engagementRange
|
||||
};
|
||||
}
|
||||
|
||||
@@ -123,6 +131,76 @@ export default class OutfittingPage extends Page {
|
||||
this.setState(stateChanges);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the control part of the route
|
||||
*/
|
||||
_updateRouteOnControlChange() {
|
||||
const { ship, shipId, buildName } = this.state;
|
||||
const code = this._fullCode(ship);
|
||||
this._updateRoute(shipId, buildName, code);
|
||||
this.setState({ code });
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a full code for this ship, including any additions due to the outfitting page
|
||||
* @param {Object} ship the ship
|
||||
* @param {number} fuel the fuel carried by the ship (if different from that in state)
|
||||
* @param {number} cargo the cargo carried by the ship (if different from that in state)
|
||||
* @returns {string} the code for this ship
|
||||
*/
|
||||
_fullCode(ship, fuel, cargo) {
|
||||
return `${ship.toString()}.${LZString.compressToBase64(this._controlCode(fuel, cargo))}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the control information from the build code
|
||||
* @param {Object} ship The ship
|
||||
* @param {string} code The build code
|
||||
* @returns {Object} The control information
|
||||
*/
|
||||
_obtainControlFromCode(ship, code) {
|
||||
// Defaults
|
||||
let sys = 2;
|
||||
let eng = 2;
|
||||
let wep = 2;
|
||||
let boost = false;
|
||||
let fuel = ship.fuelCapacity;
|
||||
let cargo = ship.cargoCapacity;
|
||||
let opponent = new Ship('eagle', Ships['eagle'].properties, Ships['eagle'].slots).buildWith(Ships['eagle'].defaults);
|
||||
let opponentBuild = undefined;
|
||||
let engagementRange = 1000;
|
||||
|
||||
// Obtain updates from code, if available
|
||||
if (code) {
|
||||
const parts = code.split('.');
|
||||
if (parts.length >= 5) {
|
||||
// We have control information in the code
|
||||
const control = LZString.decompressFromBase64(Utils.fromUrlSafe(parts[4])).split('/');
|
||||
sys = parseFloat(control[0]);
|
||||
eng = parseFloat(control[1]);
|
||||
wep = parseFloat(control[2]);
|
||||
boost = control[3] == 1 ? true : false;
|
||||
fuel = parseFloat(control[4]);
|
||||
cargo = parseInt(control[5]);
|
||||
if (control[6]) {
|
||||
const shipId = control[6];
|
||||
opponent = new Ship(shipId, Ships[shipId].properties, Ships[shipId].slots);
|
||||
if (control[7] && Persist.getBuild(shipId, control[7])) {
|
||||
// Ship is a particular build
|
||||
opponent.buildFrom(Persist.getBuild(shipId, control[7]));
|
||||
opponentBuild = control[7];
|
||||
} else {
|
||||
// Ship is a stock build
|
||||
opponent.buildWith(Ships[shipId].defaults);
|
||||
}
|
||||
}
|
||||
engagementRange = parseInt(control[8]);
|
||||
}
|
||||
}
|
||||
|
||||
return { sys, eng, wep, boost, fuel, cargo, opponent, opponentBuild, engagementRange };
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggered when pips have been updated
|
||||
* @param {number} sys SYS pips
|
||||
@@ -130,7 +208,7 @@ export default class OutfittingPage extends Page {
|
||||
* @param {number} wep WEP pips
|
||||
*/
|
||||
_pipsUpdated(sys, eng, wep) {
|
||||
this.setState({ sys, eng, wep });
|
||||
this.setState({ sys, eng, wep }, () => this._updateRouteOnControlChange());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -138,7 +216,7 @@ export default class OutfittingPage extends Page {
|
||||
* @param {boolean} boost true if boosting
|
||||
*/
|
||||
_boostUpdated(boost) {
|
||||
this.setState({ boost });
|
||||
this.setState({ boost }, () => this._updateRouteOnControlChange());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,7 +224,7 @@ export default class OutfittingPage extends Page {
|
||||
* @param {number} fuel the amount of fuel, in T
|
||||
*/
|
||||
_fuelUpdated(fuel) {
|
||||
this.setState({ fuel });
|
||||
this.setState({ fuel }, () => this._updateRouteOnControlChange());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -154,7 +232,7 @@ export default class OutfittingPage extends Page {
|
||||
* @param {number} cargo the amount of cargo, in T
|
||||
*/
|
||||
_cargoUpdated(cargo) {
|
||||
this.setState({ cargo });
|
||||
this.setState({ cargo }, () => this._updateRouteOnControlChange());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -162,24 +240,44 @@ export default class OutfittingPage extends Page {
|
||||
* @param {number} engagementRange the engagement range, in m
|
||||
*/
|
||||
_engagementRangeUpdated(engagementRange) {
|
||||
this.setState({ engagementRange });
|
||||
this.setState({ engagementRange }, () => this._updateRouteOnControlChange());
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggered when target ship has been updated
|
||||
* @param {object} opponent the opponent's ship
|
||||
* @param {string} opponentBuild the name of the opponent's build
|
||||
* @param {string} opponent the opponent's ship model
|
||||
* @param {string} opponentBuild the name of the opponent's build
|
||||
*/
|
||||
_opponentUpdated(opponent, opponentBuild) {
|
||||
this.setState({ opponent, opponentBuild });
|
||||
const opponentShip = new Ship(opponent, Ships[opponent].properties, Ships[opponent].slots);
|
||||
if (opponentBuild && Persist.getBuild(opponent, opponentBuild)) {
|
||||
// Ship is a particular build
|
||||
opponentShip.buildFrom(Persist.getBuild(opponent, opponentBuild));
|
||||
} else {
|
||||
// Ship is a stock build
|
||||
opponentShip.buildWith(Ships[opponent].defaults);
|
||||
}
|
||||
|
||||
this.setState({ opponent: opponentShip, opponentBuild }, () => this._updateRouteOnControlChange());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the control code for this outfitting page
|
||||
* @param {number} fuel the fuel carried by the ship (if different from that in state)
|
||||
* @param {number} cargo the cargo carried by the ship (if different from that in state)
|
||||
* @returns {string} The control code
|
||||
*/
|
||||
_controlCode(fuel, cargo) {
|
||||
const { sys, eng, wep, 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}`;
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the current build
|
||||
*/
|
||||
_saveBuild() {
|
||||
let code = this.state.ship.toString();
|
||||
let { buildName, newBuildName, shipId } = this.state;
|
||||
const { code, buildName, newBuildName, shipId } = this.state;
|
||||
|
||||
if (buildName === newBuildName) {
|
||||
Persist.saveBuild(shipId, buildName, code);
|
||||
@@ -196,9 +294,8 @@ export default class OutfittingPage extends Page {
|
||||
* Rename the current build
|
||||
*/
|
||||
_renameBuild() {
|
||||
let { buildName, newBuildName, shipId, ship } = this.state;
|
||||
const { code, buildName, newBuildName, shipId, ship } = this.state;
|
||||
if (buildName != newBuildName && newBuildName.length) {
|
||||
let code = ship.toString();
|
||||
Persist.deleteBuild(shipId, buildName);
|
||||
Persist.saveBuild(shipId, newBuildName, code);
|
||||
this._updateRoute(shipId, newBuildName, code);
|
||||
@@ -210,16 +307,31 @@ export default class OutfittingPage extends Page {
|
||||
* Reload build from last save
|
||||
*/
|
||||
_reloadBuild() {
|
||||
this.state.ship.buildFrom(this.state.savedCode);
|
||||
this._shipUpdated();
|
||||
this.setState({ code: this.state.savedCode }, () => this._codeUpdated());
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset build to Stock/Factory defaults
|
||||
*/
|
||||
_resetBuild() {
|
||||
this.state.ship.buildWith(Ships[this.state.shipId].defaults);
|
||||
this._shipUpdated();
|
||||
const { ship, shipId, buildName } = this.state;
|
||||
// Rebuild ship
|
||||
ship.buildWith(Ships[shipId].defaults);
|
||||
// Reset controls
|
||||
const code = ship.toString();
|
||||
const { sys, eng, wep, boost, fuel, cargo, opponent, opponentBuild, engagementRange } = this._obtainControlFromCode(ship, code);
|
||||
// Update state, and refresh the ship
|
||||
this.setState({
|
||||
sys,
|
||||
eng,
|
||||
wep,
|
||||
boost,
|
||||
fuel,
|
||||
cargo,
|
||||
opponent,
|
||||
opponentBuild,
|
||||
engagementRange
|
||||
}, () => this._updateRoute(shipId, buildName, code));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -244,14 +356,43 @@ export default class OutfittingPage extends Page {
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger render on ship model change
|
||||
* Called when the code for the ship has been updated, to synchronise the rest of the data
|
||||
*/
|
||||
_codeUpdated() {
|
||||
const { code, ship, shipId, buildName } = this.state;
|
||||
|
||||
// Rebuild ship from the code
|
||||
this.state.ship.buildFrom(code);
|
||||
|
||||
// Obtain controls from the code
|
||||
const { sys, eng, wep, boost, fuel, cargo, opponent, opponentBuild, engagementRange } = this._obtainControlFromCode(ship, code);
|
||||
// Update state, and refresh the route when complete
|
||||
this.setState({
|
||||
sys,
|
||||
eng,
|
||||
wep,
|
||||
boost,
|
||||
fuel,
|
||||
cargo,
|
||||
opponent,
|
||||
opponentBuild,
|
||||
engagementRange
|
||||
}, () => this._updateRoute(shipId, buildName, code));
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the ship has been updated, to set the code and then update accordingly
|
||||
*/
|
||||
_shipUpdated() {
|
||||
let { shipId, buildName, ship } = this.state;
|
||||
let code = ship.toString();
|
||||
|
||||
this._updateRoute(shipId, buildName, code);
|
||||
this.setState({ code });
|
||||
let { ship, shipId, buildName, cargo, fuel } = this.state;
|
||||
if (cargo > ship.cargoCapacity) {
|
||||
cargo = ship.cargoCapacity;
|
||||
}
|
||||
if (fuel > ship.fuelCapacity) {
|
||||
fuel = ship.fuelCapacity;
|
||||
}
|
||||
const code = this._fullCode(ship, fuel, cargo);
|
||||
this.setState({ code, cargo, fuel }, () => this._updateRoute(shipId, buildName, code));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -271,7 +412,7 @@ export default class OutfittingPage extends Page {
|
||||
*/
|
||||
componentWillReceiveProps(nextProps, nextContext) {
|
||||
if (this.context.route !== nextContext.route) { // Only reinit state if the route has changed
|
||||
this.setState(this._initState(nextContext));
|
||||
this.setState(this._initState(nextProps, nextContext));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -340,16 +481,23 @@ export default class OutfittingPage extends Page {
|
||||
shipUpdated = this._shipUpdated,
|
||||
canSave = (newBuildName || buildName) && code !== savedCode,
|
||||
canRename = buildName && newBuildName && buildName != newBuildName,
|
||||
canReload = savedCode && canSave,
|
||||
hStr = ship.getHardpointsString() + '.' + ship.getModificationsString(),
|
||||
iStr = ship.getInternalString() + '.' + ship.getModificationsString();
|
||||
canReload = savedCode && canSave;
|
||||
|
||||
// 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 _sStr = ship.getStandardString();
|
||||
const _iStr = ship.getInternalString();
|
||||
const _hStr = ship.getHardpointsString();
|
||||
const _pStr = `${ship.getPowerEnabledString()}${ship.getPowerPrioritiesString()}`;
|
||||
const _mStr = ship.getModificationsString();
|
||||
|
||||
const standardSlotMarker = `${ship.name}${_sStr}${_pStr}${_mStr}`;
|
||||
const internalSlotMarker = `${ship.name}${_iStr}${_pStr}${_mStr}`;
|
||||
const hardpointsSlotMarker = `${ship.name}${_hStr}${_pStr}${_mStr}`;
|
||||
const boostMarker = `${ship.canBoost()}`;
|
||||
const shipSummaryMarker = `${ship.toString()}:${eng}:${fuel}:${cargo}`;
|
||||
const shipSummaryMarker = `${ship.toString()}${eng}${fuel}${cargo}`;
|
||||
|
||||
return (
|
||||
<div id='outfit' className={'page'} style={{ fontSize: (sizeRatio * 0.9) + 'em' }}>
|
||||
@@ -386,10 +534,10 @@ export default class OutfittingPage extends Page {
|
||||
|
||||
{/* Main tables */}
|
||||
<ShipSummaryTable ship={ship} marker={shipSummaryMarker} eng={eng} sys={sys} wep={wep} cargo={cargo} fuel={fuel}/>
|
||||
<StandardSlotSection ship={ship} code={code} onChange={shipUpdated} currentMenu={menu} />
|
||||
<InternalSlotSection ship={ship} code={iStr} onChange={shipUpdated} currentMenu={menu} />
|
||||
<HardpointsSlotSection ship={ship} code={hStr || ''} onChange={shipUpdated} currentMenu={menu} />
|
||||
<UtilitySlotSection ship={ship} code={hStr || ''} onChange={shipUpdated} currentMenu={menu} />
|
||||
<StandardSlotSection ship={ship} code={standardSlotMarker} onChange={shipUpdated} currentMenu={menu} />
|
||||
<InternalSlotSection ship={ship} code={internalSlotMarker} onChange={shipUpdated} currentMenu={menu} />
|
||||
<HardpointsSlotSection ship={ship} code={hardpointsSlotMarker} onChange={shipUpdated} currentMenu={menu} />
|
||||
<UtilitySlotSection ship={ship} code={hardpointsSlotMarker} onChange={shipUpdated} currentMenu={menu} />
|
||||
|
||||
{/* Control of ship and opponent */}
|
||||
<div className='group quarter'>
|
||||
@@ -397,28 +545,28 @@ export default class OutfittingPage extends Page {
|
||||
<h2 style={{ verticalAlign: 'middle', textAlign: 'left' }}>{translate('ship control')}</h2>
|
||||
</div>
|
||||
<div className='group half'>
|
||||
<Boost marker={boostMarker} ship={ship} onChange={this._boostUpdated} />
|
||||
<Boost marker={boostMarker} ship={ship} boost={boost} onChange={this._boostUpdated} />
|
||||
</div>
|
||||
</div>
|
||||
<div className='group quarter'>
|
||||
<Pips ship={ship} onChange={this._pipsUpdated} />
|
||||
<Pips sys={sys} eng={eng} wep={wep} onChange={this._pipsUpdated} />
|
||||
</div>
|
||||
<div className='group quarter'>
|
||||
<Fuel ship={ship} onChange={this._fuelUpdated}/>
|
||||
<Fuel fuelCapacity={ship.fuelCapacity} fuel={fuel} onChange={this._fuelUpdated}/>
|
||||
</div>
|
||||
<div className='group quarter'>
|
||||
{ ship.cargoCapacity > 0 ? <Cargo ship={ship} onChange={this._cargoUpdated}/> : null }
|
||||
{ ship.cargoCapacity > 0 ? <Cargo cargoCapacity={ship.cargoCapacity} cargo={cargo} onChange={this._cargoUpdated}/> : null }
|
||||
</div>
|
||||
<div className='group half'>
|
||||
<div className='group quarter'>
|
||||
<h2 style={{ verticalAlign: 'middle', textAlign: 'left' }}>{translate('opponent')}</h2>
|
||||
</div>
|
||||
<div className='group threequarters'>
|
||||
<ShipPicker onChange={this._opponentUpdated}/>
|
||||
<ShipPicker ship={opponent.id} build={opponentBuild} onChange={this._opponentUpdated}/>
|
||||
</div>
|
||||
</div>
|
||||
<div className='group half'>
|
||||
<EngagementRange ship={ship} onChange={this._engagementRangeUpdated}/>
|
||||
<EngagementRange ship={ship} engagementRange={engagementRange} onChange={this._engagementRangeUpdated}/>
|
||||
</div>
|
||||
|
||||
{/* Tabbed subpages */}
|
||||
|
||||
@@ -808,9 +808,9 @@ export function _weaponSustainedDps(m, opponent, opponentShields, opponentArmour
|
||||
|
||||
/**
|
||||
* Calculate time to drain WEP capacitor
|
||||
* @param {object} ship The ship
|
||||
* @param {number} wep Pips to WEP
|
||||
* @return The time to drain the WEP capacitor, in seconds
|
||||
* @param {object} ship The ship
|
||||
* @param {number} wep Pips to WEP
|
||||
* @returns {number} The time to drain the WEP capacitor, in seconds
|
||||
*/
|
||||
export function timeToDrainWep(ship, wep) {
|
||||
let totalSEps = 0;
|
||||
@@ -835,6 +835,12 @@ export function timeToDrainWep(ship, wep) {
|
||||
|
||||
/**
|
||||
* Calculate the time to deplete an amount of shields or armour
|
||||
* @param {number} amount The amount to be depleted
|
||||
* @param {number} dps The depletion per second
|
||||
* @param {number} eps The energy drained per second
|
||||
* @param {number} capacity The initial energy capacity
|
||||
* @param {number} recharge The energy recharged per second
|
||||
* @returns {number} The number of seconds to deplete to 0
|
||||
*/
|
||||
export function timeToDeplete(amount, dps, eps, capacity, recharge) {
|
||||
const drainPerSecond = eps - recharge;
|
||||
|
||||
Reference in New Issue
Block a user