Fix for engineered modules in SLEF imports from Inara. Restored the deleted code.

This commit is contained in:
Alexey Gorb
2021-09-06 23:46:55 +02:00
parent 45f1dd2da9
commit 88c9bb0254

View File

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