mirror of
https://github.com/EDCD/coriolis.git
synced 2025-12-09 14:45:35 +00:00
Rework modules to be individual objects rather than references to templates
This commit is contained in:
@@ -32,6 +32,7 @@
|
|||||||
],
|
],
|
||||||
"automock": true,
|
"automock": true,
|
||||||
"unmockedModulePathPatterns": [
|
"unmockedModulePathPatterns": [
|
||||||
|
"<rootDir>/node_modules/lodash",
|
||||||
"<rootDir>/node_modules/react",
|
"<rootDir>/node_modules/react",
|
||||||
"<rootDir>/node_modules/react-dom",
|
"<rootDir>/node_modules/react-dom",
|
||||||
"<rootDir>/node_modules/react-addons-test-utils",
|
"<rootDir>/node_modules/react-addons-test-utils",
|
||||||
@@ -86,6 +87,7 @@
|
|||||||
"coriolis-data": "EDCD/coriolis-data",
|
"coriolis-data": "EDCD/coriolis-data",
|
||||||
"d3": "3.5.16",
|
"d3": "3.5.16",
|
||||||
"fbemitter": "^2.0.0",
|
"fbemitter": "^2.0.0",
|
||||||
|
"lodash": "^4.15.0",
|
||||||
"lz-string": "^1.4.4",
|
"lz-string": "^1.4.4",
|
||||||
"react": "^15.0.1",
|
"react": "^15.0.1",
|
||||||
"react-dom": "^15.0.1",
|
"react-dom": "^15.0.1",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Slot from './Slot';
|
import Slot from './Slot';
|
||||||
import { DamageKinetic, DamageThermal, DamageExplosive, MountFixed, MountGimballed, MountTurret } from './SvgIcons';
|
import { DamageKinetic, DamageThermal, DamageExplosive, MountFixed, MountGimballed, MountTurret, Modifications } from './SvgIcons';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hardpoint / Utility Slot
|
* Hardpoint / Utility Slot
|
||||||
@@ -48,17 +48,18 @@ export default class HardpointSlot extends Slot {
|
|||||||
{m.type && m.type == 'KT' ? <span><DamageKinetic /><DamageThermal /></span> : ''}
|
{m.type && m.type == 'KT' ? <span><DamageKinetic /><DamageThermal /></span> : ''}
|
||||||
{m.type && m.type == 'E' ? <DamageExplosive /> : ''}
|
{m.type && m.type == 'E' ? <DamageExplosive /> : ''}
|
||||||
{classRating} {translate(m.name || m.grp)}</div>
|
{classRating} {translate(m.name || m.grp)}</div>
|
||||||
<div className={'r'}>{m.mass}{u.T}</div>
|
<div className={'r'}>{m.getMass()}{u.T}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={'cb'}>
|
<div className={'cb'}>
|
||||||
{ m.dps ? <div className={'l'}>{translate('DPS')}: {formats.round1(m.dps)} { m.clip ? <span>({formats.round1((m.clip * m.dps / m.rof) / ((m.clip / m.rof) + m.reload)) })</span> : null }</div> : null }
|
{ m.dps ? <div className={'l'}>{translate('DPS')}: {formats.round1(m.dps)} { m.clip ? <span>({formats.round1((m.clip * m.dps / m.rof) / ((m.clip / m.rof) + m.reload)) })</span> : null }</div> : null }
|
||||||
{ m.eps ? <div className={'l'}>{translate('EPS')}: {formats.round1(m.eps)} { m.clip ? <span>({formats.round1((m.clip * m.eps / m.rof) / ((m.clip / m.rof) + m.reload)) })</span> : null }</div> : null }
|
{ m.eps ? <div className={'l'}>{translate('EPS')}: {formats.round1(m.eps)}{u.MW} { m.clip ? <span>({formats.round1((m.clip * m.eps / m.rof) / ((m.clip / m.rof) + m.reload)) }{u.MW})</span> : null }</div> : null }
|
||||||
{ m.hps ? <div className={'l'}>{translate('HPS')}: {formats.round1(m.hps)} { m.clip ? <span>({formats.round1((m.clip * m.hps / m.rof) / ((m.clip / m.rof) + m.reload)) })</span> : null }</div> : null }
|
{ m.hps ? <div className={'l'}>{translate('HPS')}: {formats.round1(m.hps)} { m.clip ? <span>({formats.round1((m.clip * m.hps / m.rof) / ((m.clip / m.rof) + m.reload)) })</span> : null }</div> : null }
|
||||||
{ m.dps && m.eps ? <div className={'l'}>{translate('DPE')}: {formats.round1(m.dps / m.eps)}</div> : null }
|
{ m.dps && m.eps ? <div className={'l'}>{translate('DPE')}: {formats.round1(m.dps / m.eps)}</div> : null }
|
||||||
{ m.rof ? <div className={'l'}>{translate('ROF')}: {m.rof}{u.ps}</div> : null }
|
{ m.rof ? <div className={'l'}>{translate('ROF')}: {m.rof}{u.ps}</div> : null }
|
||||||
{ 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 }
|
||||||
|
<div className={'r'}><Modifications /></div>
|
||||||
</div>
|
</div>
|
||||||
</div>;
|
</div>;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Slot from './Slot';
|
import Slot from './Slot';
|
||||||
import { Infinite } from './SvgIcons';
|
import { Modifications } from './SvgIcons';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal Slot
|
* Internal Slot
|
||||||
@@ -23,7 +23,7 @@ export default class InternalSlot extends Slot {
|
|||||||
return <div className='details' draggable='true' onDragStart={drag} onDragEnd={drop}>
|
return <div className='details' draggable='true' onDragStart={drag} onDragEnd={drop}>
|
||||||
<div className={'cb'}>
|
<div className={'cb'}>
|
||||||
<div className={'l'}>{classRating} {translate(m.name || m.grp)}</div>
|
<div className={'l'}>{classRating} {translate(m.name || m.grp)}</div>
|
||||||
<div className={'r'}>{m.mass || m.cargo || m.fuel || 0}{u.T}</div>
|
<div className={'r'}>{m.getMass() || m.cargo || m.fuel || 0}{u.T}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={'cb'}>
|
<div className={'cb'}>
|
||||||
{ m.optmass ? <div className={'l'}>{translate('optimal mass')}: {m.optmass}{u.T}</div> : null }
|
{ m.optmass ? <div className={'l'}>{translate('optimal mass')}: {m.optmass}{u.T}</div> : null }
|
||||||
@@ -42,6 +42,7 @@ 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 }
|
||||||
|
<div className={'r'}><Modifications /></div>
|
||||||
</div>
|
</div>
|
||||||
</div>;
|
</div>;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ export default class PowerManagement extends TranslatedComponent {
|
|||||||
case 'n': comp = comp(null, desc); break;
|
case 'n': comp = comp(null, desc); break;
|
||||||
case 't': comp = comp((a, b) => a.type.localeCompare(b.type), desc); break;
|
case 't': comp = comp((a, b) => a.type.localeCompare(b.type), desc); break;
|
||||||
case 'pri': comp = comp((a, b) => a.priority - b.priority, desc); break;
|
case 'pri': comp = comp((a, b) => a.priority - b.priority, desc); break;
|
||||||
case 'pwr': comp = comp((a, b) => a.m.power - b.m.power, desc); break;
|
case 'pwr': comp = comp((a, b) => a.m.getPowerUsage() - b.m.getPowerUsage(), desc); break;
|
||||||
case 'r': comp = comp((a, b) => ship.getSlotStatus(a) - ship.getSlotStatus(b), desc); break;
|
case 'r': comp = comp((a, b) => ship.getSlotStatus(a) - ship.getSlotStatus(b), desc); break;
|
||||||
case 'd': comp = comp((a, b) => ship.getSlotStatus(a, true) - ship.getSlotStatus(b, true), desc); break;
|
case 'd': comp = comp((a, b) => ship.getSlotStatus(a, true) - ship.getSlotStatus(b, true), desc); break;
|
||||||
}
|
}
|
||||||
@@ -113,7 +113,7 @@ export default class PowerManagement extends TranslatedComponent {
|
|||||||
for (let i = 0, l = ship.powerList.length; i < l; i++) {
|
for (let i = 0, l = ship.powerList.length; i < l; i++) {
|
||||||
let slot = ship.powerList[i];
|
let slot = ship.powerList[i];
|
||||||
|
|
||||||
if (slot.m && slot.m.power) {
|
if (slot.m && slot.m.getPowerUsage() > 0) {
|
||||||
let m = slot.m;
|
let m = slot.m;
|
||||||
let toggleEnabled = this._toggleEnabled.bind(this, slot);
|
let toggleEnabled = this._toggleEnabled.bind(this, slot);
|
||||||
let retractedElem = null, deployedElem = null;
|
let retractedElem = null, deployedElem = null;
|
||||||
@@ -134,8 +134,8 @@ export default class PowerManagement extends TranslatedComponent {
|
|||||||
{' ' + (slot.priority + 1) + ' '}
|
{' ' + (slot.priority + 1) + ' '}
|
||||||
<span className='ptr btn' onClick={this._priority.bind(this, slot, 1)}>►</span>
|
<span className='ptr btn' onClick={this._priority.bind(this, slot, 1)}>►</span>
|
||||||
</td>
|
</td>
|
||||||
<td className='ri ptr' style={{ width: '3.25em' }} onClick={toggleEnabled}>{pwr(m.power)}</td>
|
<td className='ri ptr' style={{ width: '3.25em' }} onClick={toggleEnabled}>{pwr(m.getPowerUsage())}</td>
|
||||||
<td className='ri ptr' style={{ width: '3em' }} onClick={toggleEnabled}><u>{pct(m.power / ship.powerAvailable)}</u></td>
|
<td className='ri ptr' style={{ width: '3em' }} onClick={toggleEnabled}><u>{pct(m.getPowerUsage() / ship.powerAvailable)}</u></td>
|
||||||
{retractedElem}
|
{retractedElem}
|
||||||
{deployedElem}
|
{deployedElem}
|
||||||
</tr>);
|
</tr>);
|
||||||
@@ -214,7 +214,7 @@ export default class PowerManagement extends TranslatedComponent {
|
|||||||
<td className='le shorten cap' >{translate('pp')}</td>
|
<td className='le shorten cap' >{translate('pp')}</td>
|
||||||
<td><u >{translate('SYS')}</u></td>
|
<td><u >{translate('SYS')}</u></td>
|
||||||
<td>1</td>
|
<td>1</td>
|
||||||
<td className='ri'>{pwr(pp.pGen)}</td>
|
<td className='ri'>{pwr(pp.getPowerGeneration())}</td>
|
||||||
<td className='ri'><u>100%</u></td>
|
<td className='ri'><u>100%</u></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
@@ -223,7 +223,7 @@ export default class PowerManagement extends TranslatedComponent {
|
|||||||
{this._renderPowerRows(ship, translate, pwr, formats.pct1)}
|
{this._renderPowerRows(ship, translate, pwr, formats.pct1)}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<PowerBands width={this.state.width} code={code} available={ship.standard[0].m.pGen} bands={ship.priorityBands} />
|
<PowerBands width={this.state.width} code={code} available={pp.getPowerGeneration()} bands={ship.priorityBands} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,6 +52,8 @@ export default class ShipSummaryTable extends TranslatedComponent {
|
|||||||
<th rowSpan={2} className={ cn({ 'bg-warning-disabled': !ship.canThrust() }) }>{translate('speed')}</th>
|
<th rowSpan={2} className={ cn({ 'bg-warning-disabled': !ship.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': !ship.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, 'heat per second')} onMouseLeave={hide} rowSpan={2}>{translate('HPS')}</th>
|
||||||
<th rowSpan={2}>{translate('armour')}</th>
|
<th rowSpan={2}>{translate('armour')}</th>
|
||||||
<th colSpan={3}>{translate('shields')}</th>
|
<th colSpan={3}>{translate('shields')}</th>
|
||||||
<th colSpan={3}>{translate('mass')}</th>
|
<th colSpan={3}>{translate('mass')}</th>
|
||||||
@@ -83,6 +85,8 @@ export default class ShipSummaryTable extends TranslatedComponent {
|
|||||||
<td>{ ship.canThrust() ? <span>{int(ship.topSpeed)} {u['m/s']}</span> : <span className='warning'>0 <Warning/></span> }</td>
|
<td>{ ship.canThrust() ? <span>{int(ship.topSpeed)} {u['m/s']}</span> : <span className='warning'>0 <Warning/></span> }</td>
|
||||||
<td>{ ship.canBoost() ? <span>{int(ship.topBoost)} {u['m/s']}</span> : <span className='warning'>0 <Warning/></span> }</td>
|
<td>{ ship.canBoost() ? <span>{int(ship.topBoost)} {u['m/s']}</span> : <span className='warning'>0 <Warning/></span> }</td>
|
||||||
<td>{round(ship.totalDps)}</td>
|
<td>{round(ship.totalDps)}</td>
|
||||||
|
<td>{round(ship.totalEps)}</td>
|
||||||
|
<td>{round(ship.totalHps)}</td>
|
||||||
<td>{int(ship.armour)} {armourDetails}</td>
|
<td>{int(ship.armour)} {armourDetails}</td>
|
||||||
<td className={sgClassNames}>{int(ship.shieldStrength)} {u.MJ} { ship.shieldMultiplier > 1 && ship.shieldStrength > 0 ? <u>({formats.rPct(ship.shieldMultiplier)})</u> : null }</td>
|
<td className={sgClassNames}>{int(ship.shieldStrength)} {u.MJ} { ship.shieldMultiplier > 1 && ship.shieldStrength > 0 ? <u>({formats.rPct(ship.shieldMultiplier)})</u> : null }</td>
|
||||||
<td className={sgClassNames}>{sgRecover}</td>
|
<td className={sgClassNames}>{sgRecover}</td>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import TranslatedComponent from './TranslatedComponent';
|
|||||||
import { jumpRange } from '../shipyard/Calculations';
|
import { jumpRange } from '../shipyard/Calculations';
|
||||||
import { diffDetails } from '../utils/SlotFunctions';
|
import { diffDetails } from '../utils/SlotFunctions';
|
||||||
import AvailableModulesMenu from './AvailableModulesMenu';
|
import AvailableModulesMenu from './AvailableModulesMenu';
|
||||||
|
import { Modifications } from './SvgIcons';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Standard Slot
|
* Standard Slot
|
||||||
@@ -49,7 +50,8 @@ export default class StandardSlot extends TranslatedComponent {
|
|||||||
<div className={'sz'}>{slot.maxClass}</div>
|
<div className={'sz'}>{slot.maxClass}</div>
|
||||||
<div>
|
<div>
|
||||||
<div className='l'>{classRating} {translate(m.grp == 'bh' ? m.grp : m.name || m.grp)}</div>
|
<div className='l'>{classRating} {translate(m.grp == 'bh' ? m.grp : m.name || m.grp)}</div>
|
||||||
<div className={'r'}>{m.mass || m.fuel || 0}{units.T}</div>
|
<div className={'r'}>{m.getMass() || m.fuel || 0}{units.T}</div>
|
||||||
|
<div/>
|
||||||
<div className={'cb'}>
|
<div className={'cb'}>
|
||||||
{ m.grp == 'bh' && m.name ? <div className='l'>{translate(m.name)}</div> : null }
|
{ m.grp == 'bh' && m.name ? <div className='l'>{translate(m.name)}</div> : null }
|
||||||
{ m.optmass ? <div className='l'>{translate('optimal mass')}: {m.optmass}{units.T}</div> : null }
|
{ m.optmass ? <div className='l'>{translate('optimal mass')}: {m.optmass}{units.T}</div> : null }
|
||||||
@@ -57,11 +59,12 @@ export default class StandardSlot extends TranslatedComponent {
|
|||||||
{ m.range ? <div className='l'>{translate('range')}: {m.range}{units.km}</div> : null }
|
{ m.range ? <div className='l'>{translate('range')}: {m.range}{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.eff ? <div className='l'>{translate('efficiency')}: {m.eff}</div> : null }
|
{ m.eff ? <div className='l'>{translate('efficiency')}: {m.eff}</div> : null }
|
||||||
{ m.pGen ? <div className='l'>{translate('power')}: {m.pGen}{units.MW}</div> : null }
|
{ m.getPowerGeneration() > 0 ? <div className='l'>{translate('power')}: {formats.round(m.getPowerGeneration())}{units.MW}</div> : null }
|
||||||
{ m.maxfuel ? <div className='l'>{translate('max')} {translate('fuel')}: {m.maxfuel}{units.T}</div> : null }
|
{ m.maxfuel ? <div className='l'>{translate('max')} {translate('fuel')}: {m.maxfuel}{units.T}</div> : null }
|
||||||
{ m.weaponcapacity ? <div className='l'>{translate('WEP')}: {m.weaponcapacity}{units.MJ} / {m.weaponrecharge}{units.MW}</div> : null }
|
{ m.weaponcapacity ? <div className='l'>{translate('WEP')}: {m.weaponcapacity}{units.MJ} / {m.weaponrecharge}{units.MW}</div> : null }
|
||||||
{ m.systemcapacity ? <div className='l'>{translate('SYS')}: {m.systemcapacity}{units.MJ} / {m.systemrecharge}{units.MW}</div> : null }
|
{ m.systemcapacity ? <div className='l'>{translate('SYS')}: {m.systemcapacity}{units.MJ} / {m.systemrecharge}{units.MW}</div> : null }
|
||||||
{ m.enginecapacity ? <div className='l'>{translate('ENG')}: {m.enginecapacity}{units.MJ} / {m.enginerecharge}{units.MW}</div> : null }
|
{ m.enginecapacity ? <div className='l'>{translate('ENG')}: {m.enginecapacity}{units.MJ} / {m.enginerecharge}{units.MW}</div> : null }
|
||||||
|
<div className={'r'}><Modifications /></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -488,6 +488,25 @@ export class Rocket extends SvgIcon {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modifications (engineers)
|
||||||
|
*/
|
||||||
|
export class Modifications extends SvgIcon {
|
||||||
|
/**
|
||||||
|
* Overriden view box
|
||||||
|
* @return {String} view box
|
||||||
|
*/
|
||||||
|
viewBox() { return '0 0 200 200'; }
|
||||||
|
/**
|
||||||
|
/**
|
||||||
|
* Generate the SVG
|
||||||
|
* @return {React.Component} SVG Contents
|
||||||
|
*/
|
||||||
|
svg() {
|
||||||
|
return <path d='M20 180l90-100-90 100zM176 40a40 40 0 1 1-27-28'/>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hammer
|
* Hammer
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ export default class ComparisonPage extends Page {
|
|||||||
* @return {Object} New state object
|
* @return {Object} New state object
|
||||||
*/
|
*/
|
||||||
_initState(context) {
|
_initState(context) {
|
||||||
let defaultFacets = [9, 6, 4, 1, 3, 2]; // Reverse order of Armour, Shields, Speed, Jump Range, Cargo Capacity, Cost
|
let defaultFacets = [13, 12, 11, 9, 6, 4, 1, 3, 2]; // Reverse order of Armour, Shields, Speed, Jump Range, Cargo Capacity, Cost, DPS, EPS, HPS
|
||||||
let params = context.route.params;
|
let params = context.route.params;
|
||||||
let code = params.code;
|
let code = params.code;
|
||||||
let name = params.name ? decodeURIComponent(params.name) : null;
|
let name = params.name ? decodeURIComponent(params.name) : null;
|
||||||
|
|||||||
@@ -193,6 +193,20 @@ export const ShipFacets = [
|
|||||||
lbls: ['DPS'],
|
lbls: ['DPS'],
|
||||||
fmt: 'round',
|
fmt: 'round',
|
||||||
i: 11
|
i: 11
|
||||||
|
},
|
||||||
|
{ // 12
|
||||||
|
title: 'EPS',
|
||||||
|
props: ['totalEps'],
|
||||||
|
lbls: ['EPS'],
|
||||||
|
fmt: 'round',
|
||||||
|
i: 12
|
||||||
|
},
|
||||||
|
{ // 13
|
||||||
|
title: 'HPS',
|
||||||
|
props: ['totalHps'],
|
||||||
|
lbls: ['HPS'],
|
||||||
|
fmt: 'round',
|
||||||
|
i: 13
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
15
src/app/shipyard/Modification.js
Executable file
15
src/app/shipyard/Modification.js
Executable file
@@ -0,0 +1,15 @@
|
|||||||
|
/**
|
||||||
|
* Modification - a modification and its value
|
||||||
|
*/
|
||||||
|
export default class Modification {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {String} id Unique modification ID
|
||||||
|
* @param {Number} value Value of the modification
|
||||||
|
*/
|
||||||
|
constructor(id, value) {
|
||||||
|
this.id = id;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
107
src/app/shipyard/Module.js
Executable file
107
src/app/shipyard/Module.js
Executable file
@@ -0,0 +1,107 @@
|
|||||||
|
import * as ModuleUtils from './ModuleUtils';
|
||||||
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module - active module in a ship's buildout
|
||||||
|
*/
|
||||||
|
export default class Module {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new module
|
||||||
|
* @param {Object} params Module parameters. Either grp/id or template
|
||||||
|
*/
|
||||||
|
constructor(params) {
|
||||||
|
let properties = Object.assign({ grp: null, id: null, template: null }, params);
|
||||||
|
|
||||||
|
let template;
|
||||||
|
if (properties.template == undefined) {
|
||||||
|
return ModuleUtils.findModule(properties.grp, properties.id);
|
||||||
|
} else {
|
||||||
|
template = properties.template;
|
||||||
|
if (template) {
|
||||||
|
// Copy all properties from coriolis-data template
|
||||||
|
for (let p in template) { this[p] = template[p]; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a value for a given modification ID
|
||||||
|
* @param {Number} modId The ID of the modification
|
||||||
|
* @return {Number} The value of the modification
|
||||||
|
*/
|
||||||
|
_getModValue(modId) {
|
||||||
|
let result = null;
|
||||||
|
if (this.mods) {
|
||||||
|
let mod = _.find(this.mods, function(o) { return o.id == modId; });
|
||||||
|
if (mod) {
|
||||||
|
result = mod.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the power generation of this module, taking in to account modifications
|
||||||
|
* @return {Number} the power generation of this module
|
||||||
|
*/
|
||||||
|
getPowerGeneration() {
|
||||||
|
let result = 0;
|
||||||
|
if (this.pGen) {
|
||||||
|
result = this.pGen;
|
||||||
|
if (result) {
|
||||||
|
let mult = this._getModValue(1);
|
||||||
|
if (mult) { result = result * (1 + (mult / 1000)); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the power usage of this module, taking in to account modifications
|
||||||
|
* @return {Number} the power usage of this module
|
||||||
|
*/
|
||||||
|
getPowerUsage() {
|
||||||
|
let result = 0;
|
||||||
|
if (this.power) {
|
||||||
|
result = this.power;
|
||||||
|
if (result) {
|
||||||
|
let mult = this._getModValue(2);
|
||||||
|
if (mult) { result = result * (1 + (mult / 1000)); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the mass of this module, taking in to account modifications
|
||||||
|
* @return {Number} the mass of this module
|
||||||
|
*/
|
||||||
|
getMass() {
|
||||||
|
let result = 0;
|
||||||
|
if (this.mass) {
|
||||||
|
result = this.mass;
|
||||||
|
if (result) {
|
||||||
|
let mult = this._getModValue(3);
|
||||||
|
if (mult) { result = result * (1 + (mult / 1000)); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the integrity of this module, taking in to account modifications
|
||||||
|
* @return {Number} the integrity of this module
|
||||||
|
*/
|
||||||
|
getIntegrity() {
|
||||||
|
let result = 0;
|
||||||
|
if (this.health) {
|
||||||
|
result = this.health;
|
||||||
|
if (result) {
|
||||||
|
let mult = this._getModValue(4);
|
||||||
|
if (mult) { result = result * (1 + (mult / 1000)); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
|
import Module from './Module';
|
||||||
import { BulkheadNames } from './Constants';
|
import { BulkheadNames } from './Constants';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -37,7 +37,7 @@ export default class ModuleSet {
|
|||||||
this.intClass = {};
|
this.intClass = {};
|
||||||
|
|
||||||
this.bulkheads = shipData.bulkheads.map((b, i) => {
|
this.bulkheads = shipData.bulkheads.map((b, i) => {
|
||||||
return Object.assign({ grp: 'bh', name: BulkheadNames[i], index: i, class: '', rating: '' }, b);
|
return Object.assign(new Module(), { grp: 'bh', id: i, name: BulkheadNames[i], index: i, class: '', rating: '' }, b);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.standard[0] = filter(stnd.pp, maxStandardArr[0], 0, mass); // Power Plant
|
this.standard[0] = filter(stnd.pp, maxStandardArr[0], 0, mass); // Power Plant
|
||||||
@@ -130,7 +130,7 @@ export default class ModuleSet {
|
|||||||
pd = p;
|
pd = p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return pd;
|
return new Module({ template: pd });
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -146,7 +146,7 @@ export default class ModuleSet {
|
|||||||
th = t;
|
th = t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return th;
|
return new Module({ template: th });
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -162,7 +162,7 @@ export default class ModuleSet {
|
|||||||
sg = s;
|
sg = s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return sg;
|
return new Module({ template: sg });
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -179,6 +179,6 @@ export default class ModuleSet {
|
|||||||
pp = p;
|
pp = p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return pp;
|
return new Module({ template: pp });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
import { ModuleNameToGroup, BulkheadNames, StandardArray } from './Constants';
|
import { ModuleNameToGroup, BulkheadNames, StandardArray } from './Constants';
|
||||||
import ModuleSet from './ModuleSet';
|
import ModuleSet from './ModuleSet';
|
||||||
|
import Module from './Module';
|
||||||
import { Ships, Modules } from 'coriolis-data/dist';
|
import { Ships, Modules } from 'coriolis-data/dist';
|
||||||
|
|
||||||
|
/*
|
||||||
|
* All functions below must return a fresh Module rather than a definition or existing module, as
|
||||||
|
* the resultant object can be altered with modifications.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -9,9 +14,45 @@ import { Ships, Modules } from 'coriolis-data/dist';
|
|||||||
* @return {Object} Cargo hatch model
|
* @return {Object} Cargo hatch model
|
||||||
*/
|
*/
|
||||||
export function cargoHatch() {
|
export function cargoHatch() {
|
||||||
return { name: 'Cargo Hatch', class: 1, rating: 'H', power: 0.6 };
|
let hatch = new Module();
|
||||||
|
Object.assign(hatch, { name: 'Cargo Hatch', class: 1, rating: 'H', power: 0.6 });
|
||||||
|
return hatch;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the module with the specific group and ID
|
||||||
|
* @param {String} grp Module group (pp - power plant, pl - pulse laser etc)
|
||||||
|
* @param {String} id The module ID
|
||||||
|
* @return {Object} The module or null
|
||||||
|
*/
|
||||||
|
export function findModule(grp, id) {
|
||||||
|
// See if it's a standard module
|
||||||
|
if (Modules.standard[grp]) {
|
||||||
|
let standardmod = Modules.standard[grp].find(e => e.id == id);
|
||||||
|
if (standardmod != null) {
|
||||||
|
return new Module({ template: standardmod });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// See if it's an internal module
|
||||||
|
if (Modules.internal[grp]) {
|
||||||
|
let internalmod = Modules.internal[grp].find(e => e.id == id);
|
||||||
|
if (internalmod != null) {
|
||||||
|
return new Module({ template: internalmod });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// See if it's a hardpoint module
|
||||||
|
if (Modules.hardpoints[grp]) {
|
||||||
|
let hardpointmod = Modules.hardpoints[grp].find(e => e.id == id);
|
||||||
|
if (hardpointmod != null) {
|
||||||
|
return new Module({ template: hardpointmod });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds the standard module type with the specified ID
|
* Finds the standard module type with the specified ID
|
||||||
* @param {String|Number} type Standard Module Type (0/pp - Power Plant, 1/t - Thrusters, etc)
|
* @param {String|Number} type Standard Module Type (0/pp - Power Plant, 1/t - Thrusters, etc)
|
||||||
@@ -24,6 +65,9 @@ export function standard(type, id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let s = Modules.standard[type].find(e => e.id == id || (e.class == id.charAt(0) && e.rating == id.charAt(1)));
|
let s = Modules.standard[type].find(e => e.id == id || (e.class == id.charAt(0) && e.rating == id.charAt(1)));
|
||||||
|
if (s) {
|
||||||
|
s = new Module({ template: s });
|
||||||
|
}
|
||||||
return s || null;
|
return s || null;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -37,7 +81,7 @@ export function hardpoints(id) {
|
|||||||
let group = Modules.hardpoints[n];
|
let group = Modules.hardpoints[n];
|
||||||
for (let i = 0; i < group.length; i++) {
|
for (let i = 0; i < group.length; i++) {
|
||||||
if (group[i].id == id) {
|
if (group[i].id == id) {
|
||||||
return group[i];
|
return new Module({ template: group[i] });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
import { ArmourMultiplier } from './Constants';
|
import { ArmourMultiplier } from './Constants';
|
||||||
import * as Calc from './Calculations';
|
import * as Calc from './Calculations';
|
||||||
import * as ModuleUtils from './ModuleUtils';
|
import * as ModuleUtils from './ModuleUtils';
|
||||||
|
import Module from './Module';
|
||||||
import LZString from 'lz-string';
|
import LZString from 'lz-string';
|
||||||
|
import isEqual from 'lodash/lang';
|
||||||
|
|
||||||
const UNIQUE_MODULES = ['psg', 'sg', 'bsg', 'rf', 'fs', 'fh'];
|
const UNIQUE_MODULES = ['psg', 'sg', 'bsg', 'rf', 'fs', 'fh'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the power usage type of a slot and it's particular modul
|
* Returns the power usage type of a slot and it's particular module
|
||||||
* @param {Object} slot The Slot
|
* @param {Object} slot The Slot
|
||||||
* @param {Object} modul The modul in the slot
|
* @param {Object} modul The module in the slot
|
||||||
* @return {String} The key for the power usage type
|
* @return {String} The key for the power usage type
|
||||||
*/
|
*/
|
||||||
function powerUsageType(slot, modul) {
|
function powerUsageType(slot, modul) {
|
||||||
@@ -20,6 +22,25 @@ function powerUsageType(slot, modul) {
|
|||||||
return slot.cat != 1 ? 'retracted' : 'deployed';
|
return slot.cat != 1 ? 'retracted' : 'deployed';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populate the modifications array with modification values from the code
|
||||||
|
* @param {String} code Serialized modification code
|
||||||
|
* @param {Array} arr Modification array
|
||||||
|
*/
|
||||||
|
function decodeModsToArray(code, arr) {
|
||||||
|
let moduleMods = code.split(',');
|
||||||
|
for (let i = 0; i < arr.length; i++) {
|
||||||
|
arr[i] = new Array();
|
||||||
|
if (moduleMods.length > i && moduleMods[i] != '') {
|
||||||
|
let mods = moduleMods[i].split(';');
|
||||||
|
for (let j = 0; j < mods.length; j++) {
|
||||||
|
let modElements = mods[j].split(':');
|
||||||
|
arr[i].push({ id: Number(modElements[0]), value: Number(modElements[1]) });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Populates the category array with module IDs from
|
* Populates the category array with module IDs from
|
||||||
* the provided code
|
* the provided code
|
||||||
@@ -284,7 +305,9 @@ export default class Ship {
|
|||||||
'.',
|
'.',
|
||||||
this.getPowerEnabledString(),
|
this.getPowerEnabledString(),
|
||||||
'.',
|
'.',
|
||||||
this.getPowerPrioritesString()
|
this.getPowerPrioritiesString(),
|
||||||
|
'.',
|
||||||
|
this.getModificationsString()
|
||||||
].join('');
|
].join('');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,6 +347,18 @@ export default class Ship {
|
|||||||
return this.serialized.hardpoints;
|
return this.serialized.hardpoints;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serializes the modifications to a string
|
||||||
|
* @return {String} Serialized modifications 'code'
|
||||||
|
*/
|
||||||
|
getModificationsString() {
|
||||||
|
if(!this.serialized.modifications) {
|
||||||
|
this.updateModificationsString();
|
||||||
|
}
|
||||||
|
return this.serialized.modifications;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the serialized module active/inactive settings
|
* Get the serialized module active/inactive settings
|
||||||
* @return {String} Serialized active/inactive settings
|
* @return {String} Serialized active/inactive settings
|
||||||
@@ -336,7 +371,7 @@ export default class Ship {
|
|||||||
* Get the serialized module priority settings
|
* Get the serialized module priority settings
|
||||||
* @return {String} Serialized priority settings
|
* @return {String} Serialized priority settings
|
||||||
*/
|
*/
|
||||||
getPowerPrioritesString() {
|
getPowerPrioritiesString() {
|
||||||
return this.serialized.priorities;
|
return this.serialized.priorities;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -373,9 +408,10 @@ export default class Ship {
|
|||||||
* @param {Object} comps Collection of ModuleUtils used to build the ship
|
* @param {Object} comps Collection of ModuleUtils used to build the ship
|
||||||
* @param {array} priorities Slot priorities
|
* @param {array} priorities Slot priorities
|
||||||
* @param {Array} enabled Slot active/inactive
|
* @param {Array} enabled Slot active/inactive
|
||||||
|
* @param {Array} mods Modifications
|
||||||
* @return {this} The current ship instance for chaining
|
* @return {this} The current ship instance for chaining
|
||||||
*/
|
*/
|
||||||
buildWith(comps, priorities, enabled) {
|
buildWith(comps, priorities, enabled, mods) {
|
||||||
let internal = this.internal,
|
let internal = this.internal,
|
||||||
standard = this.standard,
|
standard = this.standard,
|
||||||
hps = this.hardpoints,
|
hps = this.hardpoints,
|
||||||
@@ -393,11 +429,15 @@ export default class Ship {
|
|||||||
this.totalCost = this.m.incCost ? this.m.discountedCost : 0;
|
this.totalCost = this.m.incCost ? this.m.discountedCost : 0;
|
||||||
this.unladenMass = this.hullMass;
|
this.unladenMass = this.hullMass;
|
||||||
this.totalDps = 0;
|
this.totalDps = 0;
|
||||||
|
this.totalEps = 0;
|
||||||
|
this.totalHps = 0;
|
||||||
|
|
||||||
this.bulkheads.m = null;
|
this.bulkheads.m = null;
|
||||||
this.useBulkhead(comps && comps.bulkheads ? comps.bulkheads : 0, true);
|
this.useBulkhead(comps && comps.bulkheads ? comps.bulkheads : 0, true);
|
||||||
|
this.bulkheads.m.mods = mods && mods[0] ? mods[0] : [];
|
||||||
this.cargoHatch.priority = priorities ? priorities[0] * 1 : 0;
|
this.cargoHatch.priority = priorities ? priorities[0] * 1 : 0;
|
||||||
this.cargoHatch.enabled = enabled ? enabled[0] * 1 : true;
|
this.cargoHatch.enabled = enabled ? enabled[0] * 1 : true;
|
||||||
|
this.cargoHatch.mods = mods ? mods[0] : [];
|
||||||
|
|
||||||
for (i = 0, l = this.priorityBands.length; i < l; i++) {
|
for (i = 0, l = this.priorityBands.length; i < l; i++) {
|
||||||
this.priorityBands[i].deployed = 0;
|
this.priorityBands[i].deployed = 0;
|
||||||
@@ -405,9 +445,10 @@ export default class Ship {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.cargoHatch.enabled) {
|
if (this.cargoHatch.enabled) {
|
||||||
bands[this.cargoHatch.priority].retracted += this.cargoHatch.m.power;
|
bands[this.cargoHatch.priority].retracted += this.cargoHatch.m.getPowerUsage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for (i = 0; i < cl; i++) {
|
for (i = 0; i < cl; i++) {
|
||||||
standard[i].cat = 0;
|
standard[i].cat = 0;
|
||||||
standard[i].enabled = enabled ? enabled[i + 1] * 1 : true;
|
standard[i].enabled = enabled ? enabled[i + 1] * 1 : true;
|
||||||
@@ -415,9 +456,10 @@ export default class Ship {
|
|||||||
standard[i].type = 'SYS';
|
standard[i].type = 'SYS';
|
||||||
standard[i].m = null; // Resetting 'old' modul if there was one
|
standard[i].m = null; // Resetting 'old' modul if there was one
|
||||||
standard[i].discountedCost = 0;
|
standard[i].discountedCost = 0;
|
||||||
|
|
||||||
if (comps) {
|
if (comps) {
|
||||||
this.use(standard[i], ModuleUtils.standard(i, comps.standard[i]), true);
|
let module = ModuleUtils.standard(i, comps.standard[i]);
|
||||||
|
if (module != null) { module.mods = mods && mods[i + 1] ? mods[i + 1] : []; }
|
||||||
|
this.use(standard[i], module, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -434,7 +476,9 @@ export default class Ship {
|
|||||||
hps[i].discountedCost = 0;
|
hps[i].discountedCost = 0;
|
||||||
|
|
||||||
if (comps && comps.hardpoints[i] !== 0) {
|
if (comps && comps.hardpoints[i] !== 0) {
|
||||||
this.use(hps[i], ModuleUtils.hardpoints(comps.hardpoints[i]), true);
|
let module = ModuleUtils.hardpoints(comps.hardpoints[i]);
|
||||||
|
if (module != null) { module.mods = mods && mods[cl + i] ? mods[cl + i] : []; }
|
||||||
|
this.use(hps[i], module, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -449,7 +493,9 @@ export default class Ship {
|
|||||||
internal[i].discountedCost = 0;
|
internal[i].discountedCost = 0;
|
||||||
|
|
||||||
if (comps && comps.internal[i] !== 0) {
|
if (comps && comps.internal[i] !== 0) {
|
||||||
this.use(internal[i], ModuleUtils.internal(comps.internal[i]), true);
|
let module = ModuleUtils.internal(comps.internal[i]);
|
||||||
|
if (module != null) { module.mods = mods && mods[cl + i] ? mods[cl + i] : []; }
|
||||||
|
this.use(internal[i], module, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -461,7 +507,7 @@ export default class Ship {
|
|||||||
.updateTopSpeed();
|
.updateTopSpeed();
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.updatePowerPrioritesString().updatePowerEnabledString();
|
return this.updatePowerPrioritesString().updatePowerEnabledString().updateModificationsString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -475,6 +521,7 @@ export default class Ship {
|
|||||||
let standard = new Array(this.standard.length),
|
let standard = new Array(this.standard.length),
|
||||||
hardpoints = new Array(this.hardpoints.length),
|
hardpoints = new Array(this.hardpoints.length),
|
||||||
internal = new Array(this.internal.length),
|
internal = new Array(this.internal.length),
|
||||||
|
mods = new Array(1 + this.standard.length + this.hardpoints.length + this.internal.length),
|
||||||
parts = serializedString.split('.'),
|
parts = serializedString.split('.'),
|
||||||
priorities = null,
|
priorities = null,
|
||||||
enabled = null,
|
enabled = null,
|
||||||
@@ -488,6 +535,10 @@ export default class Ship {
|
|||||||
priorities = LZString.decompressFromBase64(parts[2].replace(/-/g, '/')).split('');
|
priorities = LZString.decompressFromBase64(parts[2].replace(/-/g, '/')).split('');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (parts[3]) {
|
||||||
|
decodeModsToArray(parts[3], mods);
|
||||||
|
}
|
||||||
|
|
||||||
decodeToArray(code, internal, decodeToArray(code, hardpoints, decodeToArray(code, standard, 1)));
|
decodeToArray(code, internal, decodeToArray(code, hardpoints, decodeToArray(code, standard, 1)));
|
||||||
|
|
||||||
return this.buildWith(
|
return this.buildWith(
|
||||||
@@ -498,7 +549,8 @@ export default class Ship {
|
|||||||
internal
|
internal
|
||||||
},
|
},
|
||||||
priorities,
|
priorities,
|
||||||
enabled
|
enabled,
|
||||||
|
mods
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -584,16 +636,23 @@ export default class Ship {
|
|||||||
if (slot.enabled != enabled) { // Enabled state is changing
|
if (slot.enabled != enabled) { // Enabled state is changing
|
||||||
slot.enabled = enabled;
|
slot.enabled = enabled;
|
||||||
if (slot.m) {
|
if (slot.m) {
|
||||||
this.priorityBands[slot.priority][powerUsageType(slot, slot.m)] += enabled ? slot.m.power : -slot.m.power;
|
this.priorityBands[slot.priority][powerUsageType(slot, slot.m)] += enabled ? slot.m.getPowerUsage() : - slot.m.getPowerUsage();
|
||||||
|
|
||||||
if (ModuleUtils.isShieldGenerator(slot.m.grp)) {
|
if (ModuleUtils.isShieldGenerator(slot.m.grp)) {
|
||||||
this.updateShieldStrength();
|
this.updateShieldStrength();
|
||||||
} else if (slot.m.grp == 'sb') {
|
} else if (slot.m.grp == 'sb') {
|
||||||
this.shieldMultiplier += slot.m.shieldmul * (enabled ? 1 : -1);
|
this.shieldMultiplier += slot.m.shieldmul * (enabled ? 1 : -1);
|
||||||
this.updateShieldStrength();
|
this.updateShieldStrength();
|
||||||
} else if (slot.m.dps) {
|
}
|
||||||
|
if (slot.m.dps) {
|
||||||
this.totalDps += slot.m.dps * (enabled ? 1 : -1);
|
this.totalDps += slot.m.dps * (enabled ? 1 : -1);
|
||||||
}
|
}
|
||||||
|
if (slot.m.eps) {
|
||||||
|
this.totalEps += slot.m.eps * (enabled ? 1 : -1);
|
||||||
|
}
|
||||||
|
if (slot.m.hps) {
|
||||||
|
this.totalHps += slot.m.hps * (enabled ? 1 : -1);
|
||||||
|
}
|
||||||
|
|
||||||
this.updatePower();
|
this.updatePower();
|
||||||
this.updatePowerEnabledString();
|
this.updatePowerEnabledString();
|
||||||
@@ -616,8 +675,8 @@ export default class Ship {
|
|||||||
|
|
||||||
if (slot.enabled) { // Only update power if the slot is enabled
|
if (slot.enabled) { // Only update power if the slot is enabled
|
||||||
let usage = powerUsageType(slot, slot.m);
|
let usage = powerUsageType(slot, slot.m);
|
||||||
this.priorityBands[oldPriority][usage] -= slot.m.power;
|
this.priorityBands[oldPriority][usage] -= slot.m.getPowerUsage();
|
||||||
this.priorityBands[newPriority][usage] += slot.m.power;
|
this.priorityBands[newPriority][usage] += slot.m.getPowerUsage();
|
||||||
this.updatePower();
|
this.updatePower();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -656,15 +715,26 @@ export default class Ship {
|
|||||||
this.totalCost -= old.cost * this.moduleCostMultiplier;
|
this.totalCost -= old.cost * this.moduleCostMultiplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (old.power && slot.enabled) {
|
if (!(old instanceof Module)) {
|
||||||
this.priorityBands[slot.priority][powerUsageType(slot, old)] -= old.power;
|
console.log(JSON.stringify(old) + ' is not a module');
|
||||||
|
console.log(new Error().stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (old.getPowerUsage() > 0 && slot.enabled) {
|
||||||
|
this.priorityBands[slot.priority][powerUsageType(slot, old)] -= old.getPowerUsage();
|
||||||
powerChange = true;
|
powerChange = true;
|
||||||
|
|
||||||
if (old.dps) {
|
if (old.dps) {
|
||||||
this.totalDps -= old.dps;
|
this.totalDps -= old.dps;
|
||||||
}
|
}
|
||||||
|
if (old.eps) {
|
||||||
|
this.totalEps -= old.eps;
|
||||||
}
|
}
|
||||||
this.unladenMass -= old.mass || 0;
|
if (old.hps) {
|
||||||
|
this.totalHps -= old.hps;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.unladenMass -= old.getMass() || 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n) {
|
if (n) {
|
||||||
@@ -688,14 +758,20 @@ export default class Ship {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (n.power && slot.enabled) {
|
if (n.power && slot.enabled) {
|
||||||
this.priorityBands[slot.priority][powerUsageType(slot, n)] += n.power;
|
this.priorityBands[slot.priority][powerUsageType(slot, n)] += n.getPowerUsage();
|
||||||
powerChange = true;
|
powerChange = true;
|
||||||
|
|
||||||
if (n.dps) {
|
if (n.dps) {
|
||||||
this.totalDps += n.dps;
|
this.totalDps += n.dps;
|
||||||
}
|
}
|
||||||
|
if (n.eps) {
|
||||||
|
this.totalEps += n.eps;
|
||||||
}
|
}
|
||||||
this.unladenMass += n.mass || 0;
|
if (n.hps) {
|
||||||
|
this.totalHps += n.hps;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.unladenMass += n.getMass() || 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.ladenMass = this.unladenMass + this.cargoCapacity + this.fuelCapacity;
|
this.ladenMass = this.unladenMass + this.cargoCapacity + this.fuelCapacity;
|
||||||
@@ -726,7 +802,7 @@ export default class Ship {
|
|||||||
prevDeployed = band.deployedSum = prevDeployed + band.deployed + band.retracted;
|
prevDeployed = band.deployedSum = prevDeployed + band.deployed + band.retracted;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.powerAvailable = this.standard[0].m.pGen;
|
this.powerAvailable = this.standard[0].m.getPowerGeneration();
|
||||||
this.powerRetracted = prevRetracted;
|
this.powerRetracted = prevRetracted;
|
||||||
this.powerDeployed = prevDeployed;
|
this.powerDeployed = prevDeployed;
|
||||||
return this;
|
return this;
|
||||||
@@ -811,16 +887,75 @@ export default class Ship {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the modifications string
|
||||||
|
* @return {this} The ship instance (for chaining operations)
|
||||||
|
*/
|
||||||
|
updateModificationsString() {
|
||||||
|
let allMods = new Array();
|
||||||
|
|
||||||
|
let bulkheadMods = new Array();
|
||||||
|
if (this.bulkheads.m && this.bulkheads.m.mods) {
|
||||||
|
for (let mod of this.bulkheads.m.mods) {
|
||||||
|
bulkheadMods.push(mod.id + ':' + mod.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
allMods.push(bulkheadMods.join(';'));
|
||||||
|
|
||||||
|
for (let slot of this.standard) {
|
||||||
|
let slotMods = new Array();
|
||||||
|
if (slot.m && slot.m.mods) {
|
||||||
|
for (let mod of slot.m.mods) {
|
||||||
|
slotMods.push(mod.id + ':' + mod.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
allMods.push(slotMods.join(';'));
|
||||||
|
}
|
||||||
|
for (let slot of this.hardpoints) {
|
||||||
|
let slotMods = new Array();
|
||||||
|
if (slot.m && slot.m.mods) {
|
||||||
|
for (let mod of slot.m.mods) {
|
||||||
|
slotMods.push(mod.id + ':' + mod.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
allMods.push(slotMods.join(';'));
|
||||||
|
}
|
||||||
|
for (let slot of this.internal) {
|
||||||
|
let slotMods = new Array();
|
||||||
|
if (slot.m && slot.m.mods) {
|
||||||
|
for (let mod of slot.m.mods) {
|
||||||
|
slotMods.push(mod.id + ':' + mod.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
allMods.push(slotMods.join(';'));
|
||||||
|
}
|
||||||
|
this.serialized.modifications = allMods.join(',').replace(/,+$/, '');
|
||||||
|
console.log('Final serialized string is ' + this.serialized.modifications);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update a slot with a the modul if the id is different from the current id for this slot.
|
* Update a slot with a the modul if the id is different from the current id for this slot.
|
||||||
* Has logic handling ModuleUtils that you may only have 1 of (Shield Generator or Refinery).
|
* Has logic handling ModuleUtils that you may only have 1 of (Shield Generator or Refinery).
|
||||||
*
|
*
|
||||||
* @param {Object} slot The modul slot
|
* @param {Object} slot The modul slot
|
||||||
* @param {Object} m Properties for the selected module
|
* @param {Object} mdef Properties for the selected modul
|
||||||
* @param {boolean} preventUpdate If true, do not update aggregated stats
|
* @param {boolean} preventUpdate If true, do not update aggregated stats
|
||||||
* @return {this} The ship instance (for chaining operations)
|
* @return {this} The ship instance (for chaining operations)
|
||||||
*/
|
*/
|
||||||
use(slot, m, preventUpdate) {
|
use(slot, mdef, preventUpdate) {
|
||||||
|
// See if the module passed in is really a module or just a definition, and fix it accordingly so that we have a module instance
|
||||||
|
let m;
|
||||||
|
if (mdef == null) {
|
||||||
|
m = null;
|
||||||
|
} else if (mdef instanceof Module) {
|
||||||
|
m = mdef;
|
||||||
|
} else {
|
||||||
|
// jgmjgm TODO see if we can use the module template instead of its group and id
|
||||||
|
// m = new Module({template: mdef});
|
||||||
|
m = new Module({ grp: mdef.grp, id: mdef.id });
|
||||||
|
}
|
||||||
|
|
||||||
if (slot.m != m) { // Selecting a different modul
|
if (slot.m != m) { // Selecting a different modul
|
||||||
// Slot is an internal slot, is not being emptied, and the selected modul group/type must be of unique
|
// Slot is an internal slot, is not being emptied, and the selected modul group/type must be of unique
|
||||||
if (slot.cat == 2 && m && UNIQUE_MODULES.indexOf(m.grp) != -1) {
|
if (slot.cat == 2 && m && UNIQUE_MODULES.indexOf(m.grp) != -1) {
|
||||||
@@ -843,6 +978,7 @@ export default class Ship {
|
|||||||
case 1: this.serialized.hardpoints = null; break;
|
case 1: this.serialized.hardpoints = null; break;
|
||||||
case 2: this.serialized.internal = null;
|
case 2: this.serialized.internal = null;
|
||||||
}
|
}
|
||||||
|
this.serialized.modifications = null;
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -907,14 +1043,14 @@ export default class Ship {
|
|||||||
updated = false;
|
updated = false;
|
||||||
// Find lightest Thruster that still works for the ship at max mass
|
// Find lightest Thruster that still works for the ship at max mass
|
||||||
let th = m.th ? ModuleUtils.standard(1, m.th) : this.availCS.lightestThruster(this.ladenMass);
|
let th = m.th ? ModuleUtils.standard(1, m.th) : this.availCS.lightestThruster(this.ladenMass);
|
||||||
if (th !== standard[1].m) {
|
if (!isEqual.isEqual(th, standard[1].m)) {
|
||||||
this.use(standard[1], th);
|
this.use(standard[1], th);
|
||||||
updated = true;
|
updated = true;
|
||||||
}
|
}
|
||||||
// Find lightest Power plant that can power the ship
|
// Find lightest Power plant that can power the ship
|
||||||
let pp = m.pp ? ModuleUtils.standard(0, m.pp) : this.availCS.lightestPowerPlant(Math.max(this.powerRetracted, this.powerDeployed), m.ppRating);
|
let pp = m.pp ? ModuleUtils.standard(0, m.pp) : this.availCS.lightestPowerPlant(Math.max(this.powerRetracted, this.powerDeployed), m.ppRating);
|
||||||
|
|
||||||
if (pp !== standard[0].m) {
|
if (!isEqual.isEqual(pp, standard[0].m)) {
|
||||||
this.use(standard[0], pp);
|
this.use(standard[0], pp);
|
||||||
updated = true;
|
updated = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ export function explorer(ship, planetary) {
|
|||||||
|
|
||||||
if (sgSlot) {
|
if (sgSlot) {
|
||||||
// The SG and Fuel scoop to not need to be powered at the same time
|
// The SG and Fuel scoop to not need to be powered at the same time
|
||||||
if (sgSlot.m.power > fuelScoopSlot.m.power) { // The Shield generator uses the most power
|
if (sgSlot.m.getPowerUsage() > fuelScoopSlot.m.getPowerUsage()) { // The Shield generator uses the most power
|
||||||
ship.setSlotEnabled(fuelScoopSlot, false);
|
ship.setSlotEnabled(fuelScoopSlot, false);
|
||||||
} else { // The Fuel scoop uses the most power
|
} else { // The Fuel scoop uses the most power
|
||||||
ship.setSlotEnabled(sgSlot, false);
|
ship.setSlotEnabled(sgSlot, false);
|
||||||
|
|||||||
@@ -210,14 +210,14 @@ export function diffDetails(language, m, mm) {
|
|||||||
let { formats, translate, units } = language;
|
let { formats, translate, units } = language;
|
||||||
let propDiffs = [];
|
let propDiffs = [];
|
||||||
let mMass = m.mass || 0;
|
let mMass = m.mass || 0;
|
||||||
let mmMass = mm.mass || 0;
|
let mmMass = mm ? mm.getMass() : 0;
|
||||||
let massDiff = mMass - mmMass;
|
let massDiff = mMass - mmMass;
|
||||||
let capDiff = (m.fuel || m.cargo || 0) - (mm.fuel || mm.cargo || 0);
|
let capDiff = (m.fuel || m.cargo || 0) - (mm.fuel || mm.cargo || 0);
|
||||||
let mAffectsShield = isShieldGenerator(m.grp) || m.grp == 'sb';
|
let mAffectsShield = isShieldGenerator(m.grp) || m.grp == 'sb';
|
||||||
let mmAffectsShield = isShieldGenerator(mm.grp) || mm.grp == 'sb';
|
let mmAffectsShield = isShieldGenerator(mm.grp) || mm.grp == 'sb';
|
||||||
|
|
||||||
propDiffs.push(<div key='cost'>{translate('cost')}: <span className={diffClass(m.cost, mm.cost, true) }>{m.cost ? Math.round(m.cost * (1 - Persist.getModuleDiscount())) : 0}{units.CR}</span></div>);
|
propDiffs.push(<div key='cost'>{translate('cost')}: <span className={diffClass(m.cost, mm.cost, true) }>{m.cost ? Math.round(m.cost * (1 - Persist.getModuleDiscount())) : 0}{units.CR}</span></div>);
|
||||||
propDiffs.push(<div key='mass'>{translate('mass')}: <span className={diffClass(mMass, mm.mass, true)}>{diff(formats.round, mMass, mmMass)}{units.T}</span></div>);
|
propDiffs.push(<div key='mass'>{translate('mass')}: <span className={diffClass(mMass, mm.getMass(), true)}>{diff(formats.round, mMass, mmMass)}{units.T}</span></div>);
|
||||||
|
|
||||||
for (let p in m) {
|
for (let p in m) {
|
||||||
if (!PROP_BLACKLIST[p] && !isNaN(m[p])) {
|
if (!PROP_BLACKLIST[p] && !isNaN(m[p])) {
|
||||||
|
|||||||
Reference in New Issue
Block a user