From e5cc3e269e7ee4b4ad481c0d7517128bfefe7751 Mon Sep 17 00:00:00 2001 From: Cmdr McDonald Date: Mon, 31 Oct 2016 11:22:36 +0000 Subject: [PATCH] Updates for modifications --- src/app/components/HardpointSlot.jsx | 16 ++--- src/app/components/HardpointsSlotSection.jsx | 1 + src/app/components/InternalSlot.jsx | 8 +-- src/app/components/InternalSlotSection.jsx | 1 + src/app/components/ModificationsMenu.jsx | 26 ++++++-- src/app/components/Slot.jsx | 5 +- src/app/components/StandardSlot.jsx | 18 ++--- src/app/components/UtilitySlotSection.jsx | 1 + src/app/i18n/en.js | 69 ++++++++++--------- src/app/shipyard/Calculations.js | 5 +- src/app/shipyard/Module.js | 70 +++++++++++++++++++- src/app/shipyard/ModuleSet.js | 2 +- src/app/shipyard/Ship.js | 9 ++- 13 files changed, 162 insertions(+), 69 deletions(-) diff --git a/src/app/components/HardpointSlot.jsx b/src/app/components/HardpointSlot.jsx index 18436ec1..18f35d36 100644 --- a/src/app/components/HardpointSlot.jsx +++ b/src/app/components/HardpointSlot.jsx @@ -56,14 +56,14 @@ export default class HardpointSlot extends Slot {
{m.getMass()}{u.T}
- { m.dps ?
{translate('DPS')}: {formats.round1(m.dps)} { m.clip ? ({formats.round1((m.clip * m.dps / m.rof) / ((m.clip / m.rof) + m.reload)) }) : null }
: null } - { m.eps ?
{translate('EPS')}: {formats.round1(m.eps)}{u.MW} { m.clip ? ({formats.round1((m.clip * m.eps / m.rof) / ((m.clip / m.rof) + m.reload)) }{u.MW}) : null }
: null } - { m.hps ?
{translate('HPS')}: {formats.round1(m.hps)} { m.clip ? ({formats.round1((m.clip * m.hps / m.rof) / ((m.clip / m.rof) + m.reload)) }) : null }
: null } - { m.dps && m.eps ?
{translate('DPE')}: {formats.round1(m.dps / m.eps)}
: null } - { m.rof ?
{translate('ROF')}: {m.rof}{u.ps}
: null } - { m.range && !m.dps ?
{translate('Range')} : {formats.round(m.range / 1000)}{u.km}
: null } - { m.shieldmul ?
+{formats.rPct(m.shieldmul)}
: null } - { m.ammo >= 0 ?
{translate('ammo')}: {formats.int(m.clip)}/{formats.int(m.ammo)}
: null } + { m.getDps() ?
{translate('DPS')}: {formats.round1(m.getDps())} { m.getClip() ? ({formats.round1((m.getClip() * m.getDps() / m.getRoF()) / ((m.getClip() / m.getRoF()) + m.getReload())) }) : null }
: null } + { 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.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 } { m && validMods.length > 0 ?
: null }
; diff --git a/src/app/components/HardpointsSlotSection.jsx b/src/app/components/HardpointsSlotSection.jsx index 3c51b3f2..378300ee 100644 --- a/src/app/components/HardpointsSlotSection.jsx +++ b/src/app/components/HardpointsSlotSection.jsx @@ -69,6 +69,7 @@ export default class HardpointsSlotSection extends SlotSection { availableModules={() => availableModules.getHps(h.maxClass)} onOpen={this._openMenu.bind(this, h)} onSelect={this._selectModule.bind(this, h)} + onChange={this.props.onChange} selected={currentMenu == h} drag={this._drag.bind(this, h)} dragOver={this._dragOverSlot.bind(this, h)} diff --git a/src/app/components/InternalSlot.jsx b/src/app/components/InternalSlot.jsx index 84fbc1c5..19b5b0c2 100644 --- a/src/app/components/InternalSlot.jsx +++ b/src/app/components/InternalSlot.jsx @@ -30,16 +30,16 @@ export default class InternalSlot extends Slot {
{m.getMass() || m.cargo || m.fuel || 0}{u.T}
- { m.optmass ?
{translate('optimal mass')}: {m.optmass}{u.T}
: null } - { m.maxmass ?
{translate('max mass')}: {m.maxmass}{u.T}
: null } + { m.getOptMass() ?
{translate('optimal mass')}: {m.getOptMass()}{u.T}
: null } + { m.getMaxMass() ?
{translate('max mass')}: {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 } - { m.ammo ?
{translate('ammo')}: {formats.gen(m.ammo)}
: null } + { m.getAmmo() ?
{translate('ammunition')}: {formats.gen(m.getAmmo())}
: null } { 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.range ?
{translate('range')} {m.range}{u.km}
: null } + { m.getRange() ?
{translate('range')} {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/InternalSlotSection.jsx b/src/app/components/InternalSlotSection.jsx index 66beab58..90e2ca73 100644 --- a/src/app/components/InternalSlotSection.jsx +++ b/src/app/components/InternalSlotSection.jsx @@ -114,6 +114,7 @@ export default class InternalSlotSection extends SlotSection { onSelect={this._selectModule.bind(this, s)} selected={currentMenu == s} enabled={s.enabled} + eligible={s.eligible} m={s.m} drag={this._drag.bind(this, s)} dragOver={this._dragOverSlot.bind(this, s)} diff --git a/src/app/components/ModificationsMenu.jsx b/src/app/components/ModificationsMenu.jsx index c844f253..9be631ac 100644 --- a/src/app/components/ModificationsMenu.jsx +++ b/src/app/components/ModificationsMenu.jsx @@ -41,15 +41,18 @@ export default class ModificationsMenu extends TranslatedComponent { let formats = context.language.formats; let { m } = props; let list = []; + let values = {}; for (let modName of Modifications.validity[m.grp]) { + values[modName] = m.getModValue(modName) * 100; list.push(
{translate(modName)}{' (%)'}
- +
); } + // - return { list }; + return { list, values }; } /** @@ -61,19 +64,30 @@ export default class ModificationsMenu extends TranslatedComponent { this.setState(this._initState(nextProps, nextContext)); } + _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 scaledValue = Math.floor(value * 100) / 10000; - let m = this.props.m; - let ship = this.props.ship; + let values = this.state.values; + values[name] = value; - ship.setModification(m, name, scaledValue); + // 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}); } /** diff --git a/src/app/components/Slot.jsx b/src/app/components/Slot.jsx index 6310ac15..7df6808a 100644 --- a/src/app/components/Slot.jsx +++ b/src/app/components/Slot.jsx @@ -22,6 +22,7 @@ export default class Slot extends TranslatedComponent { selected: React.PropTypes.bool, m: React.PropTypes.object, ship: React.PropTypes.object.isRequired, + eligible: React.PropTypes.object, warning: React.PropTypes.func, drag: React.PropTypes.func, drop: React.PropTypes.func, @@ -80,7 +81,7 @@ export default class Slot extends TranslatedComponent { let language = this.context.language; let { termtip, tooltip } = this.context; let translate = language.translate; - let { ship, m, dropClass, dragOver, onOpen, onChange, selected, onSelect, warning, shipMass, availableModules } = this.props; + let { ship, m, dropClass, dragOver, onOpen, onChange, selected, eligible, onSelect, warning, shipMass, availableModules } = this.props; let slotDetails, menu; let validMods = m == null ? [] : (Modifications.validity[m.grp] || []); @@ -92,7 +93,7 @@ export default class Slot extends TranslatedComponent { if (m) { slotDetails = this._getSlotDetails(m, translate, language.formats, language.units); // Must be implemented by sub classes } else { - slotDetails =
{translate('empty')}
; + slotDetails =
{translate(eligible ? 'emptyrestricted' : 'empty')}
; } if (selected) { diff --git a/src/app/components/StandardSlot.jsx b/src/app/components/StandardSlot.jsx index 49ae73fd..83492b90 100644 --- a/src/app/components/StandardSlot.jsx +++ b/src/app/components/StandardSlot.jsx @@ -75,20 +75,20 @@ export default class StandardSlot extends TranslatedComponent {
{slot.maxClass}
{classRating} {translate(m.grp == 'bh' ? m.grp : m.name || m.grp)}
-
{formats.round1(m.getMass()) || m.fuel || 0}{units.T}
+
{formats.round(m.getMass()) || m.fuel || 0}{units.T}
{ m.grp == 'bh' && m.name ?
{translate(m.name)}
: null } - { m.getOptimalMass() ?
{translate('optimal mass')}: {m.getOptimalMass()}{units.T}
: null } - { m.getMaxMass() ?
{translate('max mass')}: {m.getMaxMass()}{units.T}
: null } - { m.getRange() ?
{translate('range')}: {m.getRange()}{units.km}
: null } + { m.getOptimalMass() ?
{translate('optimal mass')}: {formats.round(m.getOptimalMass())}{units.T}
: null } + { m.getMaxMass() ?
{translate('max mass')}: {formats.round(m.getMaxMass())}{units.T}
: null } + { m.getRange() ?
{translate('range')}: {formats.round(m.getRange())}{units.km}
: null } { m.time ?
{translate('time')}: {formats.time(m.time)}
: null } - { m.getThermalEfficiency() ?
{translate('efficiency')}: {m.getThermalEfficiency()}
: null } + { m.getThermalEfficiency() ?
{translate('efficiency')}: {formats.round(m.getThermalEfficiency())}
: null } { m.getPowerGeneration() > 0 ?
{translate('pGen')}: {formats.round(m.getPowerGeneration())}{units.MW}
: null } - { m.getMaxFuelPerJump() ?
{translate('max')} {translate('fuel')}: {m.getMaxFuelPerJump()}{units.T}
: null } - { m.getWeaponsCapacity() ?
{translate('WEP')}: {m.getWeaponsCapacity()}{units.MJ} / {m.getWeaponsRechargeRate()}{units.MW}
: null } - { m.getSystemsCapacity() ?
{translate('SYS')}: {m.getSystemsCapacity()}{units.MJ} / {m.getSystemsRechargeRate()}{units.MW}
: null } - { m.getEnginesCapacity() ?
{translate('ENG')}: {m.getEnginesCapacity()}{units.MJ} / {m.getEnginesRechargeRate()}{units.MW}
: null } + { m.getMaxFuelPerJump() ?
{translate('max')} {translate('fuel')}: {formats.round(m.getMaxFuelPerJump())}{units.T}
: null } + { m.getWeaponsCapacity() ?
{translate('WEP')}: {formats.round(m.getWeaponsCapacity())}{units.MJ} / {formats.round(m.getWeaponsRechargeRate())}{units.MW}
: null } + { m.getSystemsCapacity() ?
{translate('SYS')}: {formats.round(m.getSystemsCapacity())}{units.MJ} / {formats.round(m.getSystemsRechargeRate())}{units.MW}
: null } + { m.getEnginesCapacity() ?
{translate('ENG')}: {formats.round(m.getEnginesCapacity())}{units.MJ} / {formats.round(m.getEnginesRechargeRate())}{units.MW}
: null } { validMods.length > 0 ?
: null }
diff --git a/src/app/components/UtilitySlotSection.jsx b/src/app/components/UtilitySlotSection.jsx index 0e922f83..7741a2c4 100644 --- a/src/app/components/UtilitySlotSection.jsx +++ b/src/app/components/UtilitySlotSection.jsx @@ -68,6 +68,7 @@ export default class UtilitySlotSection extends SlotSection { availableModules={() => availableModules.getHps(h.maxClass)} onOpen={this._openMenu.bind(this,h)} onSelect={this._selectModule.bind(this, h)} + onChange={this.props.onChange} selected={currentMenu == h} drag={this._drag.bind(this, h)} dragOver={this._dragOverSlot.bind(this, h)} diff --git a/src/app/i18n/en.js b/src/app/i18n/en.js index ce8a535f..1c9a7de6 100644 --- a/src/app/i18n/en.js +++ b/src/app/i18n/en.js @@ -80,41 +80,48 @@ export const terms = { ul: 'Burst Laser', ws: 'Frame Shift Wake Scanner', + // Items on the outfitting page + // Notification of restricted slot for Orca/Beluga + emptyrestricted: 'empty (restricted)', + // 'ammo' was overloaded for outfitting page and modul info, so changed to ammunition for outfitting page + ammunition: 'Ammo', + // Modifications - mass: 'Mass', - integrity: 'Integrity', - pGen: 'Power generation', + ammo: 'Ammunition maximum', + armourpen: 'Armour penetration', + boot: 'Boot time', + brokenregen: 'Broken regeneration rate', + burst: 'Burst', + clip: 'Ammunition clip', + damage: 'Damage', + delay: 'Delay', + dps: 'Damage per second', + distdraw: 'Distributor draw', + duration: 'Duration', eff: 'Efficiency', - power: 'Power draw', + engcap: 'Engines capacity', + engrate: 'Engines recharge rate', + eps: 'Energy per second', + explres: 'Explosive resistance', + integrity: 'Integrity', + jitter: 'Jitter', + kinres: 'Kinetic resistance', + maxfuel: 'Maximum fuel per jump', + mass: 'Mass', optmass: 'Optimal mass', optmul: 'Optimal multiplier', - dps: 'Damage per second', - eps: 'Energy per second', - thermload: 'Thermal load', - boot: 'Boot time', - maxfuel: 'Maximum fuel per jump', - syscap: 'Systems capacity', - engcap: 'Engines capacity', - wepcap: 'Weapons capacity', - sysrate: 'Systems recharge rate', - engrate: 'Engines recharge rate', - weprate: 'Weapons recharge rate', - kinres: 'Kinetic resistance', - thermres: 'Thermal resistance', - explres: 'Explosive resistance', - regen: 'Regeneration rate', - brokenregen: 'Broken regeneration rate', - delay: 'Delay', - duration: 'Duration', - shield: 'Shield', - shieldboost: 'Shield boost', - distdraw: 'Distributor draw', - damage: 'Damage', - armourpen: 'Armour penetration', + pGen: 'Power generation', + power: 'Power draw', range: 'Range', + regen: 'Regeneration rate', + reload: 'Reload time', rof: 'Rate of fire', - clip: 'Ammunition clip', - ammo: 'Ammunition maximum', - jitter: 'Jitter', - reload: 'Reload time' + shield: 'Shield', + shieldmul: 'Shield boost', + syscap: 'Systems capacity', + sysrate: 'Systems recharge rate', + thermload: 'Thermal load', + thermres: 'Thermal resistance', + wepcap: 'Weapons capacity', + weprate: 'Weapons recharge rate', }; diff --git a/src/app/shipyard/Calculations.js b/src/app/shipyard/Calculations.js index 6fa9c88d..21d818d6 100644 --- a/src/app/shipyard/Calculations.js +++ b/src/app/shipyard/Calculations.js @@ -60,11 +60,8 @@ export function shieldStrength(mass, baseShield, sg, multiplier) { let exponent = Math.log((optMul - minMul) / (maxMul - minMul)) / Math.log(Math.min(1, (maxMass - optMass) / (maxMass - minMass))) let ynorm = Math.pow(xnorm, exponent); let mul = minMul + ynorm * (maxMul - minMul); - let strength = baseShield * mul; - // TODO handle multiplier - - return strength; + return baseShield * mul * multiplier; } /** diff --git a/src/app/shipyard/Module.js b/src/app/shipyard/Module.js index efae87ca..c4eccac6 100755 --- a/src/app/shipyard/Module.js +++ b/src/app/shipyard/Module.js @@ -32,7 +32,7 @@ export default class Module { * @return {Number} The value of the modification, as a decimal value from -1 to 1 */ getModValue(name) { - return this.mods ? this.mods[name] / 10000 : null; + return this.mods && this.mods[name] ? this.mods[name] / 10000 : null; } /** @@ -390,4 +390,72 @@ export default class Module { } return result; } + + /** + * Get the shield multiplier for this module, taking in to account modifications + * @return {Number} the shield multiplier of this module + */ + getShieldMul() { + return this._getModifiedValue('shieldmul'); + } + + + /** + * Get the DPS for this module, taking in to account modifications + * @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'); + } + + /** + * Get the heat generated per second for this module, taking in to account modifications + * @return {Number} the heat generated per second of this module + */ + getHps() { + // TODO this is not correct; need to include other factors such as rate of fire, damage, etc. + return this._getModifiedValue('hps'); + } + + /** + * Get the energy used per second for this module, taking in to account modifications + * @return {Number} the energy used per second of this module + */ + getEps() { + // TODO this is not correct; need to include other factors such as rate of fire, damage, etc. + return this._getModifiedValue('eps'); + } + + /** + * Get the clip size for this module, taking in to account modifications + * @return {Number} the clip size of this module + */ + getClip() { + return this._getModifiedValue('clip'); + } + + /** + * Get the ammo size for this module, taking in to account modifications + * @return {Number} the ammo size of this module + */ + getAmmo() { + return this._getModifiedValue('ammo'); + } + + /** + * Get the reload time for this module, taking in to account modifications + * @return {Number} the reload time of this module + */ + getReload() { + return this._getModifiedValue('reload'); + } + + /** + * Get the rate of fire for this module, taking in to account modifications + * @return {Number} the rate of fire for this module + */ + getRoF() { + return this._getModifiedValue('rof'); + } } diff --git a/src/app/shipyard/ModuleSet.js b/src/app/shipyard/ModuleSet.js index b3ddf314..9fa480ee 100755 --- a/src/app/shipyard/ModuleSet.js +++ b/src/app/shipyard/ModuleSet.js @@ -126,7 +126,7 @@ export default class ModuleSet { let pd = this.standard[4][0]; for (let p of this.standard[4]) { - if (p.mass < pd.mass && p.getEnginesCapacity() >= boostEnergy) { + if (p.mass < pd.mass && p.engcap >= boostEnergy) { pd = p; } } diff --git a/src/app/shipyard/Ship.js b/src/app/shipyard/Ship.js index 09085b9a..6d1720dd 100755 --- a/src/app/shipyard/Ship.js +++ b/src/app/shipyard/Ship.js @@ -441,6 +441,9 @@ export default class Ship { // Could be for either thrusters or FSD this.updateTopSpeed(); this.updateJumpStats(); + } else if (name == 'shieldmul') { + m.setModValue(name, value); + this.updateShieldStrength(); } else { // Generic m.setModValue(name, value); @@ -686,7 +689,7 @@ export default class Ship { if (ModuleUtils.isShieldGenerator(slot.m.grp)) { this.updateShieldStrength(); } else if (slot.m.grp == 'sb') { - this.shieldMultiplier += slot.m.shieldmul * (enabled ? 1 : -1); + this.shieldMultiplier += slot.m.getShieldMul() * (enabled ? 1 : -1); this.updateShieldStrength(); } if (slot.m.dps) { @@ -752,7 +755,7 @@ export default class Ship { this.armourAdded -= old.armouradd; break; case 'sb': - this.shieldMultiplier -= slot.enabled ? old.shieldmul : 0; + this.shieldMultiplier -= slot.enabled ? old.getShieldMul() : 0; break; } @@ -794,7 +797,7 @@ export default class Ship { this.armourAdded += n.armouradd; break; case 'sb': - this.shieldMultiplier += slot.enabled ? n.shieldmul : 0; + this.shieldMultiplier += slot.enabled ? n.getShieldMul() : 0; break; }