Merge pull request #301 from BenJuan26/feature/linting

Fix obvious lint issues
This commit is contained in:
William
2018-06-08 07:15:39 +10:00
committed by GitHub
15 changed files with 757 additions and 774 deletions

View File

@@ -356,7 +356,7 @@ export default class Coriolis extends React.Component {
<div className="right cap"> <div className="right cap">
<a href="https://github.com/EDCD/coriolis" target="_blank" title="Coriolis Github Project">{window.CORIOLIS_VERSION} - {window.CORIOLIS_DATE}</a> <a href="https://github.com/EDCD/coriolis" target="_blank" title="Coriolis Github Project">{window.CORIOLIS_VERSION} - {window.CORIOLIS_DATE}</a>
<br/> <br/>
<a href={"https://github.com/EDCD/coriolis/compare/edcd:develop@{" + window.CORIOLIS_DATE + "}...edcd:develop"} target="_blank" title={"Coriolis Commits since" + window.CORIOLIS_DATE}>Commits since last release ({window.CORIOLIS_DATE})</a> <a href={'https://github.com/EDCD/coriolis/compare/edcd:develop@{' + window.CORIOLIS_DATE + '}...edcd:develop'} target="_blank" title={'Coriolis Commits since' + window.CORIOLIS_DATE}>Commits since last release ({window.CORIOLIS_DATE})</a>
</div> </div>
</footer> </footer>
</div>; </div>;

View File

@@ -137,7 +137,7 @@ export default class AvailableModulesMenu extends TranslatedComponent {
let translate = context.language.translate; let translate = context.language.translate;
let { m, warning, shipMass, onSelect, modules, firstSlotId, lastSlotId } = props; let { m, warning, shipMass, onSelect, modules, firstSlotId, lastSlotId } = props;
let list, currentGroup; let list, currentGroup;
let buildGroup = this._buildGroup.bind( let buildGroup = this._buildGroup.bind(
this, this,
translate, translate,
@@ -149,7 +149,7 @@ export default class AvailableModulesMenu extends TranslatedComponent {
onSelect(m); onSelect(m);
} }
); );
if (modules instanceof Array) { if (modules instanceof Array) {
list = buildGroup(modules[0].grp, modules); list = buildGroup(modules[0].grp, modules);
} else { } else {
@@ -210,7 +210,7 @@ export default class AvailableModulesMenu extends TranslatedComponent {
} }
} }
let trackingFocus = false; let trackingFocus = false;
return { list, currentGroup, trackingFocus}; return { list, currentGroup, trackingFocus };
} }
/** /**
@@ -227,10 +227,10 @@ export default class AvailableModulesMenu extends TranslatedComponent {
_buildGroup(translate, mountedModule, warningFunc, mass, onSelect, grp, modules, firstSlotId, lastSlotId) { _buildGroup(translate, mountedModule, warningFunc, mass, onSelect, grp, modules, firstSlotId, lastSlotId) {
let prevClass = null, prevRating = null, prevName; let prevClass = null, prevRating = null, prevName;
let elems = []; let elems = [];
const sortedModules = modules.sort(this._moduleOrder); const sortedModules = modules.sort(this._moduleOrder);
// Calculate the number of items per class. Used so we don't have long lists with only a few items in each row // Calculate the number of items per class. Used so we don't have long lists with only a few items in each row
const tmp = sortedModules.map((v, i) => v['class']).reduce((count, cls) => { count[cls] = ++count[cls] || 1; return count; }, {}); const tmp = sortedModules.map((v, i) => v['class']).reduce((count, cls) => { count[cls] = ++count[cls] || 1; return count; }, {});
const itemsPerClass = Math.max.apply(null, Object.keys(tmp).map(key => tmp[key])); const itemsPerClass = Math.max.apply(null, Object.keys(tmp).map(key => tmp[key]));
@@ -240,7 +240,7 @@ export default class AvailableModulesMenu extends TranslatedComponent {
let m = sortedModules[i]; let m = sortedModules[i];
let mount = null; let mount = null;
let disabled = false; let disabled = false;
prevName = m.name prevName = m.name;
if (ModuleUtils.isShieldGenerator(m.grp)) { if (ModuleUtils.isShieldGenerator(m.grp)) {
// Shield generators care about maximum hull mass // Shield generators care about maximum hull mass
disabled = mass > m.maxmass; disabled = mass > m.maxmass;
@@ -305,7 +305,7 @@ export default class AvailableModulesMenu extends TranslatedComponent {
{(mount ? ' ' : '') + m.class + m.rating + (m.missile ? '/' + m.missile : '') + (m.name ? ' ' + translate(m.name) : '')} {(mount ? ' ' : '') + m.class + m.rating + (m.missile ? '/' + m.missile : '') + (m.name ? ' ' + translate(m.name) : '')}
</li> </li>
); );
itemsOnThisRow++; itemsOnThisRow++;
prevClass = m.class; prevClass = m.class;
prevRating = m.rating; prevRating = m.rating;
@@ -369,21 +369,21 @@ export default class AvailableModulesMenu extends TranslatedComponent {
*/ */
_keyDown(select, event) { _keyDown(select, event) {
var className = event.currentTarget.attributes['class'].value; let className = event.currentTarget.attributes['class'].value;
if (event.key == 'Enter' && className.indexOf('disabled') < 0 && className.indexOf('active') < 0) { if (event.key == 'Enter' && className.indexOf('disabled') < 0 && className.indexOf('active') < 0) {
select(); select();
return return;
} }
var elemId = event.currentTarget.attributes['data-id'].value; let elemId = event.currentTarget.attributes['data-id'].value;
if (className.indexOf('disabled') < 0 && event.key == 'Tab') { if (className.indexOf('disabled') < 0 && event.key == 'Tab') {
if (event.shiftKey && elemId == this.firstSlotId) { if (event.shiftKey && elemId == this.firstSlotId) {
event.preventDefault(); event.preventDefault();
this.slotItems[this.lastSlotId].focus(); this.slotItems[this.lastSlotId].focus();
return; return;
} }
if (!event.shiftKey && elemId == this.lastSlotId) { if (!event.shiftKey && elemId == this.lastSlotId) {
event.preventDefault(); event.preventDefault();
this.slotItems[this.firstSlotId].focus(); this.slotItems[this.firstSlotId].focus();
return; return;
} }
} }
@@ -391,10 +391,10 @@ export default class AvailableModulesMenu extends TranslatedComponent {
/** /**
* Key Up * Key Up
* *
*/ */
_keyUp(select,event) { _keyUp(select,event) {
//nothing here yet // nothing here yet
} }
/** /**
@@ -487,7 +487,7 @@ export default class AvailableModulesMenu extends TranslatedComponent {
* @return {React.Component} List * @return {React.Component} List
*/ */
render() { render() {
console.log("Tracking focus? " + this.state.trackingFocus); console.log('Tracking focus? ' + this.state.trackingFocus);
return ( return (
<div ref={node => this.node = node} <div ref={node => this.node = node}
className={cn('select', this.props.className)} className={cn('select', this.props.className)}

View File

@@ -505,8 +505,8 @@ export default class Header extends TranslatedComponent {
return ( return (
<header> <header>
{this.props.appCacheUpdate && <div id="app-update" onClick={() => window.location.reload() }>{translate('PHRASE_UPDATE_RDY')}</div>} {this.props.appCacheUpdate && <div id="app-update" onClick={() => window.location.reload() }>{translate('PHRASE_UPDATE_RDY')}</div>}
{this.props.appCache ? <a className={"view-changes"} href={"https://github.com/EDCD/coriolis/compare/edcd:develop@{" + window.CORIOLIS_DATE + "}...edcd:develop"} target="_blank"> {this.props.appCache ? <a className={'view-changes'} href={'https://github.com/EDCD/coriolis/compare/edcd:develop@{' + window.CORIOLIS_DATE + '}...edcd:develop'} target="_blank">
{"View Release Changes"} {'View Release Changes'}
</a> : null} </a> : null}
<Link className='l' href='/' style={{ marginRight: '1em' }} title='Home'><CoriolisLogo className='icon xl' /></Link> <Link className='l' href='/' style={{ marginRight: '1em' }} title='Home'><CoriolisLogo className='icon xl' /></Link>

View File

@@ -13,7 +13,7 @@ import {
getPercent, getPercent,
setRandom, setRandom,
specialToolTip specialToolTip
} from '../utils/BlueprintFunctions' } from '../utils/BlueprintFunctions';
/** /**
* Modifications menu * Modifications menu
@@ -50,8 +50,8 @@ export default class ModificationsMenu extends TranslatedComponent {
this.firstModId = null; this.firstModId = null;
this.firstBPLabel = null;// First item in mod menu this.firstBPLabel = null;// First item in mod menu
this.lastModId = null; this.lastModId = null;
this.lastNeId = null;//Last number editor id. Used to set focus to last number editor when shift-tab pressed on first element in mod menu. this.lastNeId = null;// Last number editor id. Used to set focus to last number editor when shift-tab pressed on first element in mod menu.
this.modValDidChange = false; //used to determine if component update was caused by change in modification value. this.modValDidChange = false; // used to determine if component update was caused by change in modification value.
this._handleModChange = this._handleModChange.bind(this); this._handleModChange = this._handleModChange.bind(this);
this.state = { this.state = {
@@ -78,19 +78,19 @@ export default class ModificationsMenu extends TranslatedComponent {
// Grade is a string in the JSON so make it a number // Grade is a string in the JSON so make it a number
grade = Number(grade); grade = Number(grade);
const classes = cn('c', { const classes = cn('c', {
active: m.blueprint && blueprint.id === m.blueprint.id && grade === m.blueprint.grade active: m.blueprint && blueprint.id === m.blueprint.id && grade === m.blueprint.grade
}); });
const close = this._blueprintSelected.bind(this, blueprintName, grade); const close = this._blueprintSelected.bind(this, blueprintName, grade);
const key = blueprintName + ':' + grade; const key = blueprintName + ':' + grade;
const tooltipContent = blueprintTooltip(translate, blueprint.grades[grade], Modifications.modules[m.grp].blueprints[blueprintName].grades[grade].engineers, m.grp); const tooltipContent = blueprintTooltip(translate, blueprint.grades[grade], Modifications.modules[m.grp].blueprints[blueprintName].grades[grade].engineers, m.grp);
blueprintGrades.unshift(<li key={key} tabIndex="0" data-id={key} className={classes} style={{ width: '2em' }} onMouseOver={termtip.bind(null, tooltipContent)} onMouseOut={tooltip.bind(null, null)} onClick={close} onKeyDown={this._keyDown} ref={modItem => this.modItems[key] = modItem}>{grade}</li>); blueprintGrades.unshift(<li key={key} tabIndex="0" data-id={key} className={classes} style={{ width: '2em' }} onMouseOver={termtip.bind(null, tooltipContent)} onMouseOut={tooltip.bind(null, null)} onClick={close} onKeyDown={this._keyDown} ref={modItem => this.modItems[key] = modItem}>{grade}</li>);
} }
if (blueprintGrades) { if (blueprintGrades) {
const thisLen = blueprintGrades.length; const thisLen = blueprintGrades.length;
if (this.firstModId == null) this.firstModId = blueprintGrades[0].key; if (this.firstModId == null) this.firstModId = blueprintGrades[0].key;
this.lastModId = blueprintGrades[thisLen-1].key; this.lastModId = blueprintGrades[thisLen - 1].key;
blueprints.push(<div key={blueprint.name} className={'select-group cap'}>{translate(blueprint.name)}</div>); blueprints.push(<div key={blueprint.name} className={'select-group cap'}>{translate(blueprint.name)}</div>);
blueprints.push(<ul key={blueprintName}>{blueprintGrades}</ul>); blueprints.push(<ul key={blueprintName}>{blueprintGrades}</ul>);
} }
@@ -104,37 +104,36 @@ export default class ModificationsMenu extends TranslatedComponent {
* @param {SyntheticEvent} event Event * @param {SyntheticEvent} event Event
* *
*/ */
_keyDown(event) { _keyDown(event) {
var className = null; let className = null;
var elemId = null; let elemId = null;
if (event.currentTarget.attributes['class']) className = event.currentTarget.attributes['class'].value; if (event.currentTarget.attributes['class']) className = event.currentTarget.attributes['class'].value;
if (event.currentTarget.attributes['data-id']) elemId = event.currentTarget.attributes['data-id'].value; if (event.currentTarget.attributes['data-id']) elemId = event.currentTarget.attributes['data-id'].value;
if (event.key == 'Enter' && className.indexOf('disabled') < 0 && className.indexOf('active') < 0) { if (event.key == 'Enter' && className.indexOf('disabled') < 0 && className.indexOf('active') < 0) {
event.stopPropagation(); event.stopPropagation();
if (elemId != null) { if (elemId != null) {
this.modItems[elemId].click(); this.modItems[elemId].click();
} else { } else {
event.currentTarget.click(); event.currentTarget.click();
} }
return return;
} }
if (event.key == 'Tab') { if (event.key == 'Tab') {
//Shift-Tab // Shift-Tab
if(event.shiftKey) { if(event.shiftKey) {
if (elemId == this.firstModId && elemId != null) { if (elemId == this.firstModId && elemId != null) {
// Initial modification menu // Initial modification menu
event.preventDefault(); event.preventDefault();
this.modItems[this.lastModId].focus(); this.modItems[this.lastModId].focus();
return; return;
} else if (event.currentTarget.className.indexOf("button-inline-menu") >= 0 && event.currentTarget.previousElementSibling == null && this.lastNeId != null && this.modItems[this.lastNeId] != null) { } else if (event.currentTarget.className.indexOf('button-inline-menu') >= 0 && event.currentTarget.previousElementSibling == null && this.lastNeId != null && this.modItems[this.lastNeId] != null) {
// shift-tab on first element in modifications menu. set focus to last number editor field if open // shift-tab on first element in modifications menu. set focus to last number editor field if open
event.preventDefault(); event.preventDefault();
this.modItems[this.lastNeId].lastChild.focus(); this.modItems[this.lastNeId].lastChild.focus();
return; return;
} else if (event.currentTarget.className.indexOf("button-inline-menu") >= 0 && event.currentTarget.previousElementSibling == null) { } else if (event.currentTarget.className.indexOf('button-inline-menu') >= 0 && event.currentTarget.previousElementSibling == null) {
// shift-tab on button-inline-menu with no number editor // shift-tab on button-inline-menu with no number editor
event.preventDefault(); event.preventDefault();
event.currentTarget.parentElement.lastElementChild.focus(); event.currentTarget.parentElement.lastElementChild.focus();
@@ -143,9 +142,9 @@ export default class ModificationsMenu extends TranslatedComponent {
if (elemId == this.lastModId && elemId != null) { if (elemId == this.lastModId && elemId != null) {
// Initial modification menu // Initial modification menu
event.preventDefault(); event.preventDefault();
this.modItems[this.firstModId].focus(); this.modItems[this.firstModId].focus();
return; return;
} else if (event.currentTarget.className.indexOf("button-inline-menu") >= 0 && event.currentTarget.nextSibling == null && event.currentTarget.nodeName != "TD") { } else if (event.currentTarget.className.indexOf('button-inline-menu') >= 0 && event.currentTarget.nextSibling == null && event.currentTarget.nodeName != 'TD') {
// Experimental menu // Experimental menu
event.preventDefault(); event.preventDefault();
event.currentTarget.parentElement.firstElementChild.focus(); event.currentTarget.parentElement.firstElementChild.focus();
@@ -154,11 +153,10 @@ export default class ModificationsMenu extends TranslatedComponent {
event.preventDefault(); event.preventDefault();
this.modItems[this.firstBPLabel].focus(); this.modItems[this.firstBPLabel].focus();
} }
} }
} }
} }
/** /**
* Render the specials * Render the specials
@@ -167,7 +165,6 @@ export default class ModificationsMenu extends TranslatedComponent {
* @return {Object} list: Array of React Components * @return {Object} list: Array of React Components
*/ */
_renderSpecials(props, context) { _renderSpecials(props, context) {
const { m } = props; const { m } = props;
const { language, tooltip, termtip } = context; const { language, tooltip, termtip } = context;
const translate = language.translate; const translate = language.translate;
@@ -181,7 +178,7 @@ export default class ModificationsMenu extends TranslatedComponent {
continue; continue;
} }
const classes = cn('button-inline-menu', { const classes = cn('button-inline-menu', {
active: m.blueprint && m.blueprint.special && m.blueprint.special.edname == specialName active: m.blueprint && m.blueprint.special && m.blueprint.special.edname == specialName
}); });
const close = this._specialSelected.bind(this, specialName); const close = this._specialSelected.bind(this, specialName);
if (m.blueprint && m.blueprint.name) { if (m.blueprint && m.blueprint.name) {
@@ -200,7 +197,7 @@ export default class ModificationsMenu extends TranslatedComponent {
} }
} }
} }
console.log("_renderSpecials. specials: %O", specials); console.log('_renderSpecials. specials: %O', specials);
return specials; return specials;
} }
@@ -219,7 +216,7 @@ export default class ModificationsMenu extends TranslatedComponent {
modifications.push(<Modification key={ key } ship={ ship } m={ m } name={ modName } value={ m.getModValue(modName) / 100 || 0 } onChange={ onChange } onKeyDown={ this._keyDown } modItems={ this.modItems } handleModChange = {this._handleModChange} />); modifications.push(<Modification key={ key } ship={ ship } m={ m } name={ modName } value={ m.getModValue(modName) / 100 || 0 } onChange={ onChange } onKeyDown={ this._keyDown } modItems={ this.modItems } handleModChange = {this._handleModChange} />);
} }
} }
console.log("_renderModifications. modItems: %O", this.modItems); console.log('_renderModifications. modItems: %O', this.modItems);
return modifications; return modifications;
} }
@@ -280,10 +277,10 @@ export default class ModificationsMenu extends TranslatedComponent {
_rollFifty() { _rollFifty() {
const { m, ship } = this.props; const { m, ship } = this.props;
setPercent(ship, m, 50); setPercent(ship, m, 50);
// this will change the values in the modifications. Set modDidChange to true to prevent focus change when component updates // this will change the values in the modifications. Set modDidChange to true to prevent focus change when component updates
this._handleModChange(true); this._handleModChange(true);
this.props.onChange(); this.props.onChange();
} }
@@ -293,10 +290,10 @@ export default class ModificationsMenu extends TranslatedComponent {
_rollRandom() { _rollRandom() {
const { m, ship } = this.props; const { m, ship } = this.props;
setRandom(ship, m); setRandom(ship, m);
// this will change the values in the modifications. Set modDidChange to true to prevent focus change when component updates // this will change the values in the modifications. Set modDidChange to true to prevent focus change when component updates
this._handleModChange(true); this._handleModChange(true);
this.props.onChange(); this.props.onChange();
} }
@@ -306,10 +303,10 @@ export default class ModificationsMenu extends TranslatedComponent {
_rollBest() { _rollBest() {
const { m, ship } = this.props; const { m, ship } = this.props;
setPercent(ship, m, 100); setPercent(ship, m, 100);
// this will change the values in the modifications. Set modDidChange to true to prevent focus change when component updates // this will change the values in the modifications. Set modDidChange to true to prevent focus change when component updates
this._handleModChange(true); this._handleModChange(true);
this.props.onChange(); this.props.onChange();
} }
@@ -319,13 +316,11 @@ export default class ModificationsMenu extends TranslatedComponent {
_rollWorst() { _rollWorst() {
const { m, ship } = this.props; const { m, ship } = this.props;
setPercent(ship, m, 0); setPercent(ship, m, 0);
// this will change the values in the modifications. Set modDidChange to true to prevent focus change when component updates // this will change the values in the modifications. Set modDidChange to true to prevent focus change when component updates
this._handleModChange(true); this._handleModChange(true);
this.props.onChange();
this.props.onChange();
} }
/** /**
@@ -374,9 +369,8 @@ export default class ModificationsMenu extends TranslatedComponent {
} }
} }
} else { } else {
this._handleModChange(false);//Need to reset if component update due to value change this._handleModChange(false);// Need to reset if component update due to value change
} }
} }
componentWillUnmount() { componentWillUnmount() {
@@ -407,7 +401,7 @@ export default class ModificationsMenu extends TranslatedComponent {
let haveBlueprint = false; let haveBlueprint = false;
let blueprintTt; let blueprintTt;
let blueprintCv; let blueprintCv;
//TODO: Fix this to actually find the correct blueprint. // TODO: Fix this to actually find the correct blueprint.
if (!m.blueprint || !m.blueprint.name || !m.blueprint.fdname || !Modifications.modules[m.grp].blueprints || !Modifications.modules[m.grp].blueprints[m.blueprint.fdname]) { if (!m.blueprint || !m.blueprint.name || !m.blueprint.fdname || !Modifications.modules[m.grp].blueprints || !Modifications.modules[m.grp].blueprints[m.blueprint.fdname]) {
this.props.ship.clearModuleBlueprint(m); this.props.ship.clearModuleBlueprint(m);
this.props.ship.clearModuleSpecial(m); this.props.ship.clearModuleSpecial(m);
@@ -440,7 +434,7 @@ export default class ModificationsMenu extends TranslatedComponent {
const showReset = !blueprintMenuOpened && (!specialMenuOpened || !specials.length) && haveBlueprint; const showReset = !blueprintMenuOpened && (!specialMenuOpened || !specials.length) && haveBlueprint;
const showMods = !blueprintMenuOpened && (!specialMenuOpened || !specials.length) && haveBlueprint; const showMods = !blueprintMenuOpened && (!specialMenuOpened || !specials.length) && haveBlueprint;
if (haveBlueprint) { if (haveBlueprint) {
this.firstBPLabel = blueprintLabel this.firstBPLabel = blueprintLabel;
} else { } else {
this.firstBPLabel = 'selectBP'; this.firstBPLabel = 'selectBP';
} }
@@ -451,20 +445,20 @@ export default class ModificationsMenu extends TranslatedComponent {
onContextMenu={stopCtxPropagation} onContextMenu={stopCtxPropagation}
ref={modItem => this.modItems['modMainDiv'] = modItem} ref={modItem => this.modItems['modMainDiv'] = modItem}
> >
{ showBlueprintsMenu | showSpecialsMenu ? '' : haveBlueprint ? { showBlueprintsMenu | showSpecialsMenu ? '' : haveBlueprint ?
<div tabIndex="0" className={ cn('section-menu button-inline-menu', { selected: blueprintMenuOpened })} style={{ cursor: 'pointer' }} onMouseOver={termtip.bind(null, blueprintTt)} onMouseOut={tooltip.bind(null, null)} onClick={_toggleBlueprintsMenu} onKeyDown={ this._keyDown } ref={modItems => this.modItems[this.firstBPLabel] = modItems}>{blueprintLabel}</div> : <div tabIndex="0" className={ cn('section-menu button-inline-menu', { selected: blueprintMenuOpened })} style={{ cursor: 'pointer' }} onMouseOver={termtip.bind(null, blueprintTt)} onMouseOut={tooltip.bind(null, null)} onClick={_toggleBlueprintsMenu} onKeyDown={ this._keyDown } ref={modItems => this.modItems[this.firstBPLabel] = modItems}>{blueprintLabel}</div> :
<div tabIndex="0" className={ cn('section-menu button-inline-menu', { selected: blueprintMenuOpened })} style={{ cursor: 'pointer' }} onClick={_toggleBlueprintsMenu} onKeyDown={ this._keyDown } ref={modItems => this.modItems[this.firstBPLabel] = modItems}>{translate('PHRASE_SELECT_BLUEPRINT')}</div> } <div tabIndex="0" className={ cn('section-menu button-inline-menu', { selected: blueprintMenuOpened })} style={{ cursor: 'pointer' }} onClick={_toggleBlueprintsMenu} onKeyDown={ this._keyDown } ref={modItems => this.modItems[this.firstBPLabel] = modItems}>{translate('PHRASE_SELECT_BLUEPRINT')}</div> }
{ showBlueprintsMenu ? this._renderBlueprints(this.props, this.context) : null } { showBlueprintsMenu ? this._renderBlueprints(this.props, this.context) : null }
{ showSpecial & !showSpecialsMenu ? <div tabIndex="0" className={ cn('section-menu button-inline-menu', { selected: specialMenuOpened })} style={{ cursor: 'pointer' }} onMouseOver={specialTt ? termtip.bind(null, specialTt) : null} onMouseOut={specialTt ? tooltip.bind(null, null) : null} onClick={_toggleSpecialsMenu} onKeyDown={ this._keyDown }>{specialLabel}</div> : null } { showSpecial & !showSpecialsMenu ? <div tabIndex="0" className={ cn('section-menu button-inline-menu', { selected: specialMenuOpened })} style={{ cursor: 'pointer' }} onMouseOver={specialTt ? termtip.bind(null, specialTt) : null} onMouseOut={specialTt ? tooltip.bind(null, null) : null} onClick={_toggleSpecialsMenu} onKeyDown={ this._keyDown }>{specialLabel}</div> : null }
{ showSpecialsMenu ? specials : null } { showSpecialsMenu ? specials : null }
{ showReset ? <div tabIndex="0" className={'section-menu button-inline-menu warning'} style={{ cursor: 'pointer' }} onClick={_reset} onKeyDown={ this._keyDown } onMouseOver={termtip.bind(null, 'PHRASE_BLUEPRINT_RESET')} onMouseOut={tooltip.bind(null, null)}> { translate('reset') } </div> : null } { showReset ? <div tabIndex="0" className={'section-menu button-inline-menu warning'} style={{ cursor: 'pointer' }} onClick={_reset} onKeyDown={ this._keyDown } onMouseOver={termtip.bind(null, 'PHRASE_BLUEPRINT_RESET')} onMouseOut={tooltip.bind(null, null)}> { translate('reset') } </div> : null }
{ showRolls ? { showRolls ?
<table style={{ width: '100%', backgroundColor: 'transparent' }}> <table style={{ width: '100%', backgroundColor: 'transparent' }}>
<tbody> <tbody>
{ showRolls ? { showRolls ?
<tr> <tr>
<td tabIndex="0" className={ cn('section-menu button-inline-menu', {active: false})}> { translate('roll') }: </td> <td tabIndex="0" className={ cn('section-menu button-inline-menu', { active: false })}> { translate('roll') }: </td>
<td tabIndex="0" className={ cn('section-menu button-inline-menu', { active: blueprintCv === 0 })} style={{ cursor: 'pointer' }} onClick={_rollWorst} onKeyDown={ this._keyDown } onMouseOver={termtip.bind(null, 'PHRASE_BLUEPRINT_WORST')} onMouseOut={tooltip.bind(null, null)}> { translate('0%') } </td> <td tabIndex="0" className={ cn('section-menu button-inline-menu', { active: blueprintCv === 0 })} style={{ cursor: 'pointer' }} onClick={_rollWorst} onKeyDown={ this._keyDown } onMouseOver={termtip.bind(null, 'PHRASE_BLUEPRINT_WORST')} onMouseOut={tooltip.bind(null, null)}> { translate('0%') } </td>
<td tabIndex="0" className={ cn('section-menu button-inline-menu', { active: blueprintCv === 50 })} style={{ cursor: 'pointer' }} onClick={_rollFifty} onKeyDown={ this._keyDown } onMouseOver={termtip.bind(null, 'PHRASE_BLUEPRINT_FIFTY')} onMouseOut={tooltip.bind(null, null)}> { translate('50%') } </td> <td tabIndex="0" className={ cn('section-menu button-inline-menu', { active: blueprintCv === 50 })} style={{ cursor: 'pointer' }} onClick={_rollFifty} onKeyDown={ this._keyDown } onMouseOver={termtip.bind(null, 'PHRASE_BLUEPRINT_FIFTY')} onMouseOut={tooltip.bind(null, null)}> { translate('50%') } </td>
<td tabIndex="0" className={ cn('section-menu button-inline-menu', { active: blueprintCv === 100 })} style={{ cursor: 'pointer' }} onClick={_rollFull} onKeyDown={ this._keyDown } onMouseOver={termtip.bind(null, 'PHRASE_BLUEPRINT_BEST')} onMouseOut={tooltip.bind(null, null)}> { translate('100%') } </td> <td tabIndex="0" className={ cn('section-menu button-inline-menu', { active: blueprintCv === 100 })} style={{ cursor: 'pointer' }} onClick={_rollFull} onKeyDown={ this._keyDown } onMouseOver={termtip.bind(null, 'PHRASE_BLUEPRINT_BEST')} onMouseOut={tooltip.bind(null, null)}> { translate('100%') } </td>

View File

@@ -19,11 +19,11 @@ export default class ShipSummaryTable extends TranslatedComponent {
}; };
constructor(props) { constructor(props) {
super(props) super(props);
this.didContextChange = this.didContextChange.bind(this); this.didContextChange = this.didContextChange.bind(this);
this.state = { this.state = {
shieldColour: 'blue' shieldColour: 'blue'
} };
} }
/** /**
@@ -56,7 +56,7 @@ export default class ShipSummaryTable extends TranslatedComponent {
} }
this.state = { this.state = {
shieldColour shieldColour
} };
return <div id='summary'> return <div id='summary'>
<table className={'summaryTable'}> <table className={'summaryTable'}>
<thead> <thead>
@@ -140,8 +140,8 @@ export default class ShipSummaryTable extends TranslatedComponent {
<td>{int(ship.shieldThermRes * 100) + '%'}</td> <td>{int(ship.shieldThermRes * 100) + '%'}</td>
<td>{int(sgMetrics && sgMetrics.generator ? sgMetrics.total / sgMetrics.absolute.total : 0)}</td> <td>{int(sgMetrics && sgMetrics.generator ? sgMetrics.total / sgMetrics.absolute.total : 0)}</td>
<td>{int(sgMetrics && sgMetrics.generator ? sgMetrics.total / sgMetrics.explosive.total : 0)}</td> <td>{int(sgMetrics && sgMetrics.generator ? sgMetrics.total / sgMetrics.explosive.total : 0)}</td>
<td>{int(sgMetrics && sgMetrics.generator ? sgMetrics.total / sgMetrics.kinetic.total : 0 )}</td> <td>{int(sgMetrics && sgMetrics.generator ? sgMetrics.total / sgMetrics.kinetic.total : 0)}</td>
<td>{int(sgMetrics && sgMetrics.generator ? sgMetrics.total / sgMetrics.thermal.total : 0 )}</td> <td>{int(sgMetrics && sgMetrics.generator ? sgMetrics.total / sgMetrics.thermal.total : 0)}</td>
<td>{sgMetrics && sgMetrics.recover ? formats.time(sgMetrics.recover) : 0}</td> <td>{sgMetrics && sgMetrics.recover ? formats.time(sgMetrics.recover) : 0}</td>
<td>{sgMetrics && sgMetrics.recharge ? formats.time(sgMetrics.recharge) : 0}</td> <td>{sgMetrics && sgMetrics.recharge ? formats.time(sgMetrics.recharge) : 0}</td>
</tr> </tr>

View File

@@ -1,361 +1,353 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
const MARGIN_LR = 8; // Left/ Right margin const MARGIN_LR = 8; // Left/ Right margin
/** /**
* Horizontal Slider * Horizontal Slider
*/ */
export default class Slider extends React.Component { export default class Slider extends React.Component {
static defaultProps = { static defaultProps = {
axis: false, axis: false,
min: 0, min: 0,
max: 1, max: 1,
scale: 1 // SVG render scale scale: 1 // SVG render scale
}; };
static propTypes = { static propTypes = {
axis: PropTypes.bool, axis: PropTypes.bool,
axisUnit: PropTypes.string,//units (T, M, etc.) axisUnit: PropTypes.string,// units (T, M, etc.)
max: PropTypes.number, max: PropTypes.number,
min: PropTypes.number, min: PropTypes.number,
onChange: PropTypes.func.isRequired,// function which determins percent value onChange: PropTypes.func.isRequired,// function which determins percent value
onResize: PropTypes.func, onResize: PropTypes.func,
percent: PropTypes.number.isRequired,//value of slider percent: PropTypes.number.isRequired,// value of slider
scale: PropTypes.number scale: PropTypes.number
}; };
/** /**
* Constructor * Constructor
* @param {Object} props React Component properties * @param {Object} props React Component properties
*/ */
constructor(props) { constructor(props) {
super(props); super(props);
this._down = this._down.bind(this); this._down = this._down.bind(this);
this._move = this._move.bind(this); this._move = this._move.bind(this);
this._up = this._up.bind(this); this._up = this._up.bind(this);
this._keyup = this._keyup.bind(this); this._keyup = this._keyup.bind(this);
this._keydown = this._keydown.bind(this); this._keydown = this._keydown.bind(this);
this._touchstart = this._touchstart.bind(this); this._touchstart = this._touchstart.bind(this);
this._touchend = this._touchend.bind(this); this._touchend = this._touchend.bind(this);
this._updatePercent = this._updatePercent.bind(this); this._updatePercent = this._updatePercent.bind(this);
this._updateDimensions = this._updateDimensions.bind(this); this._updateDimensions = this._updateDimensions.bind(this);
this.state = { width: 0 }; this.state = { width: 0 };
} }
/** /**
* On Mouse/Touch down handler * On Mouse/Touch down handler
* @param {SyntheticEvent} event Event * @param {SyntheticEvent} event Event
*/ */
_down(event) { _down(event) {
let rect = event.currentTarget.getBoundingClientRect();
let rect = event.currentTarget.getBoundingClientRect(); this.left = rect.left;
this.left = rect.left; this.width = rect.width;
this.width = rect.width; this._move(event);
this._move(event); this.touchStartTimer = setTimeout(() => this.sliderInputBox._setDisplay('block'), 1500);
this.touchStartTimer = setTimeout(() => this.sliderInputBox._setDisplay('block'), 1500); }
}
/**
/** * Update the slider percentage on move
* Update the slider percentage on move * @param {SyntheticEvent} event Event
* @param {SyntheticEvent} event Event */
*/ _move(event) {
_move(event) { if(this.width !== null && this.left != null) {
if(this.width !== null && this.left != null) { let clientX = event.touches ? event.touches[0].clientX : event.clientX;
let clientX = event.touches ? event.touches[0].clientX : event.clientX; event.preventDefault();
event.preventDefault(); this._updatePercent(clientX - this.left, this.width);
this._updatePercent(clientX - this.left, this.width); }
} }
}
/**
/** * On Mouse/Touch up handler
* On Mouse/Touch up handler * @param {Event} event DOM Event
* @param {Event} event DOM Event */
*/ _up(event) {
_up(event) { this.sliderInputBox.sliderVal.focus();
this.sliderInputBox.sliderVal.focus(); clearTimeout(this.touchStartTimer);
clearTimeout(this.touchStartTimer); event.preventDefault();
event.preventDefault(); this.left = null;
this.left = null; this.width = null;
this.width = null; }
}
/**
/** * Key up handler for keyboard.
* Key up handler for keyboard. * display the number field then set focus to it
* display the number field then set focus to it * when "Enter" key is pressed
* when "Enter" key is pressed * @param {Event} event Keyboard event
* @param {Event} event Keyboard event */
*/ _keyup(event) {
_keyup(event) { switch (event.key) {
switch (event.key) { case 'Enter':
case 'Enter': event.preventDefault();
event.preventDefault(); this.sliderInputBox._setDisplay('block');
this.sliderInputBox._setDisplay('block'); // this.enterTimer = setTimeout(() => this.sliderInputBox.sliderVal.focus(), 10);
//this.enterTimer = setTimeout(() => this.sliderInputBox.sliderVal.focus(), 10); return;
return; default:
default: return;
return; }
} }
/**
} * Key down handler
/** * increment slider position by +/- 1 when right/left arrow key is pressed or held
* Key down handler * @param {Event} event
* increment slider position by +/- 1 when right/left arrow key is pressed or held */
* @param {Event} event _keydown(event) {
*/ switch (event.key) {
_keydown(event) { case 'ArrowRight':
let newVal = this.props.percent * this.props.max + 1;
switch (event.key) { if (newVal <= this.props.max) this.props.onChange(newVal / this.props.max);
case 'ArrowRight': return;
var newVal = this.props.percent*this.props.max + 1; case 'ArrowLeft':
if (newVal <= this.props.max) this.props.onChange(newVal/this.props.max); let newVal = this.props.percent * this.props.max - 1;
return; if (newVal >= 0) this.props.onChange(newVal / this.props.max);
case 'ArrowLeft': return;
var newVal = this.props.percent*this.props.max - 1; default:
if (newVal >= 0) this.props.onChange(newVal/this.props.max); return;
return; }
default: }
return;
} /**
} * Touch start handler
* @param {Event} event DOM Event
/** *
* Touch start handler */
* @param {Event} event DOM Event _touchstart(event) {
* this.touchStartTimer = setTimeout(() => this.sliderInputBox._setDisplay('block'), 1500);
*/ }
_touchstart(event) {
this.touchStartTimer = setTimeout(() => this.sliderInputBox._setDisplay('block'), 1500); _touchend(event) {
} this.sliderInputBox.sliderVal.focus();
clearTimeout(this.touchStartTimer);
_touchend(event) { }
this.sliderInputBox.sliderVal.focus();
clearTimeout(this.touchStartTimer); /**
} * Determine if the user is still dragging
* @param {SyntheticEvent} event Event
/** */
* Determine if the user is still dragging _enter(event) {
* @param {SyntheticEvent} event Event if(event.buttons !== 1) {
*/ this.left = null;
_enter(event) { this.width = null;
if(event.buttons !== 1) { }
this.left = null; }
this.width = null;
} /**
} * Update the slider percentage
* @param {number} pos Slider drag position
/** * @param {number} width Slider width
* Update the slider percentage * @param {Event} event DOM Event
* @param {number} pos Slider drag position */
* @param {number} width Slider width _updatePercent(pos, width) {
* @param {Event} event DOM Event this.props.onChange(Math.min(Math.max(pos / width, 0), 1));
*/ }
_updatePercent(pos, width) {
this.props.onChange(Math.min(Math.max(pos / width, 0), 1)); /**
} * Update dimenions from rendered DOM
*/
/** _updateDimensions() {
* Update dimenions from rendered DOM this.setState({
*/ outerWidth: this.node.getBoundingClientRect().width
_updateDimensions() { });
this.setState({ }
outerWidth: this.node.getBoundingClientRect().width
}); /**
} * Add listeners when about to mount
*/
/** componentWillMount() {
* Add listeners when about to mount if (this.props.onResize) {
*/ this.resizeListener = this.props.onResize(this._updateDimensions);
componentWillMount() { }
if (this.props.onResize) { }
this.resizeListener = this.props.onResize(this._updateDimensions);
} /**
} * Trigger DOM updates on mount
*/
/** componentDidMount() {
* Trigger DOM updates on mount this._updateDimensions();
*/ }
componentDidMount() {
this._updateDimensions(); /**
* Remove listeners on unmount
} */
componentWillUnmount() {
/** if (this.resizeListener) {
* Remove listeners on unmount this.resizeListener.remove();
*/ }
componentWillUnmount() { }
if (this.resizeListener) {
this.resizeListener.remove(); /**
} * Render the slider
} * @return {React.Component} The slider
*/
/** render() {
* Render the slider let outerWidth = this.state.outerWidth;
* @return {React.Component} The slider let { axis, axisUnit, min, max, scale } = this.props;
*/
render() { let style = {
let outerWidth = this.state.outerWidth; width: '100%',
let { axis, axisUnit, min, max, scale } = this.props; height: axis ? '2.5em' : '1.5em',
boxSizing: 'border-box'
let style = { };
width: '100%',
height: axis ? '2.5em' : '1.5em', if (!outerWidth) {
boxSizing: 'border-box' return <svg style={style} ref={node => this.node = node} />;
}; }
if (!outerWidth) { let margin = MARGIN_LR * scale;
return <svg style={style} ref={node => this.node = node} />; let width = outerWidth - (margin * 2);
} let pctPos = width * this.props.percent;
let margin = MARGIN_LR * scale; return <div><svg
let width = outerWidth - (margin * 2); onMouseUp={this._up} onMouseEnter={this._enter.bind(this)} onMouseMove={this._move} onKeyUp={this._keyup} onKeyDown={this._keydown} style={style} ref={node => this.node = node} tabIndex="0">
let pctPos = width * this.props.percent; <rect className='primary' style={{ opacity: 0.3 }} x={margin} y='0.25em' rx='0.3em' ry='0.3em' width={width} height='0.7em' />
<rect className='primary-disabled' x={margin} y='0.45em' rx='0.15em' ry='0.15em' width={pctPos} height='0.3em' />
return <div><svg <circle className='primary' r={margin} cy='0.6em' cx={pctPos + margin} />
onMouseUp={this._up} onMouseEnter={this._enter.bind(this)} onMouseMove={this._move} onKeyUp={this._keyup} onKeyDown={this._keydown} style={style} ref={node => this.node = node} tabIndex="0"> <rect x={margin} width={width} height='100%' fillOpacity='0' style={{ cursor: 'col-resize' }} onMouseDown={this._down} onTouchMove={this._move} onTouchStart={this._down} onTouchEnd={this._touchend} />
<rect className='primary' style={{ opacity: 0.3 }} x={margin} y='0.25em' rx='0.3em' ry='0.3em' width={width} height='0.7em' /> {axis && <g style={{ fontSize: '.7em' }}>
<rect className='primary-disabled' x={margin} y='0.45em' rx='0.15em' ry='0.15em' width={pctPos} height='0.3em' /> <text className='primary-disabled' y='3em' x={margin} style={{ textAnchor: 'middle' }}>{min + axisUnit}</text>
<circle className='primary' r={margin} cy='0.6em' cx={pctPos + margin} /> <text className='primary-disabled' y='3em' x='50%' style={{ textAnchor: 'middle' }}>{(min + max / 2) + axisUnit}</text>
<rect x={margin} width={width} height='100%' fillOpacity='0' style={{ cursor: 'col-resize' }} onMouseDown={this._down} onTouchMove={this._move} onTouchStart={this._down} onTouchEnd={this._touchend} /> <text className='primary-disabled' y='3em' x='100%' style={{ textAnchor: 'end' }}>{max + axisUnit}</text>
{axis && <g style={{ fontSize: '.7em' }}> </g>}
<text className='primary-disabled' y='3em' x={margin} style={{ textAnchor: 'middle' }}>{min + axisUnit}</text> </svg>
<text className='primary-disabled' y='3em' x='50%' style={{ textAnchor: 'middle' }}>{(min + max / 2) + axisUnit}</text> <TextInputBox ref={(tb) => this.sliderInputBox = tb}
<text className='primary-disabled' y='3em' x='100%' style={{ textAnchor: 'end' }}>{max + axisUnit}</text> onChange={this.props.onChange}
</g>} percent={this.props.percent}
</svg> axisUnit={this.props.axisUnit}
<TextInputBox ref={(tb) => this.sliderInputBox = tb} scale={this.props.scale}
onChange={this.props.onChange} max={this.props.max}
percent={this.props.percent}
axisUnit={this.props.axisUnit} />
scale={this.props.scale} </div>;
max={this.props.max} }
/> }
</div>; /**
} * New component to add keyboard support for sliders - works on all devices (desktop, iOS, Android)
**/
} class TextInputBox extends React.Component {
/** static propTypes = {
* New component to add keyboard support for sliders - works on all devices (desktop, iOS, Android) axisUnit: PropTypes.string,// units (T, M, etc.)
**/ max: PropTypes.number,
class TextInputBox extends React.Component { onChange: PropTypes.func.isRequired,// function which determins percent value
static propTypes = { percent: PropTypes.number.isRequired,// value of slider
axisUnit: PropTypes.string,//units (T, M, etc.) scale: PropTypes.number
max: PropTypes.number, };
onChange: PropTypes.func.isRequired,// function which determins percent value constructor(props) {
percent: PropTypes.number.isRequired,//value of slider super(props);
scale: PropTypes.number this._handleFocus = this._handleFocus.bind(this);
}; this._handleBlur = this._handleBlur.bind(this);
constructor(props) { this._handleChange = this._handleChange.bind(this);
super(props); // this._keydown = this._keydown.bind(this);
this._handleFocus = this._handleFocus.bind(this); this._keyup = this._keyup.bind(this);
this._handleBlur = this._handleBlur.bind(this); this.state = this._getInitialState();
this._handleChange = this._handleChange.bind(this); this.percent = this.props.percent;
//this._keydown = this._keydown.bind(this); this.max = this.props.max;
this._keyup = this._keyup.bind(this); this.state.inputValue = this.percent * this.max;
this.state = this._getInitialState(); }
this.percent = this.props.percent;
this.max = this.props.max; componentWillReceiveProps(nextProps, nextState) {
this.state.inputValue = this.percent * this.max; let nextValue = nextProps.percent * nextProps.max;
} // See https://stackoverflow.com/questions/32414308/updating-state-on-props-change-in-react-form
if (nextValue !== this.state.inputValue && nextValue <= nextProps.max) {
componentWillReceiveProps(nextProps, nextState) { this.setState({ inputValue: nextValue });
var nextValue = nextProps.percent * nextProps.max; }
// See https://stackoverflow.com/questions/32414308/updating-state-on-props-change-in-react-form }
if (nextValue !== this.state.inputValue && nextValue <= nextProps.max) { componentDidUpdate(prevProps, prevState) {
this.setState({ inputValue: nextValue }); if (prevState.divStyle.display == 'none' && this.state.divStyle.display == 'block') {
} this.enterTimer = setTimeout(() => this.sliderVal.focus(), 10);
} }
componentDidUpdate(prevProps, prevState) {
if (prevProps.max !== this.props.max && this.state.inputValue > this.props.max) {
if (prevState.divStyle.display == 'none' && this.state.divStyle.display == 'block') { // they chose a different module
this.enterTimer = setTimeout(() => this.sliderVal.focus(), 10); this.setState({ inputValue: this.props.max });
} }
if (prevProps.max !== this.props.max && this.state.inputValue > this.props.max) { if (this.state.inputValue != prevState.inputValue && prevProps.max == this.props.max) {
// they chose a different module this.props.onChange(this.state.inputValue / this.props.max);
this.setState({ inputValue: this.props.max }); }
} }
if (this.state.inputValue != prevState.inputValue && prevProps.max == this.props.max) { _getInitialState() {
this.props.onChange(this.state.inputValue/this.props.max); return {
} divStyle: { display:'none' },
inputStyle: { width:'4em' },
} labelStyle: { marginLeft: '.1em' },
maxLength:5,
_getInitialState() { size:5,
return { min:0,
divStyle: {display:'none'}, tabIndex:-1,
inputStyle: {width:'4em'}, type:'number',
labelStyle: {marginLeft: '.1em'}, readOnly: true
maxLength:5, };
size:5, }
min:0,
tabIndex:-1, _setDisplay(val) {
type:'number', this.setState({
readOnly: true divStyle: { display:val }
} });
} }
_setDisplay(val) { _handleFocus() {
this.setState({ this.setState({
divStyle: {display:val} inputValue:this._getValue()
}); });
} }
_handleFocus() { _handleBlur() {
this.setState({ this._setDisplay('none');
inputValue:this._getValue() if (this.state.inputValue !== '') {
}); this.props.onChange(this.state.inputValue / this.props.max);
} } else {
this.state.inputValue = this.props.percent * this.props.max;
_handleBlur() { }
this._setDisplay('none'); }
if (this.state.inputValue !== '') {
this.props.onChange(this.state.inputValue/this.props.max); _getValue() {
} else { return this.state.inputValue;
this.state.inputValue = this.props.percent * this.props.max; }
}
_handleChange(event) {
} if (event.target.value < 0) {
this.setState({ inputValue: 0 });
_getValue() { } else if (event.target.value <= this.props.max) {
return this.state.inputValue; this.setState({ inputValue: event.target.value });
} } else {
this.setState({ inputValue: this.props.max });
_handleChange(event) { }
if (event.target.value < 0) { }
this.setState({inputValue: 0});
} else if (event.target.value <= this.props.max) { /**
this.setState({inputValue: event.target.value}); * Key up handler for input field.
} else { * If user hits Enter key, blur/close the input field
this.setState({inputValue: this.props.max}); * @param {Event} event Keyboard event
} */
} _keyup(event) {
switch (event.key) {
/** case 'Enter':
* Key up handler for input field. this.sliderVal.blur();
* If user hits Enter key, blur/close the input field return;
* @param {Event} event Keyboard event default:
*/ return;
_keyup(event) { }
switch (event.key) { }
case 'Enter':
this.sliderVal.blur(); render() {
return; let { axisUnit, onChange, percent, scale } = this.props;
default: return <div style={this.state.divStyle}><input style={this.state.inputStyle} value={this._getValue()} min={this.state.min} max={this.props.max} onChange={this._handleChange} onKeyUp={this._keyup} tabIndex={this.state.tabIndex} maxLength={this.state.maxLength} size={this.state.size} onBlur={() => {this._handleBlur();}} onFocus={() => {this._handleFocus();}} type={this.state.type} ref={(ip) => this.sliderVal = ip}/><text className="primary upp" style={this.state.labelStyle}>{this.props.axisUnit}</text></div>;
return; }
} }
}
render() {
let { axisUnit, onChange, percent, scale } = this.props;
return <div style={this.state.divStyle}><input style={this.state.inputStyle} value={this._getValue()} min={this.state.min} max={this.props.max} onChange={this._handleChange} onKeyUp={this._keyup} tabIndex={this.state.tabIndex} maxLength={this.state.maxLength} size={this.state.size} onBlur={() => {this._handleBlur()}} onFocus={() => {this._handleFocus()}} type={this.state.type} ref={(ip) => this.sliderVal = ip}/><text className="primary upp" style={this.state.labelStyle}>{this.props.axisUnit}</text></div>;
}
}

View File

@@ -81,17 +81,17 @@ export default class Slot extends TranslatedComponent {
* we do more or less the same thing * we do more or less the same thing
* in every section when Enter key is pressed * in every section when Enter key is pressed
* on a focusable item * on a focusable item
* *
*/ */
_keyDown(event) { _keyDown(event) {
if (event.key == 'Enter') { if (event.key == 'Enter') {
if(event.target.className == 'r') { if(event.target.className == 'r') {
console.log("Slot: Enter key pressed on mod icon"); console.log('Slot: Enter key pressed on mod icon');
this._toggleModifications(); this._toggleModifications();
} else { } else {
console.log("Slot: Enter key pressed on: %O", event.target); console.log('Slot: Enter key pressed on: %O', event.target);
} }
this.props.onOpen(event); this.props.onOpen(event);
} }
} }
/** /**
@@ -154,7 +154,7 @@ export default class Slot extends TranslatedComponent {
); );
} }
/** /**
* Toggle the modifications flag when selecting the modifications icon * Toggle the modifications flag when selecting the modifications icon
*/ */

View File

@@ -40,12 +40,12 @@ export default class StandardSlot extends TranslatedComponent {
this.slotDiv = null; this.slotDiv = null;
} }
_keyDown(event) { _keyDown(event) {
if (event.key == 'Enter') { if (event.key == 'Enter') {
if(event.target.className == 'r') { if(event.target.className == 'r') {
this._toggleModifications(); this._toggleModifications();
} }
this.props.onOpen(event); this.props.onOpen(event);
} }
} }
@@ -151,7 +151,6 @@ export default class StandardSlot extends TranslatedComponent {
* Toggle the modifications flag when selecting the modifications icon * Toggle the modifications flag when selecting the modifications icon
*/ */
_toggleModifications() { _toggleModifications() {
this._modificationsSelected = !this._modificationsSelected; this._modificationsSelected = !this._modificationsSelected;
} }
} }

View File

@@ -554,17 +554,17 @@ export default class OutfittingPage extends Page {
const shipSummaryMarker = `${ship.name}${_sStr}${_iStr}${_hStr}${_pStr}${_mStr}${ship.ladenMass}${cargo}${fuel}`; const shipSummaryMarker = `${ship.name}${_sStr}${_iStr}${_hStr}${_pStr}${_mStr}${ship.ladenMass}${cargo}${fuel}`;
const requirements = Ships[ship.id].requirements; const requirements = Ships[ship.id].requirements;
var requirementElements = []; let requirementElements = [];
function renderRequirement(className, textKey, tooltipTextKey) { function renderRequirement(className, textKey, tooltipTextKey) {
requirementElements.push(<div key={textKey} className={className} onMouseEnter={termtip.bind(null, tooltipTextKey)} onMouseLeave={hide}><a href={textKey.startsWith("empire") ? 'http://elite-dangerous.wikia.com/wiki/Empire/Ranks' : 'http://elite-dangerous.wikia.com/wiki/Federation/Ranks'} target="_blank" rel="noopener">{translate(textKey)}</a></div>); requirementElements.push(<div key={textKey} className={className} onMouseEnter={termtip.bind(null, tooltipTextKey)} onMouseLeave={hide}><a href={textKey.startsWith('empire') ? 'http://elite-dangerous.wikia.com/wiki/Empire/Ranks' : 'http://elite-dangerous.wikia.com/wiki/Federation/Ranks'} target="_blank" rel="noopener">{translate(textKey)}</a></div>);
} }
if (requirements) { if (requirements) {
requirements.federationRank && renderRequirement('federation', 'federation rank ' + requirements.federationRank, 'federation rank required'); requirements.federationRank && renderRequirement('federation', 'federation rank ' + requirements.federationRank, 'federation rank required');
requirements.empireRank && renderRequirement('empire', 'empire rank ' + requirements.empireRank, 'empire rank required'); requirements.empireRank && renderRequirement('empire', 'empire rank ' + requirements.empireRank, 'empire rank required');
requirements.horizons && renderRequirement('horizons', 'horizons', 'horizons required'); requirements.horizons && renderRequirement('horizons', 'horizons', 'horizons required');
requirements.horizonsEarlyAdoption && renderRequirement('horizons', 'horizons early adoption', 'horizons early adoption required'); requirements.horizonsEarlyAdoption && renderRequirement('horizons', 'horizons early adoption', 'horizons early adoption required');
} }
return ( return (
@@ -602,7 +602,7 @@ export default class OutfittingPage extends Page {
</div> </div>
{/* Main tables */} {/* Main tables */}
<ShipSummaryTable ship={ship} fuel={fuel} cargo={cargo} marker={shipSummaryMarker} pips={{sys: this.state.sys, wep: this.state.wep, eng: this.state.eng}} /> <ShipSummaryTable ship={ship} fuel={fuel} cargo={cargo} marker={shipSummaryMarker} pips={{ sys: this.state.sys, wep: this.state.wep, eng: this.state.eng }} />
<StandardSlotSection ship={ship} fuel={fuel} cargo={cargo} code={standardSlotMarker} onChange={shipUpdated} onCargoChange={this._cargoUpdated} onFuelChange={this._fuelUpdated} currentMenu={menu} /> <StandardSlotSection ship={ship} fuel={fuel} cargo={cargo} code={standardSlotMarker} onChange={shipUpdated} onCargoChange={this._cargoUpdated} onFuelChange={this._fuelUpdated} currentMenu={menu} />
<InternalSlotSection ship={ship} code={internalSlotMarker} onChange={shipUpdated} onCargoChange={this._cargoUpdated} onFuelChange={this._fuelUpdated} currentMenu={menu} /> <InternalSlotSection ship={ship} code={internalSlotMarker} onChange={shipUpdated} onCargoChange={this._cargoUpdated} onFuelChange={this._fuelUpdated} currentMenu={menu} />
<HardpointSlotSection ship={ship} code={hardpointsSlotMarker} onChange={shipUpdated} onCargoChange={this._cargoUpdated} onFuelChange={this._fuelUpdated} currentMenu={menu} /> <HardpointSlotSection ship={ship} code={hardpointsSlotMarker} onChange={shipUpdated} onCargoChange={this._cargoUpdated} onFuelChange={this._fuelUpdated} currentMenu={menu} />

View File

@@ -274,11 +274,11 @@ export default class ShipyardPage extends Page {
for (let s of shipSummaries) { for (let s of shipSummaries) {
let shipSortValue = s[shipPredicate]; let shipSortValue = s[shipPredicate];
if( shipPredicateIndex != undefined ) { if(shipPredicateIndex != undefined) {
shipSortValue = shipSortValue[shipPredicateIndex]; shipSortValue = shipSortValue[shipPredicateIndex];
} }
if( shipSortValue != lastShipSortValue ) { if(shipSortValue != lastShipSortValue) {
backgroundHighlight = !backgroundHighlight; backgroundHighlight = !backgroundHighlight;
lastShipSortValue = shipSortValue; lastShipSortValue = shipSortValue;
} }
@@ -396,4 +396,4 @@ export default class ShipyardPage extends Page {
</div> </div>
); );
} }
} }

View File

@@ -136,7 +136,7 @@ export default class Module {
if (modification.type === 'percentage') { if (modification.type === 'percentage') {
modValue = this.getModValue(name) / 10000; modValue = this.getModValue(name) / 10000;
} else if (modification.type === 'numeric') { } else if (modification.type === 'numeric') {
modValue = this.getModValue(name)/ 100; modValue = this.getModValue(name) / 100;
} else { } else {
modValue = this.getModValue(name); modValue = this.getModValue(name);
} }

View File

@@ -1,5 +1,5 @@
import * as ModuleUtils from './ModuleUtils' import * as ModuleUtils from './ModuleUtils';
import { canMount } from '../utils/SlotFunctions' import { canMount } from '../utils/SlotFunctions';
/** /**
* Standard / typical role for multi-purpose or combat (if shielded with better bulkheads) * Standard / typical role for multi-purpose or combat (if shielded with better bulkheads)
@@ -7,20 +7,20 @@ import { canMount } from '../utils/SlotFunctions'
* @param {Boolean} shielded True if shield generator should be included * @param {Boolean} shielded True if shield generator should be included
* @param {integer} bulkheadIndex Bulkhead to use see Constants.BulkheadNames * @param {integer} bulkheadIndex Bulkhead to use see Constants.BulkheadNames
*/ */
export function multiPurpose (ship, shielded, bulkheadIndex) { export function multiPurpose(ship, shielded, bulkheadIndex) {
ship.useStandard('A') ship.useStandard('A')
.use(ship.standard[3], ModuleUtils.standard(3, ship.standard[3].maxClass + 'D')) // D Life Support .use(ship.standard[3], ModuleUtils.standard(3, ship.standard[3].maxClass + 'D')) // D Life Support
.use(ship.standard[5], ModuleUtils.standard(5, ship.standard[5].maxClass + 'D')) // D Sensors .use(ship.standard[5], ModuleUtils.standard(5, ship.standard[5].maxClass + 'D')) // D Sensors
.useBulkhead(bulkheadIndex) .useBulkhead(bulkheadIndex);
if (shielded) { if (shielded) {
ship.internal.some(function (slot) { ship.internal.some(function(slot) {
if (canMount(ship, slot, 'sg')) { // Assuming largest slot can hold an eligible shield if (canMount(ship, slot, 'sg')) { // Assuming largest slot can hold an eligible shield
ship.use(slot, ModuleUtils.findInternal('sg', slot.maxClass, 'A')) ship.use(slot, ModuleUtils.findInternal('sg', slot.maxClass, 'A'));
ship.setSlotEnabled(slot, true) ship.setSlotEnabled(slot, true);
return true return true;
} }
}) });
} }
} }
@@ -30,51 +30,51 @@ export function multiPurpose (ship, shielded, bulkheadIndex) {
* @param {Boolean} shielded True if shield generator should be included * @param {Boolean} shielded True if shield generator should be included
* @param {Object} standardOpts [Optional] Standard module optional overrides * @param {Object} standardOpts [Optional] Standard module optional overrides
*/ */
export function trader (ship, shielded, standardOpts) { export function trader(ship, shielded, standardOpts) {
let usedSlots = [] let usedSlots = [];
let bstCount = 2 let bstCount = 2;
let sg = ship.getAvailableModules().lightestShieldGenerator(ship.hullMass) let sg = ship.getAvailableModules().lightestShieldGenerator(ship.hullMass);
ship.useStandard('A') ship.useStandard('A')
.use(ship.standard[3], ModuleUtils.standard(3, ship.standard[3].maxClass + 'D')) // D Life Support .use(ship.standard[3], ModuleUtils.standard(3, ship.standard[3].maxClass + 'D')) // D Life Support
.use(ship.standard[1], ModuleUtils.standard(1, ship.standard[1].maxClass + 'D')) // D Life Support .use(ship.standard[1], ModuleUtils.standard(1, ship.standard[1].maxClass + 'D')) // D Life Support
.use(ship.standard[4], ModuleUtils.standard(4, ship.standard[4].maxClass + 'D')) // D Life Support .use(ship.standard[4], ModuleUtils.standard(4, ship.standard[4].maxClass + 'D')) // D Life Support
.use(ship.standard[5], ModuleUtils.standard(5, ship.standard[5].maxClass + 'D')) // D Sensors .use(ship.standard[5], ModuleUtils.standard(5, ship.standard[5].maxClass + 'D')); // D Sensors
const shieldOrder = [1, 2, 3, 4, 5, 6, 7, 8] const shieldOrder = [1, 2, 3, 4, 5, 6, 7, 8];
const shieldInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1) const shieldInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1)
.filter(a => (!a.eligible) || a.eligible.sg) .filter(a => (!a.eligible) || a.eligible.sg)
.filter(a => a.maxClass >= sg.class) .filter(a => a.maxClass >= sg.class)
.sort((a, b) => shieldOrder.indexOf(a.maxClass) - shieldOrder.indexOf(b.maxClass)) .sort((a, b) => shieldOrder.indexOf(a.maxClass) - shieldOrder.indexOf(b.maxClass));
shieldInternals.some(function (slot) { shieldInternals.some(function(slot) {
if (canMount(ship, slot, 'sg')) { // Assuming largest slot can hold an eligible shield if (canMount(ship, slot, 'sg')) { // Assuming largest slot can hold an eligible shield
const shield = ModuleUtils.findInternal('sg', slot.maxClass, 'A') const shield = ModuleUtils.findInternal('sg', slot.maxClass, 'A');
if (shield && shield.maxmass > ship.hullMass) { if (shield && shield.maxmass > ship.hullMass) {
ship.use(slot, shield) ship.use(slot, shield);
ship.setSlotEnabled(slot, true) ship.setSlotEnabled(slot, true);
usedSlots.push(slot) usedSlots.push(slot);
return true return true;
} }
} }
}) });
// Fill the empty internals with cargo racks // Fill the empty internals with cargo racks
for (let i = ship.internal.length; i--;) { for (let i = ship.internal.length; i--;) {
let slot = ship.internal[i] let slot = ship.internal[i];
if (usedSlots.indexOf(slot) == -1 && canMount(ship, slot, 'cr')) { if (usedSlots.indexOf(slot) == -1 && canMount(ship, slot, 'cr')) {
ship.use(slot, ModuleUtils.findInternal('cr', slot.maxClass, 'E')) ship.use(slot, ModuleUtils.findInternal('cr', slot.maxClass, 'E'));
} }
} }
// Empty the hardpoints // Empty the hardpoints
for (let s of ship.hardpoints) { for (let s of ship.hardpoints) {
ship.use(s, null) ship.use(s, null);
} }
for (let s of ship.hardpoints) { for (let s of ship.hardpoints) {
if (s.maxClass == 0 && bstCount) { // Mount up to 2 boosters if (s.maxClass == 0 && bstCount) { // Mount up to 2 boosters
ship.use(s, ModuleUtils.hardpoints('04')) ship.use(s, ModuleUtils.hardpoints('04'));
bstCount-- bstCount--;
} else { } else {
ship.use(s, null) ship.use(s, null);
} }
} }
// ship.useLightestStandard(standardOpts); // ship.useLightestStandard(standardOpts);
@@ -85,127 +85,127 @@ export function trader (ship, shielded, standardOpts) {
* @param {Ship} ship Ship instance * @param {Ship} ship Ship instance
* @param {Boolean} planetary True if Planetary Vehicle Hangar (PVH) should be included * @param {Boolean} planetary True if Planetary Vehicle Hangar (PVH) should be included
*/ */
export function explorer (ship, planetary) { export function explorer(ship, planetary) {
let standardOpts = {ppRating: 'A'}, let standardOpts = { ppRating: 'A' },
heatSinkCount = 2, // Fit 2 heat sinks if possible heatSinkCount = 2, // Fit 2 heat sinks if possible
usedSlots = [], usedSlots = [],
sgSlot, sgSlot,
fuelScoopSlot, fuelScoopSlot,
sg = ship.getAvailableModules().lightestShieldGenerator(ship.hullMass) sg = ship.getAvailableModules().lightestShieldGenerator(ship.hullMass);
if (!planetary) { // Non-planetary explorers don't really need to boost if (!planetary) { // Non-planetary explorers don't really need to boost
standardOpts.pd = '1D' standardOpts.pd = '1D';
} }
// Cargo hatch can be disabled // Cargo hatch can be disabled
ship.setSlotEnabled(ship.cargoHatch, false) ship.setSlotEnabled(ship.cargoHatch, false);
// Advanced Discovery Scanner - class 1 or higher // Advanced Discovery Scanner - class 1 or higher
const adsOrder = [1, 2, 3, 4, 5, 6, 7, 8] const adsOrder = [1, 2, 3, 4, 5, 6, 7, 8];
const adsInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1) const adsInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1)
.filter(a => (!a.eligible) || a.eligible.sc) .filter(a => (!a.eligible) || a.eligible.sc)
.sort((a, b) => adsOrder.indexOf(a.maxClass) - adsOrder.indexOf(b.maxClass)) .sort((a, b) => adsOrder.indexOf(a.maxClass) - adsOrder.indexOf(b.maxClass));
for (let i = 0; i < adsInternals.length; i++) { for (let i = 0; i < adsInternals.length; i++) {
if (canMount(ship, adsInternals[i], 'sc')) { if (canMount(ship, adsInternals[i], 'sc')) {
ship.use(adsInternals[i], ModuleUtils.internal('2f')) ship.use(adsInternals[i], ModuleUtils.internal('2f'));
usedSlots.push(adsInternals[i]) usedSlots.push(adsInternals[i]);
break break;
} }
} }
if (planetary) { if (planetary) {
// Planetary Vehicle Hangar - class 2 or higher // Planetary Vehicle Hangar - class 2 or higher
const pvhOrder = [2, 3, 4, 5, 6, 7, 8, 1] const pvhOrder = [2, 3, 4, 5, 6, 7, 8, 1];
const pvhInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1) const pvhInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1)
.filter(a => (!a.eligible) || a.eligible.pv) .filter(a => (!a.eligible) || a.eligible.pv)
.sort((a, b) => pvhOrder.indexOf(a.maxClass) - pvhOrder.indexOf(b.maxClass)) .sort((a, b) => pvhOrder.indexOf(a.maxClass) - pvhOrder.indexOf(b.maxClass));
for (let i = 0; i < pvhInternals.length; i++) { for (let i = 0; i < pvhInternals.length; i++) {
if (canMount(ship, pvhInternals[i], 'pv')) { if (canMount(ship, pvhInternals[i], 'pv')) {
// Planetary Vehical Hangar only has even classes // Planetary Vehical Hangar only has even classes
const pvhClass = pvhInternals[i].maxClass % 2 === 1 ? pvhInternals[i].maxClass - 1 : pvhInternals[i].maxClass const pvhClass = pvhInternals[i].maxClass % 2 === 1 ? pvhInternals[i].maxClass - 1 : pvhInternals[i].maxClass;
ship.use(pvhInternals[i], ModuleUtils.findInternal('pv', pvhClass, 'G')) // G is lower mass ship.use(pvhInternals[i], ModuleUtils.findInternal('pv', pvhClass, 'G')); // G is lower mass
ship.setSlotEnabled(pvhInternals[i], false) // Disable power for Planetary Vehical Hangar ship.setSlotEnabled(pvhInternals[i], false); // Disable power for Planetary Vehical Hangar
usedSlots.push(pvhInternals[i]) usedSlots.push(pvhInternals[i]);
break break;
} }
} }
} }
// Shield generator // Shield generator
const shieldOrder = [1, 2, 3, 4, 5, 6, 7, 8] const shieldOrder = [1, 2, 3, 4, 5, 6, 7, 8];
const shieldInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1) const shieldInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1)
.filter(a => (!a.eligible) || a.eligible.sg) .filter(a => (!a.eligible) || a.eligible.sg)
.filter(a => a.maxClass >= sg.class) .filter(a => a.maxClass >= sg.class)
.sort((a, b) => shieldOrder.indexOf(a.maxClass) - shieldOrder.indexOf(b.maxClass)) .sort((a, b) => shieldOrder.indexOf(a.maxClass) - shieldOrder.indexOf(b.maxClass));
for (let i = 0; i < shieldInternals.length; i++) { for (let i = 0; i < shieldInternals.length; i++) {
if (canMount(ship, shieldInternals[i], 'sg')) { if (canMount(ship, shieldInternals[i], 'sg')) {
ship.use(shieldInternals[i], sg) ship.use(shieldInternals[i], sg);
usedSlots.push(shieldInternals[i]) usedSlots.push(shieldInternals[i]);
sgSlot = shieldInternals[i] sgSlot = shieldInternals[i];
break break;
} }
} }
// Detailed Surface Scanner // Detailed Surface Scanner
const dssOrder = [1, 2, 3, 4, 5, 6, 7, 8] const dssOrder = [1, 2, 3, 4, 5, 6, 7, 8];
const dssInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1) const dssInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1)
.filter(a => (!a.eligible) || a.eligible.sc) .filter(a => (!a.eligible) || a.eligible.sc)
.sort((a, b) => dssOrder.indexOf(a.maxClass) - dssOrder.indexOf(b.maxClass)) .sort((a, b) => dssOrder.indexOf(a.maxClass) - dssOrder.indexOf(b.maxClass));
for (let i = 0; i < dssInternals.length; i++) { for (let i = 0; i < dssInternals.length; i++) {
if (canMount(ship, dssInternals[i], 'sc')) { if (canMount(ship, dssInternals[i], 'sc')) {
ship.use(dssInternals[i], ModuleUtils.internal('2i')) ship.use(dssInternals[i], ModuleUtils.internal('2i'));
usedSlots.push(dssInternals[i]) usedSlots.push(dssInternals[i]);
break break;
} }
} }
// Fuel scoop - best possible // Fuel scoop - best possible
const fuelScoopOrder = [8, 7, 6, 5, 4, 3, 2, 1] const fuelScoopOrder = [8, 7, 6, 5, 4, 3, 2, 1];
const fuelScoopInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1) const fuelScoopInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1)
.filter(a => (!a.eligible) || a.eligible.fs) .filter(a => (!a.eligible) || a.eligible.fs)
.sort((a, b) => fuelScoopOrder.indexOf(a.maxClass) - fuelScoopOrder.indexOf(b.maxClass)) .sort((a, b) => fuelScoopOrder.indexOf(a.maxClass) - fuelScoopOrder.indexOf(b.maxClass));
for (let i = 0; i < fuelScoopInternals.length; i++) { for (let i = 0; i < fuelScoopInternals.length; i++) {
if (canMount(ship, fuelScoopInternals[i], 'fs')) { if (canMount(ship, fuelScoopInternals[i], 'fs')) {
ship.use(fuelScoopInternals[i], ModuleUtils.findInternal('fs', fuelScoopInternals[i].maxClass, 'A')) ship.use(fuelScoopInternals[i], ModuleUtils.findInternal('fs', fuelScoopInternals[i].maxClass, 'A'));
usedSlots.push(fuelScoopInternals[i]) usedSlots.push(fuelScoopInternals[i]);
fuelScoopSlot = fuelScoopInternals[i] fuelScoopSlot = fuelScoopInternals[i];
break break;
} }
} }
// AFMUs - fill as they are 0-weight // AFMUs - fill as they are 0-weight
const afmuOrder = [8, 7, 6, 5, 4, 3, 2, 1] const afmuOrder = [8, 7, 6, 5, 4, 3, 2, 1];
const afmuInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1) const afmuInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1)
.filter(a => (!a.eligible) || a.eligible.pc) .filter(a => (!a.eligible) || a.eligible.pc)
.sort((a, b) => afmuOrder.indexOf(a.maxClass) - afmuOrder.indexOf(b.maxClass)) .sort((a, b) => afmuOrder.indexOf(a.maxClass) - afmuOrder.indexOf(b.maxClass));
for (let i = 0; i < afmuInternals.length; i++) { for (let i = 0; i < afmuInternals.length; i++) {
if (canMount(ship, afmuInternals[i], 'am')) { if (canMount(ship, afmuInternals[i], 'am')) {
ship.use(afmuInternals[i], ModuleUtils.findInternal('am', afmuInternals[i].maxClass, 'A')) ship.use(afmuInternals[i], ModuleUtils.findInternal('am', afmuInternals[i].maxClass, 'A'));
usedSlots.push(afmuInternals[i]) usedSlots.push(afmuInternals[i]);
ship.setSlotEnabled(afmuInternals[i], false) // Disable power for AFM Unit ship.setSlotEnabled(afmuInternals[i], false); // Disable power for AFM Unit
} }
} }
for (let s of ship.hardpoints) { for (let s of ship.hardpoints) {
if (s.maxClass == 0 && heatSinkCount) { // Mount up to 2 heatsinks if (s.maxClass == 0 && heatSinkCount) { // Mount up to 2 heatsinks
ship.use(s, ModuleUtils.hardpoints('02')) ship.use(s, ModuleUtils.hardpoints('02'));
ship.setSlotEnabled(s, heatSinkCount == 2) // Only enable a single Heatsink ship.setSlotEnabled(s, heatSinkCount == 2); // Only enable a single Heatsink
heatSinkCount-- heatSinkCount--;
} else { } else {
ship.use(s, null) ship.use(s, null);
} }
} }
if (sgSlot && fuelScoopSlot) { if (sgSlot && fuelScoopSlot) {
// 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.getPowerUsage() > fuelScoopSlot.m.getPowerUsage()) { // 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);
} }
} }
ship.useLightestStandard(standardOpts) ship.useLightestStandard(standardOpts);
} }
/** /**
@@ -213,188 +213,188 @@ export function explorer (ship, planetary) {
* @param {Ship} ship Ship instance * @param {Ship} ship Ship instance
* @param {Boolean} shielded True if shield generator should be included * @param {Boolean} shielded True if shield generator should be included
*/ */
export function miner (ship, shielded) { export function miner(ship, shielded) {
shielded = true shielded = true;
let standardOpts = {ppRating: 'A'}, let standardOpts = { ppRating: 'A' },
miningLaserCount = 2, miningLaserCount = 2,
usedSlots = [], usedSlots = [],
sg = ship.getAvailableModules().lightestShieldGenerator(ship.hullMass) sg = ship.getAvailableModules().lightestShieldGenerator(ship.hullMass);
// Cargo hatch should be enabled // Cargo hatch should be enabled
ship.setSlotEnabled(ship.cargoHatch, true) ship.setSlotEnabled(ship.cargoHatch, true);
// Largest possible refinery // Largest possible refinery
const refineryOrder = [4, 5, 6, 7, 8, 3, 2, 1] const refineryOrder = [4, 5, 6, 7, 8, 3, 2, 1];
const refineryInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1) const refineryInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1)
.filter(a => (!a.eligible) || a.eligible.rf) .filter(a => (!a.eligible) || a.eligible.rf)
.sort((a, b) => refineryOrder.indexOf(a.maxClass) - refineryOrder.indexOf(b.maxClass)) .sort((a, b) => refineryOrder.indexOf(a.maxClass) - refineryOrder.indexOf(b.maxClass));
for (let i = 0; i < refineryInternals.length; i++) { for (let i = 0; i < refineryInternals.length; i++) {
if (canMount(ship, refineryInternals[i], 'rf')) { if (canMount(ship, refineryInternals[i], 'rf')) {
ship.use(refineryInternals[i], ModuleUtils.findInternal('rf', Math.min(refineryInternals[i].maxClass, 4), 'A')) ship.use(refineryInternals[i], ModuleUtils.findInternal('rf', Math.min(refineryInternals[i].maxClass, 4), 'A'));
usedSlots.push(refineryInternals[i]) usedSlots.push(refineryInternals[i]);
break break;
} }
} }
// Prospector limpet controller - 3A if possible // Prospector limpet controller - 3A if possible
const prospectorOrder = [3, 4, 5, 6, 7, 8, 2, 1] const prospectorOrder = [3, 4, 5, 6, 7, 8, 2, 1];
const prospectorInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1) const prospectorInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1)
.filter(a => (!a.eligible) || a.eligible.pc) .filter(a => (!a.eligible) || a.eligible.pc)
.sort((a, b) => prospectorOrder.indexOf(a.maxClass) - prospectorOrder.indexOf(b.maxClass)) .sort((a, b) => prospectorOrder.indexOf(a.maxClass) - prospectorOrder.indexOf(b.maxClass));
for (let i = 0; i < prospectorInternals.length; i++) { for (let i = 0; i < prospectorInternals.length; i++) {
if (canMount(ship, prospectorInternals[i], 'pc')) { if (canMount(ship, prospectorInternals[i], 'pc')) {
// Prospector only has odd classes // Prospector only has odd classes
const prospectorClass = prospectorInternals[i].maxClass % 2 === 0 ? prospectorInternals[i].maxClass - 1 : prospectorInternals[i].maxClass const prospectorClass = prospectorInternals[i].maxClass % 2 === 0 ? prospectorInternals[i].maxClass - 1 : prospectorInternals[i].maxClass;
ship.use(prospectorInternals[i], ModuleUtils.findInternal('pc', prospectorClass, 'A')) ship.use(prospectorInternals[i], ModuleUtils.findInternal('pc', prospectorClass, 'A'));
usedSlots.push(prospectorInternals[i]) usedSlots.push(prospectorInternals[i]);
break break;
} }
} }
// Shield generator if required // Shield generator if required
if (shielded) { if (shielded) {
const shieldOrder = [1, 2, 3, 4, 5, 6, 7, 8] const shieldOrder = [1, 2, 3, 4, 5, 6, 7, 8];
const shieldInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1) const shieldInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1)
.filter(a => (!a.eligible) || a.eligible.sg) .filter(a => (!a.eligible) || a.eligible.sg)
.filter(a => a.maxClass >= sg.class) .filter(a => a.maxClass >= sg.class)
.sort((a, b) => shieldOrder.indexOf(a.maxClass) - shieldOrder.indexOf(b.maxClass)) .sort((a, b) => shieldOrder.indexOf(a.maxClass) - shieldOrder.indexOf(b.maxClass));
for (let i = 0; i < shieldInternals.length; i++) { for (let i = 0; i < shieldInternals.length; i++) {
if (canMount(ship, shieldInternals[i], 'sg')) { if (canMount(ship, shieldInternals[i], 'sg')) {
ship.use(shieldInternals[i], sg) ship.use(shieldInternals[i], sg);
usedSlots.push(shieldInternals[i]) usedSlots.push(shieldInternals[i]);
break break;
} }
} }
} }
// Dual mining lasers of highest possible class; remove anything else // Dual mining lasers of highest possible class; remove anything else
const miningLaserOrder = [2, 3, 4, 1, 0] const miningLaserOrder = [2, 3, 4, 1, 0];
const miningLaserHardpoints = ship.hardpoints.concat().sort(function (a, b) { const miningLaserHardpoints = ship.hardpoints.concat().sort(function(a, b) {
return miningLaserOrder.indexOf(a.maxClass) - miningLaserOrder.indexOf(b.maxClass) return miningLaserOrder.indexOf(a.maxClass) - miningLaserOrder.indexOf(b.maxClass);
}) });
for (let s of miningLaserHardpoints) { for (let s of miningLaserHardpoints) {
if (s.maxClass >= 1 && miningLaserCount) { if (s.maxClass >= 1 && miningLaserCount) {
ship.use(s, ModuleUtils.hardpoints(s.maxClass >= 2 ? '2m' : '2l')) ship.use(s, ModuleUtils.hardpoints(s.maxClass >= 2 ? '2m' : '2l'));
miningLaserCount-- miningLaserCount--;
} else { } else {
ship.use(s, null) ship.use(s, null);
} }
} }
// Number of collector limpets required to be active is a function of the size of the ship and the power of the lasers // Number of collector limpets required to be active is a function of the size of the ship and the power of the lasers
const miningLaserDps = ship.hardpoints.filter(h => h.m != null) const miningLaserDps = ship.hardpoints.filter(h => h.m != null)
.reduce(function (a, b) { .reduce(function(a, b) {
return a + b.m.getDps() return a + b.m.getDps();
}, 0) }, 0);
// Find out how many internal slots we have, and their potential cargo size // Find out how many internal slots we have, and their potential cargo size
const potentialCargo = ship.internal.filter(a => usedSlots.indexOf(a) == -1) const potentialCargo = ship.internal.filter(a => usedSlots.indexOf(a) == -1)
.filter(a => (!a.eligible) || a.eligible.cr) .filter(a => (!a.eligible) || a.eligible.cr)
.map(b => Math.pow(2, b.maxClass)) .map(b => Math.pow(2, b.maxClass));
// One collector for each 1.25 DPS, multiply by 1.25 for medium ships and 1.5 for large ships as they have further to travel // One collector for each 1.25 DPS, multiply by 1.25 for medium ships and 1.5 for large ships as they have further to travel
// 0 if we only have 1 cargo slot, otherwise minium of 1 and maximum of 6 (excluding size modifier) // 0 if we only have 1 cargo slot, otherwise minium of 1 and maximum of 6 (excluding size modifier)
const sizeModifier = ship.class == 2 ? 1.2 : ship.class == 3 ? 1.5 : 1 const sizeModifier = ship.class == 2 ? 1.2 : ship.class == 3 ? 1.5 : 1;
let collectorLimpetsRequired = potentialCargo.length == 1 ? 0 : Math.ceil(sizeModifier * Math.min(6, Math.floor(miningLaserDps / 1.25))) let collectorLimpetsRequired = potentialCargo.length == 1 ? 0 : Math.ceil(sizeModifier * Math.min(6, Math.floor(miningLaserDps / 1.25)));
if (collectorLimpetsRequired > 0) { if (collectorLimpetsRequired > 0) {
const collectorOrder = [1, 2, 3, 4, 5, 6, 7, 8] const collectorOrder = [1, 2, 3, 4, 5, 6, 7, 8];
const collectorInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1) const collectorInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1)
.filter(a => (!a.eligible) || a.eligible.cc) .filter(a => (!a.eligible) || a.eligible.cc)
.sort((a, b) => collectorOrder.indexOf(a.maxClass) - collectorOrder.indexOf(b.maxClass)) .sort((a, b) => collectorOrder.indexOf(a.maxClass) - collectorOrder.indexOf(b.maxClass));
// Always keep at least 2 slots free for cargo racks (1 for shielded) // Always keep at least 2 slots free for cargo racks (1 for shielded)
for (let i = 0; i < collectorInternals.length - (shielded ? 1 : 2) && collectorLimpetsRequired > 0; i++) { for (let i = 0; i < collectorInternals.length - (shielded ? 1 : 2) && collectorLimpetsRequired > 0; i++) {
if (canMount(ship, collectorInternals[i], 'cc')) { if (canMount(ship, collectorInternals[i], 'cc')) {
// Collector only has odd classes // Collector only has odd classes
const collectorClass = collectorInternals[i].maxClass % 2 === 0 ? collectorInternals[i].maxClass - 1 : collectorInternals[i].maxClass const collectorClass = collectorInternals[i].maxClass % 2 === 0 ? collectorInternals[i].maxClass - 1 : collectorInternals[i].maxClass;
ship.use(collectorInternals[i], ModuleUtils.findInternal('cc', collectorClass, 'D')) ship.use(collectorInternals[i], ModuleUtils.findInternal('cc', collectorClass, 'D'));
usedSlots.push(collectorInternals[i]) usedSlots.push(collectorInternals[i]);
collectorLimpetsRequired -= collectorInternals[i].m.maximum collectorLimpetsRequired -= collectorInternals[i].m.maximum;
} }
} }
} }
// Power distributor to power the mining lasers indefinitely // Power distributor to power the mining lasers indefinitely
const wepRateRequired = ship.hardpoints.filter(h => h.m != null) const wepRateRequired = ship.hardpoints.filter(h => h.m != null)
.reduce(function (a, b) { .reduce(function(a, b) {
return a + b.m.getEps() return a + b.m.getEps();
}, 0) }, 0);
standardOpts.pd = ship.getAvailableModules().matchingPowerDist({weprate: wepRateRequired}).id standardOpts.pd = ship.getAvailableModules().matchingPowerDist({ weprate: wepRateRequired }).id;
// Fill the empty internals with cargo racks // Fill the empty internals with cargo racks
for (let i = ship.internal.length; i--;) { for (let i = ship.internal.length; i--;) {
let slot = ship.internal[i] let slot = ship.internal[i];
if (usedSlots.indexOf(slot) == -1 && canMount(ship, slot, 'cr')) { if (usedSlots.indexOf(slot) == -1 && canMount(ship, slot, 'cr')) {
ship.use(slot, ModuleUtils.findInternal('cr', slot.maxClass, 'E')) ship.use(slot, ModuleUtils.findInternal('cr', slot.maxClass, 'E'));
} }
} }
ship.useLightestStandard(standardOpts) ship.useLightestStandard(standardOpts);
} }
/** /**
* Racer Role * Racer Role
* @param {Ship} ship Ship instance * @param {Ship} ship Ship instance
*/ */
export function racer (ship) { export function racer(ship) {
let standardOpts = {}, let standardOpts = {},
usedSlots = [], usedSlots = [],
sgSlot, sgSlot,
sg = ship.getAvailableModules().lightestShieldGenerator(ship.hullMass) sg = ship.getAvailableModules().lightestShieldGenerator(ship.hullMass);
// Cargo hatch can be disabled // Cargo hatch can be disabled
ship.setSlotEnabled(ship.cargoHatch, false) ship.setSlotEnabled(ship.cargoHatch, false);
// Shield generator // Shield generator
const shieldOrder = [1, 2, 3, 4, 5, 6, 7, 8] const shieldOrder = [1, 2, 3, 4, 5, 6, 7, 8];
const shieldInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1) const shieldInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1)
.filter(a => (!a.eligible) || a.eligible.sg) .filter(a => (!a.eligible) || a.eligible.sg)
.filter(a => a.maxClass >= sg.class) .filter(a => a.maxClass >= sg.class)
.sort((a, b) => shieldOrder.indexOf(a.maxClass) - shieldOrder.indexOf(b.maxClass)) .sort((a, b) => shieldOrder.indexOf(a.maxClass) - shieldOrder.indexOf(b.maxClass));
for (let i = 0; i < shieldInternals.length; i++) { for (let i = 0; i < shieldInternals.length; i++) {
if (canMount(ship, shieldInternals[i], 'sg')) { if (canMount(ship, shieldInternals[i], 'sg')) {
ship.use(shieldInternals[i], sg) ship.use(shieldInternals[i], sg);
usedSlots.push(shieldInternals[i]) usedSlots.push(shieldInternals[i]);
sgSlot = shieldInternals[i] sgSlot = shieldInternals[i];
break break;
} }
} }
// Empty the hardpoints // Empty the hardpoints
for (let s of ship.hardpoints) { for (let s of ship.hardpoints) {
ship.use(s, null) ship.use(s, null);
} }
// Empty the internals // Empty the internals
for (let i = ship.internal.length; i--;) { for (let i = ship.internal.length; i--;) {
let slot = ship.internal[i] let slot = ship.internal[i];
if (usedSlots.indexOf(slot) == -1) { if (usedSlots.indexOf(slot) == -1) {
ship.use(slot, null) ship.use(slot, null);
} }
} }
// Best thrusters // Best thrusters
if (ship.standard[1].maxClass === 3) { if (ship.standard[1].maxClass === 3) {
standardOpts.th = 'tz' standardOpts.th = 'tz';
} else if (ship.standard[1].maxClass === 2) { } else if (ship.standard[1].maxClass === 2) {
standardOpts.th = 'u0' standardOpts.th = 'u0';
} else { } else {
standardOpts.th = ship.standard[1].maxClass + 'A' standardOpts.th = ship.standard[1].maxClass + 'A';
} }
// Best power distributor for more boosting // Best power distributor for more boosting
standardOpts.pd = ship.standard[4].maxClass + 'A' standardOpts.pd = ship.standard[4].maxClass + 'A';
// Smallest possible FSD drive // Smallest possible FSD drive
standardOpts.fsd = '2D' standardOpts.fsd = '2D';
// Minimal fuel tank // Minimal fuel tank
standardOpts.ft = '1C' standardOpts.ft = '1C';
// Disable nearly everything // Disable nearly everything
standardOpts.fsdDisabled = true standardOpts.fsdDisabled = true;
standardOpts.sDisabled = true standardOpts.sDisabled = true;
standardOpts.pdDisabled = true standardOpts.pdDisabled = true;
standardOpts.lsDisabled = true standardOpts.lsDisabled = true;
ship.useLightestStandard(standardOpts) ship.useLightestStandard(standardOpts);
// Apply engineering to each module // Apply engineering to each module
// ship.standard[1].m.blueprint = getBlueprint('Engine_Dirty', ship.standard[0]); // ship.standard[1].m.blueprint = getBlueprint('Engine_Dirty', ship.standard[0]);

