Compare commits

...

20 Commits

Author SHA1 Message Date
William Blythe
9abb4f6d05 Merge branch 'develop' into dw2 2019-01-09 09:24:29 +11:00
willyb321
38038fcc32 fix a bug 2018-12-05 07:34:02 +11:00
William Blythe
9fa740f54e more work 2018-12-04 12:01:08 +11:00
William Blythe
d37d69c3a7 add some more guards on ships 2018-11-30 10:59:32 +11:00
William Blythe
78d8779641 add some guards on ships 2018-11-30 10:55:05 +11:00
Willyb321
352023f0fb Start work on roles 2018-11-30 09:08:26 +11:00
willyb321
3ea194d43e Merge branch 'develop' into dw2 2018-11-30 06:56:16 +11:00
willyb321
c6269192f0 mor edw2 2018-11-30 06:52:47 +11:00
willyb321
841e6c3348 More dw2 work, update roles etc 2018-11-30 06:37:09 +11:00
willyb321
0febc581d1 Merge branch 'develop' into dw2 2018-11-30 06:25:41 +11:00
Willyb321
dc6e398526 fighter hangar 2018-11-30 06:23:41 +11:00
Willyb321
cb24c1fc69 more dw2 work 2018-11-30 06:16:21 +11:00
William Blythe
90ad9de831 more dw2 2018-11-28 14:23:01 +11:00
William Blythe
9360b1d574 more dw2 work 2018-11-28 11:31:09 +11:00
William Blythe
08d2573d1f internals 2018-11-28 09:42:21 +11:00
Willyb321
427b9af7de up to shields 2018-11-28 08:25:05 +11:00
William Blythe
318d06d9f9 dw2 build work 2018-11-20 12:18:16 +11:00
William Blythe
1f3c3726f2 Merge branch 'dw2' of github.com:EDCD/coriolis into dw2 2018-11-20 09:29:08 +11:00
William
71beda3a6c Update docker-compose.yml 2018-11-20 08:36:16 +11:00
William
1d6644b531 Update docker-compose.yml 2018-11-20 08:34:53 +11:00
5 changed files with 1160 additions and 450 deletions

View File

@@ -43,6 +43,9 @@ services:
- "traefik.basic.port=80" - "traefik.basic.port=80"
- "traefik.basic.protocol=http" - "traefik.basic.protocol=http"
networks: networks:
web: web:
external: true external: true

View File

