Added offence and defence summary

This commit is contained in:
Cmdr McDonald
2016-11-10 00:13:56 +00:00
parent 3719bb9696
commit 0688faac93
6 changed files with 427 additions and 121 deletions

View File

@@ -0,0 +1,89 @@
import React from 'react';
import cn from 'classnames';
import TranslatedComponent from './TranslatedComponent';
/**
* Defence summary
*/
export default class DefenceSummary extends TranslatedComponent {
static PropTypes = {
ship: React.PropTypes.object.isRequired
};
/**
* Constructor
* @param {Object} props React Component properties
*/
constructor(props) {
super(props);
}
/**
* Render defence summary
* @return {React.Component} contents
*/
render() {
let ship = this.props.ship;
let { language, tooltip, termtip } = this.context;
let { formats, translate, units } = language;
let hide = tooltip.bind(null, null);
let sgClassNames = cn({ muted: !ship.findInternalByGroup('sg') });
return (
<div>
<h1>{translate('defence summary')}</h1>
<br/>
<table style={{ width: '100%', lineHeight: '1em', backgroundColor: 'transparent' }}>
<thead>
<tr>
<th rowSpan={2}>{translate('damage to')}</th>
<th colSpan={3}>{translate('damage from')}</th>
</tr>
<tr>
<th>{translate('explosive')}</th>
<th>{translate('kinetic')}</th>
<th>{translate('thermal')}</th>
</tr>
</thead>
<tbody>
{ ship.shield ?
<tr>
<td className='le {sgClassNames}'>{translate('shields')}</td>
<td className='ri {sgClassNames}'>{ship.shieldExplRes ? formats.pct(ship.shieldExplRes) : '-'}</td>
<td className='ri {sgClassNames}'>{ship.shieldKinRes ? formats.pct(ship.shieldKinRes) : '-'}</td>
<td className='ri {sgClassNames}'>{ship.shieldThermRes ? formats.pct(ship.shieldThermRes) : '-'}</td>
</tr> : null }
<tr>
<td className='le'>{translate('hull')}</td>
<td className='ri'>{formats.pct(ship.hullExplRes)}</td>
<td className='ri'>{formats.pct(ship.hullKinRes)}</td>
<td className='ri'>{formats.pct(ship.hullThermRes)}</td>
</tr>
</tbody>
</table>
<br />
{ ship.shield ?
<table style={{ width: '100%', lineHeight: '1em', backgroundColor: 'transparent' }}>
<thead>
<tr>
<th colSpan={3}>{translate('shields')}</th>
</tr>
<tr>
<th>{translate('strength')}</th>
<th onMouseEnter={termtip.bind(null, 'PHRASE_SG_RECOVER', { cap: 0 })} onMouseLeave={hide}>{translate('recovery')}</th>
<th onMouseEnter={termtip.bind(null, 'PHRASE_SG_RECHARGE', { cap: 0 })} onMouseLeave={hide}>{translate('recovery')}</th>
</tr>
</thead>
<tbody>
<tr>
<td className='ri'>{formats.int(ship.shield)} {units.MJ}</td>
<td className='ri'>{ship.shield ? formats.time(ship.calcShieldRecovery()) : '-'}</td>
<td className='ri'>{ship.shield ? formats.time(ship.calcShieldRecharge()) : '-'}</td>
</tr>
</tbody>
</table> : null }
</div>
);
}
}

View File

