This commit is contained in:
Cmdr McDonald
2017-03-19 08:41:36 +00:00
parent 49a076fd9e
commit fcb8980a38
7 changed files with 75 additions and 119 deletions

View File

@@ -27,7 +27,7 @@ export default class Range extends TranslatedComponent {
this.state = { this.state = {
maxRange, maxRange,
rangeLevel: 0.5, rangeLevel: 1000 / maxRange,
}; };
} }

View File

@@ -81,7 +81,7 @@ export default class Offence extends TranslatedComponent {
* @return {boolean} Returns true if the component should be rerendered * @return {boolean} Returns true if the component should be rerendered
*/ */
componentWillReceiveProps(nextProps) { componentWillReceiveProps(nextProps) {
if (this.props.marker != nextProps.marker || this.props.sys != nextProps.sys) { if (this.props.marker != nextProps.marker || this.props.eng != nextProps.eng) {
const damage = Calc.offenceMetrics(nextProps.ship, nextProps.opponent, nextProps.wep, nextProps.engagementrange); const damage = Calc.offenceMetrics(nextProps.ship, nextProps.opponent, nextProps.wep, nextProps.engagementrange);
this.setState({ damage }); this.setState({ damage });
} }
@@ -101,27 +101,24 @@ export default class Offence extends TranslatedComponent {
desc = true; desc = true;
} }
this._sort(this.props.ship, predicate, desc); this._sort(predicate, desc);
this.setState({ predicate, desc }); this.setState({ predicate, desc });
} }
/** /**
* Sorts the weapon list * Sorts the weapon list
* @param {Ship} ship Ship instance
* @param {string} predicate Sort predicate * @param {string} predicate Sort predicate
* @param {Boolean} desc Sort order descending * @param {Boolean} desc Sort order descending
*/ */
_sort(ship, predicate, desc) { _sort(predicate, desc) {
let comp = weaponComparator.bind(null, this.context.language.translate); let comp = weaponComparator.bind(null, this.context.language.translate);
switch (predicate) { switch (predicate) {
case 'n': comp = comp(null, desc); break; case 'n': comp = comp(null, desc); break;
case 'edpss': comp = comp((a, b) => a.effectiveDpsShields - b.effectiveDpsShields, desc); break; case 'esdpss': comp = comp((a, b) => a.sdps.shields.total - b.sdps.shields.total, desc); break;
case 'esdpss': comp = comp((a, b) => a.effectiveSDpsShields - b.effectiveSDpsShields, desc); break; case 'es': comp = comp((a, b) => a.effectiveness.shields.total - b.effectiveness.shields.total, desc); break;
case 'es': comp = comp((a, b) => a.effectivenessShields - b.effectivenessShields, desc); break; case 'esdpsh': comp = comp((a, b) => a.sdps.armour.total - b.sdps.armour.total, desc); break;
case 'edpsh': comp = comp((a, b) => a.effectiveDpsHull - b.effectiveDpsHull, desc); break; case 'eh': comp = comp((a, b) => a.effectiveness.armour.total - b.effectiveness.armour.total, desc); break;
case 'esdpsh': comp = comp((a, b) => a.effectiveSDpsHull - b.effectiveSDpsHull, desc); break;
case 'eh': comp = comp((a, b) => a.effectivenessHull - b.effectivenessHull, desc); break;
} }
this.state.damage.sort(comp); this.state.damage.sort(comp);
@@ -141,104 +138,43 @@ export default class Offence extends TranslatedComponent {
const rows = []; const rows = [];
for (let i = 0; i < damage.length; i++) { for (let i = 0; i < damage.length; i++) {
const weapon = damage[i]; const weapon = damage[i];
rows.push(<tr key={weapon.id}>
<td className='ri'> const effectivenessShieldsTooltipDetails = [];
{weapon.mount == 'F' ? <span onMouseOver={termtip.bind(null, 'fixed')} onMouseOut={tooltip.bind(null, null)}><MountFixed className='icon'/></span> : null} effectivenessShieldsTooltipDetails.push(<div key='range'>{translate('range') + ' ' + formats.pct1(weapon.effectiveness.shields.range)}</div>);
{weapon.mount == 'G' ? <span onMouseOver={termtip.bind(null, 'gimballed')} onMouseOut={tooltip.bind(null, null)}><MountGimballed /></span> : null} effectivenessShieldsTooltipDetails.push(<div key='resistance'>{translate('resistance') + ' ' + formats.pct1(weapon.effectiveness.shields.resistance)}</div>);
{weapon.mount == 'T' ? <span onMouseOver={termtip.bind(null, 'turreted')} onMouseOut={tooltip.bind(null, null)}><MountTurret /></span> : null} effectivenessShieldsTooltipDetails.push(<div key='sys'>{translate('sys') + ' ' + formats.pct1(weapon.effectiveness.shields.sys)}</div>);
{weapon.classRating} {translate(weapon.name)}
{weapon.engineering ? ' (' + weapon.engineering + ')' : null } const effectiveShieldsSDpsTooltipDetails = [];
</td> if (weapon.sdps.shields.absolute) effectiveShieldsSDpsTooltipDetails.push(<div key='absolute'>{translate('absolute') + ' ' + formats.f1(weapon.sdps.shields.absolute)}</div>);
<td className='ri'>{formats.f1(weapon.sdpsShields)}</td> if (weapon.sdps.shields.explosive) effectiveShieldsSDpsTooltipDetails.push(<div key='explosive'>{translate('explosive') + ' ' + formats.f1(weapon.sdps.shields.explosive)}</div>);
<td className='ri'>{formats.pct1(weapon.effectivenessShields)}</td> if (weapon.sdps.shields.kinetic) effectiveShieldsSDpsTooltipDetails.push(<div key='kinetic'>{translate('kinetic') + ' ' + formats.f1(weapon.sdps.shields.kinetic)}</div>);
<td className='ri'>{formats.f1(weapon.sdpsArmour)}</td> if (weapon.sdps.shields.thermal) effectiveShieldsSDpsTooltipDetails.push(<div key='thermal'>{translate('thermal') + ' ' + formats.f1(weapon.sdps.shields.thermal)}</div>);
<td className='ri'>{formats.pct1(weapon.effectivenessArmour)}</td>
</tr>); const effectivenessArmourTooltipDetails = [];
effectivenessArmourTooltipDetails.push(<div key='range'>{translate('range') + ' ' + formats.pct1(weapon.effectiveness.armour.range)}</div>);
effectivenessArmourTooltipDetails.push(<div key='resistance'>{translate('resistance') + ' ' + formats.pct1(weapon.effectiveness.armour.resistance)}</div>);
effectivenessArmourTooltipDetails.push(<div key='hardness'>{translate('hardness') + ' ' + formats.pct1(weapon.effectiveness.armour.hardness)}</div>);
const effectiveArmourSDpsTooltipDetails = [];
if (weapon.sdps.armour.absolute) effectiveArmourSDpsTooltipDetails.push(<div key='absolute'>{translate('absolute') + ' ' + formats.f1(weapon.sdps.armour.absolute)}</div>);
if (weapon.sdps.armour.explosive) effectiveArmourSDpsTooltipDetails.push(<div key='explosive'>{translate('explosive') + ' ' + formats.f1(weapon.sdps.armour.explosive)}</div>);
if (weapon.sdps.armour.kinetic) effectiveArmourSDpsTooltipDetails.push(<div key='kinetic'>{translate('kinetic') + ' ' + formats.f1(weapon.sdps.armour.kinetic)}</div>);
if (weapon.sdps.armour.thermal) effectiveArmourSDpsTooltipDetails.push(<div key='thermal'>{translate('thermal') + ' ' + formats.f1(weapon.sdps.armour.thermal)}</div>);
rows.push(
<tr key={weapon.id}>
<td className='ri'>
{weapon.mount == 'F' ? <span onMouseOver={termtip.bind(null, 'fixed')} onMouseOut={tooltip.bind(null, null)}><MountFixed className='icon'/></span> : null}
{weapon.mount == 'G' ? <span onMouseOver={termtip.bind(null, 'gimballed')} onMouseOut={tooltip.bind(null, null)}><MountGimballed /></span> : null}
{weapon.mount == 'T' ? <span onMouseOver={termtip.bind(null, 'turreted')} onMouseOut={tooltip.bind(null, null)}><MountTurret /></span> : null}
{weapon.classRating} {translate(weapon.name)}
{weapon.engineering ? ' (' + weapon.engineering + ')' : null }
</td>
<td className='ri'><span onMouseOver={termtip.bind(null, effectiveShieldsSDpsTooltipDetails)} onMouseOut={tooltip.bind(null, null)}>{formats.f1(weapon.sdps.shields.total)}</span></td>
<td className='ri'><span onMouseOver={termtip.bind(null, effectivenessShieldsTooltipDetails)} onMouseOut={tooltip.bind(null, null)}>{formats.pct1(weapon.effectiveness.shields.total)}</span></td>
<td className='ri'><span onMouseOver={termtip.bind(null, effectiveArmourSDpsTooltipDetails)} onMouseOut={tooltip.bind(null, null)}>{formats.f1(weapon.sdps.armour.total)}</span></td>
<td className='ri'><span onMouseOver={termtip.bind(null, effectivenessArmourTooltipDetails)} onMouseOut={tooltip.bind(null, null)}>{formats.pct1(weapon.effectiveness.armour.total)}</span></td>
</tr>);
} }
// const shieldSourcesData = [];
// const effectiveShieldData = [];
// const shieldDamageTakenData = [];
// const shieldTooltipDetails = [];
// const shieldAbsoluteTooltipDetails = [];
// const shieldExplosiveTooltipDetails = [];
// const shieldKineticTooltipDetails = [];
// const shieldThermalTooltipDetails = [];
// let maxEffectiveShield = 0;
// if (shield.total) {
// shieldSourcesData.push({ value: Math.round(shield.generator), label: translate('generator') });
// shieldSourcesData.push({ value: Math.round(shield.boosters), label: translate('boosters') });
// shieldSourcesData.push({ value: Math.round(shield.cells), label: translate('cells') });
// shieldTooltipDetails.push(<div key='generator'>{translate('generator') + ' ' + formats.int(shield.generator)}{units.MJ}</div>);
// shieldTooltipDetails.push(<div key='boosters'>{translate('boosters') + ' ' + formats.int(shield.boosters)}{units.MJ}</div>);
// shieldTooltipDetails.push(<div key='cells'>{translate('cells') + ' ' + formats.int(shield.cells)}{units.MJ}</div>);
// shieldAbsoluteTooltipDetails.push(<div key='generator'>{translate('generator') + ' ' + formats.pct1(shield.absolute.generator)}</div>);
// shieldAbsoluteTooltipDetails.push(<div key='boosters'>{translate('boosters') + ' ' + formats.pct1(shield.absolute.boosters)}</div>);
// shieldAbsoluteTooltipDetails.push(<div key='power distributor'>{translate('power distributor') + ' ' + formats.pct1(shield.absolute.sys)}</div>);
// shieldExplosiveTooltipDetails.push(<div key='generator'>{translate('generator') + ' ' + formats.pct1(shield.explosive.generator)}</div>);
// shieldExplosiveTooltipDetails.push(<div key='boosters'>{translate('boosters') + ' ' + formats.pct1(shield.explosive.boosters)}</div>);
// shieldExplosiveTooltipDetails.push(<div key='power distributor'>{translate('power distributor') + ' ' + formats.pct1(shield.explosive.sys)}</div>);
// shieldKineticTooltipDetails.push(<div key='generator'>{translate('generator') + ' ' + formats.pct1(shield.kinetic.generator)}</div>);
// shieldKineticTooltipDetails.push(<div key='boosters'>{translate('boosters') + ' ' + formats.pct1(shield.kinetic.boosters)}</div>);
// shieldKineticTooltipDetails.push(<div key='power distributor'>{translate('power distributor') + ' ' + formats.pct1(shield.kinetic.sys)}</div>);
// shieldThermalTooltipDetails.push(<div key='generator'>{translate('generator') + ' ' + formats.pct1(shield.thermal.generator)}</div>);
// shieldThermalTooltipDetails.push(<div key='boosters'>{translate('boosters') + ' ' + formats.pct1(shield.thermal.boosters)}</div>);
// shieldThermalTooltipDetails.push(<div key='power distributor'>{translate('power distributor') + ' ' + formats.pct1(shield.thermal.sys)}</div>);
// const effectiveAbsoluteShield = shield.total / shield.absolute.total;
// effectiveShieldData.push({ value: Math.round(effectiveAbsoluteShield), label: translate('absolute') });
// const effectiveExplosiveShield = shield.total / shield.explosive.total;
// effectiveShieldData.push({ value: Math.round(effectiveExplosiveShield), label: translate('explosive') });
// const effectiveKineticShield = shield.total / shield.kinetic.total;
// effectiveShieldData.push({ value: Math.round(effectiveKineticShield), label: translate('kinetic') });
// const effectiveThermalShield = shield.total / shield.thermal.total;
// effectiveShieldData.push({ value: Math.round(effectiveThermalShield), label: translate('thermal') });
// shieldDamageTakenData.push({ value: Math.round(shield.absolute.total * 100), label: translate('absolute') });
// shieldDamageTakenData.push({ value: Math.round(shield.explosive.total * 100), label: translate('explosive') });
// shieldDamageTakenData.push({ value: Math.round(shield.kinetic.total * 100), label: translate('kinetic') });
// shieldDamageTakenData.push({ value: Math.round(shield.thermal.total * 100), label: translate('thermal') });
// maxEffectiveShield = Math.max(shield.total / shield.absolute.max, shield.total / shield.explosive.max, shield.total / shield.kinetic.max, shield.total / shield.thermal.max);
// }
// const armourSourcesData = [];
// armourSourcesData.push({ value: Math.round(armour.bulkheads), label: translate('bulkheads') });
// armourSourcesData.push({ value: Math.round(armour.reinforcement), label: translate('reinforcement') });
// const armourTooltipDetails = [];
// armourTooltipDetails.push(<div key='bulkheads'>{translate('bulkheads') + ' ' + formats.int(armour.bulkheads)}</div>);
// armourTooltipDetails.push(<div key='reinforcement'>{translate('reinforcement') + ' ' + formats.int(armour.reinforcement)}</div>);
// const armourAbsoluteTooltipDetails = [];
// armourAbsoluteTooltipDetails.push(<div key='bulkheads'>{translate('bulkheads') + ' ' + formats.pct1(armour.absolute.bulkheads)}</div>);
// armourAbsoluteTooltipDetails.push(<div key='reinforcement'>{translate('reinforcement') + ' ' + formats.pct1(armour.absolute.reinforcement)}</div>);
// const armourExplosiveTooltipDetails = [];
// armourExplosiveTooltipDetails.push(<div key='bulkheads'>{translate('bulkheads') + ' ' + formats.pct1(armour.explosive.bulkheads)}</div>);
// armourExplosiveTooltipDetails.push(<div key='reinforcement'>{translate('reinforcement') + ' ' + formats.pct1(armour.explosive.reinforcement)}</div>);
// const armourKineticTooltipDetails = [];
// armourKineticTooltipDetails.push(<div key='bulkheads'>{translate('bulkheads') + ' ' + formats.pct1(armour.kinetic.bulkheads)}</div>);
// armourKineticTooltipDetails.push(<div key='reinforcement'>{translate('reinforcement') + ' ' + formats.pct1(armour.kinetic.reinforcement)}</div>);
// const armourThermalTooltipDetails = [];
// armourThermalTooltipDetails.push(<div key='bulkheads'>{translate('bulkheads') + ' ' + formats.pct1(armour.thermal.bulkheads)}</div>);
// armourThermalTooltipDetails.push(<div key='reinforcement'>{translate('reinforcement') + ' ' + formats.pct1(armour.thermal.reinforcement)}</div>);
// const effectiveArmourData = [];
// const effectiveAbsoluteArmour = armour.total / armour.absolute.total;
// effectiveArmourData.push({ value: Math.round(effectiveAbsoluteArmour), label: translate('absolute') });
// const effectiveExplosiveArmour = armour.total / armour.explosive.total;
// effectiveArmourData.push({ value: Math.round(effectiveExplosiveArmour), label: translate('explosive') });
// const effectiveKineticArmour = armour.total / armour.kinetic.total;
// effectiveArmourData.push({ value: Math.round(effectiveKineticArmour), label: translate('kinetic') });
// const effectiveThermalArmour = armour.total / armour.thermal.total;
// effectiveArmourData.push({ value: Math.round(effectiveThermalArmour), label: translate('thermal') });
// const armourDamageTakenData = []; // const armourDamageTakenData = [];
// armourDamageTakenData.push({ value: Math.round(armour.absolute.total * 100), label: translate('absolute') }); // armourDamageTakenData.push({ value: Math.round(armour.absolute.total * 100), label: translate('absolute') });
@@ -248,24 +184,26 @@ export default class Offence extends TranslatedComponent {
return ( return (
<span id='offence'> <span id='offence'>
<div className='group half'>
<table width='100%'> <table width='100%'>
<thead> <thead>
<tr className='main'> <tr className='main'>
<th rowSpan='2' className='sortable' onClick={sortOrder.bind(this, 'n')}>{translate('weapon')}</th> <th rowSpan='2' className='sortable' onClick={sortOrder.bind(this, 'n')}>{translate('weapon')}</th>
<th colSpan='2'>{translate('opponent shields')}</th> <th colSpan='2'>{translate('opponent\`s shields')}</th>
<th colSpan='2'>{translate('opponent armour')}</th> <th colSpan='2'>{translate('opponent\`s armour')}</th>
</tr> </tr>
<tr> <tr>
<th className='lft sortable' onClick={sortOrder.bind(this, 'esdpss')}>{translate('effective sdps')}</th> <th className='lft sortable' onMouseOver={termtip.bind(null, 'TT_EFFECTIVE_SDPS_SHIELDS')} onMouseOut={tooltip.bind(null, null)} onClick={sortOrder.bind(this, 'esdpss')}>{'sdps'}</th>
<th className='sortable' onClick={sortOrder.bind(this, 'es')}>{translate('effectiveness')}</th> <th className='sortable' onMouseOver={termtip.bind(null, 'TT_EFFECTIVENESS_SHIELDS')} onMouseOut={tooltip.bind(null, null)}onClick={sortOrder.bind(this, 'es')}>{'eft'}</th>
<th className='lft sortable' onClick={sortOrder.bind(this, 'esdpsh')}>{translate('effective sdps')}</th> <th className='lft sortable' onMouseOver={termtip.bind(null, 'TT_EFFECTIVE_SDPS_ARMOUR')} onMouseOut={tooltip.bind(null, null)}onClick={sortOrder.bind(this, 'esdpsh')}>{'sdps'}</th>
<th className='sortable' onClick={sortOrder.bind(this, 'eh')}>{translate('effectiveness')}</th> <th className='sortable' onMouseOver={termtip.bind(null, 'TT_EFFECTIVENESS_ARMOUR')} onMouseOut={tooltip.bind(null, null)}onClick={sortOrder.bind(this, 'eh')}>{'eft'}</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{rows} {rows}
</tbody> </tbody>
</table> </table>
</div>
</span>); </span>);
} }
} }

