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,
|
"shieldExplRes": 0.5,
|
||||||
"shieldKinRes": 0.4,
|
"shieldKinRes": 0.4,
|
||||||
"shieldThermRes": -0.2,
|
"shieldThermRes": -0.2,
|
||||||
"timeToDrain": 7.04,
|
|
||||||
"crew": 3
|
"crew": 3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,6 +76,7 @@
|
|||||||
"json-loader": "^0.5.3",
|
"json-loader": "^0.5.3",
|
||||||
"less": "^2.5.3",
|
"less": "^2.5.3",
|
||||||
"less-loader": "^2.2.1",
|
"less-loader": "^2.2.1",
|
||||||
|
"react-addons-perf": "^15.4.2",
|
||||||
"react-addons-test-utils": "^15.0.1",
|
"react-addons-test-utils": "^15.0.1",
|
||||||
"react-measure": "^1.4.6",
|
"react-measure": "^1.4.6",
|
||||||
"react-testutils-additions": "^15.1.0",
|
"react-testutils-additions": "^15.1.0",
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ export default class Boost extends TranslatedComponent {
|
|||||||
static propTypes = {
|
static propTypes = {
|
||||||
marker: React.PropTypes.string.isRequired,
|
marker: React.PropTypes.string.isRequired,
|
||||||
ship: React.PropTypes.object.isRequired,
|
ship: React.PropTypes.object.isRequired,
|
||||||
|
boost: React.PropTypes.bool.isRequired,
|
||||||
onChange: React.PropTypes.func.isRequired
|
onChange: React.PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -27,14 +28,10 @@ export default class Boost extends TranslatedComponent {
|
|||||||
*/
|
*/
|
||||||
constructor(props, context) {
|
constructor(props, context) {
|
||||||
super(props);
|
super(props);
|
||||||
const ship = props.ship;
|
const { ship, boost } = props;
|
||||||
|
|
||||||
this._keyDown = this._keyDown.bind(this);
|
this._keyDown = this._keyDown.bind(this);
|
||||||
this._toggleBoost = this._toggleBoost.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);
|
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
|
* Handle Key Down
|
||||||
* @param {Event} e Keyboard Event
|
* @param {Event} e Keyboard Event
|
||||||
@@ -91,10 +69,7 @@ export default class Boost extends TranslatedComponent {
|
|||||||
* Toggle the boost feature
|
* Toggle the boost feature
|
||||||
*/
|
*/
|
||||||
_toggleBoost() {
|
_toggleBoost() {
|
||||||
let { boost } = this.state;
|
this.props.onChange(!this.props.boost);
|
||||||
boost = !boost;
|
|
||||||
this.setState({ boost });
|
|
||||||
this.props.onChange(boost);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -103,8 +78,7 @@ export default class Boost extends TranslatedComponent {
|
|||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
const { formats, translate, units } = this.context.language;
|
const { formats, translate, units } = this.context.language;
|
||||||
const { ship } = this.props;
|
const { ship, boost } = this.props;
|
||||||
const { boost } = this.state;
|
|
||||||
|
|
||||||
// TODO disable if ship cannot boost
|
// TODO disable if ship cannot boost
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -9,7 +9,8 @@ import Slider from '../components/Slider';
|
|||||||
*/
|
*/
|
||||||
export default class Cargo extends TranslatedComponent {
|
export default class Cargo extends TranslatedComponent {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
ship: React.PropTypes.object.isRequired,
|
cargo: React.PropTypes.number.isRequired,
|
||||||
|
cargoCapacity: React.PropTypes.number.isRequired,
|
||||||
onChange: React.PropTypes.func.isRequired
|
onChange: React.PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -21,35 +22,7 @@ export default class Cargo extends TranslatedComponent {
|
|||||||
constructor(props, context) {
|
constructor(props, context) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
const ship = this.props.ship;
|
this._cargoChange = this._cargoChange.bind(this);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -57,14 +30,12 @@ export default class Cargo extends TranslatedComponent {
|
|||||||
* @param {number} cargoLevel percentage level from 0 to 1
|
* @param {number} cargoLevel percentage level from 0 to 1
|
||||||
*/
|
*/
|
||||||
_cargoChange(cargoLevel) {
|
_cargoChange(cargoLevel) {
|
||||||
const { cargoCapacity } = this.state;
|
const { cargo, cargoCapacity } = this.props;
|
||||||
if (cargoCapacity > 0) {
|
if (cargoCapacity > 0) {
|
||||||
// We round the cargo level to a suitable value given the capacity
|
// We round the cargo to whole number of tonnes
|
||||||
cargoLevel = Math.round(cargoLevel * cargoCapacity) / cargoCapacity;
|
const newCargo = Math.round(cargoLevel * cargoCapacity);
|
||||||
|
if (newCargo != cargo) {
|
||||||
if (cargoLevel != this.state.cargoLevel) {
|
this.props.onChange(newCargo);
|
||||||
this.setState({ cargoLevel });
|
|
||||||
this.props.onChange(Math.round(cargoLevel * cargoCapacity));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -76,20 +47,20 @@ export default class Cargo extends TranslatedComponent {
|
|||||||
render() {
|
render() {
|
||||||
const { language, onWindowResize, sizeRatio, tooltip, termtip } = this.context;
|
const { language, onWindowResize, sizeRatio, tooltip, termtip } = this.context;
|
||||||
const { formats, translate, units } = language;
|
const { formats, translate, units } = language;
|
||||||
const { cargoLevel, cargoCapacity } = this.state;
|
const { cargo, cargoCapacity } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span>
|
<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' }}>
|
<table style={{ width: '100%', lineHeight: '1em', backgroundColor: 'transparent' }}>
|
||||||
<tbody >
|
<tbody >
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<Slider
|
<Slider
|
||||||
axis={true}
|
axis={true}
|
||||||
onChange={this._cargoChange.bind(this)}
|
onChange={this._cargoChange}
|
||||||
axisUnit={translate('T')}
|
axisUnit={translate('T')}
|
||||||
percent={cargoLevel}
|
percent={cargo / cargoCapacity}
|
||||||
max={cargoCapacity}
|
max={cargoCapacity}
|
||||||
scale={sizeRatio}
|
scale={sizeRatio}
|
||||||
onResize={onWindowResize}
|
onResize={onWindowResize}
|
||||||
|
|||||||
@@ -7,9 +7,10 @@ import Slider from '../components/Slider';
|
|||||||
* Engagement range slider
|
* Engagement range slider
|
||||||
* Requires an onChange() function of the form onChange(range), providing the range in metres, which is triggered on range change
|
* 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 = {
|
static propTypes = {
|
||||||
ship: React.PropTypes.object.isRequired,
|
ship: React.PropTypes.object.isRequired,
|
||||||
|
engagementRange: React.PropTypes.number.isRequired,
|
||||||
onChange: React.PropTypes.func.isRequired
|
onChange: React.PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -21,47 +22,15 @@ export default class Range extends TranslatedComponent {
|
|||||||
constructor(props, context) {
|
constructor(props, context) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
const ship = this.props.ship;
|
const { ship } = props;
|
||||||
|
|
||||||
const maxRange = this._calcMaxRange(ship);
|
const maxRange = this._calcMaxRange(ship);
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
maxRange,
|
maxRange
|
||||||
rangeLevel: 1000 / 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
|
* Calculate the maximum range of a ship's weapons
|
||||||
* @param {Object} ship The ship
|
* @param {Object} ship The ship
|
||||||
@@ -87,12 +56,12 @@ export default class Range extends TranslatedComponent {
|
|||||||
*/
|
*/
|
||||||
_rangeChange(rangeLevel) {
|
_rangeChange(rangeLevel) {
|
||||||
const { maxRange } = this.state;
|
const { maxRange } = this.state;
|
||||||
// We round the range to an integer value
|
|
||||||
rangeLevel = Math.round(rangeLevel * maxRange) / maxRange;
|
|
||||||
|
|
||||||
if (rangeLevel != this.state.rangeLevel) {
|
// We round the range to an integer value
|
||||||
this.setState({ rangeLevel });
|
const range = Math.round(rangeLevel * maxRange);
|
||||||
this.props.onChange(Math.round(rangeLevel * maxRange));
|
|
||||||
|
if (range !== this.props.engagementRange) {
|
||||||
|
this.props.onChange(range);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,11 +72,12 @@ export default class Range extends TranslatedComponent {
|
|||||||
render() {
|
render() {
|
||||||
const { language, onWindowResize, sizeRatio, tooltip, termtip } = this.context;
|
const { language, onWindowResize, sizeRatio, tooltip, termtip } = this.context;
|
||||||
const { formats, translate, units } = language;
|
const { formats, translate, units } = language;
|
||||||
const { rangeLevel, maxRange } = this.state;
|
const { engagementRange } = this.props;
|
||||||
|
const { maxRange } = this.state;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span>
|
<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' }}>
|
<table style={{ width: '100%', lineHeight: '1em', backgroundColor: 'transparent' }}>
|
||||||
<tbody >
|
<tbody >
|
||||||
<tr>
|
<tr>
|
||||||
@@ -116,7 +86,7 @@ export default class Range extends TranslatedComponent {
|
|||||||
axis={true}
|
axis={true}
|
||||||
onChange={this._rangeChange.bind(this)}
|
onChange={this._rangeChange.bind(this)}
|
||||||
axisUnit={translate('m')}
|
axisUnit={translate('m')}
|
||||||
percent={rangeLevel}
|
percent={engagementRange / maxRange}
|
||||||
max={maxRange}
|
max={maxRange}
|
||||||
scale={sizeRatio}
|
scale={sizeRatio}
|
||||||
onResize={onWindowResize}
|
onResize={onWindowResize}
|
||||||
|
|||||||
@@ -9,7 +9,8 @@ import Slider from '../components/Slider';
|
|||||||
*/
|
*/
|
||||||
export default class Fuel extends TranslatedComponent {
|
export default class Fuel extends TranslatedComponent {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
ship: React.PropTypes.object.isRequired,
|
fuel: React.PropTypes.number.isRequired,
|
||||||
|
fuelCapacity: React.PropTypes.number.isRequired,
|
||||||
onChange: React.PropTypes.func.isRequired
|
onChange: React.PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -21,35 +22,7 @@ export default class Fuel extends TranslatedComponent {
|
|||||||
constructor(props, context) {
|
constructor(props, context) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
const ship = this.props.ship;
|
this._fuelChange = this._fuelChange.bind(this);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -57,8 +30,13 @@ export default class Fuel extends TranslatedComponent {
|
|||||||
* @param {number} fuelLevel percentage level from 0 to 1
|
* @param {number} fuelLevel percentage level from 0 to 1
|
||||||
*/
|
*/
|
||||||
_fuelChange(fuelLevel) {
|
_fuelChange(fuelLevel) {
|
||||||
this.setState({ fuelLevel });
|
const { fuel, fuelCapacity } = this.props;
|
||||||
this.props.onChange(fuelLevel * this.state.fuelCapacity);
|
|
||||||
|
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() {
|
render() {
|
||||||
const { language, onWindowResize, sizeRatio, tooltip, termtip } = this.context;
|
const { language, onWindowResize, sizeRatio, tooltip, termtip } = this.context;
|
||||||
const { formats, translate, units } = language;
|
const { formats, translate, units } = language;
|
||||||
const { fuelLevel, fuelCapacity } = this.state;
|
const { fuel, fuelCapacity } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span>
|
<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' }}>
|
<table style={{ width: '100%', lineHeight: '1em', backgroundColor: 'transparent' }}>
|
||||||
<tbody >
|
<tbody >
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<Slider
|
<Slider
|
||||||
axis={true}
|
axis={true}
|
||||||
onChange={this._fuelChange.bind(this)}
|
onChange={this._fuelChange}
|
||||||
axisUnit={translate('T')}
|
axisUnit={translate('T')}
|
||||||
percent={fuelLevel}
|
percent={fuel / fuelCapacity}
|
||||||
max={fuelCapacity}
|
max={fuelCapacity}
|
||||||
scale={sizeRatio}
|
scale={sizeRatio}
|
||||||
onResize={onWindowResize}
|
onResize={onWindowResize}
|
||||||
|
|||||||
@@ -66,9 +66,12 @@ export default class OutfittingSubpages extends TranslatedComponent {
|
|||||||
let { ship, buildName, code, onChange } = this.props;
|
let { ship, buildName, code, onChange } = this.props;
|
||||||
Persist.setOutfittingTab('power');
|
Persist.setOutfittingTab('power');
|
||||||
|
|
||||||
|
const powerMarker = `${ship.toString()}`;
|
||||||
|
const costMarker = `${ship.toString().split('.')[0]}`;
|
||||||
|
|
||||||
return <div>
|
return <div>
|
||||||
<PowerManagement ship={ship} code={code} onChange={onChange} />
|
<PowerManagement ship={ship} code={powerMarker} onChange={onChange} />
|
||||||
<CostSection ship={ship} buildName={buildName} code={code} />
|
<CostSection ship={ship} buildName={buildName} code={costMarker} />
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ import Module from '../shipyard/Module';
|
|||||||
*/
|
*/
|
||||||
export default class Pips extends TranslatedComponent {
|
export default class Pips extends TranslatedComponent {
|
||||||
static propTypes = {
|
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
|
onChange: React.PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -26,24 +28,9 @@ export default class Pips extends TranslatedComponent {
|
|||||||
*/
|
*/
|
||||||
constructor(props, context) {
|
constructor(props, context) {
|
||||||
super(props);
|
super(props);
|
||||||
const ship = props.ship;
|
const { sys, eng, wep } = props;
|
||||||
const pd = ship.standard[4].m;
|
|
||||||
|
|
||||||
this._keyDown = this._keyDown.bind(this);
|
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);
|
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
|
* Handle Key Down
|
||||||
* @param {Event} e Keyboard Event
|
* @param {Event} e Keyboard Event
|
||||||
@@ -142,10 +94,9 @@ export default class Pips extends TranslatedComponent {
|
|||||||
* Reset the capacitor
|
* Reset the capacitor
|
||||||
*/
|
*/
|
||||||
_reset() {
|
_reset() {
|
||||||
let { sys, eng, wep } = this.state;
|
let { sys, eng, wep } = this.props;
|
||||||
if (sys != 2 || eng != 2 || wep != 2) {
|
if (sys != 2 || eng != 2 || wep != 2) {
|
||||||
sys = eng = wep = 2;
|
sys = eng = wep = 2;
|
||||||
this.setState({ sys, eng, wep, pipsSvg: this._renderPips(sys, eng, wep) });
|
|
||||||
this.props.onChange(sys, eng, wep);
|
this.props.onChange(sys, eng, wep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -154,7 +105,7 @@ export default class Pips extends TranslatedComponent {
|
|||||||
* Increment the SYS capacitor
|
* Increment the SYS capacitor
|
||||||
*/
|
*/
|
||||||
_incSys() {
|
_incSys() {
|
||||||
let { sys, eng, wep } = this.state;
|
let { sys, eng, wep } = this.props;
|
||||||
|
|
||||||
const required = Math.min(1, 4 - sys);
|
const required = Math.min(1, 4 - sys);
|
||||||
if (required > 0) {
|
if (required > 0) {
|
||||||
@@ -181,7 +132,6 @@ export default class Pips extends TranslatedComponent {
|
|||||||
sys += 1;
|
sys += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.setState({ sys, eng, wep, pipsSvg: this._renderPips(sys, eng, wep) });
|
|
||||||
this.props.onChange(sys, eng, wep);
|
this.props.onChange(sys, eng, wep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -190,7 +140,7 @@ export default class Pips extends TranslatedComponent {
|
|||||||
* Increment the ENG capacitor
|
* Increment the ENG capacitor
|
||||||
*/
|
*/
|
||||||
_incEng() {
|
_incEng() {
|
||||||
let { sys, eng, wep } = this.state;
|
let { sys, eng, wep } = this.props;
|
||||||
|
|
||||||
const required = Math.min(1, 4 - eng);
|
const required = Math.min(1, 4 - eng);
|
||||||
if (required > 0) {
|
if (required > 0) {
|
||||||
@@ -217,7 +167,6 @@ export default class Pips extends TranslatedComponent {
|
|||||||
eng += 1;
|
eng += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.setState({ sys, eng, wep, pipsSvg: this._renderPips(sys, eng, wep) });
|
|
||||||
this.props.onChange(sys, eng, wep);
|
this.props.onChange(sys, eng, wep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -226,7 +175,7 @@ export default class Pips extends TranslatedComponent {
|
|||||||
* Increment the WEP capacitor
|
* Increment the WEP capacitor
|
||||||
*/
|
*/
|
||||||
_incWep() {
|
_incWep() {
|
||||||
let { sys, eng, wep } = this.state;
|
let { sys, eng, wep } = this.props;
|
||||||
|
|
||||||
const required = Math.min(1, 4 - wep);
|
const required = Math.min(1, 4 - wep);
|
||||||
if (required > 0) {
|
if (required > 0) {
|
||||||
@@ -253,7 +202,6 @@ export default class Pips extends TranslatedComponent {
|
|||||||
wep += 1;
|
wep += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.setState({ sys, eng, wep, pipsSvg: this._renderPips(sys, eng, wep) });
|
|
||||||
this.props.onChange(sys, eng, wep);
|
this.props.onChange(sys, eng, wep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -313,14 +261,14 @@ export default class Pips extends TranslatedComponent {
|
|||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
const { formats, translate, units } = this.context.language;
|
const { formats, translate, units } = this.context.language;
|
||||||
const { ship } = this.props;
|
const { sys, eng, wep } = this.props;
|
||||||
const { sys, eng, wep, sysCap, engCap, wepCap, sysRate, engRate, wepRate, pipsSvg } = this.state;
|
|
||||||
|
|
||||||
const onSysClicked = this.onClick.bind(this, 'SYS');
|
const onSysClicked = this.onClick.bind(this, 'SYS');
|
||||||
const onEngClicked = this.onClick.bind(this, 'ENG');
|
const onEngClicked = this.onClick.bind(this, 'ENG');
|
||||||
const onWepClicked = this.onClick.bind(this, 'WEP');
|
const onWepClicked = this.onClick.bind(this, 'WEP');
|
||||||
const onRstClicked = this.onClick.bind(this, 'RST');
|
const onRstClicked = this.onClick.bind(this, 'RST');
|
||||||
|
|
||||||
|
const pipsSvg = this._renderPips(sys, eng, wep);
|
||||||
return (
|
return (
|
||||||
<span id='pips'>
|
<span id='pips'>
|
||||||
<table>
|
<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 {
|
export default class ShipPicker extends TranslatedComponent {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
onChange: React.PropTypes.func.isRequired,
|
onChange: React.PropTypes.func.isRequired,
|
||||||
ship: React.PropTypes.object,
|
ship: React.PropTypes.string.isRequired,
|
||||||
build: React.PropTypes.string
|
build: React.PropTypes.string
|
||||||
};
|
};
|
||||||
|
|
||||||
static defaultProps = {
|
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._toggleMenu = this._toggleMenu.bind(this);
|
||||||
this._closeMenu = this._closeMenu.bind(this);
|
this._closeMenu = this._closeMenu.bind(this);
|
||||||
|
|
||||||
this.state = {
|
this.state = { menuOpen: false };
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update ship
|
* Update ship
|
||||||
* @param {object} shipId the ship
|
* @param {object} ship the ship
|
||||||
* @param {string} build the build, if present
|
* @param {string} build the build, if present
|
||||||
*/
|
*/
|
||||||
_shipChange(shipId, build) {
|
_shipChange(ship, 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);
|
|
||||||
}
|
|
||||||
this._closeMenu();
|
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
|
* @returns {object} the picker menu
|
||||||
*/
|
*/
|
||||||
_renderPickerMenu() {
|
_renderPickerMenu() {
|
||||||
const { ship, build } = this.state;
|
const { ship, build } = this.props;
|
||||||
const _shipChange = this._shipChange;
|
const _shipChange = this._shipChange;
|
||||||
|
|
||||||
const builds = Persist.getBuilds();
|
const builds = Persist.getBuilds();
|
||||||
@@ -86,7 +63,7 @@ export default class ShipPicker extends TranslatedComponent {
|
|||||||
for (let shipId of this.shipOrder) {
|
for (let shipId of this.shipOrder) {
|
||||||
const shipBuilds = [];
|
const shipBuilds = [];
|
||||||
// Add stock build
|
// 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>);
|
shipBuilds.push(<li key={shipId} className={ cn({ 'selected': stockSelected })} onClick={_shipChange.bind(this, shipId, null)}>Stock</li>);
|
||||||
if (builds[shipId]) {
|
if (builds[shipId]) {
|
||||||
let buildNameOrder = Object.keys(builds[shipId]).sort();
|
let buildNameOrder = Object.keys(builds[shipId]).sort();
|
||||||
@@ -126,9 +103,10 @@ export default class ShipPicker extends TranslatedComponent {
|
|||||||
render() {
|
render() {
|
||||||
const { language, onWindowResize, sizeRatio, tooltip, termtip } = this.context;
|
const { language, onWindowResize, sizeRatio, tooltip, termtip } = this.context;
|
||||||
const { formats, translate, units } = language;
|
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 (
|
return (
|
||||||
<div className='shippicker' onClick={ (e) => e.stopPropagation() }>
|
<div className='shippicker' onClick={ (e) => e.stopPropagation() }>
|
||||||
<div className='menu'>
|
<div className='menu'>
|
||||||
|
|||||||
@@ -30,24 +30,20 @@ export default class ShipSummaryTable extends TranslatedComponent {
|
|||||||
let u = language.units;
|
let u = language.units;
|
||||||
let formats = language.formats;
|
let formats = language.formats;
|
||||||
let { time, int, round, f1, f2 } = 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);
|
let hide = tooltip.bind(null, null);
|
||||||
|
|
||||||
if (ship.shield) {
|
const shieldGenerator = ship.findInternalByGroup('sg');
|
||||||
sgRecover = time(ship.calcShieldRecovery());
|
const sgClassNames = cn({ warning: shieldGenerator && !ship.shield, muted: !shieldGenerator });
|
||||||
sgRecharge = time(ship.calcShieldRecharge());
|
|
||||||
}
|
|
||||||
|
|
||||||
const timeToDrain = Calc.timeToDrainWep(ship, wep);
|
const timeToDrain = Calc.timeToDrainWep(ship, wep);
|
||||||
|
const canThrust = ship.canThrust();
|
||||||
|
const canBoost = ship.canBoost();
|
||||||
|
|
||||||
return <div id='summary'>
|
return <div id='summary'>
|
||||||
<table id='summaryTable'>
|
<table id='summaryTable'>
|
||||||
<thead>
|
<thead>
|
||||||
<tr className='main'>
|
<tr className='main'>
|
||||||
<th rowSpan={2} className={ cn({ 'bg-warning-disabled': !ship.canThrust() }) }>{translate('speed')}</th>
|
<th rowSpan={2} className={ cn({ 'bg-warning-disabled': !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': !canBoost }) }>{translate('boost')}</th>
|
||||||
<th onMouseEnter={termtip.bind(null, 'damage per second')} onMouseLeave={hide} rowSpan={2}>{translate('DPS')}</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, '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>
|
<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>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td>{ ship.canThrust() ? <span>{int(ship.calcSpeed(eng, fuel, cargo, false))}{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>{ ship.canBoost() ? <span>{int(ship.calcSpeed(eng, fuel, cargo, true))}{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.totalDps)}</td>
|
||||||
<td>{f1(ship.totalEps)}</td>
|
<td>{f1(ship.totalEps)}</td>
|
||||||
<td>{timeToDrain === Infinity ? '∞' : time(timeToDrain)}</td>
|
<td>{timeToDrain === Infinity ? '∞' : time(timeToDrain)}</td>
|
||||||
|
|||||||
@@ -1,14 +1,17 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
// import Perf from 'react-addons-perf';
|
||||||
import { findDOMNode } from 'react-dom';
|
import { findDOMNode } from 'react-dom';
|
||||||
import { Ships } from 'coriolis-data/dist';
|
import { Ships } from 'coriolis-data/dist';
|
||||||
import cn from 'classnames';
|
import cn from 'classnames';
|
||||||
import Page from './Page';
|
import Page from './Page';
|
||||||
import Router from '../Router';
|
import Router from '../Router';
|
||||||
import Persist from '../stores/Persist';
|
import Persist from '../stores/Persist';
|
||||||
|
import * as Utils from '../utils/UtilityFunctions';
|
||||||
import Ship from '../shipyard/Ship';
|
import Ship from '../shipyard/Ship';
|
||||||
import { toDetailedBuild } from '../shipyard/Serializer';
|
import { toDetailedBuild } from '../shipyard/Serializer';
|
||||||
import { outfitURL } from '../utils/UrlGenerators';
|
import { outfitURL } from '../utils/UrlGenerators';
|
||||||
import { FloppyDisk, Bin, Switch, Download, Reload, LinkIcon, ShoppingIcon } from '../components/SvgIcons';
|
import { FloppyDisk, Bin, Switch, Download, Reload, LinkIcon, ShoppingIcon } from '../components/SvgIcons';
|
||||||
|
import LZString from 'lz-string';
|
||||||
import ShipSummaryTable from '../components/ShipSummaryTable';
|
import ShipSummaryTable from '../components/ShipSummaryTable';
|
||||||
import StandardSlotSection from '../components/StandardSlotSection';
|
import StandardSlotSection from '../components/StandardSlotSection';
|
||||||
import HardpointsSlotSection from '../components/HardpointsSlotSection';
|
import HardpointsSlotSection from '../components/HardpointsSlotSection';
|
||||||
@@ -46,7 +49,8 @@ export default class OutfittingPage extends Page {
|
|||||||
*/
|
*/
|
||||||
constructor(props, context) {
|
constructor(props, context) {
|
||||||
super(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._keyDown = this._keyDown.bind(this);
|
||||||
this._exportBuild = this._exportBuild.bind(this);
|
this._exportBuild = this._exportBuild.bind(this);
|
||||||
this._pipsUpdated = this._pipsUpdated.bind(this);
|
this._pipsUpdated = this._pipsUpdated.bind(this);
|
||||||
@@ -59,10 +63,11 @@ export default class OutfittingPage extends Page {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* [Re]Create initial state from context
|
* [Re]Create initial state from context
|
||||||
|
* @param {Object} props React component properties
|
||||||
* @param {context} context React component context
|
* @param {context} context React component context
|
||||||
* @return {Object} New state object
|
* @return {Object} New state object
|
||||||
*/
|
*/
|
||||||
_initState(context) {
|
_initState(props, context) {
|
||||||
let params = context.route.params;
|
let params = context.route.params;
|
||||||
let shipId = params.ship;
|
let shipId = params.ship;
|
||||||
let code = params.code;
|
let code = params.code;
|
||||||
@@ -84,6 +89,8 @@ export default class OutfittingPage extends Page {
|
|||||||
|
|
||||||
this._getTitle = getTitle.bind(this, data.properties.name);
|
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 {
|
return {
|
||||||
error: null,
|
error: null,
|
||||||
title: this._getTitle(buildName),
|
title: this._getTitle(buildName),
|
||||||
@@ -94,14 +101,15 @@ export default class OutfittingPage extends Page {
|
|||||||
ship,
|
ship,
|
||||||
code,
|
code,
|
||||||
savedCode,
|
savedCode,
|
||||||
sys: 2,
|
sys,
|
||||||
eng: 2,
|
eng,
|
||||||
wep: 2,
|
wep,
|
||||||
fuel: ship.fuelCapacity,
|
boost,
|
||||||
cargo: 0,
|
fuel,
|
||||||
boost: false,
|
cargo,
|
||||||
engagementRange: 1000,
|
opponent,
|
||||||
opponent: new Ship('anaconda', Ships['anaconda'].properties, Ships['anaconda'].slots).buildWith(Ships['anaconda'].defaults)
|
opponentBuild,
|
||||||
|
engagementRange
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,6 +131,76 @@ export default class OutfittingPage extends Page {
|
|||||||
this.setState(stateChanges);
|
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
|
* Triggered when pips have been updated
|
||||||
* @param {number} sys SYS pips
|
* @param {number} sys SYS pips
|
||||||
@@ -130,7 +208,7 @@ export default class OutfittingPage extends Page {
|
|||||||
* @param {number} wep WEP pips
|
* @param {number} wep WEP pips
|
||||||
*/
|
*/
|
||||||
_pipsUpdated(sys, eng, wep) {
|
_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
|
* @param {boolean} boost true if boosting
|
||||||
*/
|
*/
|
||||||
_boostUpdated(boost) {
|
_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
|
* @param {number} fuel the amount of fuel, in T
|
||||||
*/
|
*/
|
||||||
_fuelUpdated(fuel) {
|
_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
|
* @param {number} cargo the amount of cargo, in T
|
||||||
*/
|
*/
|
||||||
_cargoUpdated(cargo) {
|
_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
|
* @param {number} engagementRange the engagement range, in m
|
||||||
*/
|
*/
|
||||||
_engagementRangeUpdated(engagementRange) {
|
_engagementRangeUpdated(engagementRange) {
|
||||||
this.setState({ engagementRange });
|
this.setState({ engagementRange }, () => this._updateRouteOnControlChange());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Triggered when target ship has been updated
|
* Triggered when target ship has been updated
|
||||||
* @param {object} opponent the opponent's ship
|
* @param {string} opponent the opponent's ship model
|
||||||
* @param {string} opponentBuild the name of the opponent's build
|
* @param {string} opponentBuild the name of the opponent's build
|
||||||
*/
|
*/
|
||||||
_opponentUpdated(opponent, opponentBuild) {
|
_opponentUpdated(opponent, opponentBuild) {
|
||||||
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
|
* Save the current build
|
||||||
*/
|
*/
|
||||||
_saveBuild() {
|
_saveBuild() {
|
||||||
let code = this.state.ship.toString();
|
const { code, buildName, newBuildName, shipId } = this.state;
|
||||||
let { buildName, newBuildName, shipId } = this.state;
|
|
||||||
|
|
||||||
if (buildName === newBuildName) {
|
if (buildName === newBuildName) {
|
||||||
Persist.saveBuild(shipId, buildName, code);
|
Persist.saveBuild(shipId, buildName, code);
|
||||||
@@ -196,9 +294,8 @@ export default class OutfittingPage extends Page {
|
|||||||
* Rename the current build
|
* Rename the current build
|
||||||
*/
|
*/
|
||||||
_renameBuild() {
|
_renameBuild() {
|
||||||
let { buildName, newBuildName, shipId, ship } = this.state;
|
const { code, buildName, newBuildName, shipId, ship } = this.state;
|
||||||
if (buildName != newBuildName && newBuildName.length) {
|
if (buildName != newBuildName && newBuildName.length) {
|
||||||
let code = ship.toString();
|
|
||||||
Persist.deleteBuild(shipId, buildName);
|
Persist.deleteBuild(shipId, buildName);
|
||||||
Persist.saveBuild(shipId, newBuildName, code);
|
Persist.saveBuild(shipId, newBuildName, code);
|
||||||
this._updateRoute(shipId, newBuildName, code);
|
this._updateRoute(shipId, newBuildName, code);
|
||||||
@@ -210,16 +307,31 @@ export default class OutfittingPage extends Page {
|
|||||||
* Reload build from last save
|
* Reload build from last save
|
||||||
*/
|
*/
|
||||||
_reloadBuild() {
|
_reloadBuild() {
|
||||||
this.state.ship.buildFrom(this.state.savedCode);
|
this.setState({ code: this.state.savedCode }, () => this._codeUpdated());
|
||||||
this._shipUpdated();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset build to Stock/Factory defaults
|
* Reset build to Stock/Factory defaults
|
||||||
*/
|
*/
|
||||||
_resetBuild() {
|
_resetBuild() {
|
||||||
this.state.ship.buildWith(Ships[this.state.shipId].defaults);
|
const { ship, shipId, buildName } = this.state;
|
||||||
this._shipUpdated();
|
// 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() {
|
_shipUpdated() {
|
||||||
let { shipId, buildName, ship } = this.state;
|
let { ship, shipId, buildName, cargo, fuel } = this.state;
|
||||||
let code = ship.toString();
|
if (cargo > ship.cargoCapacity) {
|
||||||
|
cargo = ship.cargoCapacity;
|
||||||
this._updateRoute(shipId, buildName, code);
|
}
|
||||||
this.setState({ code });
|
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) {
|
componentWillReceiveProps(nextProps, nextContext) {
|
||||||
if (this.context.route !== nextContext.route) { // Only reinit state if the route has changed
|
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,
|
shipUpdated = this._shipUpdated,
|
||||||
canSave = (newBuildName || buildName) && code !== savedCode,
|
canSave = (newBuildName || buildName) && code !== savedCode,
|
||||||
canRename = buildName && newBuildName && buildName != newBuildName,
|
canRename = buildName && newBuildName && buildName != newBuildName,
|
||||||
canReload = savedCode && canSave,
|
canReload = savedCode && canSave;
|
||||||
hStr = ship.getHardpointsString() + '.' + ship.getModificationsString(),
|
|
||||||
iStr = ship.getInternalString() + '.' + ship.getModificationsString();
|
|
||||||
|
|
||||||
// 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 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 || '');
|
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
|
// 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 boostMarker = `${ship.canBoost()}`;
|
||||||
const shipSummaryMarker = `${ship.toString()}:${eng}:${fuel}:${cargo}`;
|
const shipSummaryMarker = `${ship.toString()}${eng}${fuel}${cargo}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id='outfit' className={'page'} style={{ fontSize: (sizeRatio * 0.9) + 'em' }}>
|
<div id='outfit' className={'page'} style={{ fontSize: (sizeRatio * 0.9) + 'em' }}>
|
||||||
@@ -386,10 +534,10 @@ export default class OutfittingPage extends Page {
|
|||||||
|
|
||||||
{/* Main tables */}
|
{/* Main tables */}
|
||||||
<ShipSummaryTable ship={ship} marker={shipSummaryMarker} eng={eng} sys={sys} wep={wep} cargo={cargo} fuel={fuel}/>
|
<ShipSummaryTable ship={ship} marker={shipSummaryMarker} eng={eng} sys={sys} wep={wep} cargo={cargo} fuel={fuel}/>
|
||||||
<StandardSlotSection ship={ship} code={code} onChange={shipUpdated} currentMenu={menu} />
|
<StandardSlotSection ship={ship} code={standardSlotMarker} onChange={shipUpdated} currentMenu={menu} />
|
||||||
<InternalSlotSection ship={ship} code={iStr} onChange={shipUpdated} currentMenu={menu} />
|
<InternalSlotSection ship={ship} code={internalSlotMarker} onChange={shipUpdated} currentMenu={menu} />
|
||||||
<HardpointsSlotSection ship={ship} code={hStr || ''} onChange={shipUpdated} currentMenu={menu} />
|
<HardpointsSlotSection ship={ship} code={hardpointsSlotMarker} onChange={shipUpdated} currentMenu={menu} />
|
||||||
<UtilitySlotSection ship={ship} code={hStr || ''} onChange={shipUpdated} currentMenu={menu} />
|
<UtilitySlotSection ship={ship} code={hardpointsSlotMarker} onChange={shipUpdated} currentMenu={menu} />
|
||||||
|
|
||||||
{/* Control of ship and opponent */}
|
{/* Control of ship and opponent */}
|
||||||
<div className='group quarter'>
|
<div className='group quarter'>
|
||||||
@@ -397,28 +545,28 @@ export default class OutfittingPage extends Page {
|
|||||||
<h2 style={{ verticalAlign: 'middle', textAlign: 'left' }}>{translate('ship control')}</h2>
|
<h2 style={{ verticalAlign: 'middle', textAlign: 'left' }}>{translate('ship control')}</h2>
|
||||||
</div>
|
</div>
|
||||||
<div className='group half'>
|
<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>
|
</div>
|
||||||
<div className='group quarter'>
|
<div className='group quarter'>
|
||||||
<Pips ship={ship} onChange={this._pipsUpdated} />
|
<Pips sys={sys} eng={eng} wep={wep} onChange={this._pipsUpdated} />
|
||||||
</div>
|
</div>
|
||||||
<div className='group quarter'>
|
<div className='group quarter'>
|
||||||
<Fuel ship={ship} onChange={this._fuelUpdated}/>
|
<Fuel fuelCapacity={ship.fuelCapacity} fuel={fuel} onChange={this._fuelUpdated}/>
|
||||||
</div>
|
</div>
|
||||||
<div className='group quarter'>
|
<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>
|
||||||
<div className='group half'>
|
<div className='group half'>
|
||||||
<div className='group quarter'>
|
<div className='group quarter'>
|
||||||
<h2 style={{ verticalAlign: 'middle', textAlign: 'left' }}>{translate('opponent')}</h2>
|
<h2 style={{ verticalAlign: 'middle', textAlign: 'left' }}>{translate('opponent')}</h2>
|
||||||
</div>
|
</div>
|
||||||
<div className='group threequarters'>
|
<div className='group threequarters'>
|
||||||
<ShipPicker onChange={this._opponentUpdated}/>
|
<ShipPicker ship={opponent.id} build={opponentBuild} onChange={this._opponentUpdated}/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='group half'>
|
<div className='group half'>
|
||||||
<EngagementRange ship={ship} onChange={this._engagementRangeUpdated}/>
|
<EngagementRange ship={ship} engagementRange={engagementRange} onChange={this._engagementRangeUpdated}/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Tabbed subpages */}
|
{/* Tabbed subpages */}
|
||||||
|
|||||||
@@ -808,9 +808,9 @@ export function _weaponSustainedDps(m, opponent, opponentShields, opponentArmour
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate time to drain WEP capacitor
|
* Calculate time to drain WEP capacitor
|
||||||
* @param {object} ship The ship
|
* @param {object} ship The ship
|
||||||
* @param {number} wep Pips to WEP
|
* @param {number} wep Pips to WEP
|
||||||
* @return The time to drain the WEP capacitor, in seconds
|
* @returns {number} The time to drain the WEP capacitor, in seconds
|
||||||
*/
|
*/
|
||||||
export function timeToDrainWep(ship, wep) {
|
export function timeToDrainWep(ship, wep) {
|
||||||
let totalSEps = 0;
|
let totalSEps = 0;
|
||||||
@@ -835,6 +835,12 @@ export function timeToDrainWep(ship, wep) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate the time to deplete an amount of shields or armour
|
* 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) {
|
export function timeToDeplete(amount, dps, eps, capacity, recharge) {
|
||||||
const drainPerSecond = eps - recharge;
|
const drainPerSecond = eps - recharge;
|
||||||
|
|||||||
Reference in New Issue
Block a user