@@ -0,0 +1,103 @@
import React from 'react';
import cn from 'classnames';
import TranslatedComponent from './TranslatedComponent';
/**
* Offence summary
*/
export default class OffenceSummary extends TranslatedComponent {
static PropTypes = {
ship: React.PropTypes.object.isRequired
};
/**
* Constructor
* @param {Object} props React Component properties
*/
constructor(props) {
super(props);
}
/**
* Render offence summary
* @return {React.Component} contents
*/
render() {
let ship = this.props.ship;
let { language, tooltip, termtip } = this.context;
let { formats, translate, units } = language;
let hide = tooltip.bind(null, null);
return (
<div>
<h1>{translate('offence summary')}</h1>
<br/>
<table style={{ width: '100%', lineHeight: '1em', backgroundColor: 'transparent' }}>
<thead>
<tr>
<th colSpan={4}>{translate('dps')}</th>
</tr>
<tr>
<th>{translate('explosive')}</th>
<th>{translate('kinetic')}</th>
<th>{translate('thermal')}</th>
<th>{translate('total')}</th>
</tr>
</thead>
<tbody>
<tr>
<td className='ri'>{formats.f1(ship.totalExplDps)}</td>
<td className='ri'>{formats.f1(ship.totalKinDps)}</td>
<td className='ri'>{formats.f1(ship.totalThermDps)}</td>
<td className='ri'>{formats.f1(ship.totalDps)}</td>
</tr>
</tbody>
</table>
<br/>
<table style={{ width: '100%', lineHeight: '1em', backgroundColor: 'transparent' }}>
<thead>
<tr>
<th colSpan={4}>{translate('sustained dps')}</th>
</tr>
<tr>
<th>{translate('explosive')}</th>
<th>{translate('kinetic')}</th>
<th>{translate('thermal')}</th>
<th>{translate('total')}</th>
</tr>
</thead>
<tbody>
<tr>
<td className='ri'>{formats.f1(ship.totalExplSDps)}</td>
<td className='ri'>{formats.f1(ship.totalKinSDps)}</td>
<td className='ri'>{formats.f1(ship.totalThermSDps)}</td>
<td className='ri'>{formats.f1(ship.totalSDps)}</td>
</tr>
</tbody>
</table>
<br/>
<table style={{ width: '100%', lineHeight: '1em', backgroundColor: 'transparent' }}>
<thead>
<tr>
<th colSpan={4}>{translate('dpe')}</th>
</tr>
<tr>
<th>{translate('explosive')}</th>
<th>{translate('kinetic')}</th>
<th>{translate('thermal')}</th>
<th>{translate('total')}</th>
</tr>
</thead>
<tbody>
<tr>
<td className='ri'>{formats.f1(ship.totalExplDpe)}</td>
<td className='ri'>{formats.f1(ship.totalKinDpe)}</td>
<td className='ri'>{formats.f1(ship.totalThermDpe)}</td>
<td className='ri'>{formats.f1(ship.totalDpe)}</td>
</tr>
</tbody>
</table>
</div>
);
}
}

View File