View File

@@ -55,6 +55,11 @@ export const terms = {
TT_MODULE_PROTECTION_EXTERNAL: 'Percentage of damage diverted from hardpoints to module reinforcement packages', TT_MODULE_PROTECTION_EXTERNAL: 'Percentage of damage diverted from hardpoints to module reinforcement packages',
TT_MODULE_PROTECTION_INTERNAL: 'Percentage of damage diverted from non-hardpoint modules to module reinforcement packages', TT_MODULE_PROTECTION_INTERNAL: 'Percentage of damage diverted from non-hardpoint modules to module reinforcement packages',
TT_EFFECTIVE_SDPS_SHIELDS: 'Actual sustained DPS whilst WEP capacitor is not empty',
TT_EFFECTIVENESS_SHIELDS: 'Effectivness compared to hitting a 0-resistance target with 0 pips to SYS at 0m',
TT_EFFECTIVE_SDPS_ARMOUR: 'Actual sustained DPS whilst WEP capacitor is not empty',
TT_EFFECTIVENESS_ARMOUR: 'Effectivness compared to hitting a 0-resistance target at 0m',
HELP_MODIFICATIONS_MENU: 'Click on a number to enter a new value, or drag along the bar for small changes', HELP_MODIFICATIONS_MENU: 'Click on a number to enter a new value, or drag along the bar for small changes',
// Other languages fallback to these values // Other languages fallback to these values

View File

@@ -100,7 +100,7 @@ export default class OutfittingPage extends Page {
fuel: ship.fuelCapacity, fuel: ship.fuelCapacity,
cargo: 0, cargo: 0,
boost: false, boost: false,
engagementRange: 1500, engagementRange: 1000,
opponent: new Ship('anaconda', Ships['anaconda'].properties, Ships['anaconda'].slots).buildWith(Ships['anaconda'].defaults) opponent: new Ship('anaconda', Ships['anaconda'].properties, Ships['anaconda'].slots).buildWith(Ships['anaconda'].defaults)
}; };
} }

View File

@@ -602,10 +602,8 @@ export function offenceMetrics(ship, opponent, wep, engagementrange) {
name: m.name || m.grp, name: m.name || m.grp,
classRating, classRating,
engineering, engineering,
sdpsShields: weaponSustainedDps.damage.shields.total, sdps: weaponSustainedDps.damage,
sdpsArmour: weaponSustainedDps.damage.armour.total, effectiveness: weaponSustainedDps.effectiveness
effectivenessShields: weaponSustainedDps.effectiveness.shields.total,
effectivenessArmour: weaponSustainedDps.effectiveness.armour.total
}); });
} }
} }

View File

@@ -24,6 +24,7 @@
@import 'movement'; @import 'movement';
@import 'shippicker'; @import 'shippicker';
@import 'defence'; @import 'defence';
@import 'offence';
html, body { html, body {
height: 100%; height: 100%;

14
src/less/offence.less Executable file
View File

@@ -0,0 +1,14 @@
#offence {
table {
background-color: @bgBlack;
color: @fg;
margin: 0 auto;
}
.icon {
stroke: @fg;
stroke-width: 20;
fill: transparent;
}
}