@@ -20,16 +20,28 @@ export default class StandardSlotSection extends SlotSection {
super(props, context, 'standard', 'core internal'); super(props, context, 'standard', 'core internal');
this._optimizeStandard = this._optimizeStandard.bind(this); this._optimizeStandard = this._optimizeStandard.bind(this);
this._selectBulkhead = this._selectBulkhead.bind(this); this._selectBulkhead = this._selectBulkhead.bind(this);
this._showDW2Menu = this._showDW2Menu.bind(this);
this._dw2 = this._dw2.bind(this);
this.selectedRefId = null; this.selectedRefId = null;
this.firstRefId = 'maxjump'; this.firstRefId = 'maxjump';
this.lastRefId = 'racer'; this.lastRefId = 'dw2';
this.state = {
showDW2: false,
DW2Tier: -1,
DW2Eng: -1,
DW2Role: '',
DW2Gfsb: false,
DW2Gpp: false,
DW2Fighter: false
};
} }
/** /**
* Handle focus if the component updates * Handle focus if the component updates
* @param {Object} prevProps React Component properties * @param {Object} prevProps React Component properties
*/ */
componentDidUpdate(prevProps) { componentDidUpdate(prevProps) {
this._handleSectionFocus(prevProps,this.firstRefId, this.lastRefId); this._handleSectionFocus(prevProps, this.firstRefId, this.lastRefId);
} }
/** /**
@@ -72,6 +84,114 @@ export default class StandardSlotSection extends SlotSection {
this._close(); this._close();
} }
/**
* DW2 Build
*/
_dw2() {
this.selectedRefId = 'dw2';
this.setState({ showDW2: false });
ShipRoles.dw2Build(this.props.ship, this.state.DW2Tier, this.state.DW2Eng, this.state.DW2Role, this.state.DW2Gfsb, this.state.DW2Gpp, this.state.DW2Fighter);
this.props.ship.updateModificationsString();
this.props.onChange();
this.props.onCargoChange(this.props.ship.cargoCapacity);
this.props.onFuelChange(this.props.ship.fuelCapacity);
this._close();
}
_showDW2Menu(translate) {
return (
<div className='select' onClick={(e) => e.stopPropagation()} onContextMenu={stopCtxPropagation}>
<div className='select-group cap'>{translate('Tier')}</div>
<ul id={'tier'}>
<li className={cn({ active: this.state.DW2Tier === 1 }, 'lc')} tabIndex="0"
onClick={() => this.setState({ DW2Tier: 1 })} onKeyDown={this._keyDown}
>{translate('1 - Max. Jump Range, Unshielded')}</li>
<li className={cn({ active: this.state.DW2Tier === 2 }, 'lc')} tabIndex="0"
onClick={() => this.setState({ DW2Tier: 2 })} onKeyDown={this._keyDown}
>{translate('2 - Max. Jump Range, Minimal Shields')}</li>
<li className={cn({ active: this.state.DW2Tier === 3 }, 'lc')} tabIndex="0"
onClick={() => this.setState({ DW2Tier: 3 })} onKeyDown={this._keyDown}
>{translate('3 - Max. Jump Range, Optimal Shields')}</li>
<li className={cn({ active: this.state.DW2Tier === 4 }, 'lc')} tabIndex="0"
onClick={() => this.setState({ DW2Tier: 4 })} onKeyDown={this._keyDown}
>{translate('4 - Max. Jump Range, Optimal Shields & Thrusters')}</li>
</ul>
<hr/>
<div className='select-group cap'>{translate('Engineering Level')}</div>
<ul id={'engLevel'}>
<li className={cn({ active: this.state.DW2Eng === 1 }, 'lc')} tabIndex="0"
onClick={() => this.setState({ DW2Eng: 1 })} onKeyDown={this._keyDown}
>{translate('No engineering')}</li>
<li className={cn({ active: this.state.DW2Eng === 2 }, 'lc')} tabIndex="0"
onClick={() => this.setState({ DW2Eng: 2 })} onKeyDown={this._keyDown}
>{translate('Only Felicity Farseer and Elvira Martuuk')}</li>
<li className={cn({ active: this.state.DW2Eng === 3 }, 'lc')} tabIndex="0"
onClick={() => this.setState({ DW2Eng: 3 })} onKeyDown={this._keyDown}
>{translate('All exploration engineers')}</li>
</ul>
<hr/>
<div className='select-group cap'>{translate('Role')}</div>
<ul id={'role'}>
<li className={cn({ active: this.state.DW2Role === 'exploration' }, 'lc')} tabIndex="0"
onClick={() => this.setState({ DW2Role: 'exploration' })}
onKeyDown={this._keyDown}
>{translate('Space exploration')}</li>
<li className={cn({ active: this.state.DW2Role === 'surface' }, 'lc')} tabIndex="0"
onClick={() => this.setState({ DW2Role: 'surface' })}
onKeyDown={this._keyDown}
>{translate('Surface exploration')}</li>
<li className={cn({ active: this.state.DW2Role === 'materialProspector' }, 'lc')} tabIndex="0"
onClick={() => this.setState({ DW2Role: 'materialProspector' })}
onKeyDown={this._keyDown}
>{translate('Material prospector')}</li>
<li className={cn({ active: this.state.DW2Role === 'propectorMining' }, 'lc')} tabIndex="0"
onClick={() => this.setState({ DW2Role: 'propectorMining' })}
onKeyDown={this._keyDown}
>{translate('Prospector/Sapper Miner')}</li>
<li className={cn({ active: this.state.DW2Role === 'bigRigMining' }, 'lc')} tabIndex="0"
onClick={() => this.setState({ DW2Role: 'bigRigMining' })}
onKeyDown={this._keyDown}
>{translate('Big Rig, full mining')}</li>
<li className={cn({ active: this.state.DW2Role === 'fuelRat' }, 'lc')} tabIndex="0"
onClick={() => this.setState({ DW2Role: 'fuelRat' })} onKeyDown={this._keyDown}
>{translate('Fuel Rat')}</li>
<li className={cn({ active: this.state.DW2Role === 'mechanic' }, 'lc')} tabIndex="0"
onClick={() => this.setState({ DW2Role: 'mechanic' })} onKeyDown={this._keyDown}
>{translate('Mechanic')}</li>
<li className={cn({ active: this.state.DW2Role === 'trucker' }, 'lc')} tabIndex="0"
onClick={() => this.setState({ DW2Role: 'trucker' })} onKeyDown={this._keyDown}
>{translate('Trucker')}</li>
</ul>
<hr/>
<ul>
<li className={cn({ active: this.state.DW2Gfsb === true }, 'lc')}
onClick={() => this.setState({ DW2Gfsb: this.state.DW2Gfsb !== true })}>
Add Guardian FSD Booster
</li>
</ul>
<ul>
<li className={cn({ active: this.state.DW2Gpp === true }, 'lc')}
onClick={() => this.setState({ DW2Gpp: this.state.DW2Gpp !== true })}>
Add Guardian Power Plant
</li>
</ul>
<ul>
<li className={cn({ active: this.state.DW2Fighter === true }, 'lc')}
onClick={() => this.setState({ DW2Fighter: this.state.DW2Fighter !== true })}>
Add Fighter
</li>
</ul>
<hr/>
<ul>
<li onClick={this._dw2} className={cn('lc')} tabIndex="0"
onKeyDown={this._keyDown}>
<button className="button">Apply</button>
</li>
</ul>
</div>
);
}
/** /**
* Miner Build * Miner Build
* @param {Boolean} shielded True if shield generator should be included * @param {Boolean} shielded True if shield generator should be included
@@ -177,7 +297,6 @@ export default class StandardSlotSection extends SlotSection {
warning={m => m instanceof Module ? m.getMaxMass() < (ship.unladenMass + cargo + fuel - st[1].m.mass + m.mass) : m.maxmass < (ship.unladenMass + cargo + fuel - st[1].m.mass + m.mass)} warning={m => m instanceof Module ? m.getMaxMass() < (ship.unladenMass + cargo + fuel - st[1].m.mass + m.mass) : m.maxmass < (ship.unladenMass + cargo + fuel - st[1].m.mass + m.mass)}
/>; />;
slots[3] = <StandardSlot slots[3] = <StandardSlot
key='fsd' key='fsd'
slot={st[2]} slot={st[2]}
@@ -232,7 +351,7 @@ export default class StandardSlotSection extends SlotSection {
selected={currentMenu == st[6]} selected={currentMenu == st[6]}
onChange={this.props.onChange} onChange={this.props.onChange}
ship={ship} ship={ship}
warning= {m => m.fuel < st[2].m.maxfuel} // Show warning when fuel tank is smaller than FSD Max Fuel warning={m => m.fuel < st[2].m.maxfuel} // Show warning when fuel tank is smaller than FSD Max Fuel
/>; />;
return slots; return slots;
@@ -245,19 +364,34 @@ export default class StandardSlotSection extends SlotSection {
*/ */
_getSectionMenu(translate) { _getSectionMenu(translate) {
let planetaryDisabled = this.props.ship.internal.length < 4; let planetaryDisabled = this.props.ship.internal.length < 4;
if (this.state.showDW2 === true) {
return this._showDW2Menu(translate);
}
return <div className='select' onClick={(e) => e.stopPropagation()} onContextMenu={stopCtxPropagation}> return <div className='select' onClick={(e) => e.stopPropagation()} onContextMenu={stopCtxPropagation}>
<ul> <ul>
<li className='lc' tabIndex="0" onClick={this._optimizeStandard} onKeyDown={this._keyDown} ref={smRef => this.sectionRefArr['maxjump'] = smRef}>{translate('Maximize Jump Range')}</li> <li className='lc' tabIndex="0" onClick={this._optimizeStandard} onKeyDown={this._keyDown}
ref={smRef => this.sectionRefArr['maxjump'] = smRef}>{translate('Maximize Jump Range')}</li>
</ul> </ul>
<div className='select-group cap'>{translate('roles')}</div> <div className='select-group cap'>{translate('roles')}</div>
<ul> <ul>
<li className='lc' tabIndex="0" onClick={this._multiPurpose.bind(this, false, 0)} onKeyDown={this._keyDown} ref={smRef => this.sectionRefArr['multipurpose'] = smRef}>{translate('Multi-purpose')}</li> <li className='lc' tabIndex="0" onClick={this._multiPurpose.bind(this, false, 0)} onKeyDown={this._keyDown}
<li className='lc' tabIndex="0" onClick={this._multiPurpose.bind(this, true, 2)} onKeyDown={this._keyDown} ref={smRef => this.sectionRefArr['combat'] = smRef}>{translate('Combat')}</li> ref={smRef => this.sectionRefArr['multipurpose'] = smRef}>{translate('Multi-purpose')}</li>
<li className='lc' tabIndex="0" onClick={this._optimizeCargo.bind(this, true)} onKeyDown={this._keyDown} ref={smRef => this.sectionRefArr['trader'] = smRef}>{translate('Trader')}</li> <li className='lc' tabIndex="0" onClick={this._multiPurpose.bind(this, true, 2)} onKeyDown={this._keyDown}
<li className='lc' tabIndex="0" onClick={this._optimizeExplorer.bind(this, false)} onKeyDown={this._keyDown} ref={smRef => this.sectionRefArr['explorer'] = smRef}>{translate('Explorer')}</li> ref={smRef => this.sectionRefArr['combat'] = smRef}>{translate('Combat')}</li>
<li className={cn('lc', { disabled: planetaryDisabled })} tabIndex={planetaryDisabled ? '' : '0'} onClick={!planetaryDisabled && this._optimizeExplorer.bind(this, true)} onKeyDown={this._keyDown} ref={smRef => this.sectionRefArr['planetary'] = smRef}>{translate('Planetary Explorer')}</li> <li className='lc' tabIndex="0" onClick={this._optimizeCargo.bind(this, true)} onKeyDown={this._keyDown}
<li className='lc' tabIndex="0" onClick={this._optimizeMiner.bind(this, true)} onKeyDown={this._keyDown} ref={smRef => this.sectionRefArr['miner'] = smRef}>{translate('Miner')}</li> ref={smRef => this.sectionRefArr['trader'] = smRef}>{translate('Trader')}</li>
<li className='lc' tabIndex="0" onClick={this._optimizeRacer.bind(this)} onKeyDown={this._keyDown} ref={smRef => this.sectionRefArr['racer'] = smRef}>{translate('Racer')}</li> <li className='lc' tabIndex="0" onClick={this._optimizeExplorer.bind(this, false)} onKeyDown={this._keyDown}
ref={smRef => this.sectionRefArr['explorer'] = smRef}>{translate('Explorer')}</li>
<li className={cn('lc', { disabled: planetaryDisabled })} tabIndex={planetaryDisabled ? '' : '0'}
onClick={!planetaryDisabled && this._optimizeExplorer.bind(this, true)} onKeyDown={this._keyDown}
ref={smRef => this.sectionRefArr['planetary'] = smRef}>{translate('Planetary Explorer')}</li>
<li className='lc' tabIndex="0" onClick={this._optimizeMiner.bind(this, true)} onKeyDown={this._keyDown}
ref={smRef => this.sectionRefArr['miner'] = smRef}>{translate('Miner')}</li>
<li className='lc' tabIndex="0" onClick={this._optimizeRacer.bind(this)} onKeyDown={this._keyDown}
ref={smRef => this.sectionRefArr['racer'] = smRef}>{translate('Racer')}</li>
<li className='lc' tabIndex="0" onClick={() => this.setState({ showDW2: !this.state.showDW2 })}
onKeyDown={this._keyDown}
ref={smRef => this.sectionRefArr['dw2'] = smRef}>{translate('DW2')}</li>
</ul> </ul>
</div>; </div>;
} }