@@ -34,20 +34,6 @@ export default class ShipSummaryTable extends TranslatedComponent {
sgRecharge = time(ship.calcShieldRecharge());
}
// <th colSpan={3}>{translate('shield resistance')}</th>
// <th colSpan={3}>{translate('hull resistance')}</th>
// <th className='lft'>{translate('explosive')}</th>
// <th className='lft'>{translate('kinetic')}</th>
// <th className='lft'>{translate('thermal')}</th>
// <th className='lft'>{translate('explosive')}</th>
// <th className='lft'>{translate('kinetic')}</th>
// <th className='lft'>{translate('thermal')}</th>
// <td>{pct(ship.shieldExplRes)}</td>
// <td>{pct(ship.shieldKinRes)}</td>
// <td>{pct(ship.shieldThermRes)}</td>
// <td>{pct(ship.hullExplRes)}</td>
// <td>{pct(ship.hullKinRes)}</td>
// <td>{pct(ship.hullThermRes)}</td>
return <div id='summary'>
<table id='summaryTable'>
<thead>
@@ -58,7 +44,7 @@ export default class ShipSummaryTable extends TranslatedComponent {
<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 colSpan={3}>{translate('shields')}</th>
<th rowSpan={2}>{translate('shields')}</th>
<th colSpan={3}>{translate('mass')}</th>
<th rowSpan={2}>{translate('cargo')}</th>
<th rowSpan={2}>{translate('fuel')}</th>
@@ -67,9 +53,6 @@ export default class ShipSummaryTable extends TranslatedComponent {
<th onMouseEnter={termtip.bind(null, 'mass lock factor')} onMouseLeave={hide} rowSpan={2}>{translate('MLF')}</th>
</tr>
<tr>
<th className='lft'>{translate('strength')}</th>
<th onMouseEnter={termtip.bind(null, 'PHRASE_SG_RECOVER', { cap: 0 })} onMouseLeave={hide}>{translate('recovery')}</th>
<th onMouseEnter={termtip.bind(null, 'PHRASE_SG_RECHARGE', { cap: 0 })} onMouseLeave={hide}>{translate('recharge')}</th>
<th className='lft'>{translate('hull')}</th>
<th onMouseEnter={termtip.bind(null, 'PHRASE_UNLADEN', { cap: 0 })} onMouseLeave={hide}>{translate('unladen')}</th>
<th onMouseEnter={termtip.bind(null, 'PHRASE_LADEN', { cap: 0 })} onMouseLeave={hide}>{translate('laden')}</th>
@@ -90,8 +73,6 @@ export default class ShipSummaryTable extends TranslatedComponent {
<td>{f1(ship.totalHps)}</td>
<td>{int(ship.armour)}</td>
<td className={sgClassNames}>{int(ship.shield)} {u.MJ}</td>
<td className={sgClassNames}>{sgRecover}</td>
<td className={sgClassNames}>{sgRecharge}</td>
<td>{ship.hullMass} {u.T}</td>
<td>{int(ship.unladenMass)} {u.T}</td>
<td>{int(ship.ladenMass)} {u.T}</td>

View File

@@ -8,13 +8,14 @@ import Persist from '../stores/Persist';
import Ship from '../shipyard/Ship';
import { toDetailedBuild } from '../shipyard/Serializer';
import { outfitURL } from '../utils/UrlGenerators';
import { FloppyDisk, Bin, Switch, Download, Reload, Fuel } from '../components/SvgIcons';
import ShipSummaryTable from '../components/ShipSummaryTable';
import StandardSlotSection from '../components/StandardSlotSection';
import HardpointsSlotSection from '../components/HardpointsSlotSection';
import InternalSlotSection from '../components/InternalSlotSection';
import UtilitySlotSection from '../components/UtilitySlotSection';
import OffenceSummary from '../components/OffenceSummary';
import DefenceSummary from '../components/DefenceSummary';
import LineChart from '../components/LineChart';
import PowerManagement from '../components/PowerManagement';
import CostSection from '../components/CostSection';
@@ -324,31 +325,11 @@ export default class OutfittingPage extends Page {
<CostSection ship={ship} buildName={buildName} code={sStr + hStr + iStr} />
<div ref='chartThird' className='group third'>
<h1>{translate('jump range')}</h1>
<LineChart
width={chartWidth}
xMax={ship.cargoCapacity}
yMax={ship.unladenRange}
xUnit={translate('T')}
yUnit={translate('LY')}
yLabel={translate('jump range')}
xLabel={translate('cargo')}
func={state.jumpRangeChartFunc}
/>
<OffenceSummary ship={ship} code={code}/>
</div>
<div className='group third'>
<h1>{translate('total range')}</h1>
<LineChart
width={chartWidth}
xMax={ship.cargoCapacity}
yMax={ship.unladenFastestRange}
xUnit={translate('T')}
yUnit={translate('LY')}
yLabel={translate('fastest range')}
xLabel={translate('cargo')}
func={state.fastestRangeChartFunc}
/>
<DefenceSummary ship={ship} code={code}/>
</div>
<div className='group third'>
@@ -397,3 +378,16 @@ export default class OutfittingPage extends Page {
);
}
}
// <div ref='chartThird' className='group third'>
// <h1>{translate('jump range')}</h1>
// <LineChart
// width={chartWidth}
// xMax={ship.cargoCapacity}
// yMax={ship.unladenRange}
// xUnit={translate('T')}
// yUnit={translate('LY')}
// yLabel={translate('jump range')}
// xLabel={translate('cargo')}
// func={state.jumpRangeChartFunc}
// />
// </div>

View File

@@ -54,16 +54,23 @@ export default class Module {
/**
* Helper to obtain a modified value using standard multipliers
* @param {String} name the name of the modifier to obtain
* @return {Number} the mass of this module
* @param {String} name the name of the modifier to obtain
* @param {Boolean} additive Optional true if the value is additive rather than multiplicative
* @return {Number} the mass of this module
*/
_getModifiedValue(name) {
_getModifiedValue(name, additive) {
let result = 0;
if (this[name]) {
result = this[name];
if (result) {
let mult = this.getModValue(name);
if (mult) { result = result * (1 + mult); }
const modValue = this.getModValue(name);
if (modValue) {
if (additive) {
result = result + modValue;
} else {
result = result * (1 + modValue);
}
}
}
}
return result;
@@ -193,7 +200,7 @@ export default class Module {
* @return {Number} the kinetic resistance of this module
*/
getKineticResistance() {
return this._getModifiedValue('kinres');
return this._getModifiedValue('kinres', true);
}
/**
@@ -201,7 +208,7 @@ export default class Module {
* @return {Number} the thermal resistance of this module
*/
getThermalResistance() {
return this._getModifiedValue('thermres');
return this._getModifiedValue('thermres', true);
}
/**
@@ -209,7 +216,7 @@ export default class Module {
* @return {Number} the explosive resistance of this module
*/
getExplosiveResistance() {
return this._getModifiedValue('explres');
return this._getModifiedValue('explres', true);
}
/**

View File

@@ -194,10 +194,12 @@ export default class Ship {
*/
calcShieldRecovery() {
if (this.shield > 0) {
let sgSlot = this.findInternalByGroup('sg');
let brokenRegenRate = 1 + sgSlot.m.getModValue('brokenregen');
// 50% of shield strength / recovery recharge rate + 15 second delay before recharge starts
return ((this.shield / 2) / (sgSlot.m.recover * brokenRegenRate)) + 15;
const sgSlot = this.findInternalByGroup('sg');
if (sgSlot != null) {
let brokenRegenRate = 1 + sgSlot.m.getModValue('brokenregen');
// 50% of shield strength / recovery recharge rate + 15 second delay before recharge starts
return ((this.shield / 2) / (sgSlot.m.recover * brokenRegenRate)) + 15;
}
}
return 0;
}
@@ -210,10 +212,12 @@ export default class Ship {
*/
calcShieldRecharge() {
if (this.shield > 0) {
let sgSlot = this.findInternalByGroup('sg');
let regenRate = 1 + sgSlot.m.getModValue('regen');
// 50% -> 100% recharge time, Bi-Weave shields charge at 1.8 MJ/s
return (this.shield / 2) / ((sgSlot.m.grp == 'bsg' ? 1.8 : 1) * regenRate);
const sgSlot = this.findInternalByGroup('sg');
if (sgSlot != null) {
let regenRate = 1 + sgSlot.m.getModValue('regen');
// 50% -> 100% recharge time, Bi-Weave shields charge at 1.8 MJ/s
return (this.shield / 2) / ((sgSlot.m.grp == 'bsg' ? 1.8 : 1) * regenRate);
}
}
return 0;
}
@@ -401,15 +405,15 @@ export default class Ship {
*/
setModification(m, name, value) {
// Handle special cases
if (name == 'pgen') {
if (name === 'pgen') {
// Power generation
m.setModValue(name, value);
this.updatePowerGenerated();
} else if (name == 'power') {
} else if (name === 'power') {
// Power usage
m.setModValue(name, value);
this.updatePowerUsed();
} else if (name == 'mass') {
} else if (name === 'mass') {
// Mass
let oldMass = m.getMass();
m.setModValue(name, value);
@@ -418,32 +422,37 @@ export default class Ship {
this.ladenMass = this.ladenMass - oldMass + newMass;
this.updateTopSpeed();
this.updateJumpStats();
} else if (name == 'maxfuel') {
} else if (name === 'maxfuel') {
m.setModValue(name, value);
this.updateJumpStats();
} else if (name == 'optmass') {
} else if (name === 'optmass') {
m.setModValue(name, value);
// Could be for any of thrusters, FSD or shield
this.updateTopSpeed();
this.updateJumpStats();
this.updateShield();
} else if (name == 'optmul') {
this.recalculateShield();
} else if (name === 'optmul') {
m.setModValue(name, value);
// Could be for any of thrusters, FSD or shield
this.updateTopSpeed();
this.updateJumpStats();
this.updateShield();
} else if (name == 'shieldboost') {
this.recalculateShield();
} else if (name === 'shieldboost') {
m.setModValue(name, value);
this.updateShield();
} else if (name == 'hullboost') {
this.recalculateShield();
} else if (name === 'hullboost' || name === 'hullreinforcement') {
m.setModValue(name, value);
this.updateArmour();
} else if (name == 'burst' || name == 'clip' || name == 'damage' || name == 'distdraw' || name == 'jitter' || name == 'piercing' || name == 'range' || name == 'reload' || name == 'rof' || name == 'thermload') {
this.recalculateArmour();
} else if (name === 'burst' || name === 'clip' || name === 'damage' || name === 'distdraw' || name === 'jitter' || name === 'piercing' || name === 'range' || name === 'reload' || name === 'rof' || name === 'thermload') {
m.setModValue(name, value);
this.recalculateDps();
this.recalculateHps();
this.recalculateEps();
} else if (name === 'explres' || name === 'kinres' || name === 'thermres') {
m.setModValue(name, value);
// Could be for shields or armour
this.recalculateArmour();
this.recalculateShield();
} else {
// Generic
m.setModValue(name, value);
@@ -473,7 +482,18 @@ export default class Ship {
this.shield = this.baseShieldStrength;
this.totalCost = this.m.incCost ? this.m.discountedCost : 0;
this.unladenMass = this.hullMass;
this.totalDpe = 0;
this.totalExplDpe = 0;
this.totalKinDpe = 0;
this.totalThermDpe = 0;
this.totalDps = 0;
this.totalExplDps = 0;
this.totalKinDps = 0;
this.totalThermDps = 0;
this.totalSDps = 0;
this.totalExplSDps = 0;
this.totalKinSDps = 0;
this.totalThermSDps = 0;
this.totalEps = 0;
this.totalHps = 0;
this.shieldExplRes = 0;
@@ -544,8 +564,11 @@ export default class Ship {
this.updatePowerGenerated()
.updatePowerUsed()
.updateJumpStats()
.updateShield()
.updateArmour()
.recalculateShield()
.recalculateArmour()
.recalculateDps()
.recalculateEps()
.recalculateHps()
.updateTopSpeed();
}
@@ -688,20 +711,23 @@ export default class Ship {
slot.enabled = enabled;
if (slot.m) {
if (ModuleUtils.isShieldGenerator(slot.m.grp) || slot.m.grp == 'sb') {
this.updateShield();
}
if (slot.m.getDps()) {
this.totalDps += slot.m.getDps() * (enabled ? 1 : -1);
}
if (slot.m.getEps()) {
this.totalEps += slot.m.getEps() * (enabled ? 1 : -1);
}
if (slot.m.getHps()) {
this.totalHps += slot.m.getHps() * (enabled ? 1 : -1);
this.recalculateShield();
}
this.updatePowerUsed();
this.updatePowerEnabledString();
if (slot.m.getDps()) {
this.recalculateDps();
}
if (slot.m.getHps()) {
this.recalculateHps();
}
if (slot.m.getEps()) {
this.recalculateEps();
}
}
}
return this;
@@ -738,6 +764,9 @@ export default class Ship {
updateStats(slot, n, old, preventUpdate) {
let powerGeneratedChange = slot == this.standard[0];
let powerUsedChange = false;
let dpsChanged = n && n.getDps() || old && old.getDps();
let epsChanged = n && n.getEps() || old && old.getEps();
let hpsChanged = n && n.getHps() || old && old.getHps();
let armourChange = (slot == this.bulkheads) || (n && n.grp == 'hr') || (old && old.grp == 'hr');
@@ -761,16 +790,6 @@ export default class Ship {
powerUsedChange = true;
}
if (old.getDps()) {
this.totalDps -= old.getDps();
}
if (old.getEps()) {
this.totalEps -= old.getEps();
}
if (old.getHps()) {
this.totalHps -= old.getHps();
}
this.unladenMass -= old.getMass() || 0;
}
@@ -792,22 +811,21 @@ export default class Ship {
powerUsedChange = true;
}
if (n.getDps()) {
this.totalDps += n.getDps();
}
if (n.getEps()) {
this.totalEps += n.getEps();
}
if (n.getHps()) {
this.totalHps += n.getHps();
}
this.unladenMass += n.getMass() || 0;
}
this.ladenMass = this.unladenMass + this.cargoCapacity + this.fuelCapacity;
if (!preventUpdate) {
if (dpsChanged) {
this.recalculateDps();
}
if (epsChanged) {
this.recalculateEps();
}
if (hpsChanged) {
this.recalculateHps();
}
if (powerGeneratedChange) {
this.updatePowerGenerated();
}
@@ -815,10 +833,10 @@ export default class Ship {
this.updatePowerUsed();
}
if (armourChange) {
this.updateArmour();
this.recalculateArmour();
}
if (shieldChange) {
this.updateShield();
this.recalculateShield();
}
this.updateTopSpeed();
this.updateJumpStats();
@@ -826,20 +844,108 @@ export default class Ship {
return this;
}
/**
* Calculate diminishing returns value, where values below a given limit are returned
* as-is, and values between the lower and upper limit of the diminishing returns are
* given at half value.
* Commonly used for resistances.
* @param {Number} val The value
* @param {Number} drll The lower limit for diminishing returns
* @param {Number} drul The upper limit for diminishing returns
* @return {this} The ship instance (for chaining operations)
*/
diminishingReturns(val, drll, drul) {
if (val > drll) {
val = drll + (val - drll) / 2;
}
if (val > drul) {
val = drul;
}
return val;
}
/**
* Calculate damage per second for weapons
* @return {this} The ship instance (for chaining operations)
*/
recalculateDps() {
let totalDpe = 0;
let totalExplDpe = 0;
let totalKinDpe = 0;
let totalThermDpe = 0;
let totalDps = 0;
let totalExplDps = 0;
let totalKinDps = 0;
let totalThermDps = 0;
let totalSDps = 0;
let totalExplSDps = 0;
let totalKinSDps = 0;
let totalThermSDps = 0;
for (let slotNum in this.hardpoints) {
const slot = this.hardpoints[slotNum];
if (slot.m && slot.enabled && slot.m.getDps()) {
totalDps += slot.m.getDps();
const dpe = slot.m.getDps() / slot.m.getEps();
const dps = slot.m.getDps();
const sdps = slot.m.getClip() ? (slot.m.getClip() * slot.m.getDps() / slot.m.getRoF()) / ((slot.m.getClip() / slot.m.getRoF()) + slot.m.getReload()) : dps;
totalDpe += dpe;
totalDps += dps;
totalSDps += sdps;
if (slot.m.type === 'E') {
totalExplDpe += dpe;
totalExplDps += dps;
totalExplSDps += sdps;
}
if (slot.m.type === 'K') {
totalKinDpe += dpe;
totalKinDps += dps;
totalKinSDps += sdps;
}
if (slot.m.type === 'T') {
totalThermDpe += dpe;
totalThermDps += dps;
totalThermSDps += sdps;
}
if (slot.m.type === 'EK') {
totalExplDpe += dpe / 2;
totalKinDpe += dpe / 2;
totalExplDps += dps / 2;
totalKinDps += dps / 2;
totalExplSDps += sdps / 2;
totalKinSDps += sdps / 2;
}
if (slot.m.type === 'ET') {
totalExplDpe += dpe / 2;
totalThermDpe += dpe / 2;
totalExplDps += dps / 2;
totalThermDps += dps / 2;
totalExplSDps += sdps / 2;
totalThermSDps += sdps / 2;
}
if (slot.m.type === 'KT') {
totalKinDpe += dpe / 2;
totalThermDpe += dpe / 2;
totalKinDps += dps / 2;
totalThermDps += dps / 2;
totalKinSDps += sdps / 2;
totalThermSDps += sdps / 2;
}
}
}
this.totalDpe = totalDpe;
this.totalExplDpe = totalExplDpe;
this.totalKinDpe = totalKinDpe;
this.totalThermDpe = totalThermDpe;
this.totalDps = totalDps;
this.totalExplDps = totalExplDps;
this.totalKinDps = totalKinDps;
this.totalThermDps = totalThermDps;
this.totalSDps = totalSDps;
this.totalExplSDps = totalExplSDps;
this.totalKinSDps = totalKinSDps;
this.totalThermSDps = totalThermSDps;
return this;
}
@@ -958,34 +1064,51 @@ export default class Ship {
* Update shield
* @return {this} The ship instance (for chaining operations)
*/
updateShield() {
// Base shield from generator
let baseShield = 0;
let sgSlot = this.findInternalByGroup('sg');
recalculateShield() {
let shield = 0;
let shieldExplRes = null;
let shieldKinRes = null;
let shieldThermRes = null;
const sgSlot = this.findInternalByGroup('sg');
if (sgSlot && sgSlot.enabled) {
baseShield = Calc.shieldStrength(this.hullMass, this.baseShieldStrength, sgSlot.m, 1);
}
// Shield from generator
const baseShield = Calc.shieldStrength(this.hullMass, this.baseShieldStrength, sgSlot.m, 1);
shield = baseShield;
shieldExplRes = 1 - sgSlot.m.getExplosiveResistance();
shieldKinRes = 1 - sgSlot.m.getKineticResistance();
shieldThermRes = 1 - sgSlot.m.getThermalResistance();
let shield = baseShield;
// Shield from boosters
for (let slot of this.hardpoints) {
if (slot.m && slot.m.grp == 'sb') {
shield += baseShield * slot.m.getShieldBoost();
// Shield from boosters
for (let slot of this.hardpoints) {
if (slot.m && slot.m.grp == 'sb') {
shield += baseShield * slot.m.getShieldBoost();
shieldExplRes *= (1 - slot.m.getExplosiveResistance());
shieldKinRes *= (1 - slot.m.getKineticResistance());
shieldThermRes *= (1 - slot.m.getThermalResistance());
}
}
}
this.shield = shield;
this.shieldExplRes = shieldExplRes ? 1 - this.diminishingReturns(1 - shieldExplRes, 0.5, 0.75) : null;
this.shieldKinRes = shieldKinRes ? 1 - this.diminishingReturns(1 - shieldKinRes, 0.5, 0.75) : null;
this.shieldThermRes = shieldThermRes ? 1 - this.diminishingReturns(1 - shieldThermRes, 0.5, 0.75) : null;
return this;
}
/**
* Update armour
* Update armour and hull resistances
* @return {this} The ship instance (for chaining operations)
*/
updateArmour() {
recalculateArmour() {
// Armour from bulkheads
let bulkhead = this.bulkheads.m;
let armour = this.baseArmour + (this.baseArmour * bulkhead.getHullBoost());
let hullExplRes = 1 - bulkhead.getExplosiveResistance();
let hullKinRes = 1 - bulkhead.getKineticResistance();
let hullThermRes = 1 - bulkhead.getThermalResistance();
// Armour from HRPs
for (let slot of this.internal) {
@@ -993,9 +1116,18 @@ export default class Ship {
armour += slot.m.getHullReinforcement();
// Hull boost for HRPs is applied against the ship's base armour
armour += this.baseArmour * slot.m.getModValue('hullboost');
hullExplRes *= (1 - slot.m.getExplosiveResistance());
hullKinRes *= (1 - slot.m.getKineticResistance());
hullThermRes *= (1 - slot.m.getThermalResistance());
}
}
this.armour = armour;
this.hullExplRes = 1 - this.diminishingReturns(1 - hullExplRes, 0.5, 0.75);
this.hullKinRes = 1 - this.diminishingReturns(1 - hullKinRes, 0.5, 0.75);
this.hullThermRes = 1 - this.diminishingReturns(1 - hullThermRes, 0.5, 0.75);
return this;
}