Compare commits

...

22 Commits
2.5.2 ... 2.9.0

Author SHA1 Message Date
willyb321
928e02c718 Merge branch 'release/2.9.0' 2018-04-14 16:53:08 +10:00
willyb321
7f494dd200 bump 2018-04-14 16:52:05 +10:00
William
f38e743e59 Merge pull request #244 from EDCD/feature/beyond-coriolis
Engineer mods.
2018-04-14 15:14:13 +10:00
Willyb321
58b55eb3da Engineers. Are. Back. Probably. 2018-04-14 14:50:37 +10:00
willyb321
8375ad95b3 Merge branch 'master' into feature/beyond-coriolis 2018-04-14 10:16:20 +10:00
willyb321
506d027a2d Merge branch 'develop' 2018-04-14 09:52:03 +10:00
willyb321
fbeb6237cf fix webpack 2018-04-14 09:51:46 +10:00
willyb321
bd95e2c5a5 Merge branch 'master' into develop 2018-04-14 09:48:03 +10:00
willyb321
f3276e557a Merge branch 'release/2.5.3' 2018-04-14 09:47:08 +10:00
willyb321
8b813e0e7f bump 2018-04-14 09:46:41 +10:00
willyb321
d660d2959f more roles fixing
use a smaller shield, add boosters, d rate some internals
2018-04-14 09:44:29 +10:00
willyb321
014ebda7d2 start fixing suggested roles. Thanks to rinzler + others 2018-04-14 08:06:44 +10:00
William
607398d364 Merge pull request #241 from Blackth0rn/fix/#240_incorrect_passenger_counts
Fix/#240 incorrect passenger counts
2018-04-13 16:20:52 +10:00
willyb321
97d141ce2b update lockfile version 2018-04-13 16:17:59 +10:00
willyb321
9f492db9c6 source map 2018-04-13 16:16:42 +10:00
willyb321
6ed82b366c update bugsnag 2018-04-13 16:16:01 +10:00
willyb321
a7ca037f48 loadout event prep 2018-04-13 14:38:22 +10:00
willyb321
6e21d0e74a Work on engineering import 2018-04-13 13:39:33 +10:00
willyb321
e6c75bf2af Merge branch 'develop' into feature/beyond-coriolis 2018-04-13 09:16:23 +10:00
Greg Matthews
94037cea38 Fix #240: Added passenger count to individual ship page 2018-04-11 21:09:57 -07:00
Greg Matthews
5c1a9d9eea Fix #240: There is no size 7 passenger cabin so use the new findMaxInternal function to get the biggest one that fits in the slot 2018-04-11 21:07:00 -07:00
Greg Matthews
3835c73ffd Add findMaxInternal function to find the biggest module of a given group, rating, slotsize 2018-04-11 21:06:07 -07:00
13 changed files with 418 additions and 285 deletions

2
package-lock.json generated
View File