View File

@@ -164,13 +164,13 @@ export default class ModuleSet {
/** /**
* Finds the lightest usable Shield Generator * Finds the lightest usable Shield Generator
* @param {number} hullMass Ship hull mass * @param {number} hullMass Ship hull mass
* @return {Object} Thruster * @param {string} rating The optional rating of the shield
* @return {Object} Shield Generator
*/ */
lightestShieldGenerator(hullMass) { lightestShieldGenerator(hullMass, rating) {
let sg = this.internal.sg[0]; let sg = this.internal.sg[0];
for (let s of this.internal.sg) { for (let s of this.internal.sg) {
if (s.mass < sg.mass && s.maxmass > hullMass) { if ((!rating || rating === s.rating) && s.mass <= sg.mass && s.maxmass > hullMass) {
sg = s; sg = s;
} }
} }

View File

@@ -1,5 +1,7 @@
import * as ModuleUtils from './ModuleUtils'; import * as ModuleUtils from './ModuleUtils';
import { Modifications } from 'coriolis-data/dist';
import { canMount } from '../utils/SlotFunctions'; import { canMount } from '../utils/SlotFunctions';
import { getBlueprint, setPercent } from '../utils/BlueprintFunctions';
/** /**
* 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)
@@ -14,7 +16,7 @@ export function multiPurpose(ship, shielded, bulkheadIndex) {
.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);
@@ -24,6 +26,577 @@ export function multiPurpose(ship, shielded, bulkheadIndex) {
} }
} }
/**
* Distant Worlds 2 role
* Tiers:
* 1- Max. Jump Range, Unshielded
* 2- Max. Jump Range, Minimal Shields
* 3- Max. Jump Range, Optimal Shields
* 4- Max. Jump Range, Optimal Shields & Thrusters
*
* Engineering level:
* No engineering
* Only Felicity Farseer and Elvira Martuuk
* All exploration related engineers
*
* Role
* Exploration
* Surface exploration
* Big Rig, full mining
* Saper / Prospector mining
* Fuel rat
* Repair rat
* Mechanic
* Trucker
*
* @param ship {Ship} Ship instance
* @param tier {Number}
* @param engineeringLevel {Number}
* @param role {String}
* @param gfsb {Boolean} add Guardian FSD Booster
* @param gpp {Boolean} add Guardian Power Plant
* @param fighter {Boolean} add fighter if supported
*/
export function dw2Build(ship, tier, engineeringLevel, role, gfsb, gpp, fighter) {
ship
.emptyInternal()
.emptyHardpoints()
.emptyUtility();
const fsd = ModuleUtils.findStandard('fsd', ship.standard[2].maxClass, 'A');
ship.use(ship.standard[2], fsd);
ship.use(ship.standard[3], ModuleUtils.findStandard('ls', ship.standard[3].maxClass, 'D'));
ship.use(ship.standard[4], ModuleUtils.findStandard('pd', 1, 'D'));
ship.use(ship.standard[5], ModuleUtils.findStandard('s', ship.standard[5].maxClass, 'D'));
const fuelNeeded = ship.standard[2].m.maxfuel * 2;
const fuelTank = ship.availCS.standard[6]
.filter(e => e.fuel)
.filter(e => e.fuel >= fuelNeeded);
ship.use(ship.standard[6], fuelTank[0]);
ship.useBulkhead(0, false);
if (engineeringLevel === 2) {
const bp = getBlueprint('FSD_LongRange', ship.standard[2]);
bp.grade = 5;
bp.special = Modifications.specials['special_fsd_heavy'];
ship.standard[2].m.blueprint = bp;
setPercent(ship, ship.standard[2].m, 100);
// Sensors G3 LW
const sBP = getBlueprint('Sensor_Sensor_LightWeight', ship.standard[5]);
sBP.grade = 3;
ship.standard[5].m.blueprint = sBP;
setPercent(ship, ship.standard[5].m, 100);
} else if (engineeringLevel === 3) {
// Armour G5 HD + Deep Plating
const armourBP = getBlueprint('Armour_HeavyDuty', ship.bulkheads);
armourBP.grade = 5;
armourBP.special = Modifications.specials['special_armour_chunky'];
ship.bulkheads.m.blueprint = armourBP;
setPercent(ship, ship.bulkheads.m, 100);
// FSD G5 IR + Mass Manager
const fsdBP = getBlueprint('FSD_LongRange', ship.standard[2]);
fsdBP.grade = 5;
fsdBP.special = Modifications.specials['special_fsd_heavy'];
ship.standard[2].m.blueprint = fsdBP;
setPercent(ship, ship.standard[2].m, 100);
// LS G4 LW
const lsBP = getBlueprint('LifeSupport_LightWeight', ship.standard[3]);
lsBP.grade = 4;
ship.standard[3].m.blueprint = lsBP;
setPercent(ship, ship.standard[3].m, 100);
// Sensors G5 LW
const sBP = getBlueprint('Sensor_Sensor_LightWeight', ship.standard[5]);
sBP.grade = 5;
ship.standard[5].m.blueprint = sBP;
setPercent(ship, ship.standard[5].m, 100);
}
if (ship.id === 'imperial_clipper') {
const fs = ModuleUtils.findInternal('fs', 4, 'A');
const slot = ship.internal.filter(a => a.maxClass === 4)[0];
ship.use(slot, fs);
} else if (ship.id === 'imperial_cutter') {
const fs = ModuleUtils.findInternal('fs', 6, 'A');
const slot = ship.internal.filter(a => a.maxClass === 6)[0];
ship.use(slot, fs);
} else if (fsd.class === 2 && fsd.rating === 'A') {
let fs = ModuleUtils.findInternal('fs', 2, 'A');
let slot = ship.internal.filter(a => a.maxClass >= 2).filter(a => a.maxClass >= fs.class)
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))
[0];
if (slot.m) {
fs = ModuleUtils.findInternal('fs', 1, 'A');
slot = ship.internal.filter(a => a.maxClass === 1)[0];
ship.use(slot, fs);
} else {
ship.use(slot, fs);
}
} else if (fsd.class === 3 && fsd.rating === 'A') {
let fs = ModuleUtils.findInternal('fs', 3, 'B');
let slot = ship.internal.filter(a => a.maxClass >= 3).filter(a => a.maxClass >= fs.class)
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))
[0];
if (slot.m) {
fs = ModuleUtils.findInternal('fs', 2, 'A');
slot = ship.internal.filter(a => a.maxClass === 2)[0];
ship.use(slot, fs);
} else {
ship.use(slot, fs);
}
} else if (fsd.class === 4 && fsd.rating === 'A') {
let fs = ModuleUtils.findInternal('fs', 4, 'b');
let slot = ship.internal.filter(a => a.maxClass >= 4).filter(a => a.maxClass >= fs.class)
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))
[0];
if (slot.m) {
fs = ModuleUtils.findInternal('fs', 3, 'A');
slot = ship.internal.filter(a => a.maxClass === 3)[0];
ship.use(slot, fs);
} else {
ship.use(slot, fs);
}
} else if (fsd.class === 5 && fsd.rating === 'A') {
let fs = ModuleUtils.findInternal('fs', 5, 'B');
let slot = ship.internal.filter(a => a.maxClass >= 5).filter(a => a.maxClass >= fs.class)
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))
[0];
if (slot.m) {
fs = ModuleUtils.findInternal('fs', 4, 'A');
slot = ship.internal.filter(a => a.maxClass === 4).filter(a => a.maxClass >= fs.class)
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))
[0];
if (fs) {
ship.use(slot, fs);
}
} else {
if (fs) {
ship.use(slot, fs);
}
}
} else if (fsd.class === 6 && fsd.rating === 'A') {
let fs = ModuleUtils.findInternal('fs', 6, 'B');
let slot = ship.internal.filter(a => a.maxClass >= 6)
.filter(a => a.maxClass >= fs.class)
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))
[0];
if (slot.m) {
fs = ModuleUtils.findInternal('fs', 5, 'A');
slot = ship.internal.filter(a => a.maxClass === 5)[0];
if (fs) {
ship.use(slot, fs);
}
} else {
if (fs) {
ship.use(slot, fs);
}
}
} else if (fsd.class === 7 && fsd.rating === 'A') {
let fs = ModuleUtils.findInternal('fs', 7, 'B');
let slot = ship.internal.filter(a => a.maxClass >= 7).filter(a => a.maxClass >= fs.class)
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))
[0];
if (slot && slot.m) {
fs = ModuleUtils.findInternal('fs', 6, 'A');
slot = ship.internal.filter(a => a.maxClass === 6)[0];
if (fs) {
ship.use(slot, fs);
}
} else {
if (fs) {
ship.use(slot, fs);
}
}
}
if (tier !== 1) {
const fuelNeeded = ship.standard[2].m.maxfuel * 3;
const fuelTank = ship.availCS.standard[6]
.filter(e => e.fuel)
.filter(e => e.fuel >= fuelNeeded);
if (fuelTank[0]) {
ship.use(ship.standard[6], fuelTank[0]);
}
}
if (tier === 2) {
if (ship.id === 'alliance_chieftain' || ship.id === 'alliance_crusader' || ship.id === 'federal_gunship' || ship.id === 'vulture') {
const hrp = ModuleUtils.findInternal('hrp', 3, 'D');
const slot = ship.internal.filter(e => e.eligible && e.maxClass === 3);
if (hrp) {
ship.use(slot, hrp);
}
} else {
const sg = ship.getAvailableModules().lightestShieldGenerator(ship.ladenMass);
const slot = ship.internal.filter(a => !a.m)
.filter(a => a.maxClass >= sg.class)
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))
[0];
if (sg) {
ship.use(slot, sg);
}
if (engineeringLevel === 2) {
// ELP G3
const shieldBP = getBlueprint('ShieldGenerator_Optimised', ship.findShieldGenerator());
shieldBP.grade = 3;
ship.findShieldGenerator().blueprint = shieldBP;
setPercent(ship, ship.findShieldGenerator(), 100);
} else if (engineeringLevel === 3) {
// ELP G5
const shieldBP = getBlueprint('ShieldGenerator_Optimised', ship.findShieldGenerator());
shieldBP.grade = 5;
ship.findShieldGenerator().blueprint = shieldBP;
setPercent(ship, ship.findShieldGenerator(), 100);
}
// const shieldOrder = [1, 2, 3, 4, 5, 6, 7, 8].reverse();
// const shieldInternals = ship.internal.filter(a => !a.m)
// .filter(a => (!a.eligible) || a.eligible.sg)
// .filter(a => a.maxClass >= sg.class)
// .sort((a, b) => shieldOrder.indexOf(a.maxClass) - shieldOrder.indexOf(b.maxClass));
// for (let i = 0; i < shieldInternals.length; i++) {
// if (canMount(ship, shieldInternals[i], 'sg')) {
// ship.use(shieldInternals[i], sg);
// break;
// }
// }
}
} else if (tier === 3 || tier === 4) {
const sg = ship.getAvailableModules().lightestShieldGenerator(ship.hullMass, 'A');
const slot = ship.internal.filter(a => !a.m)
.filter(a => a.maxClass >= sg.class)
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))
[0];
if (sg) {
ship.use(slot, sg);
}
if (engineeringLevel === 1) {
// ELP G3
const shieldBP = getBlueprint('ShieldGenerator_Optimised', ship.findShieldGenerator());
shieldBP.grade = 3;
shieldBP.special = Modifications.specials['special_shield_lightweight'];
ship.findShieldGenerator().blueprint = shieldBP;
setPercent(ship, ship.findShieldGenerator(), 100);
} else if (engineeringLevel === 2) {
// ELP G5
const shieldBP = getBlueprint('ShieldGenerator_Optimised', ship.findShieldGenerator());
shieldBP.grade = 5;
shieldBP.special = Modifications.specials['special_shield_lightweight'];
ship.findShieldGenerator().blueprint = shieldBP;
setPercent(ship, ship.findShieldGenerator(), 100);
}
}
if (tier === 4) {
let t;
if (canMount(ship, ship.standard[1], 't', ship.standard[1].maxClass - 1)) {
t = ModuleUtils.findStandard('t', ship.standard[1].maxClass - 1, 'A');
} else {
t = ModuleUtils.findStandard('t', ship.standard[1].maxClass, 'A');
}
if (t) {
ship.use(ship.standard[1], t);
}
if (engineeringLevel === 1) {
// DD G3
const tBP = getBlueprint('Engine_Dirty', ship.standard[1]);
tBP.grade = 3;
tBP.special = Modifications.specials['special_engine_lightweight'];
ship.standard[1].m.blueprint = tBP;
setPercent(ship, ship.standard[1].m, 100);
} else if (engineeringLevel === 2) {
// DD G5
const tBP = getBlueprint('Engine_Dirty', ship.standard[1]);
tBP.grade = 5;
tBP.special = Modifications.specials['special_engine_lightweight'];
ship.standard[1].m.blueprint = tBP;
setPercent(ship, ship.standard[1].m, 100);
}
}
if (tier === 4 || tier === 3) {
if (engineeringLevel === 3) {
const pd = ship.availCS.standard[4]
.filter(d => d.rating === 'D')
.filter(d => (d.engcap * 1.728) >= ship.boostEnergy)
.sort((a, b) => a.class.toString().localeCompare(b.class.toString()))[0];
if (pd) {
ship.use(ship.standard[4], pd);
}
// CE G5
const pdBP = getBlueprint('PowerDistributor_HighFrequency', ship.standard[4]);
pdBP.grade = 5;
pdBP.special = Modifications.specials['special_powerdistributor_capacity'];
ship.standard[4].m.blueprint = pdBP;
setPercent(ship, ship.standard[4].m, 100);
} else {
const pd = ship.availCS.standard[4]
.filter(d => d.rating === 'D')
.sort((a, b) => a.engcap > b.engcap)
[0];
if (pd) {
ship.use(ship.standard[4], pd);
}
}
} else if (tier === 4) {
if (engineeringLevel === 3) {
const pd = ship.availCS.standard[4]
.filter(d => d.rating === 'D')
.sort((a, b) => b.class.toString().localeCompare(a.class.toString()))[0];
if (pd) {
ship.use(ship.standard[4], pd);
}
// CE G5
const pdBP = getBlueprint('PowerDistributor_HighFrequency', ship.standard[4]);
pdBP.grade = 5;
pdBP.special = Modifications.specials['special_powerdistributor_capacity'];
ship.standard[4].m.blueprint = pdBP;
setPercent(ship, ship.standard[4].m, 100);
} else {
const pd = ship.availCS.standard[4]
.filter(d => d.rating === 'D')
.sort((a, b) => b.class.toString().localeCompare(a.class.toString()))[0];
if (pd) {
ship.use(ship.standard[4], pd);
}
}
}
if (ship.fighterHangars && fighter) {
const slot = ship.internal.filter(s => s.maxClass >= 5 && !s.m)
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))
[0];
const mod = ModuleUtils.findInternal('fh', 5, 'D');
if (slot && mod) {
ship.use(slot, mod);
}
}
if (tier === 1) {
const pd = ModuleUtils.findStandard('pd', 1, 'D');
if (pd) {
ship.use(ship.standard[4]);
}
}
let dssPriority = 0;
let srvPriority = 0;
let afmu = true;
let cargo = false;
let miningLaserPriority = 0;
let refinery = false;
let collector = false;
let prospector = false;
let miningTools = false;
let refuelLimpets = false;
let repairLimpets = false;
console.log(role);
if (role === 'exploration') {
dssPriority = 2;
afmu = true;
} else if (role === 'surface') {
dssPriority = 2;
srvPriority = 2;
} else if (role === 'materialProspector') {
miningLaserPriority = 2;
srvPriority = 1;
} else if (role === 'propectorMining') {
dssPriority = 1;
prospector = true;
miningLaserPriority = 1;
cargo = true;
miningTools = true;
} else if (role === 'bigRigMining') {
dssPriority = 1;
miningLaserPriority = 2;
cargo = true;
collector = true;
refinery = true;
miningTools = true;
} else if (role === 'fuelRat') {
refuelLimpets = true;
cargo = true;
srvPriority = 1;
} else if (role === 'mechanic') {
repairLimpets = true;
cargo = true;
srvPriority = 1;
} else if (role === 'trucker') {
cargo = true;
}
if (dssPriority === 2) {
const mod = ModuleUtils.findModule('ss', '2i');
const slot = ship.internal.filter(s => !s.m)
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))[0];
console.log(slot);
console.log(mod);
ship.use(slot, mod);
}
if (srvPriority === 2) {
let mod;
let slot = ship.internal.filter(s => !s.m)
.filter(s => s.maxClass >= 6)
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))[0];
if (slot) {
mod = ModuleUtils.findModule('pv', 'v2');
ship.use(slot, mod);
} else if (!slot) {
slot = ship.internal.filter(s => !s.m)
.filter(s => s.maxClass >= 4)
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))[0];
if (slot) {
mod = ModuleUtils.findModule('pv', 'v4');
ship.use(slot, mod);
} else {
slot = ship.internal.filter(s => !s.m)
.filter(s => s.maxClass >= 2)
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))[0];
if (slot) {
mod = ModuleUtils.findModule('pv', 'v6');
ship.use(slot, mod);
}
}
}
}
if (cargo === true) {
const slot = ship.internal.filter(s => !s.m)
.sort((a, b) => b.maxClass.toString().localeCompare(a.maxClass.toString()))[0];
const mod = ModuleUtils.findInternal('cr', slot.maxClass, 'E');
ship.use(slot, mod);
}
if (refuelLimpets === true) {
const mod = ModuleUtils.findModule('fx', 'F4');
const slot = ship.internal.filter(s => !s.m)
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))[0];
ship.use(mod, slot);
}
if (repairLimpets === true) {
const slot = ship.internal.filter(s => !s.m)
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))[0];
let mod;
if (slot.maxClass >= 3) {
mod = ModuleUtils.findModule('rpl', '9e');
} else {
mod = ModuleUtils.findModule('rpl', '9s');
}
ship.use(mod, slot);
}
if (prospector === true) {
const slot = ship.internal.filter(s => !s.m)
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))[0];
let mod;
if (slot.maxClass >= 3) {
mod = ModuleUtils.findModule('pc', 'P9');
} else {
mod = ModuleUtils.findModule('pc', 'P4');
}
ship.use(mod, slot);
}
if (collector === true) {
const slots = ship.internal.filter(s => !s.m)
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()));
if (slots.length >= 2) {
let slot = slots.find(s => s.maxClass >= 5);
let mod;
if (slot) {
mod = ModuleUtils.findInternal('cc', slot.maxClass, 'D');
} else if (slots.find(s => s.maxClass <= 4)) {
slot = slots.find(s => s.maxClass <= 4);
mod = ModuleUtils.findInternal('cc', slot.maxClass, 'D');
}
ship.use(slot, mod);
}
}
if (refinery === true) {
const slots = ship.internal.filter(s => !s.m)
.filter(s => s.maxClass >= 4)
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))[0];
if (slots) {
const mod = ModuleUtils.findInternal('rf', 4, 'A');
ship.use(slots, mod);
} else {
const slot = ship.internal.filter(s => !s.m)
.filter(s => s.maxClass <= 3)
.sort((a, b) => b.maxClass.toString().localeCompare(a.maxClass.toString()))[0];
const mod = ModuleUtils.findInternal('rf', slot.maxClass, 'A');
ship.use(slots, mod);
}
}
if (dssPriority === 1) {
const slot = ship.internal.filter(s => !s.m)
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))[0];
const dss = ModuleUtils.findInternal('ss', 1, 'C')
if (slot) {
ship.use(slot, dss);
}
}
if (srvPriority === 1) {
const slot = ship.internal.filter(s => !s.m)
.filter(s => s.maxClass >= 2)
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()));
if (slot.find(s => s.maxClass >= 4)) {
const slot = slot.find(s => s.maxClass >= 4);
const srv = ModuleUtils.findInternal('pv', 4, 'G')
ship.use(slot, srv);
} else if (slot.find(s => s.maxClass >= 2)) {
const slot = slot.find(s => s.maxClass >= 2);
const srv = ModuleUtils.findInternal('pv', 2, 'G')
ship.use(slot, srv);
}
}
if (gfsb === true) {
const slots = ship.internal.filter(s => !s.m)
.filter(s => s.maxClass >= 1)
.sort((a, b) => b.maxClass.toString().localeCompare(a.maxClass.toString()));
if (slots.find(s => s.maxClass >= 5)) {
const mod = ModuleUtils.findInternal('gfsb', 5, 'H');
ship.use(slots.find(s => s.maxClass >= 5), mod)
} else if (slots.find(s => s.maxClass >= 4)) {
const mod = ModuleUtils.findInternal('gfsb', 4, 'H');
ship.use(slots.find(s => s.maxClass >= 4), mod)
} else if (slots.find(s => s.maxClass >= 3)) {
const mod = ModuleUtils.findInternal('gfsb', 3, 'H');
ship.use(slots.find(s => s.maxClass >= 3), mod)
} else if (slots.find(s => s.maxClass >= 2)) {
const mod = ModuleUtils.findInternal('gfsb', 2, 'H');
ship.use(slots.find(s => s.maxClass >= 2), mod)
} else if (slots.find(s => s.maxClass >= 1)) {
const mod = ModuleUtils.findInternal('gfsb', 1, 'H');
ship.use(slots.find(s => s.maxClass >= 1), mod)
}
}
// const pp = ship.getAvailableModules().lightestPowerPlant(Math.max(ship.powerRetracted, ship.powerDeployed), 'A');
// const t = ship.getAvailableModules().lightestThruster(ship.ladenMass);
// ship.use(ship.standard[0], pp);
// ship.use(ship.standard[1], t);
// ship.useLightestStandard(standardOpts);
ship.updatePowerGenerated()
.updatePowerUsed()
.recalculateMass()
.updateJumpStats()
.recalculateShield()
.recalculateShieldCells()
.recalculateArmour()
.recalculateDps()
.recalculateEps()
.recalculateHps()
.updateMovement()
.updateModificationsString();
}
/** /**
* Trader Role * Trader Role
* @param {Ship} ship Ship instance * @param {Ship} ship Ship instance
@@ -36,7 +609,7 @@ export function trader(ship, shielded, standardOpts) {
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 Power Plant
.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
@@ -45,7 +618,7 @@ export function trader(ship, shielded, standardOpts) {
.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) {
@@ -269,7 +842,7 @@ export function miner(ship, shielded) {
// 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) {
@@ -283,7 +856,7 @@ export function miner(ship, shielded) {
// 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
@@ -314,7 +887,7 @@ export function miner(ship, shielded) {
// 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;