View File

@@ -18,36 +18,35 @@ export function specialToolTip(translate, blueprint, grp, m, specialName) {
if (m) { if (m) {
// We also add in any benefits from specials that aren't covered above // We also add in any benefits from specials that aren't covered above
if (m.blueprint) { if (m.blueprint) {
for (const feature in Modifications.modifierActions[specialName]) { for (const feature in Modifications.modifierActions[specialName]) {
// if (!blueprint.features[feature] && !m.mods.feature) { // if (!blueprint.features[feature] && !m.mods.feature) {
const featureDef = Modifications.modifications[feature]; const featureDef = Modifications.modifications[feature];
if (featureDef && !featureDef.hidden) { if (featureDef && !featureDef.hidden) {
let symbol = ''; let symbol = '';
if (feature === 'jitter') { if (feature === 'jitter') {
symbol = '°'; symbol = '°';
} else if (featureDef.type === 'percentage') { } else if (featureDef.type === 'percentage') {
symbol = '%'; symbol = '%';
} }
let current = m.getModValue(feature) - m.getModValue(feature, true); let current = m.getModValue(feature) - m.getModValue(feature, true);
if (featureDef.type === 'percentage') { if (featureDef.type === 'percentage') {
current = Math.round(current / 10) / 10; current = Math.round(current / 10) / 10;
} else if (featureDef.type === 'numeric') { } else if (featureDef.type === 'numeric') {
current /= 100; current /= 100;
} }
const currentIsBeneficial = isValueBeneficial(feature, current); const currentIsBeneficial = isValueBeneficial(feature, current);
effects.push( effects.push(
<tr key={feature + '_specialTT'}> <tr key={feature + '_specialTT'}>
<td style={{textAlign: 'left'}}>{translate(feature, grp)}</td> <td style={{ textAlign: 'left' }}>{translate(feature, grp)}</td>
<td>&nbsp;</td> <td>&nbsp;</td>
<td className={current === 0 ? '' : currentIsBeneficial ? 'secondary' : 'warning'} <td className={current === 0 ? '' : currentIsBeneficial ? 'secondary' : 'warning'}
style={{textAlign: 'right'}}>{current}{symbol}</td> style={{ textAlign: 'right' }}>{current}{symbol}</td>
<td>&nbsp;</td> <td>&nbsp;</td>
</tr> </tr>
); );
} }
} }
} }
} }
@@ -289,7 +288,7 @@ export function isValueBeneficial(feature, value) {
*/ */
export function getBlueprint(name, module) { export function getBlueprint(name, module) {
// Start with a copy of the blueprint // Start with a copy of the blueprint
const findMod = val => Object.keys(Modifications.blueprints).find(elem => elem.toString().toLowerCase().search(val.toString().toLowerCase().replace(/(OutfittingFieldType_|persecond)/igm, '')) >= 0) const findMod = val => Object.keys(Modifications.blueprints).find(elem => elem.toString().toLowerCase().search(val.toString().toLowerCase().replace(/(OutfittingFieldType_|persecond)/igm, '')) >= 0);
const found = Modifications.blueprints[findMod(name)]; const found = Modifications.blueprints[findMod(name)];
if (!found || !found.fdname) { if (!found || !found.fdname) {
return {}; return {};
@@ -382,36 +381,35 @@ export function getPercent(m) {
let result = null; let result = null;
const features = m.blueprint.grades[m.blueprint.grade].features; const features = m.blueprint.grades[m.blueprint.grade].features;
for (const featureName in features) { for (const featureName in features) {
if (features[featureName][0] === features[featureName][1]) {
if (features[featureName][0] === features[featureName][1]) { continue;
continue; }
}
let value = _getValue(m, featureName);
let value = _getValue(m, featureName); let mult;
let mult;
if (Modifications.modifications[featureName].higherbetter) { if (Modifications.modifications[featureName].higherbetter) {
// Higher is better, but is this making it better or worse? // Higher is better, but is this making it better or worse?
if (features[featureName][0] < 0 || (features[featureName][0] === 0 && features[featureName][1] < 0)) { if (features[featureName][0] < 0 || (features[featureName][0] === 0 && features[featureName][1] < 0)) {
mult = Math.round((value - features[featureName][1]) / (features[featureName][0] - features[featureName][1]) * 100); mult = Math.round((value - features[featureName][1]) / (features[featureName][0] - features[featureName][1]) * 100);
} else { } else {
mult = Math.round((value - features[featureName][0]) / (features[featureName][1] - features[featureName][0]) * 100); mult = Math.round((value - features[featureName][0]) / (features[featureName][1] - features[featureName][0]) * 100);
} }
} else { } else {
// Higher is worse, but is this making it better or worse? // Higher is worse, but is this making it better or worse?
if (features[featureName][0] < 0 || (features[featureName][0] === 0 && features[featureName][1] < 0)) { if (features[featureName][0] < 0 || (features[featureName][0] === 0 && features[featureName][1] < 0)) {
mult = Math.round((value - features[featureName][0]) / (features[featureName][1] - features[featureName][0]) * 100); mult = Math.round((value - features[featureName][0]) / (features[featureName][1] - features[featureName][0]) * 100);
} else { } else {
mult = Math.round((value - features[featureName][1]) / (features[featureName][0] - features[featureName][1]) * 100); mult = Math.round((value - features[featureName][1]) / (features[featureName][0] - features[featureName][1]) * 100);
} }
} }
if (result && result != mult) { if (result && result != mult) {
return null; return null;
} else if (result != mult) { } else if (result != mult) {
result = mult; result = mult;
} }
} }
return result; return result;
} }

View File

@@ -318,7 +318,7 @@ function _addModifications(module, modifiers, blueprint, grade, specialModificat
if (!modifiers) return; if (!modifiers) return;
let special; let special;
if (specialModifications) { if (specialModifications) {
special = Modifications.specials[Object.keys(specialModifications)[0]] special = Modifications.specials[Object.keys(specialModifications)[0]];
} }
for (const i in modifiers) { for (const i in modifiers) {
// Some special modifications // Some special modifications
@@ -345,7 +345,7 @@ function _addModifications(module, modifiers, blueprint, grade, specialModificat
let value; let value;
if (i === 'OutfittingFieldType_DefenceModifierShieldMultiplier') { if (i === 'OutfittingFieldType_DefenceModifierShieldMultiplier') {
value = modifiers[i].value - 1; value = modifiers[i].value - 1;
} else if (i === 'OutfittingFieldType_DefenceModifierHealthMultiplier' && blueprint.startsWith('Armour_')) { } else if (i === 'OutfittingFieldType_DefenceModifierHealthMultiplier' && blueprint.startsWith('Armour_')) {
value = (modifiers[i].value - module.hullboost) / module.hullboost; value = (modifiers[i].value - module.hullboost) / module.hullboost;
} else if (i === 'OutfittingFieldType_DefenceModifierHealthMultiplier') { } else if (i === 'OutfittingFieldType_DefenceModifierHealthMultiplier') {
value = modifiers[i].value / module.hullboost; value = modifiers[i].value / module.hullboost;

View File

@@ -1,26 +1,26 @@
import Ship from '../shipyard/Ship' import Ship from '../shipyard/Ship';
import { HARDPOINT_NUM_TO_CLASS, shipModelFromJson } from './CompanionApiUtils' import { HARDPOINT_NUM_TO_CLASS, shipModelFromJson } from './CompanionApiUtils';
import { Ships } from 'coriolis-data/dist' import { Ships } from 'coriolis-data/dist';
import Module from '../shipyard/Module' import Module from '../shipyard/Module';
import { Modules } from 'coriolis-data/dist' import { Modules } from 'coriolis-data/dist';
import { Modifications } from 'coriolis-data/dist' import { Modifications } from 'coriolis-data/dist';
import { getBlueprint } from './BlueprintFunctions' import { getBlueprint } from './BlueprintFunctions';
/** /**
* Obtain a module given its FD Name * Obtain a module given its FD Name
* @param {string} fdname the FD Name of the module * @param {string} fdname the FD Name of the module
* @return {Module} the module * @return {Module} the module
*/ */
function _moduleFromFdName (fdname) { function _moduleFromFdName(fdname) {
if (!fdname) return null if (!fdname) return null;
fdname = fdname.toLowerCase() fdname = fdname.toLowerCase();
// Check standard modules // Check standard modules
for (const grp in Modules.standard) { for (const grp in Modules.standard) {
if (Modules.standard.hasOwnProperty(grp)) { if (Modules.standard.hasOwnProperty(grp)) {
for (const i in Modules.standard[grp]) { for (const i in Modules.standard[grp]) {
if (Modules.standard[grp][i].symbol && Modules.standard[grp][i].symbol.toLowerCase() === fdname) { if (Modules.standard[grp][i].symbol && Modules.standard[grp][i].symbol.toLowerCase() === fdname) {
// Found it // Found it
return new Module({template: Modules.standard[grp][i]}) return new Module({ template: Modules.standard[grp][i] });
} }
} }
} }
@@ -32,7 +32,7 @@ function _moduleFromFdName (fdname) {
for (const i in Modules.hardpoints[grp]) { for (const i in Modules.hardpoints[grp]) {
if (Modules.hardpoints[grp][i].symbol && Modules.hardpoints[grp][i].symbol.toLowerCase() === fdname) { if (Modules.hardpoints[grp][i].symbol && Modules.hardpoints[grp][i].symbol.toLowerCase() === fdname) {
// Found it // Found it
return new Module({template: Modules.hardpoints[grp][i]}) return new Module({ template: Modules.hardpoints[grp][i] });
} }
} }
} }
@@ -44,14 +44,14 @@ function _moduleFromFdName (fdname) {
for (const i in Modules.internal[grp]) { for (const i in Modules.internal[grp]) {
if (Modules.internal[grp][i].symbol && Modules.internal[grp][i].symbol.toLowerCase() === fdname) { if (Modules.internal[grp][i].symbol && Modules.internal[grp][i].symbol.toLowerCase() === fdname) {
// Found it // Found it
return new Module({template: Modules.internal[grp][i]}) return new Module({ template: Modules.internal[grp][i] });
} }
} }
} }
} }
// Not found // Not found
return null return null;
} }
/** /**
@@ -59,16 +59,16 @@ function _moduleFromFdName (fdname) {
* @param {object} json the Loadout event JSON * @param {object} json the Loadout event JSON
* @return {Ship} the built ship * @return {Ship} the built ship
*/ */
export function shipFromLoadoutJSON (json) { export function shipFromLoadoutJSON(json) {
// Start off building a basic ship // Start off building a basic ship
const shipModel = shipModelFromJson(json) const shipModel = shipModelFromJson(json);
if (!shipModel) { if (!shipModel) {
throw 'No such ship found: "' + json.Ship + '"' throw 'No such ship found: "' + json.Ship + '"';
} }
const shipTemplate = Ships[shipModel] const shipTemplate = Ships[shipModel];
let ship = new Ship(shipModel, shipTemplate.properties, shipTemplate.slots) let ship = new Ship(shipModel, shipTemplate.properties, shipTemplate.slots);
ship.buildWith(null) ship.buildWith(null);
// Initial Ship building, don't do engineering yet. // Initial Ship building, don't do engineering yet.
let opts = []; let opts = [];
@@ -76,135 +76,135 @@ export function shipFromLoadoutJSON (json) {
switch (module.Slot.toLowerCase()) { switch (module.Slot.toLowerCase()) {
// Cargo Hatch. // Cargo Hatch.
case 'cargohatch': case 'cargohatch':
ship.cargoHatch.enabled = module.On ship.cargoHatch.enabled = module.On;
ship.cargoHatch.priority = module.Priority ship.cargoHatch.priority = module.Priority;
break break;
// Add the bulkheads // Add the bulkheads
case 'armour': case 'armour':
if (module.Item.toLowerCase().endsWith('_armour_grade1')) { if (module.Item.toLowerCase().endsWith('_armour_grade1')) {
ship.useBulkhead(0, true) ship.useBulkhead(0, true);
} else if (module.Item.toLowerCase().endsWith('_armour_grade2')) { } else if (module.Item.toLowerCase().endsWith('_armour_grade2')) {
ship.useBulkhead(1, true) ship.useBulkhead(1, true);
} else if (module.Item.toLowerCase().endsWith('_armour_grade3')) { } else if (module.Item.toLowerCase().endsWith('_armour_grade3')) {
ship.useBulkhead(2, true) ship.useBulkhead(2, true);
} else if (module.Item.toLowerCase().endsWith('_armour_mirrored')) { } else if (module.Item.toLowerCase().endsWith('_armour_mirrored')) {
ship.useBulkhead(3, true) ship.useBulkhead(3, true);
} else if (module.Item.toLowerCase().endsWith('_armour_reactive')) { } else if (module.Item.toLowerCase().endsWith('_armour_reactive')) {
ship.useBulkhead(4, true) ship.useBulkhead(4, true);
} else { } else {
throw 'Unknown bulkheads "' + module.Item + '"' throw 'Unknown bulkheads "' + module.Item + '"';
} }
ship.bulkheads.enabled = true ship.bulkheads.enabled = true;
if (module.Engineering) _addModifications(ship.bulkheads.m, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level, module.Engineering.ExperimentalEffect) if (module.Engineering) _addModifications(ship.bulkheads.m, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level, module.Engineering.ExperimentalEffect);
break break;
case 'powerplant': case 'powerplant':
const powerplant = _moduleFromFdName(module.Item) const powerplant = _moduleFromFdName(module.Item);
ship.use(ship.standard[0], powerplant, true) ship.use(ship.standard[0], powerplant, true);
ship.standard[0].enabled = module.On ship.standard[0].enabled = module.On;
ship.standard[0].priority = module.Priority ship.standard[0].priority = module.Priority;
if (module.Engineering) _addModifications(powerplant, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level, module.Engineering.ExperimentalEffect) if (module.Engineering) _addModifications(powerplant, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level, module.Engineering.ExperimentalEffect);
break break;
case 'mainengines': case 'mainengines':
const thrusters = _moduleFromFdName(module.Item) const thrusters = _moduleFromFdName(module.Item);
ship.use(ship.standard[1], thrusters, true) ship.use(ship.standard[1], thrusters, true);
ship.standard[1].enabled = module.On ship.standard[1].enabled = module.On;
ship.standard[1].priority = module.Priority ship.standard[1].priority = module.Priority;
if (module.Engineering) _addModifications(thrusters, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level, module.Engineering.ExperimentalEffect) if (module.Engineering) _addModifications(thrusters, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level, module.Engineering.ExperimentalEffect);
break break;
case 'frameshiftdrive': case 'frameshiftdrive':
const frameshiftdrive = _moduleFromFdName(module.Item) const frameshiftdrive = _moduleFromFdName(module.Item);
ship.use(ship.standard[2], frameshiftdrive, true) ship.use(ship.standard[2], frameshiftdrive, true);
ship.standard[2].enabled = module.On ship.standard[2].enabled = module.On;
ship.standard[2].priority = module.Priority ship.standard[2].priority = module.Priority;
if (module.Engineering) _addModifications(frameshiftdrive, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level, module.Engineering.ExperimentalEffect) if (module.Engineering) _addModifications(frameshiftdrive, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level, module.Engineering.ExperimentalEffect);
break break;
case 'lifesupport': case 'lifesupport':
const lifesupport = _moduleFromFdName(module.Item) const lifesupport = _moduleFromFdName(module.Item);
ship.use(ship.standard[3], lifesupport, true) ship.use(ship.standard[3], lifesupport, true);
ship.standard[3].enabled = module.On === true ship.standard[3].enabled = module.On === true;
ship.standard[3].priority = module.Priority ship.standard[3].priority = module.Priority;
if (module.Engineering) _addModifications(lifesupport, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level, module.Engineering.ExperimentalEffect) if (module.Engineering) _addModifications(lifesupport, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level, module.Engineering.ExperimentalEffect);
break break;
case 'powerdistributor': case 'powerdistributor':
const powerdistributor = _moduleFromFdName(module.Item) const powerdistributor = _moduleFromFdName(module.Item);
ship.use(ship.standard[4], powerdistributor, true) ship.use(ship.standard[4], powerdistributor, true);
ship.standard[4].enabled = module.On ship.standard[4].enabled = module.On;
ship.standard[4].priority = module.Priority ship.standard[4].priority = module.Priority;
if (module.Engineering) _addModifications(powerdistributor, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level, module.Engineering.ExperimentalEffect) if (module.Engineering) _addModifications(powerdistributor, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level, module.Engineering.ExperimentalEffect);
break break;
case 'radar': case 'radar':
const sensors = _moduleFromFdName(module.Item) const sensors = _moduleFromFdName(module.Item);
ship.use(ship.standard[5], sensors, true) ship.use(ship.standard[5], sensors, true);
ship.standard[5].enabled = module.On ship.standard[5].enabled = module.On;
ship.standard[5].priority = module.Priority ship.standard[5].priority = module.Priority;
if (module.Engineering) _addModifications(sensors, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level, module.Engineering.ExperimentalEffect) if (module.Engineering) _addModifications(sensors, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level, module.Engineering.ExperimentalEffect);
break break;
case 'fueltank': case 'fueltank':
const fueltank = _moduleFromFdName(module.Item) const fueltank = _moduleFromFdName(module.Item);
ship.use(ship.standard[6], fueltank, true) ship.use(ship.standard[6], fueltank, true);
ship.standard[6].enabled = true ship.standard[6].enabled = true;
ship.standard[6].priority = 0 ship.standard[6].priority = 0;
break break;
default: default:
} }
for (const module of json.Modules) { for (const module of json.Modules) {
if (module.Slot.toLowerCase().search(/hardpoint/) !== -1) { if (module.Slot.toLowerCase().search(/hardpoint/) !== -1) {
// Add hardpoints // Add hardpoints
let hardpoint; let hardpoint;
let hardpointClassNum = -1 let hardpointClassNum = -1;
let hardpointSlotNum = -1 let hardpointSlotNum = -1;
let hardpointArrayNum = 0 let hardpointArrayNum = 0;
for (let i in shipTemplate.slots.hardpoints) { for (let i in shipTemplate.slots.hardpoints) {
if (shipTemplate.slots.hardpoints[i] === hardpointClassNum) { if (shipTemplate.slots.hardpoints[i] === hardpointClassNum) {
// Another slot of the same class // Another slot of the same class
hardpointSlotNum++ hardpointSlotNum++;
} else { } else {
// The first slot of a new class // The first slot of a new class
hardpointClassNum = shipTemplate.slots.hardpoints[i] hardpointClassNum = shipTemplate.slots.hardpoints[i];
hardpointSlotNum = 1 hardpointSlotNum = 1;
} }
// Now that we know what we're looking for, find it // Now that we know what we're looking for, find it
const hardpointName = HARDPOINT_NUM_TO_CLASS[hardpointClassNum] + 'Hardpoint' + hardpointSlotNum const hardpointName = HARDPOINT_NUM_TO_CLASS[hardpointClassNum] + 'Hardpoint' + hardpointSlotNum;
const hardpointSlot = json.Modules.find(elem => elem.Slot.toLowerCase() === hardpointName.toLowerCase()) const hardpointSlot = json.Modules.find(elem => elem.Slot.toLowerCase() === hardpointName.toLowerCase());
if (!hardpointSlot) { if (!hardpointSlot) {
// This can happen with old imports that don't contain new hardpoints // This can happen with old imports that don't contain new hardpoints
} else if (!hardpointSlot) { } else if (!hardpointSlot) {
// No module // No module
} else { } else {
hardpoint = _moduleFromFdName(hardpointSlot.Item) hardpoint = _moduleFromFdName(hardpointSlot.Item);
ship.use(ship.hardpoints[hardpointArrayNum], hardpoint, true) ship.use(ship.hardpoints[hardpointArrayNum], hardpoint, true);
ship.hardpoints[hardpointArrayNum].enabled = hardpointSlot.On ship.hardpoints[hardpointArrayNum].enabled = hardpointSlot.On;
ship.hardpoints[hardpointArrayNum].priority = hardpointSlot.Priority ship.hardpoints[hardpointArrayNum].priority = hardpointSlot.Priority;
opts.push({coriolisMod: hardpoint, json: hardpointSlot}); opts.push({ coriolisMod: hardpoint, json: hardpointSlot });
} }
hardpointArrayNum++ hardpointArrayNum++;
} }
} }
if (module.Slot.toLowerCase().search(/slot\d/) !== -1) { if (module.Slot.toLowerCase().search(/slot\d/) !== -1) {
let internalSlotNum = 1 let internalSlotNum = 1;
let militarySlotNum = 1 let militarySlotNum = 1;
for (let i in shipTemplate.slots.internal) { for (let i in shipTemplate.slots.internal) {
const isMilitary = isNaN(shipTemplate.slots.internal[i]) ? shipTemplate.slots.internal[i].name = 'military' : false const isMilitary = isNaN(shipTemplate.slots.internal[i]) ? shipTemplate.slots.internal[i].name = 'military' : false;
// The internal slot might be a standard or a military slot. Military slots have a different naming system // The internal slot might be a standard or a military slot. Military slots have a different naming system
let internalSlot = null let internalSlot = null;
if (isMilitary) { if (isMilitary) {
const internalName = 'Military0' + militarySlotNum const internalName = 'Military0' + militarySlotNum;
internalSlot = json.Modules.find(elem => elem.Slot.toLowerCase() === internalName.toLowerCase()) internalSlot = json.Modules.find(elem => elem.Slot.toLowerCase() === internalName.toLowerCase());
militarySlotNum++ militarySlotNum++;
} else { } else {
// Slot numbers are not contiguous so handle skips. // Slot numbers are not contiguous so handle skips.
while (internalSlot === null && internalSlotNum < 99) { while (internalSlot === null && internalSlotNum < 99) {
// Slot sizes have no relationship to the actual size, either, so check all possibilities // Slot sizes have no relationship to the actual size, either, so check all possibilities
for (let slotsize = 0; slotsize < 9; slotsize++) { for (let slotsize = 0; slotsize < 9; slotsize++) {
const internalName = 'Slot' + (internalSlotNum <= 9 ? '0' : '') + internalSlotNum + '_Size' + slotsize const internalName = 'Slot' + (internalSlotNum <= 9 ? '0' : '') + internalSlotNum + '_Size' + slotsize;
if (json.Modules.find(elem => elem.Slot.toLowerCase() === internalName.toLowerCase())) { if (json.Modules.find(elem => elem.Slot.toLowerCase() === internalName.toLowerCase())) {
internalSlot = json.Modules.find(elem => elem.Slot.toLowerCase() === internalName.toLowerCase()); internalSlot = json.Modules.find(elem => elem.Slot.toLowerCase() === internalName.toLowerCase());
break break;
} }
} }
internalSlotNum++ internalSlotNum++;
} }
} }
@@ -213,12 +213,12 @@ export function shipFromLoadoutJSON (json) {
} else if (!internalSlot) { } else if (!internalSlot) {
// No module // No module
} else { } else {
const internalJson = internalSlot const internalJson = internalSlot;
const internal = _moduleFromFdName(internalJson.Item) const internal = _moduleFromFdName(internalJson.Item);
ship.use(ship.internal[i], internal, true) ship.use(ship.internal[i], internal, true);
ship.internal[i].enabled = internalJson.On === true ship.internal[i].enabled = internalJson.On === true;
ship.internal[i].priority = internalJson.Priority ship.internal[i].priority = internalJson.Priority;
opts.push({coriolisMod: internal, json: internalSlot}); opts.push({ coriolisMod: internal, json: internalSlot });
} }
} }
} }
@@ -226,17 +226,17 @@ export function shipFromLoadoutJSON (json) {
} }
for (const i of opts) { for (const i of opts) {
if (i.json.Engineering) _addModifications(i.coriolisMod, i.json.Engineering.Modifiers, i.json.Engineering.BlueprintName, i.json.Engineering.Level, i.json.Engineering.ExperimentalEffect) if (i.json.Engineering) _addModifications(i.coriolisMod, i.json.Engineering.Modifiers, i.json.Engineering.BlueprintName, i.json.Engineering.Level, i.json.Engineering.ExperimentalEffect);
} }
// We don't have any information on it so guess it's priority 5 and disabled // We don't have any information on it so guess it's priority 5 and disabled
if (!ship.cargoHatch) { if (!ship.cargoHatch) {
ship.cargoHatch.enabled = false ship.cargoHatch.enabled = false;
ship.cargoHatch.priority = 4 ship.cargoHatch.priority = 4;
} }
console.log(ship) console.log(ship);
// Now update the ship's codes before returning it // Now update the ship's codes before returning it
return ship.updatePowerPrioritesString().updatePowerEnabledString().updateModificationsString() return ship.updatePowerPrioritesString().updatePowerEnabledString().updateModificationsString();
} }
/** /**
@@ -247,18 +247,18 @@ export function shipFromLoadoutJSON (json) {
* @param {Object} grade the grade of the modification * @param {Object} grade the grade of the modification
* @param {Object} specialModifications special modification * @param {Object} specialModifications special modification
*/ */
function _addModifications (module, modifiers, blueprint, grade, specialModifications) { function _addModifications(module, modifiers, blueprint, grade, specialModifications) {
if (!modifiers) return if (!modifiers) return;
let special let special;
if (specialModifications) { if (specialModifications) {
special = Modifications.specials[specialModifications] special = Modifications.specials[specialModifications];
} }
for (const i in modifiers) { for (const i in modifiers) {
// Some special modifications // Some special modifications
// Look up the modifiers to find what we need to do // Look up the modifiers to find what we need to do
const findMod = val => Object.keys(Modifications.modifierActions).find(elem => elem.toString().toLowerCase().replace(/(outfittingfieldtype_|persecond)/igm, '') === val.toString().toLowerCase().replace(/(outfittingfieldtype_|persecond)/igm, '')) const findMod = val => Object.keys(Modifications.modifierActions).find(elem => elem.toString().toLowerCase().replace(/(outfittingfieldtype_|persecond)/igm, '') === val.toString().toLowerCase().replace(/(outfittingfieldtype_|persecond)/igm, ''));
const modifierActions = Modifications.modifierActions[findMod(modifiers[i].Label)] const modifierActions = Modifications.modifierActions[findMod(modifiers[i].Label)];
//TODO: Figure out how to scale this value. // TODO: Figure out how to scale this value.
if (!!modifiers[i].LessIsGood) { if (!!modifiers[i].LessIsGood) {
} }
@@ -267,26 +267,26 @@ function _addModifications (module, modifiers, blueprint, grade, specialModifica
value = modifiers[i].Value * 100; value = modifiers[i].Value * 100;
} }
if (modifiers[i].Label.search('Resistance') >= 0) { if (modifiers[i].Label.search('Resistance') >= 0) {
value = (modifiers[i].Value * 100) - (modifiers[i].OriginalValue * 100) value = (modifiers[i].Value * 100) - (modifiers[i].OriginalValue * 100);
} }
// Carry out the required changes // Carry out the required changes
for (const action in modifierActions) { for (const action in modifierActions) {
if (isNaN(modifierActions[action])) { if (isNaN(modifierActions[action])) {
module.setModValue(action, modifierActions[action]) module.setModValue(action, modifierActions[action]);
} else { } else {
module.setModValue(action, value) module.setModValue(action, value);
} }
} }
} }
// Add the blueprint definition, grade and special // Add the blueprint definition, grade and special
if (blueprint) { if (blueprint) {
module.blueprint = getBlueprint(blueprint, module) module.blueprint = getBlueprint(blueprint, module);
if (grade) { if (grade) {
module.blueprint.grade = Number(grade) module.blueprint.grade = Number(grade);
} }
if (special) { if (special) {
module.blueprint.special = special module.blueprint.special = special;
} }
} }
} }