mirror of
https://github.com/EDCD/coriolis.git
synced 2025-12-09 14:45:35 +00:00
Changes for mods
This commit is contained in:
@@ -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 {
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user