Changes for mods

This commit is contained in:
Cmdr McDonald
2016-10-30 20:54:36 +00:00
parent 0df051e40f
commit 4b14f617ec
9 changed files with 270 additions and 73 deletions

View File

@@ -2,6 +2,7 @@ import React from 'react';
import Slot from './Slot'; import Slot from './Slot';
import { DamageKinetic, DamageThermal, DamageExplosive, MountFixed, MountGimballed, MountTurret, ListModifications } from './SvgIcons'; import { DamageKinetic, DamageThermal, DamageExplosive, MountFixed, MountGimballed, MountTurret, ListModifications } from './SvgIcons';
import { Modifications } from 'coriolis-data/dist'; import { Modifications } from 'coriolis-data/dist';
import { stopCtxPropagation } from '../utils/UtilityFunctions';
/** /**
@@ -38,6 +39,7 @@ export default class HardpointSlot extends Slot {
if (m) { if (m) {
let classRating = `${m.class}${m.rating}${m.missile ? '/' + m.missile : ''}`; let classRating = `${m.class}${m.rating}${m.missile ? '/' + m.missile : ''}`;
let { drag, drop } = this.props; let { drag, drop } = this.props;
let { termtip, tooltip } = this.context;
let validMods = Modifications.validity[m.grp] || []; let validMods = Modifications.validity[m.grp] || [];
return <div className='details' draggable='true' onDragStart={drag} onDragEnd={drop}> return <div className='details' draggable='true' onDragStart={drag} onDragEnd={drop}>
@@ -62,7 +64,7 @@ export default class HardpointSlot extends Slot {
{ m.range && !m.dps ? <div className={'l'}>{translate('Range')} : {formats.round(m.range / 1000)}{u.km}</div> : null } { m.range && !m.dps ? <div className={'l'}>{translate('Range')} : {formats.round(m.range / 1000)}{u.km}</div> : null }
{ m.shieldmul ? <div className={'l'}>+{formats.rPct(m.shieldmul)}</div> : null } { m.shieldmul ? <div className={'l'}>+{formats.rPct(m.shieldmul)}</div> : null }
{ m.ammo >= 0 ? <div className={'l'}>{translate('ammo')}: {formats.int(m.clip)}/{formats.int(m.ammo)}</div> : null } { m.ammo >= 0 ? <div className={'l'}>{translate('ammo')}: {formats.int(m.clip)}/{formats.int(m.ammo)}</div> : null }
{ validMods.length > 0 ? <div className='r' ><ListModifications /></div> : null } { m && validMods.length > 0 ? <div className='r' ><button onClick={this._toggleModifications.bind(this)} onContextMenu={stopCtxPropagation} onMouseOver={termtip.bind(null, 'modifications')} onMouseOut={tooltip.bind(null, null)}><ListModifications /></button></div> : null }
</div> </div>
</div>; </div>;
} else { } else {

View File

@@ -2,6 +2,7 @@ import React from 'react';
import Slot from './Slot'; import Slot from './Slot';
import { ListModifications } from './SvgIcons'; import { ListModifications } from './SvgIcons';
import { Modifications } from 'coriolis-data/dist'; import { Modifications } from 'coriolis-data/dist';
import { stopCtxPropagation } from '../utils/UtilityFunctions';
/** /**
* Internal Slot * Internal Slot
@@ -20,6 +21,7 @@ export default class InternalSlot extends Slot {
if (m) { if (m) {
let classRating = m.class + m.rating; let classRating = m.class + m.rating;
let { drag, drop } = this.props; let { drag, drop } = this.props;
let { termtip, tooltip } = this.context;
let validMods = Modifications.validity[m.grp] || []; let validMods = Modifications.validity[m.grp] || [];
return <div className='details' draggable='true' onDragStart={drag} onDragEnd={drop}> return <div className='details' draggable='true' onDragStart={drag} onDragEnd={drop}>
@@ -44,7 +46,8 @@ export default class InternalSlot extends Slot {
{ m.rangeLS === null ? <div className={'l'}>{u.Ls}</div> : null } { m.rangeLS === null ? <div className={'l'}>{u.Ls}</div> : null }
{ m.rangeRating ? <div className={'l'}>{translate('range')}: {m.rangeRating}</div> : null } { m.rangeRating ? <div className={'l'}>{translate('range')}: {m.rangeRating}</div> : null }
{ m.armouradd ? <div className={'l'}>+{m.armouradd} <u className='cap'>{translate('armour')}</u></div> : null } { m.armouradd ? <div className={'l'}>+{m.armouradd} <u className='cap'>{translate('armour')}</u></div> : null }
{ validMods.length > 0 ? <div className='r' ><ListModifications /></div> : null } { m.passengers ? <div className={'l'}>{translate('passengers')}: {m.passengers}</div> : null }
{ m && validMods.length > 0 ? <div className='r' ><button onClick={this._toggleModifications.bind(this)} onContextMenu={stopCtxPropagation} onMouseOver={termtip.bind(null, 'modifications')} onMouseOut={tooltip.bind(null, null)}><ListModifications /></button></div> : null }
</div> </div>
</div>; </div>;
} else { } else {

View File

@@ -110,6 +110,7 @@ export default class InternalSlotSection extends SlotSection {
maxClass={s.maxClass} maxClass={s.maxClass}
availableModules={() => availableModules.getInts(ship, s.maxClass, s.eligible)} availableModules={() => availableModules.getInts(ship, s.maxClass, s.eligible)}
onOpen={this._openMenu.bind(this,s)} onOpen={this._openMenu.bind(this,s)}
onChange={this.props.onChange}
onSelect={this._selectModule.bind(this, s)} onSelect={this._selectModule.bind(this, s)}
selected={currentMenu == s} selected={currentMenu == s}
enabled={s.enabled} enabled={s.enabled}

View File

@@ -3,8 +3,11 @@ import TranslatedComponent from './TranslatedComponent';
import cn from 'classnames'; import cn from 'classnames';
import AvailableModulesMenu from './AvailableModulesMenu'; import AvailableModulesMenu from './AvailableModulesMenu';
import ModificationsMenu from './ModificationsMenu'; import ModificationsMenu from './ModificationsMenu';
import { Modifications } from 'coriolis-data/dist';
import { ListModifications } from './SvgIcons';
import { diffDetails } from '../utils/SlotFunctions'; import { diffDetails } from '../utils/SlotFunctions';
import { wrapCtxMenu } from '../utils/UtilityFunctions'; import { wrapCtxMenu } from '../utils/UtilityFunctions';
import { stopCtxPropagation } from '../utils/UtilityFunctions';
/** /**
* Abstract Slot * Abstract Slot
@@ -32,6 +35,8 @@ export default class Slot extends TranslatedComponent {
constructor(props) { constructor(props) {
super(props); super(props);
this._modificationsSelected = false;
this._contextMenu = wrapCtxMenu(this._contextMenu.bind(this)); this._contextMenu = wrapCtxMenu(this._contextMenu.bind(this));
this._getMaxClassLabel = this._getMaxClassLabel.bind(this); this._getMaxClassLabel = this._getMaxClassLabel.bind(this);
} }
@@ -73,9 +78,16 @@ export default class Slot extends TranslatedComponent {
*/ */
render() { render() {
let language = this.context.language; let language = this.context.language;
let { termtip, tooltip } = this.context;
let translate = language.translate; let translate = language.translate;
let { ship, m, dropClass, dragOver, onOpen, selected, onSelect, warning, shipMass, availableModules } = this.props; let { ship, m, dropClass, dragOver, onOpen, onChange, selected, onSelect, warning, shipMass, availableModules } = this.props;
let slotDetails, menu; let slotDetails, menu;
let validMods = m == null ? [] : (Modifications.validity[m.grp] || []);
if (!selected) {
// If not selected then sure that modifications flag is unset
this._modificationsSelected = false;
}
if (m) { if (m) {
slotDetails = this._getSlotDetails(m, translate, language.formats, language.units); // Must be implemented by sub classes slotDetails = this._getSlotDetails(m, translate, language.formats, language.units); // Must be implemented by sub classes
@@ -83,34 +95,41 @@ export default class Slot extends TranslatedComponent {
slotDetails = <div className={'empty'}>{translate('empty')}</div>; slotDetails = <div className={'empty'}>{translate('empty')}</div>;
} }
if (this.props.selected) { if (selected) {
menu = <AvailableModulesMenu if (this._modificationsSelected) {
className={this._getClassNames()} menu = <ModificationsMenu
modules={availableModules()} className={this._getClassNames()}
shipMass={ship.hullMass} onChange={onChange}
m={m} ship={ship}
onSelect={onSelect} m={m}
warning={warning} />;
diffDetails={diffDetails.bind(ship, this.context.language)} } else {
/>; menu = <AvailableModulesMenu
className={this._getClassNames()}
modules={availableModules()}
shipMass={ship.hullMass}
m={m}
onSelect={onSelect}
warning={warning}
diffDetails={diffDetails.bind(ship, this.context.language)}
/>;
}
} }
if (this.props.selected) {
menu = <ModificationsMenu
className={this._getClassNames()}
m={m}
/>;
}
// TODO: implement touch dragging // TODO: implement touch dragging
return ( return (
<div className={cn('slot', dropClass, { selected })} onClick={onOpen} onContextMenu={this._contextMenu} onDragOver={dragOver}> <div className={cn('slot', dropClass, { selected })} onClick={onOpen} onContextMenu={this._contextMenu} onDragOver={dragOver}>
<div className='details-container'> <div className='details-container'>
<div className='sz'>{this._getMaxClassLabel(translate)}</div> <div className='sz'>{this._getMaxClassLabel(translate)}</div>
{slotDetails} {slotDetails}
</div> </div>
{menu} {menu}
</div> </div>
); );
} }
_toggleModifications(event) {
this._modificationsSelected = !this._modificationsSelected;
}
} }

