From 258701c3776eeffb38d43c0b1391a446397bce56 Mon Sep 17 00:00:00 2001 From: Cmdr McDonald Date: Mon, 31 Oct 2016 23:19:22 +0000 Subject: [PATCH] Separate modification slider in to its own component --- src/app/components/HardpointSlot.jsx | 2 +- src/app/components/InternalSlot.jsx | 6 +-- src/app/components/Modification.jsx | 60 ++++++++++++++++++++++++ src/app/components/ModificationsMenu.jsx | 53 ++------------------- src/app/shipyard/Module.js | 18 ++++++- 5 files changed, 84 insertions(+), 55 deletions(-) create mode 100644 src/app/components/Modification.jsx diff --git a/src/app/components/HardpointSlot.jsx b/src/app/components/HardpointSlot.jsx index e2589d5d..ede05551 100644 --- a/src/app/components/HardpointSlot.jsx +++ b/src/app/components/HardpointSlot.jsx @@ -60,7 +60,7 @@ export default class HardpointSlot extends Slot { { m.getEps() ?
{translate('EPS')}: {formats.round1(m.getEps())}{u.MW} { m.getClip() ? ({formats.round1((m.getClip() * m.getEps() / m.getRoF()) / ((m.getClip() / m.getRoF()) + m.getReload())) }{u.MW}) : null }
: null } { m.getHps() ?
{translate('HPS')}: {formats.round1(m.getHps())} { m.getClip() ? ({formats.round1((m.getClip() * m.getHps() / m.getRoF()) / ((m.getClip() / m.getRoF()) + m.getReload())) }) : null }
: null } { m.getDps() && m.getEps() ?
{translate('DPE')}: {formats.round1(m.getDps() / m.getEps())}
: null } - { m.getRoF() ?
{translate('ROF')}: {m.getRoF()}{u.ps}
: null } + { m.getRoF() ?
{translate('ROF')}: {formats.f1(m.getRoF())}{u.ps}
: null } { m.getRange() && !m.getDps() ?
{translate('Range')} : {formats.round(m.getRange() / 1000)}{u.km}
: null } { m.getShieldMul() ?
+{formats.rPct(m.getShieldMul())}
: null } { m.getAmmo() ?
{translate('ammunition')}: {formats.int(m.getClip())}/{formats.int(m.getAmmo())}
: null } diff --git a/src/app/components/InternalSlot.jsx b/src/app/components/InternalSlot.jsx index a5467b01..e5771787 100644 --- a/src/app/components/InternalSlot.jsx +++ b/src/app/components/InternalSlot.jsx @@ -30,8 +30,8 @@ export default class InternalSlot extends Slot {
{formats.round1(m.getMass()) || m.cargo || m.fuel || 0}{u.T}
- { m.getOptMass() ?
{translate('optimal mass')}: {m.getOptMass()}{u.T}
: null } - { m.getMaxMass() ?
{translate('max mass')}: {m.getMaxMass()}{u.T}
: null } + { m.getOptMass() ?
{translate('optimal mass')}: {formats.int(m.getOptMass())}{u.T}
: null } + { m.getMaxMass() ?
{translate('max mass')}: {formats.int(m.getMaxMass())}{u.T}
: null } { m.bins ?
{m.bins} {translate('bins')}
: null } { m.bays ?
{translate('bays')}: {m.bays}
: null } { m.rate ?
{translate('rate')}: {m.rate}{u.kgs}   {translate('refuel time')}: {formats.time(this.props.fuel * 1000 / m.rate)}
: null } @@ -39,7 +39,7 @@ export default class InternalSlot extends Slot { { m.cells ?
{translate('cells')}: {m.cells}
: null } { m.recharge ?
{translate('recharge')}: {m.recharge} MJ   {translate('total')}: {m.cells * m.recharge}{u.MJ}
: null } { m.repair ?
{translate('repair')}: {m.repair}
: null } - { m.getRange() ?
{translate('range')} {m.getRange()}{u.km}
: null } + { m.getRange() ?
{translate('range')} {formats.f2(m.getRange())}{u.km}
: null } { m.time ?
{translate('time')}: {formats.time(m.time)}
: null } { m.maximum ?
{translate('max')}: {(m.maximum)}
: null } { m.rangeLS ?
{translate('range')}: {m.rangeLS}{u.Ls}
: null } diff --git a/src/app/components/Modification.jsx b/src/app/components/Modification.jsx new file mode 100644 index 00000000..072b6d92 --- /dev/null +++ b/src/app/components/Modification.jsx @@ -0,0 +1,60 @@ +import React from 'react'; +import { findDOMNode } from 'react-dom'; +import TranslatedComponent from './TranslatedComponent'; +import cn from 'classnames'; +import NumberEditor from 'react-number-editor'; + +/** + * Modification + */ +export default class ModificationsMenu extends TranslatedComponent { + + static propTypes = { + ship: React.PropTypes.object.isRequired, + m: React.PropTypes.object.isRequired, + name: React.PropTypes.string.isRequired, + onChange: React.PropTypes.func.isRequired + }; + + /** + * Constructor + * @param {Object} props React Component properties + * @param {Object} context React Component context + */ + constructor(props, context) { + super(props); + this.state = {}; + this.state.value = this.props.m.getModValue(this.props.name) * 100 || 0; + } + + /** + * Update modification given a value. + * @param {Number} value The value to set + */ + _updateValue(value) { + let scaledValue = Math.floor(Number(value) * 100) / 10000; + let m = this.props.m; + let name = this.props.name; + let ship = this.props.ship; + ship.setModification(m, name, scaledValue); + + this.setState({ value }); + this.props.onChange(); + } + + /** + * Render the modification + * @return {React.Component} modification + */ + render() { + let translate = this.context.language.translate; + let name = this.props.name; + + return ( +
+
{translate(name)}{' (%)'}
+ +
+ ); + } +} diff --git a/src/app/components/ModificationsMenu.jsx b/src/app/components/ModificationsMenu.jsx index a70de410..871b6a08 100644 --- a/src/app/components/ModificationsMenu.jsx +++ b/src/app/components/ModificationsMenu.jsx @@ -5,7 +5,7 @@ import { stopCtxPropagation } from '../utils/UtilityFunctions'; import cn from 'classnames'; import { MountFixed, MountGimballed, MountTurret } from './SvgIcons'; import { Modifications } from 'coriolis-data/dist'; -import NumberEditor from 'react-number-editor'; +import Modification from './Modification'; const PRESS_THRESHOLD = 500; // mouse/touch down threshold @@ -39,59 +39,14 @@ export default class ModificationsMenu extends TranslatedComponent { _initState(props, context) { let translate = context.language.translate; let formats = context.language.formats; - let { m } = props; + let { m, onChange, ship } = props; let list = []; - let values = {}; for (let modName of Modifications.validity[m.grp]) { - values[modName] = m.getModValue(modName) * 100; - list.push(
-
{translate(modName)}{' (%)'}
- -
); + list.push(); } - return { list, values }; - } - - /** - * Update state based on property and context changes - * @param {Object} nextProps Incoming/Next properties - * @param {Object} nextContext Incoming/Next conext - */ - componentWillReceiveProps(nextProps, nextContext) { - this.setState(this._initState(nextProps, nextContext)); - } - - /** - * Get the locally stored value of the modifier - * @param {string} name the name of the value to obtain - * @param {Number} defaultValue the value to use if none is held locally - * @return {Number} the value - */ - _getValue(name, defaultValue) { - let values = this.state ? this.state.values : null; - return values ? values[name] : defaultValue; - } - - /** - * Update modification given a value. - * @param {Number} name The name of the modification - * @param {Number} value The value to set, in the range [0,1] - */ - _updateValue(name, value) { - let values = this.state.values; - values[name] = value; - - // Only update the modification if this is a valid number - if (!isNaN(Number(value)) && !value.endsWith('.')) { - let scaledValue = Math.floor(Number(value) * 100) / 10000; - let m = this.props.m; - let ship = this.props.ship; - ship.setModification(m, name, scaledValue); - } - this.props.onChange(); - this.setState({ values }); + return { list }; } /** diff --git a/src/app/shipyard/Module.js b/src/app/shipyard/Module.js index c4eccac6..a8074409 100755 --- a/src/app/shipyard/Module.js +++ b/src/app/shipyard/Module.js @@ -405,8 +405,22 @@ export default class Module { * @return {Number} the DPS of this module */ getDps() { - // TODO this is not correct; need to include other factors such as rate of fire, damage, etc. - return this._getModifiedValue('dps'); + // Modifications are not made to DPS directly, but to damage and rate of fire + + // Obtain unmodified rate of fire + let rof = this['rof']; + + // Obtain unmodified damage + let damage = this['dps'] / rof; + + // Obtain modified rate of fire + let modRof = this._getModifiedValue('rof'); + + // Obtain modified damage + let damageMult = this.getModValue('damage'); + let modDamage = damageMult ? damage * (1 + damageMult) : damage; + + return modDamage * modRof; } /**