@@ -1,6 +1,6 @@
{ {
"name": "coriolis_shipyard", "name": "coriolis_shipyard",
"version": "2.5.1", "version": "2.9.0",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {

View File

@@ -1,6 +1,6 @@
{ {
"name": "coriolis_shipyard", "name": "coriolis_shipyard",
"version": "2.5.2", "version": "2.9.0",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/EDCD/coriolis" "url": "https://github.com/EDCD/coriolis"

View File

@@ -53,6 +53,7 @@ export default class ShipSummaryTable extends TranslatedComponent {
<th rowSpan={2}>{translate('TTD')}</th> <th rowSpan={2}>{translate('TTD')}</th>
{/* <th onMouseEnter={termtip.bind(null, 'heat per second')} onMouseLeave={hide} rowSpan={2}>{translate('HPS')}</th> */} {/* <th onMouseEnter={termtip.bind(null, 'heat per second')} onMouseLeave={hide} rowSpan={2}>{translate('HPS')}</th> */}
<th rowSpan={2}>{translate('cargo')}</th> <th rowSpan={2}>{translate('cargo')}</th>
<th rowSpan={2}>{translate('passengers')}</th>
<th rowSpan={2}>{translate('fuel')}</th> <th rowSpan={2}>{translate('fuel')}</th>
<th colSpan={3}>{translate('mass')}</th> <th colSpan={3}>{translate('mass')}</th>
<th onMouseEnter={termtip.bind(null, 'hull hardness', { cap: 0 })} onMouseLeave={hide} rowSpan={2}>{translate('hrd')}</th> <th onMouseEnter={termtip.bind(null, 'hull hardness', { cap: 0 })} onMouseLeave={hide} rowSpan={2}>{translate('hrd')}</th>
@@ -86,6 +87,7 @@ export default class ShipSummaryTable extends TranslatedComponent {
<td onMouseEnter={termtip.bind(null, 'TT_SUMMARY_TTD', { cap: 0 })} onMouseLeave={hide}>{timeToDrain === Infinity ? '∞' : time(timeToDrain)}</td> <td onMouseEnter={termtip.bind(null, 'TT_SUMMARY_TTD', { cap: 0 })} onMouseLeave={hide}>{timeToDrain === Infinity ? '∞' : time(timeToDrain)}</td>
{/* <td>{f1(ship.totalHps)}</td> */} {/* <td>{f1(ship.totalHps)}</td> */}
<td>{round(ship.cargoCapacity)}{u.T}</td> <td>{round(ship.cargoCapacity)}{u.T}</td>
<td>{ship.passengerCapacity}</td>
<td>{round(ship.fuelCapacity)}{u.T}</td> <td>{round(ship.fuelCapacity)}{u.T}</td>
<td onMouseEnter={termtip.bind(null, 'TT_SUMMARY_HULL_MASS', { cap: 0 })} onMouseLeave={hide}>{ship.hullMass}{u.T}</td> <td onMouseEnter={termtip.bind(null, 'TT_SUMMARY_HULL_MASS', { cap: 0 })} onMouseLeave={hide}>{ship.hullMass}{u.T}</td>
<td onMouseEnter={termtip.bind(null, 'TT_SUMMARY_UNLADEN_MASS', { cap: 0 })} onMouseLeave={hide}>{int(ship.unladenMass)}{u.T}</td> <td onMouseEnter={termtip.bind(null, 'TT_SUMMARY_UNLADEN_MASS', { cap: 0 })} onMouseLeave={hide}>{int(ship.unladenMass)}{u.T}</td>

View File

@@ -235,12 +235,10 @@ export default class StandardSlotSection extends SlotSection {
<ul> <ul>
<li className='lc' onClick={this._multiPurpose.bind(this, false, 0)}>{translate('Multi-purpose')}</li> <li className='lc' onClick={this._multiPurpose.bind(this, false, 0)}>{translate('Multi-purpose')}</li>
<li className='lc' onClick={this._multiPurpose.bind(this, true, 2)}>{translate('Combat')}</li> <li className='lc' onClick={this._multiPurpose.bind(this, true, 2)}>{translate('Combat')}</li>
<li className='lc' onClick={this._optimizeCargo.bind(this, false)}>{translate('Trader')}</li> <li className='lc' onClick={this._optimizeCargo.bind(this, true)}>{translate('Trader')}</li>
<li className='lc' onClick={this._optimizeCargo.bind(this, true)}>{translate('Shielded Trader')}</li>
<li className='lc' onClick={this._optimizeExplorer.bind(this, false)}>{translate('Explorer')}</li> <li className='lc' onClick={this._optimizeExplorer.bind(this, false)}>{translate('Explorer')}</li>
<li className={cn('lc', { disabled: planetaryDisabled })} onClick={!planetaryDisabled && this._optimizeExplorer.bind(this, true)}>{translate('Planetary Explorer')}</li> <li className={cn('lc', { disabled: planetaryDisabled })} onClick={!planetaryDisabled && this._optimizeExplorer.bind(this, true)}>{translate('Planetary Explorer')}</li>
<li className='lc' onClick={this._optimizeMiner.bind(this, false)}>{translate('Miner')}</li> <li className='lc' onClick={this._optimizeMiner.bind(this, true)}>{translate('Miner')}</li>
<li className='lc' onClick={this._optimizeMiner.bind(this, true)}>{translate('Shielded Miner')}</li>
<li className='lc' onClick={this._optimizeRacer.bind(this)}>{translate('Racer')}</li> <li className='lc' onClick={this._optimizeRacer.bind(this)}>{translate('Racer')}</li>
</ul> </ul>
</div>; </div>;

View File

@@ -42,7 +42,7 @@ function countInt(slot) {
passSlotType = 'pcq'; passSlotType = 'pcq';
passSlotRating = 'B'; passSlotRating = 'B';
} }
let passengerBay = passSlotType ? ModuleUtils.findInternal(passSlotType, slot.maxClass, passSlotRating) : null; let passengerBay = passSlotType ? ModuleUtils.findMaxInternal(passSlotType, slot.maxClass, passSlotRating) : null;
this.maxPassengers += passengerBay ? passengerBay.passengers : 0; this.maxPassengers += passengerBay ? passengerBay.passengers : 0;
} }

View File

@@ -64,10 +64,29 @@ export default class Module {
} }
} }
} }
// Sanitise the resultant value to 4dp equivalent // Sanitise the resultant value to 4dp equivalent
return isNaN(result) ? result : Math.round(result); return isNaN(result) ? result : Math.round(result);
} }
/**
* Set a value for a given modification ID
* @param {Number} name The name of the modification
* @param {object} value The value of the modification. If it is a numeric value then it should be an integer scaled so that -2.34% == -234
*/
setModValueFromJournal(name, value, origVal) {
if (!this.mods) {
this.mods = {};
}
if (!this.origVals) {
this.origVals = {};
}
if (value == null || value == 0) {
delete this.mods[name];
} else {
this.mods[name] = value;
this.origVals[name] = origVal;
}
}
/** /**
* Set a value for a given modification ID * Set a value for a given modification ID
@@ -79,6 +98,9 @@ export default class Module {
if (!this.mods) { if (!this.mods) {
this.mods = {}; this.mods = {};
} }
if (!this.origVals) {
this.origVals = {};
}
if (valueiswithspecial && this.blueprint && this.blueprint.special) { if (valueiswithspecial && this.blueprint && this.blueprint.special) {
// This module has a special effect, see if we need to alter the stored value // This module has a special effect, see if we need to alter the stored value
const modifierActions = Modifications.modifierActions[this.blueprint.special.edname]; const modifierActions = Modifications.modifierActions[this.blueprint.special.edname];
@@ -117,7 +139,7 @@ export default class Module {
_getModifiedValue(name) { _getModifiedValue(name) {
const modification = Modifications.modifications[name]; const modification = Modifications.modifications[name];
let result = this[name]; let result = this[name];
// console.log(`${name} = ${this[name]}`)
if (!result) { if (!result) {
if (modification && modification.method === 'additive') { if (modification && modification.method === 'additive') {
// Additive modifications start at 0 rather than NULL // Additive modifications start at 0 rather than NULL

View File

@@ -195,6 +195,29 @@ export function findInternal(groupName, clss, rating, name) {
return null; return null;
} }
/**
* Finds an internal module based on Class, Rating, Group and/or name.
* At least one of Group name or unique module name must be provided.
* will start searching at specified class and proceed lower until a
* module is found or 0 is hit
* Uses findInternal internally
*
* @param {String} groupName [Optional] Full name or abbreviated name for module group
* @param {integer} clss module Class
* @param {String} rating module Rating
* @param {String} name [Optional] Long/unique name for module -e.g. 'Advanced Discover Scanner'
* @return {Object} The module if found, null if not found
*/
export function findMaxInternal(groupName, clss, rating, name) {
let foundModule = null;
let currentClss = clss;
while (currentClss > 0 && foundModule == null) {
foundModule = findInternal(groupName, currentClss, rating, name);
currentClss = currentClss - 1;
}
return foundModule;
}
/** /**
* Finds an internal Module ID based on Class, Rating, Group and/or name. * Finds an internal Module ID based on Class, Rating, Group and/or name.
* At least one ofGroup name or unique module name must be provided * At least one ofGroup name or unique module name must be provided

View File

@@ -490,7 +490,6 @@ export default class Ship {
// Value passed is invalid; reset it to 0 // Value passed is invalid; reset it to 0
value = 0; value = 0;
} }
// Handle special cases // Handle special cases
if (name === 'pgen') { if (name === 'pgen') {
// Power generation // Power generation
@@ -569,6 +568,7 @@ export default class Ship {
// Reset Cumulative stats // Reset Cumulative stats
this.fuelCapacity = 0; this.fuelCapacity = 0;
this.cargoCapacity = 0; this.cargoCapacity = 0;
this.passengerCapacity = 0;
this.ladenMass = 0; this.ladenMass = 0;
this.armour = this.baseArmour; this.armour = this.baseArmour;
this.shield = this.baseShieldStrength; this.shield = this.baseShieldStrength;
@@ -1188,6 +1188,7 @@ export default class Ship {
let unladenMass = this.hullMass; let unladenMass = this.hullMass;
let cargoCapacity = 0; let cargoCapacity = 0;
let fuelCapacity = 0; let fuelCapacity = 0;
let passengerCapacity = 0;
unladenMass += this.bulkheads.m.getMass(); unladenMass += this.bulkheads.m.getMass();
@@ -1209,6 +1210,8 @@ export default class Ship {
fuelCapacity += slot.m.fuel; fuelCapacity += slot.m.fuel;
} else if (slot.m.grp === 'cr') { } else if (slot.m.grp === 'cr') {
cargoCapacity += slot.m.cargo; cargoCapacity += slot.m.cargo;
} else if (slot.m.grp.slice(0,2) === 'pc') {
passengerCapacity += slot.m.passengers
} }
} }
} }
@@ -1224,6 +1227,7 @@ export default class Ship {
this.unladenMass = unladenMass; this.unladenMass = unladenMass;
this.cargoCapacity = cargoCapacity; this.cargoCapacity = cargoCapacity;
this.fuelCapacity = fuelCapacity; this.fuelCapacity = fuelCapacity;
this.passengerCapacity = passengerCapacity;
this.ladenMass = unladenMass + fuelCapacity + cargoCapacity; this.ladenMass = unladenMass + fuelCapacity + cargoCapacity;
return this; return this;

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)
@@ -11,16 +11,16 @@ 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
} }
}); })
} }
} }
@@ -31,39 +31,54 @@ export function multiPurpose(ship, shielded, bulkheadIndex) {
* @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 = []
sg = ship.getAvailableModules().lightestShieldGenerator(ship.hullMass); let bstCount = 2
let sg = ship.getAvailableModules().lightestShieldGenerator(ship.hullMass)
ship.useStandard('A')
.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[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
// Shield generator if required const shieldOrder = [1, 2, 3, 4, 5, 6, 7, 8]
if (shielded) {
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++) { shieldInternals.some(function (slot) {
if (canMount(ship, shieldInternals[i], 'sg')) { if (canMount(ship, slot, 'sg')) { // Assuming largest slot can hold an eligible shield
ship.use(shieldInternals[i], sg); const shield = ModuleUtils.findInternal('sg', slot.maxClass, 'A')
usedSlots.push(shieldInternals[i]); if (shield && shield.maxmass > ship.hullMass) {
break; console.log(shield)
} ship.use(slot, shield)
ship.setSlotEnabled(slot, true)
usedSlots.push(slot)
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) {
ship.useLightestStandard(standardOpts); if (s.maxClass == 0 && bstCount) { // Mount up to 2 boosters
ship.use(s, ModuleUtils.hardpoints('04'))
bstCount--
} else {
ship.use(s, null)
}
}
// ship.useLightestStandard(standardOpts);
} }
/** /**
@@ -77,121 +92,121 @@ export function explorer(ship, planetary) {
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)
} }
/** /**
@@ -200,99 +215,100 @@ export function explorer(ship, planetary) {
* @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
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
} }
} }
} }
@@ -300,19 +316,19 @@ 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
// 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)
} }
/** /**
@@ -323,63 +339,63 @@ 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

@@ -225,7 +225,13 @@ 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 blueprint = JSON.parse(JSON.stringify(Modifications.blueprints[name])); 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)];
if (!found || !found.fdname) {
return undefined;
}
const blueprint = JSON.parse(JSON.stringify(found));
console.log(blueprint)
if (module) { if (module) {
if (module.grp === 'bh' || module.grp === 'hr' || module.grp === 'sg' || module.grp === 'psg' || module.grp === 'bsg') { if (module.grp === 'bh' || module.grp === 'hr' || module.grp === 'sg' || module.grp === 'psg' || module.grp === 'bsg') {
// Bulkheads, hull reinforcements and shield generators need to have their resistances altered by the base values // Bulkheads, hull reinforcements and shield generators need to have their resistances altered by the base values

View File

@@ -106,7 +106,7 @@ function _moduleFromEdId(edId) {
* @return {string} the Coriolis model of the ship * @return {string} the Coriolis model of the ship
*/ */
function _shipModelFromEDName(edName) { function _shipModelFromEDName(edName) {
return SHIP_FD_NAME_TO_CORIOLIS_NAME[edName]; return SHIP_FD_NAME_TO_CORIOLIS_NAME[Object.keys(SHIP_FD_NAME_TO_CORIOLIS_NAME).find(elem => elem.toLowerCase() === edName.toLowerCase())];
} }
/** /**

View File

@@ -2,7 +2,9 @@ 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 { getBlueprint } from './BlueprintFunctions'
/** /**
* Obtain a module given its FD Name * Obtain a module given its FD Name
@@ -10,15 +12,15 @@ import { Modules } from '../../../../coriolis-data/dist'
* @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]})
} }
} }
} }
@@ -30,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]})
} }
} }
} }
@@ -42,7 +44,7 @@ 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]})
} }
} }
} }
@@ -50,8 +52,9 @@ function _moduleFromFdName(fdname) {
console.log(fdname) console.log(fdname)
// Not found // Not found
return null; return null
} }
/** /**
* Build a ship from the journal Loadout event JSON * Build a ship from the journal Loadout event JSON
* @param {object} json the Loadout event JSON * @param {object} json the Loadout event JSON
@@ -59,138 +62,147 @@ function _moduleFromFdName(fdname) {
*/ */
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.
for (const module of json.Modules) { for (const module of json.Modules) {
if (!module.Engineering) module.Engineering = {};
switch (module.Slot) { switch (module.Slot) {
// 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.endsWith('_Armour_Grade1')) { if (module.Item.toLowerCase().endsWith('_armour_grade1')) {
ship.useBulkhead(0, true); ship.useBulkhead(0, true)
} else if (module.Item.endsWith('_Armour_Grade2')) { } else if (module.Item.toLowerCase().endsWith('_armour_grade2')) {
ship.useBulkhead(1, true); ship.useBulkhead(1, true)
} else if (module.Item.endsWith('_Armour_Grade3')) { } else if (module.Item.toLowerCase().endsWith('_armour_grade3')) {
ship.useBulkhead(2, true); ship.useBulkhead(2, true)
} else if (module.Item.endsWith('_Armour_Mirrored')) { } else if (module.Item.toLowerCase().endsWith('_armour_mirrored')) {
ship.useBulkhead(3, true); ship.useBulkhead(3, true)
} else if (module.Item.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
break; _addModifications(ship.bulkheads.m, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level)
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
break; _addModifications(powerplant, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level)
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
break; _addModifications(thrusters, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level)
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
break; _addModifications(frameshiftdrive, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level)
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
break; _addModifications(lifesupport, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level)
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
break; _addModifications(powerdistributor, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level)
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
break; _addModifications(sensors, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level)
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:
} }
if (module.Slot.search(/Hardpoint/) !== -1) { if (module.Slot.search(/Hardpoint/) !== -1) {
// Add hardpoints // Add hardpoints
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 === hardpointName); const hardpointSlot = json.Modules.find(elem => elem.Slot === hardpointName)
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 {
const hardpoint = _moduleFromFdName(hardpointSlot.Item); const 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
_addModifications(hardpoint, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level)
} }
hardpointArrayNum++; hardpointArrayNum++
} }
} }
if (module.Slot.search(/Slot\d/) !== -1) { if (module.Slot.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 === internalName); internalSlot = json.Modules.find(elem => elem.Slot === internalName)
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 === internalName)) { if (json.Modules.find(elem => elem.Slot === internalName)) {
internalSlot = json.Modules.find(elem => elem.Slot === internalName); internalSlot = json.Modules.find(elem => elem.Slot === internalName)
break; break
} }
} }
internalSlotNum++; internalSlotNum++
} }
} }
@@ -199,11 +211,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
_addModifications(internal, module.Engineering.Modifiers, module.Engineering.BlueprintName, module.Engineering.Level)
} }
} }
} }
@@ -211,11 +224,60 @@ export function shipFromLoadoutJSON(json) {
} }
// 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()
}
/**
* Add the modifications for a module
* @param {Module} module the module
* @param {Object} modifiers the modifiers
* @param {Object} blueprint the blueprint of the modification
* @param {Object} grade the grade of the modification
* @param {Object} specialModifications special modification
*/
function _addModifications (module, modifiers, blueprint, grade, specialModifications) {
if (!modifiers) return
let special
if (specialModifications) {
special = Modifications.specials[Object.keys(specialModifications)[0]]
}
for (const i in modifiers) {
// Some special modifications
// Look up the modifiers to find what we need to do
const findMod = val => Object.keys(Modifications.modifierActions).find(elem => elem.toString().toLowerCase().search(val.toString().toLowerCase().replace(/(OutfittingFieldType_|persecond)/igm, '')) >= 0)
const modifierActions = Modifications.modifierActions[findMod(modifiers[i].Label)]
console.log(`${modifiers[i].Label}: ${findMod(modifiers[i].Label)}`)
//TODO: Figure out how to scale this value.
if (!!modifiers[i].LessIsGood) {
}
let value = modifiers[i].Value / modifiers[i].OriginalValue * 100 - 100;
// Carry out the required changes
for (const action in modifierActions) {
if (isNaN(modifierActions[action])) {
module.setModValue(action, modifierActions[action])
} else {
const actionValue = modifierActions[action] * value
module.setModValue(action, value * 100)
}
}
}
// Add the blueprint definition, grade and special
if (blueprint) {
console.log(blueprint);
module.blueprint = getBlueprint(blueprint, module)
if (grade) {
module.blueprint.grade = Number(grade)
}
if (special) {
module.blueprint.special = special
}
}
} }

View File

@@ -57,7 +57,7 @@
<!-- Bugsnag --> <!-- Bugsnag -->
<script <script
src="//d2wy8f7a9ursnm.cloudfront.net/bugsnag-3.min.js" src="//d2wy8f7a9ursnm.cloudfront.net/bugsnag-3.min.js"
data-apikey="2382691c622937f28f8fa82a1bfd797a"></script> data-apikey="ba9fae819372850fb660755341fa6ef5"></script>
</head> </head>
<body style="background-color:#000;"> <body style="background-color:#000;">