View File

@@ -25,6 +25,11 @@ export default class StandardSlot extends TranslatedComponent {
warning: React.PropTypes.func, warning: React.PropTypes.func,
}; };
constructor(props) {
super(props);
this._modificationsSelected = false;
}
/** /**
* Render the slot * Render the slot
* @return {React.Component} Slot component * @return {React.Component} Slot component
@@ -32,31 +37,36 @@ export default class StandardSlot extends TranslatedComponent {
render() { render() {
let { termtip, tooltip } = this.context; let { termtip, tooltip } = this.context;
let { translate, formats, units } = this.context.language; let { translate, formats, units } = this.context.language;
let { modules, slot, warning, onSelect, onChange, ladenMass, ship } = this.props; let { modules, slot, selected, warning, onSelect, onChange, ladenMass, ship } = this.props;
let m = slot.m; let m = slot.m;
let classRating = m.class + m.rating; let classRating = m.class + m.rating;
let menu; let menu;
let validMods = m == null ? [] : (Modifications.validity[m.grp] || []); let validMods = m == null ? [] : (Modifications.validity[m.grp] || []);
if (this.props.selected) { if (!selected) {
menu = <AvailableModulesMenu // If not selected then sure that modifications flag is unset
className='standard' this._modificationsSelected = false;
modules={modules}
shipMass={ship.ladenMass}
m={m}
onSelect={onSelect}
warning={warning}
diffDetails={diffDetails.bind(ship, this.context.language)}
/>;
} }
if (this.props.selected) { if (selected) {
menu = <ModificationsMenu if (this._modificationsSelected) {
className='standard' menu = <ModificationsMenu
onChange={onChange} className='standard'
ship={ship} onChange={onChange}
m={m} ship={ship}
/>; m={m}
/>;
} else {
menu = <AvailableModulesMenu
className='standard'
modules={modules}
shipMass={ship.ladenMass}
m={m}
onSelect={onSelect}
warning={warning}
diffDetails={diffDetails.bind(ship, this.context.language)}
/>;
}
} }
return ( return (
@@ -74,17 +84,22 @@ export default class StandardSlot extends TranslatedComponent {
{ m.getRange() ? <div className='l'>{translate('range')}: {m.getRange()}{units.km}</div> : null } { m.getRange() ? <div className='l'>{translate('range')}: {m.getRange()}{units.km}</div> : null }
{ m.time ? <div className='l'>{translate('time')}: {formats.time(m.time)}</div> : null } { m.time ? <div className='l'>{translate('time')}: {formats.time(m.time)}</div> : null }
{ m.getThermalEfficiency() ? <div className='l'>{translate('efficiency')}: {m.getThermalEfficiency()}</div> : null } { m.getThermalEfficiency() ? <div className='l'>{translate('efficiency')}: {m.getThermalEfficiency()}</div> : null }
{ m.getPowerGeneration() > 0 ? <div className='l'>{translate('power')}: {formats.round(m.getPowerGeneration())}{units.MW}</div> : null } { m.getPowerGeneration() > 0 ? <div className='l'>{translate('pGen')}: {formats.round(m.getPowerGeneration())}{units.MW}</div> : null }
{ m.getMaxFuelPerJump() ? <div className='l'>{translate('max')} {translate('fuel')}: {m.getMaxFuelPerJump()}{units.T}</div> : null } { m.getMaxFuelPerJump() ? <div className='l'>{translate('max')} {translate('fuel')}: {m.getMaxFuelPerJump()}{units.T}</div> : null }
{ m.getWeaponsCapacity() ? <div className='l'>{translate('WEP')}: {m.getWeaponsCapacity()}{units.MJ} / {m.getWeaponsRechargeRate()}{units.MW}</div> : null } { m.getWeaponsCapacity() ? <div className='l'>{translate('WEP')}: {m.getWeaponsCapacity()}{units.MJ} / {m.getWeaponsRechargeRate()}{units.MW}</div> : null }
{ m.getSystemsCapacity() ? <div className='l'>{translate('SYS')}: {m.getSystemsCapacity()}{units.MJ} / {m.getSystemsRechargeRate()}{units.MW}</div> : null } { m.getSystemsCapacity() ? <div className='l'>{translate('SYS')}: {m.getSystemsCapacity()}{units.MJ} / {m.getSystemsRechargeRate()}{units.MW}</div> : null }
{ m.getEnginesCapacity() ? <div className='l'>{translate('ENG')}: {m.getEnginesCapacity()}{units.MJ} / {m.getEnginesRechargeRate()}{units.MW}</div> : null } { m.getEnginesCapacity() ? <div className='l'>{translate('ENG')}: {m.getEnginesCapacity()}{units.MJ} / {m.getEnginesRechargeRate()}{units.MW}</div> : null }
{ validMods.length > 0 ? <div className='r' ><button onClick={this._toggleModifications.bind(this)} onContextMenu={stopCtxPropagation} onMouseOver={termtip.bind(null, 'modifications')} onMouseOut={tooltip.bind(null, null)}><ListModifications /></button></div> : null }
</div> </div>
</div> </div>
</div> </div>
{menu} {menu}
</div> </div>
); );
// { validMods.length > 0 ? <div className='r' ><button onClick={this._showModificationsMenu.bind(this, m)} onContextMenu={stopCtxPropagation} onMouseOver={termtip.bind(null, 'modifications')} onMouseOut={tooltip.bind(null, null)}><ListModifications /></button></div> : null } }
_toggleModifications() {
this._modificationsSelected = !this._modificationsSelected;
} }
} }

View File

@@ -78,5 +78,43 @@ export const terms = {
t: 'thrusters', t: 'thrusters',
tp: 'Torpedo Pylon', tp: 'Torpedo Pylon',
ul: 'Burst Laser', ul: 'Burst Laser',
ws: 'Frame Shift Wake Scanner' ws: 'Frame Shift Wake Scanner',
// Modifications
mass: 'Mass',
integrity: 'Integrity',
pGen: 'Power generation',
eff: 'Efficiency',
power: 'Power draw',
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',
range: 'Range',
rof: 'Rate of fire',
clip: 'Ammunition clip',
ammo: 'Ammunition maximum',
jitter: 'Jitter',
reload: 'Reload time'
}; };

View File

@@ -1,3 +1,4 @@
import Module from './Module';
/** /**
* Calculate the maximum single jump range based on mass and a specific FSD * Calculate the maximum single jump range based on mass and a specific FSD
@@ -8,7 +9,9 @@
* @return {number} Distance in Light Years * @return {number} Distance in Light Years
*/ */
export function jumpRange(mass, fsd, fuel) { export function jumpRange(mass, fsd, fuel) {
return Math.pow(Math.min(fuel === undefined ? fsd.getMaxFuelPerJump() : fuel, fsd.getMaxFuelPerJump()) / fsd.fuelmul, 1 / fsd.fuelpower) * fsd.getOptimalMass() / mass; let fsdMaxFuelPerJump = fsd instanceof Module ? fsd.getMaxFuelPerJump() : fsd.maxfuel;
let fsdOptimalMass = fsd instanceof Module ? fsd.getOptimalMass() : fsd.optmass;
return Math.pow(Math.min(fuel === undefined ? fsdMaxFuelPerJump : fuel, fsdMaxFuelPerJump) / fsd.fuelmul, 1 / fsd.fuelpower) * fsdOptimalMass / mass;
} }
/** /**
@@ -20,15 +23,17 @@ export function jumpRange(mass, fsd, fuel) {
* @return {number} Distance in Light Years * @return {number} Distance in Light Years
*/ */
export function fastestRange(mass, fsd, fuel) { export function fastestRange(mass, fsd, fuel) {
let fuelRemaining = fuel % fsd.getMaxFuelPerJump(); // Fuel left after making N max jumps let fsdMaxFuelPerJump = fsd instanceof Module ? fsd.getMaxFuelPerJump() : fsd.maxfuel;
let jumps = Math.floor(fuel / fsd.getMaxFuelPerJump()); let fsdOptimalMass = fsd instanceof Module ? fsd.getOptimalMass() : fsd.optmass;
let fuelRemaining = fuel % fsdMaxFuelPerJump; // Fuel left after making N max jumps
let jumps = Math.floor(fuel / fsdMaxFuelPerJump);
mass += fuelRemaining; mass += fuelRemaining;
// Going backwards, start with the last jump using the remaining fuel // Going backwards, start with the last jump using the remaining fuel
let fastestRange = fuelRemaining > 0 ? Math.pow(fuelRemaining / fsd.fuelmul, 1 / fsd.fuelpower) * fsd.getOptimalMass() / mass : 0; let fastestRange = fuelRemaining > 0 ? Math.pow(fuelRemaining / fsd.fuelmul, 1 / fsd.fuelpower) * fsdOptimalMass / mass : 0;
// For each max fuel jump, calculate the max jump range based on fuel mass left in the tank // For each max fuel jump, calculate the max jump range based on fuel mass left in the tank
for (let j = 0; j < jumps; j++) { for (let j = 0; j < jumps; j++) {
mass += fsd.maxfuel; mass += fsd.maxfuel;
fastestRange += Math.pow(fsd.getMaxFuelPerJump() / fsd.fuelmul, 1 / fsd.fuelpower) * fsd.getOptimalMass() / mass; fastestRange += Math.pow(fsdMaxFuelPerJump / fsd.fuelmul, 1 / fsd.fuelpower) * fsdOptimalMass / mass;
} }
return fastestRange; return fastestRange;
}; };
@@ -36,29 +41,30 @@ export function fastestRange(mass, fsd, fuel) {
/** /**
* Calculate the a ships shield strength based on mass, shield generator and shield boosters used. * Calculate the a ships shield strength based on mass, shield generator and shield boosters used.
* *
* @param {number} mass Current mass of the ship * @param {number} mass Current mass of the ship
* @param {number} shields Base Shield strength MJ for ship * @param {number} baseShield Base Shield strength MJ for ship
* @param {object} sg The shield generator used * @param {object} sg The shield generator used
* @param {number} multiplier Shield multiplier for ship (1 + shield boosters if any) * @param {number} multiplier Shield multiplier for ship (1 + shield boosters if any)
* @return {number} Approximate shield strengh in MJ * @return {number} Approximate shield strengh in MJ
*/ */
export function shieldStrength(mass, shields, sg, multiplier) { export function shieldStrength(mass, baseShield, sg, multiplier) {
let opt; // sg might be a module or a template; handle either here
if (mass < sg.minmass) { let minMass = sg instanceof Module ? sg.getMinMass() : sg.minmass;
return shields * multiplier * sg.minmul; let optMass = sg instanceof Module ? sg.getOptMass() : sg.optmass;
} let maxMass = sg instanceof Module ? sg.getMaxMass() : sg.maxmass;
if (mass > sg.maxmass) { let minMul = sg instanceof Module ? sg.getMinMul() : sg.minmul;
return shields * multiplier * sg.maxmul; let optMul = sg instanceof Module ? sg.getOptMul() : sg.optmul;
} let maxMul = sg instanceof Module ? sg.getMaxMul() : sg.maxmul;
if (mass < sg.optmass) {
opt = (sg.optmass - mass) / (sg.optmass - sg.minmass); let xnorm = Math.min(1, (maxMass - mass) / (maxMass - minMass));
opt = 1 - Math.pow(1 - opt, 0.87); let exponent = Math.log((optMul - minMul) / (maxMul - minMul)) / Math.log(Math.min(1, (maxMass - optMass) / (maxMass - minMass)))
return shields * multiplier * ((opt * sg.minmul) + ((1 - opt) * sg.optmul)); let ynorm = Math.pow(xnorm, exponent);
} else { let mul = minMul + ynorm * (maxMul - minMul);
opt = (sg.optmass - mass) / (sg.maxmass - sg.optmass); let strength = baseShield * mul;
opt = -1 + Math.pow(1 + opt, 2.425);
return shields * multiplier * ((-1 * opt * sg.maxmul) + ((1 + opt) * sg.optmul)); // TODO handle multiplier
}
return strength;
} }
/** /**
@@ -72,13 +78,24 @@ export function shieldStrength(mass, shields, sg, multiplier) {
* @return {object} Approximate speed by pips * @return {object} Approximate speed by pips
*/ */
export function speed(mass, baseSpeed, baseBoost, thrusters, pipSpeed) { export function speed(mass, baseSpeed, baseBoost, thrusters, pipSpeed) {
let multiplier = mass > thrusters.maxmass ? 0 : ((1 - thrusters.M) + (thrusters.M * Math.pow(3 - (2 * Math.max(0.5, mass / thrusters.optmass)), thrusters.P))); // thrusters might be a module or a template; handle either here
let speed = baseSpeed * multiplier; let minMass = thrusters instanceof Module ? thrusters.getMinMass() : thrusters.minmass;
let optMass = thrusters instanceof Module ? thrusters.getOptMass() : thrusters.optmass;
let maxMass = thrusters instanceof Module ? thrusters.getMaxMass() : thrusters.maxmass;
let minMul = thrusters instanceof Module ? thrusters.getMinMul() : thrusters.minmul;
let optMul = thrusters instanceof Module ? thrusters.getOptMul() : thrusters.optmul;
let maxMul = thrusters instanceof Module ? thrusters.getMaxMul() : thrusters.maxmul;
let xnorm = Math.min(1, (maxMass - mass) / (maxMass - minMass));
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 speed = baseSpeed * mul;
return { return {
'0 Pips': speed * (1 - (pipSpeed * 4)), '0 Pips': speed * (1 - (pipSpeed * 4)),
'2 Pips': speed * (1 - (pipSpeed * 2)), '2 Pips': speed * (1 - (pipSpeed * 2)),
'4 Pips': speed, '4 Pips': speed,
'boost': baseBoost * multiplier 'boost': baseBoost * mul
}; };
} }

View File

@@ -150,7 +150,17 @@ export default class Module {
* @return {Number} the heat per second of this module * @return {Number} the heat per second of this module
*/ */
getHeatPerSecond() { getHeatPerSecond() {
// Modifier for hps is thermload
return this._getModifiedValue('hps'); return this._getModifiedValue('hps');
let result = 0;
if (this['hps']) {
result = this['hps'];
if (result) {
let mult = this.getModValue('thermload');
if (mult) { result = result * (1 + mult); }
}
}
return result;
} }
/** /**
@@ -296,4 +306,88 @@ export default class Module {
getShieldReinforcement() { getShieldReinforcement() {
return this._getModifiedValue('shieldreinforcement'); return this._getModifiedValue('shieldreinforcement');
} }
/**
* Get the minimum mass for this module, taking in to account modifications
* @return {Number} the minimum mass of this module
*/
getMinMass() {
// Modifier is optmass
let result = 0;
if (this['minmass']) {
result = this['minmass'];
if (result) {
let mult = this.getModValue('optmass');
if (mult) { result = result * (1 + mult); }
}
}
return result;
}
/**
* Get the optimum mass for this module, taking in to account modifications
* @return {Number} the optimum mass of this module
*/
getOptMass() {
return this._getModifiedValue('optmass');
}
/**
* Get the maximum mass for this module, taking in to account modifications
* @return {Number} the maximum mass of this module
*/
getMaxMass() {
// Modifier is optmass
let result = 0;
if (this['maxmass']) {
result = this['maxmass'];
if (result) {
let mult = this.getModValue('optmass');
if (mult) { result = result * (1 + mult); }
}
}
return result;
}
/**
* Get the minimum multiplier for this module, taking in to account modifications
* @return {Number} the minimum multiplier of this module
*/
getMinMul() {
// Modifier is optmul
let result = 0;
if (this['minmul']) {
result = this['minmul'];
if (result) {
let mult = this.getModValue('optmul');
if (mult) { result = result * (1 + mult); }
}
}
return result;
}
/**
* Get the optimum multiplier for this module, taking in to account modifications
* @return {Number} the optimum multiplier of this module
*/
getOptMul() {
return this._getModifiedValue('optmul');
}
/**
* Get the maximum multiplier for this module, taking in to account modifications
* @return {Number} the maximum multiplier of this module
*/
getMaxMul() {
// Modifier is optmul
let result = 0;
if (this['maxmul']) {
result = this['maxmul'];
if (result) {
let mult = this.getModValue('optmul');
if (mult) { result = result * (1 + mult); }
}
}
return result;
}
} }

