diff --git a/__tests__/fixtures/courier-test-detailed-export-v4.json b/__tests__/fixtures/courier-test-detailed-export-v4.json new file mode 100644 index 00000000..26e8540d --- /dev/null +++ b/__tests__/fixtures/courier-test-detailed-export-v4.json @@ -0,0 +1,327 @@ +{ + "$schema": "http://cdn.coriolis.io/schemas/ship-loadout/4.json#", + "name": "Multi-purpose Imperial Courier", + "ship": "Imperial Courier", + "references": [ + { + "name": "Coriolis.io", + "url": "https://coriolis.edcd.io/outfit/imperial_courier?code=0patzF5l0das8f31a1a270202000e402t0101-2f.AwRj4zKA.CwRgDBldLiQ%3D.H4sIAAAAAAAAA12OP0tCYRjFj9fuVbvF1du9ekkT8s%2FkIg4NElyIBBd321yaGvwUQTS3N7UFfYygIT9EoyQUJA36ns47XJCWA%2B%2Fz%2Bz3Pe3ImBbDNKaqNPSBoGrL4ngfomKpFGiJ%2BLgHteR1IPjxJT5pF11uSeXNsJVcRfgdC92syWUuK0iMdKZqrjJ%2F0aoA71lJ5oKf38knWcCiptCPdhJIerdS00vlK0qktlqoj983UmqqHjQ33VsW8eazFmaTyULP2hQ4lX8LBme6g%2F6v0TTdbxJ2KhdEIaCw15MF%2FNB0L%2BS2hwEwyFM8KgP%2BqEpWWA3Qu9Z3z9kPWHzakt7Dt%2BAeD7ghSTgEAAA%3D%3D&bn=Multi-purpose%20Imperial%20Courier", + "code": "0patzF5l0das8f31a1a270202000e402t0101-2f.AwRj4zKA.CwRgDBldLiQ=.H4sIAAAAAAAAA12OP0tCYRjFj9fuVbvF1du9ekkT8s/kIg4NElyIBBd321yaGvwUQTS3N7UFfYygIT9EoyQUJA36ns47XJCWA+/z+z3Pe3ImBbDNKaqNPSBoGrL4ngfomKpFGiJ+LgHteR1IPjxJT5pF11uSeXNsJVcRfgdC92syWUuK0iMdKZqrjJ/0aoA71lJ5oKf38knWcCiptCPdhJIerdS00vlK0qktlqoj983UmqqHjQ33VsW8eazFmaTyULP2hQ4lX8LBme6g/6v0TTdbxJ2KhdEIaCw15MF/NB0L+S2hwEwyFM8KgP+qEpWWA3Qu9Z3z9kPWHzakt7Dt+AeD7ghSTgEAAA==", + "shipId": "imperial_courier" + } + ], + "components": { + "standard": { + "bulkheads": "Lightweight Alloy", + "cargoHatch": { + "enabled": false, + "priority": 5 + }, + "powerPlant": { + "class": 4, + "rating": "A", + "enabled": true, + "priority": 2, + "modifications": { + "pgen": 1052, + "integrity": -482, + "eff": 974 + }, + "blueprint": { + "id": 63, + "name": "Overcharged", + "grade": 1 + } + }, + "thrusters": { + "class": 3, + "rating": "A", + "enabled": true, + "priority": 1, + "name": "Enhanced Performance", + "modifications": { + "optmul": 2476, + "thermload": 7023, + "power": 1763, + "integrity": 165, + "optmass": -667 + }, + "blueprint": { + "id": 22, + "name": "Dirty", + "grade": 4 + } + }, + "frameShiftDrive": { + "class": 3, + "rating": "A", + "enabled": true, + "priority": 1, + "modifications": { + "mass": 4082, + "integrity": -2422, + "power": 1782, + "optmass": 4927 + }, + "blueprint": { + "id": 26, + "name": "Increased range", + "grade": 5 + } + }, + "lifeSupport": { + "class": 1, + "rating": "A", + "enabled": true, + "priority": 1 + }, + "powerDistributor": { + "class": 3, + "rating": "A", + "enabled": true, + "priority": 1 + }, + "sensors": { + "class": 2, + "rating": "D", + "enabled": true, + "priority": 1 + }, + "fuelTank": { + "class": 3, + "rating": "C", + "enabled": true, + "priority": 1 + } + }, + "hardpoints": [ + { + "class": 2, + "rating": "F", + "enabled": true, + "priority": 1, + "group": "Pulse Laser", + "mount": "Fixed", + "modifications": { + "rof": 5931, + "damage": -184, + "jitter": 50, + "distdraw": -4689, + "piercing": 3328 + }, + "blueprint": { + "id": 89, + "name": "Rapid fire", + "grade": 5 + } + }, + { + "class": 2, + "rating": "F", + "enabled": true, + "priority": 1, + "group": "Pulse Laser", + "mount": "Fixed", + "modifications": { + "rof": 4715, + "damage": -97, + "jitter": 30, + "distdraw": -4548, + "piercing": 1057, + "integrity": 319 + }, + "blueprint": { + "id": 89, + "name": "Rapid fire", + "grade": 5 + } + }, + { + "class": 2, + "rating": "F", + "enabled": true, + "priority": 1, + "group": "Multi-cannon", + "mount": "Gimballed", + "modifications": { + "damage": 2437, + "distdraw": 5487, + "rof": 1120, + "jitter": 58, + "thermload": 1346, + "power": 1009, + "integrity": -202, + "ammo": -2000 + }, + "blueprint": { + "id": 88, + "name": "Overcharged", + "grade": 3, + "special": { + "id": 3, + "name": "Corrosive shell" + } + } + } + ], + "utility": [ + { + "class": 0, + "rating": "I", + "enabled": true, + "priority": 1, + "group": "Heat Sink Launcher", + "name": "Heat Sink Launcher", + "modifications": { + "ammo": 5000, + "mass": 17684, + "reload": 9707 + }, + "blueprint": { + "id": 37, + "name": "Ammo capacity", + "grade": 3 + } + }, + { + "class": 0, + "rating": "I", + "enabled": true, + "priority": 1, + "group": "Heat Sink Launcher", + "name": "Heat Sink Launcher", + "modifications": { + "ammo": 5000, + "mass": 18520, + "reload": 8715 + }, + "blueprint": { + "id": 37, + "name": "Ammo capacity", + "grade": 3 + } + }, + { + "class": 0, + "rating": "I", + "enabled": true, + "priority": 1, + "group": "Chaff Launcher", + "name": "Chaff Launcher" + }, + { + "class": 0, + "rating": "A", + "enabled": true, + "priority": 1, + "group": "Frame Shift Wake Scanner" + } + ], + "internal": [ + { + "class": 3, + "rating": "A", + "enabled": true, + "priority": 1, + "group": "Shield Generator", + "modifications": { + "optmul": 1888, + "explres": 455, + "kinres": 546, + "thermres": 1092, + "brokenregen": -2614, + "regen": -876, + "distdraw": 463 + }, + "blueprint": { + "id": 77, + "name": "Reinforced", + "grade": 3 + } + }, + { + "class": 3, + "rating": "A", + "enabled": true, + "priority": 1, + "group": "Fuel Scoop" + }, + { + "class": 2, + "rating": "E", + "enabled": true, + "priority": 2, + "group": "Cargo Rack" + }, + { + "class": 2, + "rating": "E", + "enabled": true, + "priority": 2, + "group": "Cargo Rack" + }, + null, + { + "class": 1, + "rating": "C", + "enabled": true, + "priority": 2, + "group": "Scanner", + "name": "Advanced Discovery Scanner" + } + ] + }, + "stats": { + "class": 1, + "hullCost": 2481550, + "speed": 280, + "boost": 380, + "boostEnergy": 10, + "agility": 6, + "baseShieldStrength": 200, + "baseArmour": 80, + "hullMass": 35, + "masslock": 7, + "pipSpeed": 0.05, + "moduleCostMultiplier": 1, + "fuelCapacity": 8, + "cargoCapacity": 8, + "ladenMass": 104.25, + "armour": 144, + "shield": 404.19, + "shieldCells": 0, + "totalCost": 14059860, + "unladenMass": 88.25, + "totalDpe": 32.25, + "totalExplDpe": 0, + "totalKinDpe": 9.41, + "totalThermDpe": 22.84, + "totalDps": 53.8, + "totalExplDps": 0, + "totalKinDps": 17.44, + "totalThermDps": 36.35, + "totalSDps": 48.99, + "totalExplSDps": 0, + "totalKinSDps": 12.64, + "totalThermSDps": 36.35, + "totalEps": 9.84, + "totalHps": 12.28, + "shieldExplRes": 0.48, + "shieldKinRes": 0.55, + "shieldThermRes": 1.09, + "hullExplRes": 1.4, + "hullKinRes": 1.2, + "hullThermRes": 1, + "powerAvailable": 17.24, + "powerRetracted": 11.3, + "powerDeployed": 16.41, + "unladenRange": 25.57, + "fullTankRange": 23.92, + "ladenRange": 22.09, + "unladenFastestRange": 116.23, + "ladenFastestRange": 107, + "maxJumpCount": 5, + "topSpeed": 386.56, + "topBoost": 524.62 + } +} diff --git a/__tests__/test-import.js b/__tests__/test-import.js index 31dd0dcf..dbfd0bfd 100644 --- a/__tests__/test-import.js +++ b/__tests__/test-import.js @@ -186,6 +186,18 @@ describe('Import Modal', function() { expect(MockRouter.go.mock.calls.length).toBe(1); expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/asp?code=0pftiFflfddsnf5------020202033c044002v62f2i.AwRj4yvI.CwRgDBldHnJA.H4sIAAAAAAAAA2P858DAwPCXEUhwHPvx%2F78YG5AltB7I%2F8%2F0TwImJboDSPJ%2F%2B%2Ff%2Fv%2FKlX%2F%2F%2Fi3AwMTBIfARK%2FGf%2BJwVSxArStVAYqOjvz%2F%2F%2FJVo5GRhE2IBc4SKQSSz%2FDGEmCa398P8%2F%2F2%2BgTf%2F%2FAwDFxwtofAAAAA%3D%3D&bn=Multi-purpose%20Asp%20Explorer'); }); + + it('imports a valid v4 build with modifications', function() { + const importData = require('./fixtures/courier-test-detailed-export-v4'); + pasteText(JSON.stringify(importData)); + + expect(modal.state.importValid).toBeTruthy(); + expect(modal.state.errorMsg).toEqual(null); + expect(modal.state.singleBuild).toBe(true); + clickProceed(); + expect(MockRouter.go.mock.calls.length).toBe(1); + expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/imperial_courier?code=0patzF5l0das8f31a1a270202000e402t0101-2f.AwRj4zKA.CwRgDBldLiQ%3D.H4sIAAAAAAAAA12OP0tCYRjFj9fuVbvF1du9ekkT8s%2FkIg4NElyIBBd321yaGvwUQTS3N7UFfYygIT9EoyQUJA36ns47XJCWA%2B%2Fz%2Bz3Pe3ImBbDNKaqNPSBoGrL4ngfomKpFGiJ%2BLgHteR1IPjxJT5pF11uSeXNsJVcRfgdC92syWUuK0iMdKZqrjJ%2F0aoA71lJ5oKf38knWcCiptCPdhJIerdS00vlK0qktlqoj983UmqqHjQ33VsW8eazFmaTyULP2hQ4lX8LBme6g%2F6v0TTdbxJ2KhdEIaCw15MF%2FNB0L%2BS2hwEwyFM8KgP%2BqEpWWA3Qu9Z3z9kPWHzakt7Dt%2BAeD7ghSTgEAAA%3D%3D&bn=Multi-purpose%20Imperial%20Courier'); + }); }); describe('Import Detaild Builds Array', function() { @@ -226,7 +238,7 @@ describe('Import Modal', function() { expect(modal.state.singleBuild).toBe(true); clickProceed(); expect(MockRouter.go.mock.calls.length).toBe(1); - expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/federal_corvette?code=2putsFklndzsxf50x0x7l28281919040404040402020l06p05sf63c5ifrv66g2f.AwRj4zNaKA%3D%3D.CwRgDBldUExuBiQqA%3D%3D%3D.H4sIAAAAAAAAA02SPy8EURTF7%2ByambVPvN0xmF3%2Fhh0bGpItUEiUbEInoSAqqo0PoFBINLTiE0goSIQoRLfNVooVGhE%2BgkIi4s%2B7zpWMTHNy3zu%2Fe%2Ba9uc8yM0T0Y0G6HJtInzJzZh1LTpkusdKQzoZDVPJ8ouAiBaj%2Fi9kfN8zePmxOm6KQaCfv0IO%2F%2Bckc%2BK1Efg09bJvpOGnYVUTlG5SDDUBDGwhpPf5mzj5iqSeQzhmzFJ%2BpsOUS2c13ZqeKHu8Im8ECcM6a5TjTruFLjh8Q9Z2jPzeFvVJthaj7CeBIGIaLrBJ4PQt8uwf4aUuMf8DR1zgMtyXIvb9gIetCTgp5hkpX5Kq4GgVVnIi1mY1PHMxB1APKvEgkovckOJeAvqDqUiCRSETfCZRPQG8C3QokEonodjADOxl800uQz7i2uheSUEVS6V2J60hAY7iSeoKfF4lEtALDgVn4H%2FQqotWJJElT9InNVOmDuecAcc4LEH8dP4ALphoHh%2B94De4o%2FPIDllZDZtib8K8wL7cpfhprqyJPZsD0xX5xTSZLkGAeT6jtVcbLv3JM%2BlSZAgAA&bn=Imported%20Federal%20Corvette'); + expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/federal_corvette?code=2putsFklndzsxf50x0x7l28281919040404040402020l06p05sf63c5ifrv66g2f.AwRj4zNaKA%3D%3D.CwRgDBldUExuBiQqA%3D%3D%3D.H4sIAAAAAAAAA02Svy9DURTHT1vvtfoat30eXlvV0ufXQmLAIDHSRDcJAzHV1PgDDAaJpVbxF0gYKhFiEFuXTgbCIsKfYJCItHWP75E83vLNue%2F7Od977zs3pBeJ6DsE6TcNIlVn5lgFSw7rfrEikL6mSVS0HSL3MgxoqM3sTGtm%2BxA2R3RGSLSTfWzD32kxu043kVNFDxt6wU8ajVpEY7coh5uARrYR0n3aYY4%2FY6lmkc4xveafqZOHpHejRMb9J7NZQqN9Ascto4fjet0P7iQgRhV7mo5LlLtAUnIe34rVDaKBF9AThUJhla3%2FHqMRB76XBV7v8vEvOOoGx%2BJEgKz9BgvZEHJOyHNUakYujUuSW8KxWOkl%2F%2BzuMsR6QpkS8URUTYKTAagNta4EEvFE1INAqQD0IdCdQCKeiOoBk9%2BPYU87QL7i2tajkITKk0odSFxvAJrClawX%2BCkRT0RZYNjV5b%2BRbyLaOpMkafJa%2BBgufjFnjxBnvgFxKvgBnNYlP7jwiXcRnYQ%2F%2FoRlqCnTHAz41xha9F78CNahGXk8eZ3z%2FcyWjJcg7goeU%2BJdZsw%2FFW2pAaMCAAA%3D&bn=Imported%20Federal%20Corvette'); }); it('imports a valid v4 build', function() { diff --git a/src/app/components/HardpointSlot.jsx b/src/app/components/HardpointSlot.jsx index b2c32edf..57f38bbb 100644 --- a/src/app/components/HardpointSlot.jsx +++ b/src/app/components/HardpointSlot.jsx @@ -48,6 +48,9 @@ export default class HardpointSlot extends Slot { let modTT = translate('modified'); if (m && m.blueprint) { modTT = translate(m.blueprint.name) + ' ' + translate('grade') + ' ' + m.blueprint.grade; + if (m.blueprint.special && m.blueprint.special.id) { + modTT += ', ' + translate(m.blueprint.special.name); + } } return
diff --git a/src/app/shipyard/ModuleUtils.js b/src/app/shipyard/ModuleUtils.js index 4949fd85..5a90a160 100755 --- a/src/app/shipyard/ModuleUtils.js +++ b/src/app/shipyard/ModuleUtils.js @@ -105,6 +105,59 @@ export function internal(id) { return null; }; +/** + * Finds a standard module based on Class, Rating, Group and/or name. + * At least one of Group name or unique module name must be provided + * + * @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 findStandard(groupName, clss, rating, name) { + let groups = {}; + + if (groupName) { + if (Modules.standard[groupName]) { + groups[groupName] = Modules.standard[groupName]; + } else { + let grpCode = ModuleNameToGroup[groupName.toLowerCase()]; + if (grpCode && Modules.standard[grpCode]) { + groups[grpCode] = Modules.standard[grpCode]; + } + } + } else if (name) { + groups = Modules.standard; + } + + for (let g in groups) { + let group = groups[g]; + for (let i = 0, l = group.length; i < l; i++) { + if (group[i].class == clss && group[i].rating == rating && ((!name && !group[i].name) || group[i].name == name)) { + return group[i]; + } + } + } + + return null; +} + +/** + * Finds a standard Module ID based on Class, Rating, Group and/or name. + * At least one of Group name or unique module name must be provided + * + * @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 {String} The id of the module if found, null if not found + */ +export function findStandardId(groupName, clss, rating, name) { + let i = this.findStandard(groupName, clss, rating, name); + return i ? i.id : 0; +} + /** * Finds an internal module based on Class, Rating, Group and/or name. * At least one ofGroup name or unique module name must be provided diff --git a/src/app/shipyard/Serializer.js b/src/app/shipyard/Serializer.js index 6aeefe0d..6732049c 100644 --- a/src/app/shipyard/Serializer.js +++ b/src/app/shipyard/Serializer.js @@ -8,6 +8,8 @@ import { outfitURL } from '../utils/UrlGenerators'; const STANDARD = ['powerPlant', 'thrusters', 'frameShiftDrive', 'lifeSupport', 'powerDistributor', 'sensors', 'fuelTank']; +const STANDARD_GROUPS = {'powerPlant': 'pp', 'thrusters': 't', 'frameShiftDrive': 'fsd', 'lifeSupport': 'ls', 'powerDistributor': 'pd', 'sensors': 's', 'fuelTank': 'ft'}; + /** * Generates ship-loadout JSON Schema standard object * @param {Object} standard model @@ -159,13 +161,12 @@ export function fromDetailedBuild(detailedBuild) { enabled.push(stn[c].enabled === undefined ? true : stn[c].enabled); modifications.push(stn[c].modifications); blueprints.push(stn[c].blueprint); - return stn[c].class + stn[c].rating; + return ModuleUtils.findStandardId(STANDARD_GROUPS[c], stn[c].class, stn[c].rating, stn[c].name); }); let internal = comps.internal.map(c => c ? ModuleUtils.findInternalId(c.group, c.class, c.rating, c.name) : 0); - let hardpoints = comps.hardpoints - .map(c => c ? ModuleUtils.findHardpointId(c.group, c.class, c.rating, c.name, MountMap[c.mount], c.missile) : 0) + let hardpoints = comps.hardpoints.map(c => c ? ModuleUtils.findHardpointId(c.group, c.class, c.rating, c.name, MountMap[c.mount], c.missile) : 0) .concat(comps.utility.map(c => c ? ModuleUtils.findHardpointId(c.group, c.class, c.rating, c.name, MountMap[c.mount]) : 0)); // The ordering of these arrays must match the order in which they are read in Ship.buildWith @@ -180,14 +181,14 @@ export function fromDetailedBuild(detailedBuild) { comps.internal.map(c => (!c || c.enabled === undefined) ? true : c.enabled * 1) ); modifications = modifications.concat( - comps.hardpoints.map(c => (c && c.m ? c.m.modifications : null)), - comps.utility.map(c => (c && c.m ? c.m.modifications : null)), - comps.internal.map(c => (c && c.m ? c.m.modifications : null)) + comps.hardpoints.map(c => (c ? c.modifications : null)), + comps.utility.map(c => (c ? c.modifications : null)), + comps.internal.map(c => (c ? c.modifications : null)) ); blueprints = blueprints.concat( - comps.hardpoints.map(c => (c && c.m ? c.m.blueprint : null)), - comps.utility.map(c => (c && c.m ? c.m.blueprint : null)), - comps.internal.map(c => (c && c.m ? c.m.blueprint : null)) + comps.hardpoints.map(c => (c ? c.blueprint : null)), + comps.utility.map(c => (c ? c.blueprint : null)), + comps.internal.map(c => (c ? c.blueprint : null)) ); ship.buildWith({ bulkheads, standard, hardpoints, internal }, priorities, enabled, modifications, blueprints); diff --git a/src/app/shipyard/Ship.js b/src/app/shipyard/Ship.js index ea8d5f51..1a9a386e 100755 --- a/src/app/shipyard/Ship.js +++ b/src/app/shipyard/Ship.js @@ -480,7 +480,7 @@ export default class Ship { * @param {array} priorities Slot priorities * @param {Array} enabled Slot active/inactive * @param {Array} mods Modifications - * @param {Array} blueprints Blueprints + * @param {Array} blueprints Blueprints for modifications * @return {this} The current ship instance for chaining */ buildWith(comps, priorities, enabled, mods, blueprints) { @@ -1282,10 +1282,11 @@ export default class Ship { // Start off by gathering the information that we need let slots = new Array(); let blueprints = new Array(); + let specials = new Array(); let bulkheadMods = new Array(); - let bulkheadBlueprint = undefined; - let bulkheadBlueprintGrade = undefined; + let bulkheadBlueprint = null; + let bulkheadBlueprintGrade = null; if (this.bulkheads.m && this.bulkheads.m.mods) { for (let modKey in this.bulkheads.m.mods) { // Filter out invalid modifications @@ -1297,6 +1298,7 @@ export default class Ship { } slots.push(bulkheadMods); blueprints.push(bulkheadBlueprint) + specials.push(bulkheadBlueprint ? bulkheadBlueprint.special : null); for (let slot of this.standard) { let slotMods = new Array(); @@ -1309,7 +1311,8 @@ export default class Ship { } } slots.push(slotMods); - blueprints.push(slot.m ? slot.m.blueprint : undefined); + blueprints.push(slot.m ? slot.m.blueprint : null); + specials.push(slot.m && slot.m.blueprint ? slot.m.blueprint.special : null); } for (let slot of this.hardpoints) { @@ -1323,7 +1326,8 @@ export default class Ship { } } slots.push(slotMods); - blueprints.push(slot.m ? slot.m.blueprint : undefined); + blueprints.push(slot.m ? slot.m.blueprint : null); + specials.push(slot.m && slot.m.blueprint ? slot.m.blueprint.special : null); } for (let slot of this.internal) { @@ -1337,7 +1341,8 @@ export default class Ship { } } slots.push(slotMods); - blueprints.push(slot.m ? slot.m.blueprint : undefined); + blueprints.push(slot.m ? slot.m.blueprint : null); + specials.push(slot.m && slot.m.blueprint ? slot.m.blueprint.special : null); } // Now work out the size of the binary buffer from our modifications array @@ -1348,6 +1353,12 @@ export default class Ship { bufsize = bufsize + 1 + 10 + (5 * slot.length) + 1; } } + for (let special of specials) { + if (special) { + // Length is 5 for each special + bufsize += 5; + } + } if (bufsize > 0) { bufsize = bufsize + 1; // For end marker @@ -1366,6 +1377,11 @@ export default class Ship { buffer.writeInt32LE(blueprints[i].grade, curpos); curpos += 4; } + if (specials[i]) { + buffer.writeInt8(MODIFICATION_ID_SPECIAL, curpos++); + buffer.writeInt32LE(specials[i].id, curpos); + curpos += 4; + } for (let slotMod of slot) { buffer.writeInt8(slotMod.id, curpos++); if (isNaN(slotMod.value)) { @@ -1421,6 +1437,8 @@ export default class Ship { blueprint = Object.assign(blueprint, _.find(Modifications.blueprints, function(o) { return o.id === modificationValue; })); } else if (modificationId === MODIFICATION_ID_GRADE) { blueprint.grade = modificationValue; + } else if (modificationId === MODIFICATION_ID_SPECIAL) { + blueprint.special = _.find(Modifications.specials, function(o) { return o.id === modificationValue; }); } else { const modification = _.find(Modifications.modifications, function(o) { return o.id === modificationId; }); // console.log('DECODE Slot ' + slot + ': ' + modification.name + ' = ' + modificationValue); diff --git a/src/app/utils/CompanionApiUtils.js b/src/app/utils/CompanionApiUtils.js index 227acb07..c11783ab 100644 --- a/src/app/utils/CompanionApiUtils.js +++ b/src/app/utils/CompanionApiUtils.js @@ -277,6 +277,7 @@ export function shipFromJson(json) { function _addModifications(module, modifiers, blueprint, grade) { if (!modifiers || !modifiers.modifiers) return; + var special; for (const i in modifiers.modifiers) { // Look up the modifiers to find what we need to do const modifierActions = Modifications.modifierActions[modifiers.modifiers[i].name]; @@ -295,14 +296,22 @@ function _addModifications(module, modifiers, blueprint, grade) { module.setModValue(action, ((1 + mod) * (1 + actionValue) - 1) * 10000); } } + + // Note the special if present + if (modifiers.modifiers[i].name && modifiers.modifiers[i].name.startsWith('special_')) { + special = Modifications.specials[modifiers.modifiers[i].name]; + } } - // Add the blueprint ID and grade + // Add the blueprint ID, grade and special if (blueprint) { - module.blueprint = Modifications.blueprints[blueprint]; + module.blueprint = Object.assign({}, Modifications.blueprints[blueprint]); if (grade) { module.blueprint.grade = Number(grade); } + if (special) { + module.blueprint.special = special; + } } // Need to fix up a few items