View File

@@ -179,7 +179,8 @@ export default class Ship {
*/ */
calcUnladenRange(massDelta, fuel, fsd) { calcUnladenRange(massDelta, fuel, fsd) {
fsd = fsd || this.standard[2].m; fsd = fsd || this.standard[2].m;
return Calc.jumpRange(this.unladenMass + (massDelta || 0) + Math.min(fsd.getMaxFuelPerJump(), fuel || this.fuelCapacity), fsd || this.standard[2].m, fuel); let fsdMaxFuelPerJump = fsd instanceof Module ? fsd.getMaxFuelPerJump() : fsd.maxfuel;
return Calc.jumpRange(this.unladenMass + (massDelta || 0) + Math.min(fsdMaxFuelPerJump, fuel || this.fuelCapacity), fsd || this.standard[2].m, fuel);
} }
/** /**
@@ -432,6 +433,13 @@ export default class Ship {
this.updateJumpStats(); this.updateJumpStats();
} else if (name == 'optmass') { } else if (name == 'optmass') {
m.setModValue(name, value); m.setModValue(name, value);
// Could be for either thrusters or FSD
this.updateTopSpeed();
this.updateJumpStats();
} else if (name == 'optmul') {
m.setModValue(name, value);
// Could be for either thrusters or FSD
this.updateTopSpeed();
this.updateJumpStats(); this.updateJumpStats();
} else { } else {
// Generic // Generic