mirror of
https://github.com/EDCD/coriolis.git
synced 2025-12-09 14:45:35 +00:00
Compare commits
43 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0a37b36ec2 | ||
|
|
85e6796e88 | ||
|
|
fa1ef47b71 | ||
|
|
f31e3c09f4 | ||
|
|
e6ab536601 | ||
|
|
5bced9fe56 | ||
|
|
67742060d3 | ||
|
|
ca2136544c | ||
|
|
ee19e9af50 | ||
|
|
f457fd0bff | ||
|
|
c1ce07e039 | ||
|
|
c8d1536f77 | ||
|
|
231ad4af59 | ||
|
|
d5f61d7ae8 | ||
|
|
8a5d4a36bf | ||
|
|
2c9237626d | ||
|
|
37f889e317 | ||
|
|
f86ba48295 | ||
|
|
aac35633a3 | ||
|
|
e73e0a305d | ||
|
|
4b2b0efe37 | ||
|
|
8fe20f6f65 | ||
|
|
11af7f567a | ||
|
|
3b8444482f | ||
|
|
c09e1b1b3e | ||
|
|
5770cf8d39 | ||
|
|
6da09f2e5d | ||
|
|
294fadf7cd | ||
|
|
2a97678574 | ||
|
|
76b3bd34f5 | ||
|
|
02bfecb92d | ||
|
|
719759ad56 | ||
|
|
fd446b29ba | ||
|
|
e5552d3e10 | ||
|
|
50946eeeb8 | ||
|
|
faab41117c | ||
|
|
0ab59c1f9a | ||
|
|
1067dceaa3 | ||
|
|
9042de422a | ||
|
|
f0547feb93 | ||
|
|
f863daa347 | ||
|
|
fdb202e7d6 | ||
|
|
c6bde19052 |
32
ChangeLog.md
32
ChangeLog.md
@@ -1,4 +1,34 @@
|
|||||||
#2.2.x
|
#2.2.5
|
||||||
|
* Calculate rate of fire for multi-burst weapons
|
||||||
|
* Add note to disable ghostery in error situation
|
||||||
|
* Use coriolis-data 2.2.5:
|
||||||
|
* Fix incorrect ID for emissive munitions special
|
||||||
|
* Fix rate of fire for burst lasers
|
||||||
|
* Add fragment cannon modifications
|
||||||
|
* Fix internal name of dazzle shell
|
||||||
|
|
||||||
|
#2.2.4
|
||||||
|
* Add shortlink for outfitting page
|
||||||
|
* Use coriolis-data 2.2.4:
|
||||||
|
* Fix incorrect ID for class 5 luxury passenger cabin
|
||||||
|
* Add damage type modifier
|
||||||
|
* Change modifications from simple strings to objects, to allow more data-driven behaviour
|
||||||
|
* Add special effects
|
||||||
|
* Modification tooltip now shows special effect
|
||||||
|
|
||||||
|
#2.2.3
|
||||||
|
* Fix hull boost calculation - now shows correct % modifier and total armour
|
||||||
|
* Fix import of DiamondBack - can now be imported
|
||||||
|
* Fix import of Beluga - can now be imported
|
||||||
|
* Use coriolis-data 2.2.3:
|
||||||
|
* Fix mismatch between class 5 and class 7 fighter hangars - now shows correct module
|
||||||
|
* Add details for concordant sequence special effect - now shows correct damage
|
||||||
|
* Fix details for thermal shock special effect - now shows correct damage
|
||||||
|
* Add engineer blueprints
|
||||||
|
* Modification tooltip now shows name and grade of modifications for imported builds
|
||||||
|
* Retain import URL unless user changes the build - allows future updates of Coriolis to take advantage of additional build information
|
||||||
|
|
||||||
|
#2.2.2
|
||||||
* Update DPS/HPS/EPS in real-time as modifiers change
|
* Update DPS/HPS/EPS in real-time as modifiers change
|
||||||
* Use coriolis-data 2.2.2:
|
* Use coriolis-data 2.2.2:
|
||||||
* Add distributor draw modifier to shield generators
|
* Add distributor draw modifier to shield generators
|
||||||
|
|||||||
@@ -271,7 +271,7 @@
|
|||||||
"totalExplDpe": 0,
|
"totalExplDpe": 0,
|
||||||
"totalExplDps": 0,
|
"totalExplDps": 0,
|
||||||
"totalExplSDps": 0,
|
"totalExplSDps": 0,
|
||||||
"totalHps": 33.28,
|
"totalHps": 33.62,
|
||||||
"totalKinDpe": 103.97,
|
"totalKinDpe": 103.97,
|
||||||
"totalKinDps": 28.92,
|
"totalKinDps": 28.92,
|
||||||
"totalKinSDps": 21.23,
|
"totalKinSDps": 21.23,
|
||||||
|
|||||||
255
__tests__/fixtures/asp-test-detailed-export-v4.json
Normal file
255
__tests__/fixtures/asp-test-detailed-export-v4.json
Normal file
@@ -0,0 +1,255 @@
|
|||||||
|
{
|
||||||
|
"$schema": "http://cdn.coriolis.io/schemas/ship-loadout/4.json#",
|
||||||
|
"name": "Multi-purpose Asp Explorer",
|
||||||
|
"ship": "Asp Explorer",
|
||||||
|
"references": [
|
||||||
|
{
|
||||||
|
"name": "Coriolis.io",
|
||||||
|
"url": "https://coriolis.edcd.io/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",
|
||||||
|
"code": "0pftiFflfddsnf5------020202033c044002v62f2i.AwRj4yvI.CwRgDBldHnJA.H4sIAAAAAAAAA2P858DAwPCXEUhwHPvx/78YG5AltB7I/8/0TwImJboDSPJ/+/f/v/KlX///i3AwMTBIfARK/Gf+JwVSxArStVAYqOjvz///JVo5GRhE2IBc4SKQSSz/DGEmCa398P8//2+gTf//AwDFxwtofAAAAA==",
|
||||||
|
"shipId": "asp"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"components": {
|
||||||
|
"standard": {
|
||||||
|
"bulkheads": "Lightweight Alloy",
|
||||||
|
"cargoHatch": {
|
||||||
|
"enabled": false,
|
||||||
|
"priority": 5
|
||||||
|
},
|
||||||
|
"powerPlant": {
|
||||||
|
"class": 5,
|
||||||
|
"rating": "A",
|
||||||
|
"enabled": true,
|
||||||
|
"priority": 2,
|
||||||
|
"modifications": {
|
||||||
|
"eff": -1850,
|
||||||
|
"pgen": 6,
|
||||||
|
"mass": 431
|
||||||
|
},
|
||||||
|
"blueprint": {
|
||||||
|
"id": 64,
|
||||||
|
"name": "Low emissions",
|
||||||
|
"grade": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"thrusters": {
|
||||||
|
"class": 5,
|
||||||
|
"rating": "D",
|
||||||
|
"enabled": true,
|
||||||
|
"priority": 1,
|
||||||
|
"modifications": {
|
||||||
|
"optmul": 440,
|
||||||
|
"integrity": -266,
|
||||||
|
"thermload": -1326,
|
||||||
|
"optmass": 520,
|
||||||
|
"power": 241
|
||||||
|
},
|
||||||
|
"blueprint": {
|
||||||
|
"id": 24,
|
||||||
|
"name": "Clean",
|
||||||
|
"grade": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"frameShiftDrive": {
|
||||||
|
"class": 5,
|
||||||
|
"rating": "A",
|
||||||
|
"enabled": true,
|
||||||
|
"priority": 1,
|
||||||
|
"modifications": {
|
||||||
|
"mass": 5025,
|
||||||
|
"integrity": -1539,
|
||||||
|
"power": 2437,
|
||||||
|
"optmass": 4870,
|
||||||
|
"maxfuel": 370
|
||||||
|
},
|
||||||
|
"blueprint": {
|
||||||
|
"id": 26,
|
||||||
|
"name": "Increased range",
|
||||||
|
"grade": 5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lifeSupport": {
|
||||||
|
"class": 4,
|
||||||
|
"rating": "A",
|
||||||
|
"enabled": true,
|
||||||
|
"priority": 1,
|
||||||
|
"modifications": {
|
||||||
|
"mass": -3923,
|
||||||
|
"integrity": -1797
|
||||||
|
},
|
||||||
|
"blueprint": {
|
||||||
|
"id": 49,
|
||||||
|
"name": "Lightweight",
|
||||||
|
"grade": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"powerDistributor": {
|
||||||
|
"class": 3,
|
||||||
|
"rating": "D",
|
||||||
|
"enabled": true,
|
||||||
|
"priority": 1
|
||||||
|
},
|
||||||
|
"sensors": {
|
||||||
|
"class": 5,
|
||||||
|
"rating": "D",
|
||||||
|
"enabled": true,
|
||||||
|
"priority": 1
|
||||||
|
},
|
||||||
|
"fuelTank": {
|
||||||
|
"class": 5,
|
||||||
|
"rating": "C",
|
||||||
|
"enabled": true,
|
||||||
|
"priority": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"hardpoints": [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
],
|
||||||
|
"utility": [
|
||||||
|
{
|
||||||
|
"class": 0,
|
||||||
|
"rating": "I",
|
||||||
|
"enabled": true,
|
||||||
|
"priority": 1,
|
||||||
|
"group": "Heat Sink Launcher",
|
||||||
|
"name": "Heat Sink Launcher"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class": 0,
|
||||||
|
"rating": "I",
|
||||||
|
"enabled": true,
|
||||||
|
"priority": 1,
|
||||||
|
"group": "Heat Sink Launcher",
|
||||||
|
"name": "Heat Sink Launcher"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class": 0,
|
||||||
|
"rating": "I",
|
||||||
|
"enabled": true,
|
||||||
|
"priority": 1,
|
||||||
|
"group": "Heat Sink Launcher",
|
||||||
|
"name": "Heat Sink Launcher"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class": 0,
|
||||||
|
"rating": "I",
|
||||||
|
"enabled": true,
|
||||||
|
"priority": 1,
|
||||||
|
"group": "Point Defence",
|
||||||
|
"name": "Point Defence"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"internal": [
|
||||||
|
{
|
||||||
|
"class": 6,
|
||||||
|
"rating": "A",
|
||||||
|
"enabled": true,
|
||||||
|
"priority": 1,
|
||||||
|
"group": "Fuel Scoop"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class": 5,
|
||||||
|
"rating": "E",
|
||||||
|
"enabled": true,
|
||||||
|
"priority": 2,
|
||||||
|
"group": "Cargo Rack"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class": 3,
|
||||||
|
"rating": "A",
|
||||||
|
"enabled": true,
|
||||||
|
"priority": 1,
|
||||||
|
"group": "Shield Generator"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class": 3,
|
||||||
|
"rating": "E",
|
||||||
|
"enabled": true,
|
||||||
|
"priority": 2,
|
||||||
|
"group": "Cargo Rack"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class": 2,
|
||||||
|
"rating": "G",
|
||||||
|
"enabled": true,
|
||||||
|
"priority": 1,
|
||||||
|
"group": "Planetary Vehicle Hangar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class": 1,
|
||||||
|
"rating": "C",
|
||||||
|
"enabled": true,
|
||||||
|
"priority": 2,
|
||||||
|
"group": "Scanner",
|
||||||
|
"name": "Advanced Discovery Scanner"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class": 1,
|
||||||
|
"rating": "C",
|
||||||
|
"enabled": true,
|
||||||
|
"priority": 2,
|
||||||
|
"group": "Scanner",
|
||||||
|
"name": "Detailed Surface Scanner"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"stats": {
|
||||||
|
"class": 2,
|
||||||
|
"hullCost": 6135660,
|
||||||
|
"speed": 250,
|
||||||
|
"boost": 340,
|
||||||
|
"boostEnergy": 13,
|
||||||
|
"agility": 6,
|
||||||
|
"baseShieldStrength": 140,
|
||||||
|
"baseArmour": 210,
|
||||||
|
"hullMass": 280,
|
||||||
|
"masslock": 11,
|
||||||
|
"pipSpeed": 0.13,
|
||||||
|
"moduleCostMultiplier": 1,
|
||||||
|
"fuelCapacity": 32,
|
||||||
|
"cargoCapacity": 40,
|
||||||
|
"ladenMass": 435.26,
|
||||||
|
"armour": 378,
|
||||||
|
"shield": 113.43,
|
||||||
|
"shieldCells": 0,
|
||||||
|
"totalCost": 48402550,
|
||||||
|
"unladenMass": 363.26,
|
||||||
|
"totalDpe": 0,
|
||||||
|
"totalExplDpe": 0,
|
||||||
|
"totalKinDpe": 0,
|
||||||
|
"totalThermDpe": 0,
|
||||||
|
"totalDps": 0,
|
||||||
|
"totalExplDps": 0,
|
||||||
|
"totalKinDps": 0,
|
||||||
|
"totalThermDps": 0,
|
||||||
|
"totalSDps": 0,
|
||||||
|
"totalExplSDps": 0,
|
||||||
|
"totalKinSDps": 0,
|
||||||
|
"totalThermSDps": 0,
|
||||||
|
"totalEps": 1.2,
|
||||||
|
"totalHps": 1,
|
||||||
|
"shieldExplRes": 0.5,
|
||||||
|
"shieldKinRes": 0.6,
|
||||||
|
"shieldThermRes": 1.2,
|
||||||
|
"hullExplRes": 1.4,
|
||||||
|
"hullKinRes": 1.2,
|
||||||
|
"hullThermRes": 1,
|
||||||
|
"powerAvailable": 20.41,
|
||||||
|
"powerRetracted": 11.91,
|
||||||
|
"powerDeployed": 11.91,
|
||||||
|
"unladenRange": 50.45,
|
||||||
|
"fullTankRange": 47.03,
|
||||||
|
"ladenRange": 42.71,
|
||||||
|
"unladenFastestRange": 317.24,
|
||||||
|
"ladenFastestRange": 287.02,
|
||||||
|
"maxJumpCount": 7,
|
||||||
|
"topSpeed": 274.01,
|
||||||
|
"topBoost": 372.65
|
||||||
|
}
|
||||||
|
}
|
||||||
552
__tests__/fixtures/companion-api-import-2.json
Normal file
552
__tests__/fixtures/companion-api-import-2.json
Normal file
@@ -0,0 +1,552 @@
|
|||||||
|
{
|
||||||
|
"cargo": {
|
||||||
|
"capacity": 32
|
||||||
|
},
|
||||||
|
"free": false,
|
||||||
|
"fuel": {
|
||||||
|
"main": {
|
||||||
|
"capacity": 128
|
||||||
|
},
|
||||||
|
"reserve": {
|
||||||
|
"capacity": 0.81
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"id": 31,
|
||||||
|
"modules": {
|
||||||
|
"Armour": {
|
||||||
|
"module": {
|
||||||
|
"free": false,
|
||||||
|
"id": 128049346,
|
||||||
|
"name": "BelugaLiner_Armour_Grade1",
|
||||||
|
"on": true,
|
||||||
|
"priority": 1,
|
||||||
|
"unloaned": 0,
|
||||||
|
"value": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Bobble01": [],
|
||||||
|
"Bobble02": [],
|
||||||
|
"Bobble03": [],
|
||||||
|
"Bobble04": [],
|
||||||
|
"Bobble05": [],
|
||||||
|
"Bobble06": [],
|
||||||
|
"Bobble07": [],
|
||||||
|
"Bobble08": [],
|
||||||
|
"Bobble09": [],
|
||||||
|
"Bobble10": [],
|
||||||
|
"Decal1": {
|
||||||
|
"module": {
|
||||||
|
"free": false,
|
||||||
|
"id": 128667757,
|
||||||
|
"name": "Decal_Explorer_Ranger",
|
||||||
|
"on": true,
|
||||||
|
"priority": 1,
|
||||||
|
"unloaned": 0,
|
||||||
|
"value": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Decal2": {
|
||||||
|
"module": {
|
||||||
|
"free": false,
|
||||||
|
"id": 128667742,
|
||||||
|
"name": "Decal_Combat_Deadly",
|
||||||
|
"on": true,
|
||||||
|
"priority": 1,
|
||||||
|
"unloaned": 0,
|
||||||
|
"value": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Decal3": {
|
||||||
|
"module": {
|
||||||
|
"free": false,
|
||||||
|
"id": 128667750,
|
||||||
|
"name": "Decal_Trade_Tycoon",
|
||||||
|
"on": true,
|
||||||
|
"priority": 1,
|
||||||
|
"unloaned": 0,
|
||||||
|
"value": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"EngineColour": [],
|
||||||
|
"FrameShiftDrive": {
|
||||||
|
"module": {
|
||||||
|
"free": false,
|
||||||
|
"id": 128064132,
|
||||||
|
"modifiers": {
|
||||||
|
"engineerID": 300100,
|
||||||
|
"id": 175,
|
||||||
|
"modifiers": [
|
||||||
|
{
|
||||||
|
"name": "mod_mass",
|
||||||
|
"type": 1,
|
||||||
|
"value": 0.4457540512085
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mod_health",
|
||||||
|
"type": 1,
|
||||||
|
"value": -0.24584779143333
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mod_passive_power",
|
||||||
|
"type": 1,
|
||||||
|
"value": 0.24457727372646
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mod_fsd_optimised_mass",
|
||||||
|
"type": 1,
|
||||||
|
"value": 0.49257898330688
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mod_fsd_max_fuel_per_jump",
|
||||||
|
"type": 2,
|
||||||
|
"value": 0.028505677357316
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mod_fsd_heat_rate",
|
||||||
|
"type": 2,
|
||||||
|
"value": -0.079360365867615
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"moduleTags": [
|
||||||
|
16
|
||||||
|
],
|
||||||
|
"recipeID": 128673694,
|
||||||
|
"slotIndex": 53
|
||||||
|
},
|
||||||
|
"name": "Int_Hyperdrive_Size7_Class5",
|
||||||
|
"on": true,
|
||||||
|
"priority": 0,
|
||||||
|
"recipeLevel": 5,
|
||||||
|
"recipeName": "FSD_LongRange",
|
||||||
|
"recipeValue": 0,
|
||||||
|
"unloaned": 0,
|
||||||
|
"value": 46160201
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"FuelTank": {
|
||||||
|
"module": {
|
||||||
|
"free": false,
|
||||||
|
"id": 128064352,
|
||||||
|
"name": "Int_FuelTank_Size7_Class3",
|
||||||
|
"on": true,
|
||||||
|
"priority": 1,
|
||||||
|
"unloaned": 1602822,
|
||||||
|
"value": 1602822
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"LifeSupport": {
|
||||||
|
"module": {
|
||||||
|
"free": false,
|
||||||
|
"id": 128064174,
|
||||||
|
"name": "Int_LifeSupport_Size8_Class2",
|
||||||
|
"on": true,
|
||||||
|
"priority": 0,
|
||||||
|
"unloaned": 0,
|
||||||
|
"value": 1569565
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"MainEngines": {
|
||||||
|
"module": {
|
||||||
|
"free": false,
|
||||||
|
"id": 128064094,
|
||||||
|
"modifiers": {
|
||||||
|
"engineerID": 300100,
|
||||||
|
"id": 253,
|
||||||
|
"modifiers": [
|
||||||
|
{
|
||||||
|
"name": "mod_engine_mass_curve_multiplier",
|
||||||
|
"type": 1,
|
||||||
|
"value": 0.098235413432121
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mod_engine_heat",
|
||||||
|
"type": 1,
|
||||||
|
"value": 0.18069696426392
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mod_passive_power",
|
||||||
|
"type": 1,
|
||||||
|
"value": 0.033788848668337
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mod_health",
|
||||||
|
"type": 1,
|
||||||
|
"value": -0.056404989212751
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mod_engine_mass_curve",
|
||||||
|
"type": 1,
|
||||||
|
"value": -0.027384582906961
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mod_engine_heat",
|
||||||
|
"type": 2,
|
||||||
|
"value": -0.072683908045292
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"moduleTags": [
|
||||||
|
17
|
||||||
|
],
|
||||||
|
"recipeID": 128673655,
|
||||||
|
"slotIndex": 52
|
||||||
|
},
|
||||||
|
"name": "Int_Engine_Size7_Class2",
|
||||||
|
"on": true,
|
||||||
|
"priority": 0,
|
||||||
|
"recipeLevel": 1,
|
||||||
|
"recipeName": "Engine_Dirty",
|
||||||
|
"recipeValue": 0,
|
||||||
|
"unloaned": 0,
|
||||||
|
"value": 1709638
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"MediumHardpoint1": {
|
||||||
|
"module": {
|
||||||
|
"free": false,
|
||||||
|
"id": 128049436,
|
||||||
|
"name": "Hpt_BeamLaser_Turret_Medium",
|
||||||
|
"on": true,
|
||||||
|
"priority": 0,
|
||||||
|
"unloaned": 0,
|
||||||
|
"value": 1889910
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"MediumHardpoint2": {
|
||||||
|
"module": {
|
||||||
|
"free": false,
|
||||||
|
"id": 128049436,
|
||||||
|
"name": "Hpt_BeamLaser_Turret_Medium",
|
||||||
|
"on": true,
|
||||||
|
"priority": 0,
|
||||||
|
"unloaned": 0,
|
||||||
|
"value": 1889910
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"MediumHardpoint3": {
|
||||||
|
"module": {
|
||||||
|
"free": false,
|
||||||
|
"id": 128049460,
|
||||||
|
"name": "Hpt_MultiCannon_Gimbal_Medium",
|
||||||
|
"on": true,
|
||||||
|
"priority": 0,
|
||||||
|
"unloaned": 0,
|
||||||
|
"value": 51300
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"MediumHardpoint4": {
|
||||||
|
"module": {
|
||||||
|
"free": false,
|
||||||
|
"id": 128049460,
|
||||||
|
"name": "Hpt_MultiCannon_Gimbal_Medium",
|
||||||
|
"on": true,
|
||||||
|
"priority": 0,
|
||||||
|
"unloaned": 0,
|
||||||
|
"value": 51300
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"MediumHardpoint5": {
|
||||||
|
"module": {
|
||||||
|
"free": false,
|
||||||
|
"id": 128049460,
|
||||||
|
"name": "Hpt_MultiCannon_Gimbal_Medium",
|
||||||
|
"on": true,
|
||||||
|
"priority": 0,
|
||||||
|
"unloaned": 0,
|
||||||
|
"value": 51300
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"PaintJob": {
|
||||||
|
"module": {
|
||||||
|
"free": false,
|
||||||
|
"id": 128732290,
|
||||||
|
"name": "PaintJob_BelugaLiner_Tactical_White",
|
||||||
|
"on": true,
|
||||||
|
"priority": 1,
|
||||||
|
"unloaned": 0,
|
||||||
|
"value": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"PlanetaryApproachSuite": {
|
||||||
|
"module": {
|
||||||
|
"free": false,
|
||||||
|
"id": 128672317,
|
||||||
|
"name": "Int_PlanetApproachSuite",
|
||||||
|
"on": true,
|
||||||
|
"priority": 1,
|
||||||
|
"unloaned": 450,
|
||||||
|
"value": 450
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"PowerDistributor": {
|
||||||
|
"module": {
|
||||||
|
"free": false,
|
||||||
|
"id": 128064207,
|
||||||
|
"name": "Int_PowerDistributor_Size6_Class5",
|
||||||
|
"on": true,
|
||||||
|
"priority": 0,
|
||||||
|
"unloaned": 0,
|
||||||
|
"value": 3128120
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"PowerPlant": {
|
||||||
|
"module": {
|
||||||
|
"free": false,
|
||||||
|
"id": 128064057,
|
||||||
|
"modifiers": {
|
||||||
|
"engineerID": 300100,
|
||||||
|
"id": 277,
|
||||||
|
"modifiers": [
|
||||||
|
{
|
||||||
|
"name": "mod_powerplant_power",
|
||||||
|
"type": 1,
|
||||||
|
"value": 0.054692290723324
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mod_health",
|
||||||
|
"type": 1,
|
||||||
|
"value": -0.033690698444843
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mod_powerplant_heat",
|
||||||
|
"type": 1,
|
||||||
|
"value": 0.027470717206597
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mod_powerplant_heat",
|
||||||
|
"type": 2,
|
||||||
|
"value": -0.056317910552025
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"moduleTags": [
|
||||||
|
18
|
||||||
|
],
|
||||||
|
"recipeID": 128673765,
|
||||||
|
"slotIndex": 51
|
||||||
|
},
|
||||||
|
"name": "Int_Powerplant_Size6_Class5",
|
||||||
|
"on": true,
|
||||||
|
"priority": 1,
|
||||||
|
"recipeLevel": 1,
|
||||||
|
"recipeName": "PowerPlant_Boosted",
|
||||||
|
"recipeValue": 0,
|
||||||
|
"unloaned": 0,
|
||||||
|
"value": 14561578
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Radar": {
|
||||||
|
"module": {
|
||||||
|
"free": false,
|
||||||
|
"id": 128064239,
|
||||||
|
"name": "Int_Sensors_Size5_Class2",
|
||||||
|
"on": true,
|
||||||
|
"priority": 0,
|
||||||
|
"unloaned": 0,
|
||||||
|
"value": 71500
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Slot01_Size6": {
|
||||||
|
"module": {
|
||||||
|
"free": false,
|
||||||
|
"id": 128666681,
|
||||||
|
"name": "Int_FuelScoop_Size6_Class5",
|
||||||
|
"on": true,
|
||||||
|
"priority": 1,
|
||||||
|
"unloaned": 0,
|
||||||
|
"value": 25887249
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Slot02_Size6": {
|
||||||
|
"module": {
|
||||||
|
"free": false,
|
||||||
|
"id": 128064287,
|
||||||
|
"name": "Int_ShieldGenerator_Size6_Class5",
|
||||||
|
"on": true,
|
||||||
|
"priority": 0,
|
||||||
|
"unloaned": 0,
|
||||||
|
"value": 14561578
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Slot03_Size6": {
|
||||||
|
"module": {
|
||||||
|
"free": false,
|
||||||
|
"id": 128727927,
|
||||||
|
"name": "Int_PassengerCabin_Size6_Class2",
|
||||||
|
"on": true,
|
||||||
|
"priority": 1,
|
||||||
|
"unloaned": 165808,
|
||||||
|
"value": 165808
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Slot04_Size6": {
|
||||||
|
"module": {
|
||||||
|
"free": false,
|
||||||
|
"id": 128727928,
|
||||||
|
"name": "Int_PassengerCabin_Size6_Class3",
|
||||||
|
"on": true,
|
||||||
|
"priority": 1,
|
||||||
|
"unloaned": 0,
|
||||||
|
"value": 497429
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Slot05_Size5": {
|
||||||
|
"module": {
|
||||||
|
"free": false,
|
||||||
|
"id": 128727925,
|
||||||
|
"name": "Int_PassengerCabin_Size5_Class4",
|
||||||
|
"on": true,
|
||||||
|
"priority": 1,
|
||||||
|
"unloaned": 0,
|
||||||
|
"value": 1492286
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Slot06_Size5": {
|
||||||
|
"module": {
|
||||||
|
"free": false,
|
||||||
|
"id": 128064342,
|
||||||
|
"name": "Int_CargoRack_Size5_Class1",
|
||||||
|
"on": true,
|
||||||
|
"priority": 1,
|
||||||
|
"unloaned": 100409,
|
||||||
|
"value": 100409
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Slot07_Size4": {
|
||||||
|
"module": {
|
||||||
|
"free": false,
|
||||||
|
"id": 128727922,
|
||||||
|
"name": "Int_PassengerCabin_Size4_Class1",
|
||||||
|
"on": true,
|
||||||
|
"priority": 1,
|
||||||
|
"unloaned": 0,
|
||||||
|
"value": 17059
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Slot08_Size3": {
|
||||||
|
"module": {
|
||||||
|
"free": false,
|
||||||
|
"id": 128667632,
|
||||||
|
"name": "Int_Repairer_Size3_Class5",
|
||||||
|
"on": true,
|
||||||
|
"priority": 1,
|
||||||
|
"unloaned": 0,
|
||||||
|
"value": 2361960
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Slot09_Size3": {
|
||||||
|
"module": {
|
||||||
|
"free": false,
|
||||||
|
"id": 128672289,
|
||||||
|
"name": "Int_BuggyBay_Size2_Class2",
|
||||||
|
"on": true,
|
||||||
|
"priority": 1,
|
||||||
|
"unloaned": 0,
|
||||||
|
"value": 19440
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Slot10_Size3": {
|
||||||
|
"module": {
|
||||||
|
"free": false,
|
||||||
|
"id": 128666634,
|
||||||
|
"name": "Int_DetailedSurfaceScanner_Tiny",
|
||||||
|
"on": true,
|
||||||
|
"priority": 1,
|
||||||
|
"unloaned": 0,
|
||||||
|
"value": 225000
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Slot11_Size3": {
|
||||||
|
"module": {
|
||||||
|
"free": false,
|
||||||
|
"id": 128663561,
|
||||||
|
"name": "Int_StellarBodyDiscoveryScanner_Advanced",
|
||||||
|
"on": true,
|
||||||
|
"priority": 1,
|
||||||
|
"unloaned": 0,
|
||||||
|
"value": 1390500
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"TinyHardpoint1": {
|
||||||
|
"module": {
|
||||||
|
"free": false,
|
||||||
|
"id": 128049513,
|
||||||
|
"name": "Hpt_ChaffLauncher_Tiny",
|
||||||
|
"on": true,
|
||||||
|
"priority": 0,
|
||||||
|
"unloaned": 0,
|
||||||
|
"value": 7650
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"TinyHardpoint2": {
|
||||||
|
"module": {
|
||||||
|
"free": false,
|
||||||
|
"id": 128668536,
|
||||||
|
"name": "Hpt_ShieldBooster_Size0_Class5",
|
||||||
|
"on": true,
|
||||||
|
"priority": 0,
|
||||||
|
"unloaned": 0,
|
||||||
|
"value": 252900
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"TinyHardpoint3": {
|
||||||
|
"module": {
|
||||||
|
"free": false,
|
||||||
|
"id": 128668536,
|
||||||
|
"name": "Hpt_ShieldBooster_Size0_Class5",
|
||||||
|
"on": true,
|
||||||
|
"priority": 0,
|
||||||
|
"unloaned": 0,
|
||||||
|
"value": 252900
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"TinyHardpoint4": {
|
||||||
|
"module": {
|
||||||
|
"free": false,
|
||||||
|
"id": 128668536,
|
||||||
|
"name": "Hpt_ShieldBooster_Size0_Class5",
|
||||||
|
"on": true,
|
||||||
|
"priority": 0,
|
||||||
|
"unloaned": 0,
|
||||||
|
"value": 281000
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"TinyHardpoint5": {
|
||||||
|
"module": {
|
||||||
|
"free": false,
|
||||||
|
"id": 128668536,
|
||||||
|
"name": "Hpt_ShieldBooster_Size0_Class5",
|
||||||
|
"on": true,
|
||||||
|
"priority": 0,
|
||||||
|
"unloaned": 0,
|
||||||
|
"value": 281000
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"TinyHardpoint6": {
|
||||||
|
"module": {
|
||||||
|
"free": false,
|
||||||
|
"id": 128668536,
|
||||||
|
"name": "Hpt_ShieldBooster_Size0_Class5",
|
||||||
|
"on": true,
|
||||||
|
"priority": 0,
|
||||||
|
"unloaned": 0,
|
||||||
|
"value": 281000
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"WeaponColour": {
|
||||||
|
"module": {
|
||||||
|
"free": false,
|
||||||
|
"id": 128732194,
|
||||||
|
"name": "WeaponCustomisation_Purple",
|
||||||
|
"on": true,
|
||||||
|
"priority": 1,
|
||||||
|
"unloaned": 0,
|
||||||
|
"value": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"name": "BelugaLiner",
|
||||||
|
"value": {
|
||||||
|
"hull": 71688743,
|
||||||
|
"modules": 120812762,
|
||||||
|
"unloaned": 1869489
|
||||||
|
}
|
||||||
|
}
|
||||||
327
__tests__/fixtures/courier-test-detailed-export-v4.json
Normal file
327
__tests__/fixtures/courier-test-detailed-export-v4.json
Normal file
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"type_6_transporter": {
|
"type_6_transporter": {
|
||||||
"Cargo": "0p0tdFal8d8s8f4-----04040303430101.Iw1-kA==.Aw1-kA==.",
|
"Cargo": "0p0tdFal8d8s8f4-----04040303430101.Iw1/kA==.Aw1/kA==.",
|
||||||
"Miner": "0p5tdFal8d8s8f42l2l---040403451q0101.Iw1-kA==.Aw1-kA==.",
|
"Miner": "0p5tdFal8d8s8f42l2l---040403451q0101.Iw1/kA==.Aw1/kA==.",
|
||||||
"Hopper": "0p0tdFal8d0s8f41717---030302024300-.Iw1-kA==.Aw1-kA==."
|
"Hopper": "0p0tdFal8d0s8f41717---030302024300-.Iw1/kA==.Aw1/kA==."
|
||||||
},
|
},
|
||||||
"type_7_transport": {
|
"type_7_transport": {
|
||||||
"Cargo": "0p0tiFfliddsdf5--------0505040403480101.Iw18aQ==.Aw18aQ==.",
|
"Cargo": "0p0tiFfliddsdf5--------0505040403480101.Iw18aQ==.Aw18aQ==.",
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
"Test": "4putkFklkdzsuf52c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04--0303326b.Iw18ZlA=.Aw18ZlA=."
|
"Test": "4putkFklkdzsuf52c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04--0303326b.Iw18ZlA=.Aw18ZlA=."
|
||||||
},
|
},
|
||||||
"diamondback_explorer": {
|
"diamondback_explorer": {
|
||||||
"Explorer": "0p0tdFfldddsdf5---0202--320p432i2f.Iw1-kA==.Aw1-kA==."
|
"Explorer": "0p0tdFfldddsdf5---0202--320p432i2f.Iw1/kA==.Aw1/kA==."
|
||||||
},
|
},
|
||||||
"vulture": {
|
"vulture": {
|
||||||
"Bounty Hunter": "3patcFalddksff31e1e0404-0l4a5d27662j.Iw19kA==.Aw19kA==."
|
"Bounty Hunter": "3patcFalddksff31e1e0404-0l4a5d27662j.Iw19kA==.Aw19kA==."
|
||||||
@@ -45,6 +45,6 @@
|
|||||||
"Attack": "2pfthFalidpsff31r0s0s0s0s000404-04-4a-5d27-.Iw18aQ==.Aw18aQ==."
|
"Attack": "2pfthFalidpsff31r0s0s0s0s000404-04-4a-5d27-.Iw18aQ==.Aw18aQ==."
|
||||||
},
|
},
|
||||||
"eagle": {
|
"eagle": {
|
||||||
"Figther": "4p0t5F5l3d5s5f20p0p24-40532j-.Iw1-EA==.Aw1-EA==."
|
"Figther": "4p0t5F5l3d5s5f20p0p24-40532j-.Iw1/EA==.Aw1/EA==."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ describe('Import Modal', function() {
|
|||||||
expect(modal.state.singleBuild).toBe(true);
|
expect(modal.state.singleBuild).toBe(true);
|
||||||
clickProceed();
|
clickProceed();
|
||||||
expect(MockRouter.go.mock.calls.length).toBe(1);
|
expect(MockRouter.go.mock.calls.length).toBe(1);
|
||||||
expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/anaconda/4putkFklkdzsuf52c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04--0303326b.AwRj4zNKqA==.CwBhCYzBGW9qCTSqs5xA.?bn=Test%20My%20Ship');
|
expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/anaconda?code=4putkFklkdzsuf52c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04--0303326b.AwRj4zNKqA%3D%3D.CwBhCYzBGW9qCTSqs5xA.&bn=Test%20My%20Ship');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('catches an invalid build', function() {
|
it('catches an invalid build', function() {
|
||||||
@@ -167,7 +167,36 @@ describe('Import Modal', function() {
|
|||||||
expect(modal.state.singleBuild).toBe(true);
|
expect(modal.state.singleBuild).toBe(true);
|
||||||
clickProceed();
|
clickProceed();
|
||||||
expect(MockRouter.go.mock.calls.length).toBe(1);
|
expect(MockRouter.go.mock.calls.length).toBe(1);
|
||||||
expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/anaconda/4putkFklkdzsuf52c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04--0303326b.AwRj4zNKqA==.CwBhCYzBGW9qCTSqs5xA.H4sIAAAAAAAAA2MUe8HMwPD-PwDDhxeuCAAAAA==?bn=Test%20My%20Ship');
|
expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/anaconda?code=4putkFklkdzsuf52c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04--0303326b.AwRj4zNKqA%3D%3D.CwBhCYzBGW9qCTSqs5xA.H4sIAAAAAAAAA2P8xwAEf0GE2AtmBob%2F%2FwFvM%2BjKEgAAAA%3D%3D&bn=Test%20My%20Ship');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Import Detailed Engineered V4 Build', function() {
|
||||||
|
|
||||||
|
beforeEach(reset);
|
||||||
|
|
||||||
|
it('imports a valid v4 build', function() {
|
||||||
|
const importData = require('./fixtures/asp-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/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');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -209,26 +238,38 @@ describe('Import Modal', function() {
|
|||||||
expect(modal.state.singleBuild).toBe(true);
|
expect(modal.state.singleBuild).toBe(true);
|
||||||
clickProceed();
|
clickProceed();
|
||||||
expect(MockRouter.go.mock.calls.length).toBe(1);
|
expect(MockRouter.go.mock.calls.length).toBe(1);
|
||||||
expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/federal_corvette/2putsFklndzsxf50x0x7l28281919040404040402020l06p05sf63c5ifhv66g2f.AwRj4zNaKA==.CwRgDBldUExuBiQqA===.H4sIAAAAAAAAAx2Rzy4DURTGz7TuzHRu47ZjWreKlg5iQ9KFZ9CENyBWtWo8gIUFsamteAIJi0qEWIhdN11ZEN1IwyNYVKRpcXzH5su553f_XyfvKiLTYma-TkScyHVcokoYEdmbBNDsiDla-WUOT5LgyfAshHdvyGyjFFHUQCSrBU8TLT4gYq4DNL_LhNTFN3PwiqdZQyX2C-sekep-Mrs1RIbnDppsIogD1UAtN7JEM9eIzZg8hmhsEU32gFmrdgB_UARvjYEr4QMUMffoxGnV-M8X3hZ_lAO-gmWq2Eq2IVtDOzZ2Hbbuws6KxCKmKUUydgRb3woSiUXMs6Cs7Qt6FCQSi5hxkNKhj6qhfcPU_kU4wYrFMseSOmFXMKbuwZsViUWMlq1sbhvJ_lKyfqTqEJGJyoC5eIpU9x2TRnUswYXyF77BW4Z3qQuv05GDTpfvcDzvSbxJ5DtV_aHS1I4clyB2A5_b-pAL8x_enn626gEAAA==?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() {
|
||||||
|
const importData = require('./fixtures/companion-api-import-2');
|
||||||
|
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/beluga?code=0pktsFplCdpsnf70t0t2727270004040404043c4fmimlmm04mc0iv62i2f.AwRj4yukg%3D%3D%3D.CwRgDBldHi8IUA%3D%3D.H4sIAAAAAAAAA2P8Z8%2FAwPCXEUiIKTMxMPCv%2F%2Ff%2FP8cFIPGf6Z8YTEr0GjMDg%2FJWICERBOTzn%2Fn7%2F7%2FIO5Ai5n9SIEWsQEIoSxAolfbt%2F3%2BJPk4GBhE7YQYGYVmgcuVnf4Aq%2FwMAIrEcGGsAAAA%3D&bn=Imported%20Beluga%20Liner');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Import E:D Shipyard Builds', function() {
|
describe('Import E:D Shipyard Builds', function() {
|
||||||
|
|
||||||
it('imports a valid builds', function() {
|
// it('imports a valid build', function() {
|
||||||
const imports = require('./fixtures/ed-shipyard-import-valid');
|
// const imports = require('./fixtures/ed-shipyard-import-valid');
|
||||||
|
//
|
||||||
for (let i = 0; i < imports.length; i++ ) {
|
// for (let i = 0; i < imports.length; i++ ) {
|
||||||
reset();
|
// reset();
|
||||||
let fixture = imports[i];
|
// let fixture = imports[i];
|
||||||
pasteText(fixture.buildText);
|
// pasteText(fixture.buildText);
|
||||||
expect(modal.state.importValid).toBeTruthy();
|
// expect(modal.state.importValid).toBeTruthy();
|
||||||
expect(modal.state.errorMsg).toEqual(null);
|
// expect(modal.state.errorMsg).toEqual(null);
|
||||||
clickProceed();
|
// clickProceed();
|
||||||
expect(MockRouter.go.mock.calls.length).toBe(1);
|
// expect(MockRouter.go.mock.calls.length).toBe(1);
|
||||||
expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/' + fixture.shipId + '/' + fixture.buildCode + '?bn=' + encodeURIComponent(fixture.buildName));
|
// expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/' + fixture.shipId + '?code=' + encodeURIComponent(fixture.buildCode) + '&bn=' + encodeURIComponent(fixture.buildName));
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
|
|
||||||
it('catches invalid builds', function() {
|
it('catches invalid builds', function() {
|
||||||
const imports = require('./fixtures/ed-shipyard-import-invalid');
|
const imports = require('./fixtures/ed-shipyard-import-invalid');
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "coriolis_shipyard",
|
"name": "coriolis_shipyard",
|
||||||
"version": "2.2.2",
|
"version": "2.2.5",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/EDCD/coriolis"
|
"url": "https://github.com/EDCD/coriolis"
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import Header from './components/Header';
|
|||||||
import Tooltip from './components/Tooltip';
|
import Tooltip from './components/Tooltip';
|
||||||
import ModalImport from './components/ModalImport';
|
import ModalImport from './components/ModalImport';
|
||||||
import * as CompanionApiUtils from './utils/CompanionApiUtils';
|
import * as CompanionApiUtils from './utils/CompanionApiUtils';
|
||||||
import { outfitURL } from './utils/UrlGenerators'
|
import { outfitURL } from './utils/UrlGenerators';
|
||||||
|
|
||||||
import AboutPage from './pages/AboutPage';
|
import AboutPage from './pages/AboutPage';
|
||||||
import NotFoundPage from './pages/NotFoundPage';
|
import NotFoundPage from './pages/NotFoundPage';
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ export default class ComparisonTable extends TranslatedComponent {
|
|||||||
* @return {React.Component} Table row
|
* @return {React.Component} Table row
|
||||||
*/
|
*/
|
||||||
_buildRow(build, facets, formats, units) {
|
_buildRow(build, facets, formats, units) {
|
||||||
let url = outfitURL(build.id, build.toString(), build.buildName)
|
let url = outfitURL(build.id, build.toString(), build.buildName);
|
||||||
let cells = [
|
let cells = [
|
||||||
<td key='s' className='tl'><Link href={url}>{build.name}</Link></td>,
|
<td key='s' className='tl'><Link href={url}>{build.name}</Link></td>,
|
||||||
<td key='bn' className='tl'><Link href={url}>{build.buildName}</Link></td>
|
<td key='bn' className='tl'><Link href={url}>{build.buildName}</Link></td>
|
||||||
|
|||||||
@@ -44,17 +44,26 @@ export default class HardpointSlot extends Slot {
|
|||||||
let validMods = Modifications.validity[m.grp] || [];
|
let validMods = Modifications.validity[m.grp] || [];
|
||||||
let showModuleResistances = Persist.showModuleResistances();
|
let showModuleResistances = Persist.showModuleResistances();
|
||||||
|
|
||||||
|
// Modifications tooltip shows blueprint and grade, if available
|
||||||
|
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 <div className='details' draggable='true' onDragStart={drag} onDragEnd={drop}>
|
return <div className='details' draggable='true' onDragStart={drag} onDragEnd={drop}>
|
||||||
<div className={'cb'}>
|
<div className={'cb'}>
|
||||||
<div className={'l'}>
|
<div className={'l'}>
|
||||||
{m.mount && m.mount == 'F' ? <span onMouseOver={termtip.bind(null, 'fixed')} onMouseOut={tooltip.bind(null, null)}><MountFixed /></span> : ''}
|
{m.mount && m.mount == 'F' ? <span onMouseOver={termtip.bind(null, 'fixed')} onMouseOut={tooltip.bind(null, null)}><MountFixed /></span> : ''}
|
||||||
{m.mount && m.mount == 'G' ? <span onMouseOver={termtip.bind(null, 'gimballed')} onMouseOut={tooltip.bind(null, null)}><MountGimballed /></span> : ''}
|
{m.mount && m.mount == 'G' ? <span onMouseOver={termtip.bind(null, 'gimballed')} onMouseOut={tooltip.bind(null, null)}><MountGimballed /></span> : ''}
|
||||||
{m.mount && m.mount == 'T' ? <span onMouseOver={termtip.bind(null, 'turreted')} onMouseOut={tooltip.bind(null, null)}><MountTurret /></span> : ''}
|
{m.mount && m.mount == 'T' ? <span onMouseOver={termtip.bind(null, 'turreted')} onMouseOut={tooltip.bind(null, null)}><MountTurret /></span> : ''}
|
||||||
{m.type && m.type.match('K') ? <span onMouseOver={termtip.bind(null, 'kinetic')} onMouseOut={tooltip.bind(null, null)}><DamageKinetic /></span> : ''}
|
{m.getDamageType() && m.getDamageType().match('K') ? <span onMouseOver={termtip.bind(null, 'kinetic')} onMouseOut={tooltip.bind(null, null)}><DamageKinetic /></span> : ''}
|
||||||
{m.type && m.type.match('T') ? <span onMouseOver={termtip.bind(null, 'thermal')} onMouseOut={tooltip.bind(null, null)}><DamageThermal /></span> : ''}
|
{m.getDamageType() && m.getDamageType().match('T') ? <span onMouseOver={termtip.bind(null, 'thermal')} onMouseOut={tooltip.bind(null, null)}><DamageThermal /></span> : ''}
|
||||||
{m.type && m.type.match('E') ? <span onMouseOver={termtip.bind(null, 'explosive')} onMouseOut={tooltip.bind(null, null)}><DamageExplosive /></span> : ''}
|
{m.getDamageType() && m.getDamageType().match('E') ? <span onMouseOver={termtip.bind(null, 'explosive')} onMouseOut={tooltip.bind(null, null)}><DamageExplosive /></span> : ''}
|
||||||
{classRating} {translate(m.name || m.grp)}{ m.mods && Object.keys(m.mods).length > 0 ? <span className='r' onMouseOver={termtip.bind(null, 'modified')} onMouseOut={tooltip.bind(null, null)}><Modified /></span> : null }
|
{classRating} {translate(m.name || m.grp)}{ m.mods && Object.keys(m.mods).length > 0 ? <span className='r' onMouseOver={termtip.bind(null, modTT)} onMouseOut={tooltip.bind(null, null)}><Modified /></span> : null }
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={'r'}>{formats.round(m.getMass())}{u.T}</div>
|
<div className={'r'}>{formats.round(m.getMass())}{u.T}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -26,10 +26,16 @@ export default class InternalSlot extends Slot {
|
|||||||
let validMods = Modifications.validity[m.grp] || [];
|
let validMods = Modifications.validity[m.grp] || [];
|
||||||
let showModuleResistances = Persist.showModuleResistances();
|
let showModuleResistances = Persist.showModuleResistances();
|
||||||
|
|
||||||
|
// Modifications tooltip shows blueprint and grade, if available
|
||||||
|
let modTT = translate('modified');
|
||||||
|
if (m && m.blueprint) {
|
||||||
|
modTT = translate(m.blueprint.name) + ' ' + translate('grade') + ' ' + m.blueprint.grade;
|
||||||
|
}
|
||||||
|
|
||||||
let mass = m.getMass() || m.cargo || m.fuel || 0;
|
let mass = m.getMass() || m.cargo || m.fuel || 0;
|
||||||
return <div className='details' draggable='true' onDragStart={drag} onDragEnd={drop}>
|
return <div className='details' draggable='true' onDragStart={drag} onDragEnd={drop}>
|
||||||
<div className={'cb'}>
|
<div className={'cb'}>
|
||||||
<div className={'l'}>{classRating} {translate(m.name || m.grp)}{m.mods && Object.keys(m.mods).length > 0 ? <span onMouseOver={termtip.bind(null, 'modified')} onMouseOut={tooltip.bind(null, null)}><Modified /></span> : ''}</div>
|
<div className={'l'}>{classRating} {translate(m.name || m.grp)}{m.mods && Object.keys(m.mods).length > 0 ? <span onMouseOver={termtip.bind(null, modTT)} onMouseOut={tooltip.bind(null, null)}><Modified /></span> : ''}</div>
|
||||||
<div className={'r'}>{formats.round(mass)}{u.T}</div>
|
<div className={'r'}>{formats.round(mass)}{u.T}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={'cb'}>
|
<div className={'cb'}>
|
||||||
|
|||||||
@@ -346,6 +346,7 @@ export default class ModalImport extends TranslatedComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
// console.log(e.stack);
|
||||||
this.setState({ errorMsg: (typeof e == 'string') ? e : 'Cannot Parse the data!' });
|
this.setState({ errorMsg: (typeof e == 'string') ? e : 'Cannot Parse the data!' });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,9 +63,24 @@ export default class Modification extends TranslatedComponent {
|
|||||||
let translate = this.context.language.translate;
|
let translate = this.context.language.translate;
|
||||||
let name = this.props.name;
|
let name = this.props.name;
|
||||||
|
|
||||||
|
if (name === 'type') {
|
||||||
|
// We don't show type
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let symbol;
|
||||||
|
if (name === 'jitter') {
|
||||||
|
symbol = '°';
|
||||||
|
} else if (name !== 'burst') {
|
||||||
|
symbol = '%';
|
||||||
|
}
|
||||||
|
if (symbol) {
|
||||||
|
symbol = ' (' + symbol + ')';
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={'cb'} key={name}>
|
<div className={'cb'} key={name}>
|
||||||
<div className={'cb'}>{translate(name)}{name === 'jitter' ? ' (°)' : ' (%)'}</div>
|
<div className={'cb'}>{translate(name)}{symbol}</div>
|
||||||
<NumberEditor className={'cb'} style={{ width: '90%', textAlign: 'center' }} step={0.01} stepModifier={1} decimals={2} value={this.state.value} onValueChange={this._updateValue.bind(this)} />
|
<NumberEditor className={'cb'} style={{ width: '90%', textAlign: 'center' }} step={0.01} stepModifier={1} decimals={2} value={this.state.value} onValueChange={this._updateValue.bind(this)} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -50,6 +50,12 @@ export default class StandardSlot extends TranslatedComponent {
|
|||||||
let showModuleResistances = Persist.showModuleResistances();
|
let showModuleResistances = Persist.showModuleResistances();
|
||||||
let mass = m.getMass() || m.cargo || m.fuel || 0;
|
let mass = m.getMass() || m.cargo || m.fuel || 0;
|
||||||
|
|
||||||
|
// Modifications tooltip shows blueprint and grade, if available
|
||||||
|
let modTT = translate('modified');
|
||||||
|
if (m && m.blueprint) {
|
||||||
|
modTT = translate(m.blueprint.name) + ' ' + translate('grade') + ' ' + m.blueprint.grade;
|
||||||
|
}
|
||||||
|
|
||||||
if (!selected) {
|
if (!selected) {
|
||||||
// If not selected then sure that modifications flag is unset
|
// If not selected then sure that modifications flag is unset
|
||||||
this._modificationsSelected = false;
|
this._modificationsSelected = false;
|
||||||
@@ -81,7 +87,7 @@ export default class StandardSlot extends TranslatedComponent {
|
|||||||
<div className={cn('details-container', { warning: warning && warning(slot.m) })}>
|
<div className={cn('details-container', { warning: warning && warning(slot.m) })}>
|
||||||
<div className={'sz'}>{slot.maxClass}</div>
|
<div className={'sz'}>{slot.maxClass}</div>
|
||||||
<div>
|
<div>
|
||||||
<div className={'l'}>{classRating} {translate(m.name || m.grp)}{m.mods && Object.keys(m.mods).length > 0 ? <span className='r' onMouseOver={termtip.bind(null, 'modified')} onMouseOut={tooltip.bind(null, null)}><Modified /></span> : null }</div>
|
<div className={'l'}>{classRating} {translate(m.name || m.grp)}{m.mods && Object.keys(m.mods).length > 0 ? <span className='r' onMouseOver={termtip.bind(null, modTT)} onMouseOut={tooltip.bind(null, null)}><Modified /></span> : null }</div>
|
||||||
<div className={'r'}>{formats.round(mass)}{units.T}</div>
|
<div className={'r'}>{formats.round(mass)}{units.T}</div>
|
||||||
<div/>
|
<div/>
|
||||||
<div className={'cb'}>
|
<div className={'cb'}>
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ export default class ErrorDetails extends React.Component {
|
|||||||
return <div className='error'>
|
return <div className='error'>
|
||||||
<h1>Jameson, we have a problem..</h1>
|
<h1>Jameson, we have a problem..</h1>
|
||||||
<h1><small>{error.message}</small></h1>
|
<h1><small>{error.message}</small></h1>
|
||||||
|
<div>Please note that this site uses Google Analytics to track performance and usage. If you are blocking cookies, for example using Ghostery, please disable blocking for this site and try again.</div>
|
||||||
{content}
|
{content}
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import Persist from '../stores/Persist';
|
|||||||
import Ship from '../shipyard/Ship';
|
import Ship from '../shipyard/Ship';
|
||||||
import { toDetailedBuild } from '../shipyard/Serializer';
|
import { toDetailedBuild } from '../shipyard/Serializer';
|
||||||
import { outfitURL } from '../utils/UrlGenerators';
|
import { outfitURL } from '../utils/UrlGenerators';
|
||||||
import { FloppyDisk, Bin, Switch, Download, Reload, Fuel } from '../components/SvgIcons';
|
import { FloppyDisk, Bin, Switch, Download, Reload, Fuel, LinkIcon } from '../components/SvgIcons';
|
||||||
import ShipSummaryTable from '../components/ShipSummaryTable';
|
import ShipSummaryTable from '../components/ShipSummaryTable';
|
||||||
import StandardSlotSection from '../components/StandardSlotSection';
|
import StandardSlotSection from '../components/StandardSlotSection';
|
||||||
import HardpointsSlotSection from '../components/HardpointsSlotSection';
|
import HardpointsSlotSection from '../components/HardpointsSlotSection';
|
||||||
@@ -20,6 +20,7 @@ import LineChart from '../components/LineChart';
|
|||||||
import PowerManagement from '../components/PowerManagement';
|
import PowerManagement from '../components/PowerManagement';
|
||||||
import CostSection from '../components/CostSection';
|
import CostSection from '../components/CostSection';
|
||||||
import ModalExport from '../components/ModalExport';
|
import ModalExport from '../components/ModalExport';
|
||||||
|
import ModalPermalink from '../components/ModalPermalink';
|
||||||
import Slider from '../components/Slider';
|
import Slider from '../components/Slider';
|
||||||
|
|
||||||
const SPEED_SERIES = ['boost', '4 Pips', '2 Pips', '0 Pips'];
|
const SPEED_SERIES = ['boost', '4 Pips', '2 Pips', '0 Pips'];
|
||||||
@@ -270,6 +271,13 @@ export default class OutfittingPage extends Page {
|
|||||||
this.resizeListener.remove();
|
this.resizeListener.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the short URL
|
||||||
|
*/
|
||||||
|
_genShortlink() {
|
||||||
|
this.context.showModal(<ModalPermalink url={window.location.href}/>);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render the Page
|
* Render the Page
|
||||||
* @return {React.Component} The page contents
|
* @return {React.Component} The page contents
|
||||||
@@ -289,8 +297,6 @@ export default class OutfittingPage extends Page {
|
|||||||
sStr = ship.getStandardString() + '.' + ship.getModificationsString(),
|
sStr = ship.getStandardString() + '.' + ship.getModificationsString(),
|
||||||
iStr = ship.getInternalString() + '.' + ship.getModificationsString();
|
iStr = ship.getInternalString() + '.' + ship.getModificationsString();
|
||||||
|
|
||||||
Router.replace(outfitURL(ship.id, code, buildName));
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id='outfit' className={'page'} style={{ fontSize: (sizeRatio * 0.9) + 'em' }}>
|
<div id='outfit' className={'page'} style={{ fontSize: (sizeRatio * 0.9) + 'em' }}>
|
||||||
<div id='overview'>
|
<div id='overview'>
|
||||||
@@ -315,6 +321,9 @@ export default class OutfittingPage extends Page {
|
|||||||
<button onClick={buildName && this._exportBuild} disabled={!buildName} onMouseOver={termtip.bind(null, 'export')} onMouseOut={hide}>
|
<button onClick={buildName && this._exportBuild} disabled={!buildName} onMouseOver={termtip.bind(null, 'export')} onMouseOut={hide}>
|
||||||
<Download className='lg'/>
|
<Download className='lg'/>
|
||||||
</button>
|
</button>
|
||||||
|
<button onClick={this._genShortlink} onMouseOver={termtip.bind(null, 'shortlink')} onMouseOut={hide}>
|
||||||
|
<LinkIcon className='lg' />
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import * as ModuleUtils from './ModuleUtils';
|
import * as ModuleUtils from './ModuleUtils';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
import { Modifications } from 'coriolis-data/dist';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Module - active module in a ship's buildout
|
* Module - active module in a ship's buildout
|
||||||
@@ -28,7 +29,7 @@ export default class Module {
|
|||||||
/**
|
/**
|
||||||
* Get a value for a given modification
|
* Get a value for a given modification
|
||||||
* @param {Number} name The name of the modification
|
* @param {Number} name The name of the modification
|
||||||
* @return {Number} The value of the modification, as an integer value scaled so that 1.23% == 123
|
* @return {object} The value of the modification. If it is a numeric value then it is returned as an integer value scaled so that 1.23% == 123
|
||||||
*/
|
*/
|
||||||
getModValue(name) {
|
getModValue(name) {
|
||||||
return this.mods && this.mods[name] ? this.mods[name] : null;
|
return this.mods && this.mods[name] ? this.mods[name] : null;
|
||||||
@@ -37,7 +38,7 @@ export default class Module {
|
|||||||
/**
|
/**
|
||||||
* Set a value for a given modification ID
|
* Set a value for a given modification ID
|
||||||
* @param {Number} name The name of the modification
|
* @param {Number} name The name of the modification
|
||||||
* @param {Number} value The value of the modification, as an integer scaled so that -2.34% == -234
|
* @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
|
||||||
*/
|
*/
|
||||||
setModValue(name, value) {
|
setModValue(name, value) {
|
||||||
if (!this.mods) {
|
if (!this.mods) {
|
||||||
@@ -47,8 +48,12 @@ export default class Module {
|
|||||||
if (value == null || value == 0) {
|
if (value == null || value == 0) {
|
||||||
delete this.mods[name];
|
delete this.mods[name];
|
||||||
} else {
|
} else {
|
||||||
// Round just to be sure
|
if (isNaN(value)) {
|
||||||
this.mods[name] = Math.round(value);
|
this.mods[name] = value;
|
||||||
|
} else {
|
||||||
|
// Round just to be sure
|
||||||
|
this.mods[name] = Math.round(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,8 +66,20 @@ export default class Module {
|
|||||||
_getModifiedValue(name, additive) {
|
_getModifiedValue(name, additive) {
|
||||||
let result = this[name] || (additive ? 0 : null); // Additive NULL === 0
|
let result = this[name] || (additive ? 0 : null); // Additive NULL === 0
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
// Jitter is special, being the only non-percentage value (it is in fact degrees)
|
const modification = Modifications.modifications[name];
|
||||||
const modValue = name === 'jitter' ? this.getModValue(name) / 100 : this.getModValue(name) / 10000;
|
if (!modification) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
// We store percentages as decimals, so to get them back we need to divide by 10000. Otherwise
|
||||||
|
// we divide by 100. Both ways we end up with a value with two decimal places
|
||||||
|
let modValue;
|
||||||
|
if (modification.type === 'percentage') {
|
||||||
|
modValue = this.getModValue(name) / 10000;
|
||||||
|
} else if (modification.type === 'numeric') {
|
||||||
|
modValue = this.getModValue(name) / 100;
|
||||||
|
} else {
|
||||||
|
modValue = this.getModValue(name);
|
||||||
|
}
|
||||||
if (modValue) {
|
if (modValue) {
|
||||||
if (additive) {
|
if (additive) {
|
||||||
result = result + modValue;
|
result = result + modValue;
|
||||||
@@ -70,7 +87,18 @@ export default class Module {
|
|||||||
result = result * (1 + modValue);
|
result = result * (1 + modValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (name === 'burst') {
|
||||||
|
// Burst is special, as if it can not exist but have a modification
|
||||||
|
const modValue = this.getModValue(name) / 100;
|
||||||
|
return modValue;
|
||||||
|
} else if (name === 'burstrof') {
|
||||||
|
// Burst rate of fire is special, as if it can not exist but have a modification
|
||||||
|
const modValue = this.getModValue(name) / 100;
|
||||||
|
return modValue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -421,7 +449,7 @@ export default class Module {
|
|||||||
getDps() {
|
getDps() {
|
||||||
// DPS is a synthetic value
|
// DPS is a synthetic value
|
||||||
let damage = this.getDamage();
|
let damage = this.getDamage();
|
||||||
let rpshot = this.getRoundsPerShot() || 1;
|
let rpshot = this.roundspershot || 1;
|
||||||
let rof = this.getRoF() || 1;
|
let rof = this.getRoF() || 1;
|
||||||
|
|
||||||
return damage * rpshot * rof;
|
return damage * rpshot * rof;
|
||||||
@@ -434,7 +462,7 @@ export default class Module {
|
|||||||
getEps() {
|
getEps() {
|
||||||
// EPS is a synthetic value
|
// EPS is a synthetic value
|
||||||
let distdraw = this.getDistDraw();
|
let distdraw = this.getDistDraw();
|
||||||
let rpshot = this.getRoundsPerShot() || 1;
|
let rpshot = this.roundspershot || 1;
|
||||||
let rof = this.getRoF() || 1;
|
let rof = this.getRoF() || 1;
|
||||||
|
|
||||||
return distdraw * rpshot * rof;
|
return distdraw * rpshot * rof;
|
||||||
@@ -447,7 +475,7 @@ export default class Module {
|
|||||||
getHps() {
|
getHps() {
|
||||||
// HPS is a synthetic value
|
// HPS is a synthetic value
|
||||||
let heat = this.getThermalLoad();
|
let heat = this.getThermalLoad();
|
||||||
let rpshot = this.getRoundsPerShot() || 1;
|
let rpshot = this.roundspershot || 1;
|
||||||
let rof = this.getRoF() || 1;
|
let rof = this.getRoF() || 1;
|
||||||
|
|
||||||
return heat * rpshot * rof;
|
return heat * rpshot * rof;
|
||||||
@@ -478,11 +506,35 @@ export default class Module {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the rate of fire for this module, taking in to account modifications
|
* Get the burst size for this module, taking in to account modifications
|
||||||
|
* @return {Number} the burst size of this module
|
||||||
|
*/
|
||||||
|
getBurst() {
|
||||||
|
return this._getModifiedValue('burst');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the burst rate of fire for this module, taking in to account modifications
|
||||||
|
* @return {Number} the burst rate of fire of this module
|
||||||
|
*/
|
||||||
|
getBurstRoF() {
|
||||||
|
return this._getModifiedValue('burstrof');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the rate of fire for this module, taking in to account modifications.
|
||||||
|
* The rate of fire is a combination value, and needs to take in to account
|
||||||
|
* bursts of fire.
|
||||||
|
* Firing goes [burst 1] [burst interval] [burst 2] [burst interval] ... [burst n] [interval]
|
||||||
|
* where 'n' is 'burst', 'burst interval' is '1/burstrof' and 'interval' is '1/rof'
|
||||||
* @return {Number} the rate of fire for this module
|
* @return {Number} the rate of fire for this module
|
||||||
*/
|
*/
|
||||||
getRoF() {
|
getRoF() {
|
||||||
return this._getModifiedValue('rof');
|
const burst = this.getBurst() || 1;
|
||||||
|
const burstRoF = this.getBurstRoF() || 1;
|
||||||
|
const intRoF = this._getModifiedValue('rof');
|
||||||
|
|
||||||
|
return burst / (((burst - 1) / burstRoF) + 1 / intRoF);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -533,7 +585,6 @@ export default class Module {
|
|||||||
return this._getModifiedValue('cells');
|
return this._getModifiedValue('cells');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the jitter for this module, taking in to account modifications
|
* Get the jitter for this module, taking in to account modifications
|
||||||
* @return {Number} the jitter for this module
|
* @return {Number} the jitter for this module
|
||||||
@@ -541,4 +592,12 @@ export default class Module {
|
|||||||
getJitter() {
|
getJitter() {
|
||||||
return this._getModifiedValue('jitter', true);
|
return this._getModifiedValue('jitter', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the damage type for this module, taking in to account modifications
|
||||||
|
* @return {string} the damage types for this module; any combination of E T and K
|
||||||
|
*/
|
||||||
|
getDamageType() {
|
||||||
|
return this.getModValue('type') || this.type;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,6 +105,59 @@ export function internal(id) {
|
|||||||
return null;
|
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.
|
* Finds an internal module 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
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ import { outfitURL } from '../utils/UrlGenerators';
|
|||||||
|
|
||||||
const STANDARD = ['powerPlant', 'thrusters', 'frameShiftDrive', 'lifeSupport', 'powerDistributor', 'sensors', 'fuelTank'];
|
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
|
* Generates ship-loadout JSON Schema standard object
|
||||||
* @param {Object} standard model
|
* @param {Object} standard model
|
||||||
@@ -30,6 +32,10 @@ function standardToSchema(standard) {
|
|||||||
o.modifications = standard.m.mods;
|
o.modifications = standard.m.mods;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (standard.m.blueprint && Object.keys(standard.m.blueprint).length > 0) {
|
||||||
|
o.blueprint = standard.m.blueprint;
|
||||||
|
}
|
||||||
|
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@@ -62,6 +68,10 @@ function slotToSchema(slot) {
|
|||||||
if (slot.m.mods && Object.keys(slot.m.mods).length > 0) {
|
if (slot.m.mods && Object.keys(slot.m.mods).length > 0) {
|
||||||
o.modifications = slot.m.mods;
|
o.modifications = slot.m.mods;
|
||||||
}
|
}
|
||||||
|
if (slot.m.blueprint && Object.keys(slot.m.blueprint).length > 0) {
|
||||||
|
o.blueprint = slot.m.blueprint;
|
||||||
|
}
|
||||||
|
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@@ -137,6 +147,7 @@ export function fromDetailedBuild(detailedBuild) {
|
|||||||
let ship = new Ship(shipId, shipData.properties, shipData.slots);
|
let ship = new Ship(shipId, shipData.properties, shipData.slots);
|
||||||
let bulkheads = ModuleUtils.bulkheadIndex(stn.bulkheads);
|
let bulkheads = ModuleUtils.bulkheadIndex(stn.bulkheads);
|
||||||
let modifications = new Array(stn.bulkheads.modifications);
|
let modifications = new Array(stn.bulkheads.modifications);
|
||||||
|
let blueprints = new Array(stn.bulkheads.blueprint);
|
||||||
|
|
||||||
if (bulkheads < 0) {
|
if (bulkheads < 0) {
|
||||||
throw 'Invalid bulkheads: ' + stn.bulkheads;
|
throw 'Invalid bulkheads: ' + stn.bulkheads;
|
||||||
@@ -149,13 +160,13 @@ export function fromDetailedBuild(detailedBuild) {
|
|||||||
priorities.push(stn[c].priority === undefined ? 0 : stn[c].priority - 1);
|
priorities.push(stn[c].priority === undefined ? 0 : stn[c].priority - 1);
|
||||||
enabled.push(stn[c].enabled === undefined ? true : stn[c].enabled);
|
enabled.push(stn[c].enabled === undefined ? true : stn[c].enabled);
|
||||||
modifications.push(stn[c].modifications);
|
modifications.push(stn[c].modifications);
|
||||||
return stn[c].class + stn[c].rating;
|
blueprints.push(stn[c].blueprint);
|
||||||
|
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 internal = comps.internal.map(c => c ? ModuleUtils.findInternalId(c.group, c.class, c.rating, c.name) : 0);
|
||||||
|
|
||||||
let hardpoints = comps.hardpoints
|
let hardpoints = comps.hardpoints.map(c => c ? ModuleUtils.findHardpointId(c.group, c.class, c.rating, c.name, MountMap[c.mount], c.missile) : 0)
|
||||||
.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));
|
.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
|
// The ordering of these arrays must match the order in which they are read in Ship.buildWith
|
||||||
@@ -170,12 +181,17 @@ export function fromDetailedBuild(detailedBuild) {
|
|||||||
comps.internal.map(c => (!c || c.enabled === undefined) ? true : c.enabled * 1)
|
comps.internal.map(c => (!c || c.enabled === undefined) ? true : c.enabled * 1)
|
||||||
);
|
);
|
||||||
modifications = modifications.concat(
|
modifications = modifications.concat(
|
||||||
comps.hardpoints.map(c => (c && c.m ? c.m.modifications : null)),
|
comps.hardpoints.map(c => (c ? c.modifications : null)),
|
||||||
comps.utility.map(c => (c && c.m ? c.m.modifications : null)),
|
comps.utility.map(c => (c ? c.modifications : null)),
|
||||||
comps.internal.map(c => (c && c.m ? c.m.modifications : null))
|
comps.internal.map(c => (c ? c.modifications : null))
|
||||||
|
);
|
||||||
|
blueprints = blueprints.concat(
|
||||||
|
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);
|
ship.buildWith({ bulkheads, standard, hardpoints, internal }, priorities, enabled, modifications, blueprints);
|
||||||
|
|
||||||
return ship;
|
return ship;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,12 +3,20 @@ import * as ModuleUtils from './ModuleUtils';
|
|||||||
import * as Utils from '../utils/UtilityFunctions';
|
import * as Utils from '../utils/UtilityFunctions';
|
||||||
import Module from './Module';
|
import Module from './Module';
|
||||||
import LZString from 'lz-string';
|
import LZString from 'lz-string';
|
||||||
|
import * as _ from 'lodash';
|
||||||
import isEqual from 'lodash/lang';
|
import isEqual from 'lodash/lang';
|
||||||
import { Modifications } from 'coriolis-data/dist';
|
import { Modifications } from 'coriolis-data/dist';
|
||||||
const zlib = require('zlib');
|
const zlib = require('zlib');
|
||||||
|
|
||||||
const UNIQUE_MODULES = ['psg', 'sg', 'bsg', 'rf', 'fs', 'fh'];
|
const UNIQUE_MODULES = ['psg', 'sg', 'bsg', 'rf', 'fs', 'fh'];
|
||||||
|
|
||||||
|
// Constants for modifications struct
|
||||||
|
const SLOT_ID_DONE = -1;
|
||||||
|
const MODIFICATION_ID_DONE = -1;
|
||||||
|
const MODIFICATION_ID_BLUEPRINT = -2;
|
||||||
|
const MODIFICATION_ID_GRADE = -3;
|
||||||
|
const MODIFICATION_ID_SPECIAL = -4;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the power usage type of a slot and it's particular module
|
* Returns the power usage type of a slot and it's particular module
|
||||||
* @param {Object} slot The Slot
|
* @param {Object} slot The Slot
|
||||||
@@ -450,7 +458,7 @@ export default class Ship {
|
|||||||
} else if (name === 'shieldreinforcement') {
|
} else if (name === 'shieldreinforcement') {
|
||||||
m.setModValue(name, value);
|
m.setModValue(name, value);
|
||||||
this.recalculateShieldCells();
|
this.recalculateShieldCells();
|
||||||
} else if (name === 'burst' || name === 'clip' || name === 'damage' || name === 'distdraw' || name === 'jitter' || name === 'piercing' || name === 'range' || name === 'reload' || name === 'rof' || name === 'thermload') {
|
} else if (name === 'burst' || name == 'burstrof' || name === 'clip' || name === 'damage' || name === 'distdraw' || name === 'jitter' || name === 'piercing' || name === 'range' || name === 'reload' || name === 'rof' || name === 'thermload') {
|
||||||
m.setModValue(name, value);
|
m.setModValue(name, value);
|
||||||
this.recalculateDps();
|
this.recalculateDps();
|
||||||
this.recalculateHps();
|
this.recalculateHps();
|
||||||
@@ -472,9 +480,10 @@ export default class Ship {
|
|||||||
* @param {array} priorities Slot priorities
|
* @param {array} priorities Slot priorities
|
||||||
* @param {Array} enabled Slot active/inactive
|
* @param {Array} enabled Slot active/inactive
|
||||||
* @param {Array} mods Modifications
|
* @param {Array} mods Modifications
|
||||||
|
* @param {Array} blueprints Blueprints for modifications
|
||||||
* @return {this} The current ship instance for chaining
|
* @return {this} The current ship instance for chaining
|
||||||
*/
|
*/
|
||||||
buildWith(comps, priorities, enabled, mods) {
|
buildWith(comps, priorities, enabled, mods, blueprints) {
|
||||||
let internal = this.internal,
|
let internal = this.internal,
|
||||||
standard = this.standard,
|
standard = this.standard,
|
||||||
hps = this.hardpoints,
|
hps = this.hardpoints,
|
||||||
@@ -514,6 +523,7 @@ export default class Ship {
|
|||||||
this.bulkheads.m = null;
|
this.bulkheads.m = null;
|
||||||
this.useBulkhead(comps && comps.bulkheads ? comps.bulkheads : 0, true);
|
this.useBulkhead(comps && comps.bulkheads ? comps.bulkheads : 0, true);
|
||||||
this.bulkheads.m.mods = mods && mods[0] ? mods[0] : {};
|
this.bulkheads.m.mods = mods && mods[0] ? mods[0] : {};
|
||||||
|
this.bulkheads.m.blueprint = blueprints && blueprints[0] ? blueprints[0] : {};
|
||||||
this.cargoHatch.priority = priorities ? priorities[0] * 1 : 0;
|
this.cargoHatch.priority = priorities ? priorities[0] * 1 : 0;
|
||||||
this.cargoHatch.enabled = enabled ? enabled[0] * 1 : true;
|
this.cargoHatch.enabled = enabled ? enabled[0] * 1 : true;
|
||||||
|
|
||||||
@@ -526,7 +536,10 @@ export default class Ship {
|
|||||||
standard[i].discountedCost = 0;
|
standard[i].discountedCost = 0;
|
||||||
if (comps) {
|
if (comps) {
|
||||||
let module = ModuleUtils.standard(i, comps.standard[i]);
|
let module = ModuleUtils.standard(i, comps.standard[i]);
|
||||||
if (module != null) { module.mods = mods && mods[i + 1] ? mods[i + 1] : {}; }
|
if (module != null) {
|
||||||
|
module.mods = mods && mods[i + 1] ? mods[i + 1] : {};
|
||||||
|
module.blueprint = blueprints && blueprints[i + 1] ? blueprints[i + 1] : {};
|
||||||
|
}
|
||||||
this.use(standard[i], module, true);
|
this.use(standard[i], module, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -545,7 +558,10 @@ export default class Ship {
|
|||||||
|
|
||||||
if (comps && comps.hardpoints[i] !== 0) {
|
if (comps && comps.hardpoints[i] !== 0) {
|
||||||
let module = ModuleUtils.hardpoints(comps.hardpoints[i]);
|
let module = ModuleUtils.hardpoints(comps.hardpoints[i]);
|
||||||
if (module != null) { module.mods = mods && mods[cl + i] ? mods[cl + i] : {}; }
|
if (module != null) {
|
||||||
|
module.mods = mods && mods[cl + i] ? mods[cl + i] : {};
|
||||||
|
module.blueprint = blueprints && blueprints[cl + i] ? blueprints[cl + i] : {};
|
||||||
|
}
|
||||||
this.use(hps[i], module, true);
|
this.use(hps[i], module, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -562,7 +578,10 @@ export default class Ship {
|
|||||||
|
|
||||||
if (comps && comps.internal[i] !== 0) {
|
if (comps && comps.internal[i] !== 0) {
|
||||||
let module = ModuleUtils.internal(comps.internal[i]);
|
let module = ModuleUtils.internal(comps.internal[i]);
|
||||||
if (module != null) { module.mods = mods && mods[cl + i] ? mods[cl + i] : {}; }
|
if (module != null) {
|
||||||
|
module.mods = mods && mods[cl + i] ? mods[cl + i] : {};
|
||||||
|
module.blueprint = blueprints && blueprints[cl + i] ? blueprints[cl + i] : {};
|
||||||
|
}
|
||||||
this.use(internal[i], module, true);
|
this.use(internal[i], module, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -596,6 +615,7 @@ export default class Ship {
|
|||||||
hardpoints = new Array(this.hardpoints.length),
|
hardpoints = new Array(this.hardpoints.length),
|
||||||
internal = new Array(this.internal.length),
|
internal = new Array(this.internal.length),
|
||||||
modifications = new Array(1 + this.standard.length + this.hardpoints.length + this.internal.length),
|
modifications = new Array(1 + this.standard.length + this.hardpoints.length + this.internal.length),
|
||||||
|
blueprints = new Array(1 + this.standard.length + this.hardpoints.length + this.internal.length),
|
||||||
parts = serializedString.split('.'),
|
parts = serializedString.split('.'),
|
||||||
priorities = null,
|
priorities = null,
|
||||||
enabled = null,
|
enabled = null,
|
||||||
@@ -615,7 +635,7 @@ export default class Ship {
|
|||||||
this.decodeModificationsString(modstr, modifications);
|
this.decodeModificationsString(modstr, modifications);
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
this.decodeModificationsStruct(zlib.gunzipSync(new Buffer(Utils.fromUrlSafe(modstr), 'base64')), modifications);
|
this.decodeModificationsStruct(zlib.gunzipSync(new Buffer(Utils.fromUrlSafe(modstr), 'base64')), modifications, blueprints);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// Could be out-of-date URL; ignore
|
// Could be out-of-date URL; ignore
|
||||||
}
|
}
|
||||||
@@ -633,7 +653,8 @@ export default class Ship {
|
|||||||
},
|
},
|
||||||
priorities,
|
priorities,
|
||||||
enabled,
|
enabled,
|
||||||
modifications
|
modifications,
|
||||||
|
blueprints,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -909,22 +930,22 @@ export default class Ship {
|
|||||||
totalDpe += dpe;
|
totalDpe += dpe;
|
||||||
totalDps += dps;
|
totalDps += dps;
|
||||||
totalSDps += sdps;
|
totalSDps += sdps;
|
||||||
if (slot.m.type === 'E') {
|
if (slot.m.getDamageType() === 'E') {
|
||||||
totalExplDpe += dpe;
|
totalExplDpe += dpe;
|
||||||
totalExplDps += dps;
|
totalExplDps += dps;
|
||||||
totalExplSDps += sdps;
|
totalExplSDps += sdps;
|
||||||
}
|
}
|
||||||
if (slot.m.type === 'K') {
|
if (slot.m.getDamageType() === 'K') {
|
||||||
totalKinDpe += dpe;
|
totalKinDpe += dpe;
|
||||||
totalKinDps += dps;
|
totalKinDps += dps;
|
||||||
totalKinSDps += sdps;
|
totalKinSDps += sdps;
|
||||||
}
|
}
|
||||||
if (slot.m.type === 'T') {
|
if (slot.m.getDamageType() === 'T') {
|
||||||
totalThermDpe += dpe;
|
totalThermDpe += dpe;
|
||||||
totalThermDps += dps;
|
totalThermDps += dps;
|
||||||
totalThermSDps += sdps;
|
totalThermSDps += sdps;
|
||||||
}
|
}
|
||||||
if (slot.m.type === 'EK') {
|
if (slot.m.getDamageType() === 'EK') {
|
||||||
totalExplDpe += dpe / 2;
|
totalExplDpe += dpe / 2;
|
||||||
totalKinDpe += dpe / 2;
|
totalKinDpe += dpe / 2;
|
||||||
totalExplDps += dps / 2;
|
totalExplDps += dps / 2;
|
||||||
@@ -932,7 +953,7 @@ export default class Ship {
|
|||||||
totalExplSDps += sdps / 2;
|
totalExplSDps += sdps / 2;
|
||||||
totalKinSDps += sdps / 2;
|
totalKinSDps += sdps / 2;
|
||||||
}
|
}
|
||||||
if (slot.m.type === 'ET') {
|
if (slot.m.getDamageType() === 'ET') {
|
||||||
totalExplDpe += dpe / 2;
|
totalExplDpe += dpe / 2;
|
||||||
totalThermDpe += dpe / 2;
|
totalThermDpe += dpe / 2;
|
||||||
totalExplDps += dps / 2;
|
totalExplDps += dps / 2;
|
||||||
@@ -940,7 +961,7 @@ export default class Ship {
|
|||||||
totalExplSDps += sdps / 2;
|
totalExplSDps += sdps / 2;
|
||||||
totalThermSDps += sdps / 2;
|
totalThermSDps += sdps / 2;
|
||||||
}
|
}
|
||||||
if (slot.m.type === 'KT') {
|
if (slot.m.getDamageType() === 'KT') {
|
||||||
totalKinDpe += dpe / 2;
|
totalKinDpe += dpe / 2;
|
||||||
totalThermDpe += dpe / 2;
|
totalThermDpe += dpe / 2;
|
||||||
totalKinDps += dps / 2;
|
totalKinDps += dps / 2;
|
||||||
@@ -1224,52 +1245,6 @@ export default class Ship {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the modifications string in a human-readable format
|
|
||||||
* @return {this} The ship instance (for chaining operations)
|
|
||||||
*/
|
|
||||||
debugupdateModificationsString() {
|
|
||||||
let allMods = new Array();
|
|
||||||
|
|
||||||
let bulkheadMods = new Array();
|
|
||||||
if (this.bulkheads.m && this.bulkheads.m.mods) {
|
|
||||||
for (let modKey in this.bulkheads.m.mods) {
|
|
||||||
bulkheadMods.push(Modifications.modifications.indexOf(modKey) + ':' + this.bulkheads.m.getModValue(modKey));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
allMods.push(bulkheadMods.join(';'));
|
|
||||||
|
|
||||||
for (let slot of this.standard) {
|
|
||||||
let slotMods = new Array();
|
|
||||||
if (slot.m && slot.m.mods) {
|
|
||||||
for (let modKey in slot.m.mods) {
|
|
||||||
slotMods.push(Modifications.modifications.indexOf(modKey) + ':' + slot.m.getModValue(modKey));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
allMods.push(slotMods.join(';'));
|
|
||||||
}
|
|
||||||
for (let slot of this.hardpoints) {
|
|
||||||
let slotMods = new Array();
|
|
||||||
if (slot.m && slot.m.mods) {
|
|
||||||
for (let modKey in slot.m.mods) {
|
|
||||||
slotMods.push(Modifications.modifications.indexOf(modKey) + ':' + slot.m.getModValue(modKey));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
allMods.push(slotMods.join(';'));
|
|
||||||
}
|
|
||||||
for (let slot of this.internal) {
|
|
||||||
let slotMods = new Array();
|
|
||||||
if (slot.m && slot.m.mods) {
|
|
||||||
for (let modKey in slot.m.mods) {
|
|
||||||
slotMods.push(Modifications.modifications.indexOf(modKey) + ':' + slot.m.getModValue(modKey));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
allMods.push(slotMods.join(';'));
|
|
||||||
}
|
|
||||||
this.serialized.modifications = LZString.compressToBase64(allMods.join(',').replace(/,+$/, ''));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Populate the modifications array with modification values from the code
|
* Populate the modifications array with modification values from the code
|
||||||
* @param {String} code Serialized modification code
|
* @param {String} code Serialized modification code
|
||||||
@@ -1284,7 +1259,8 @@ export default class Ship {
|
|||||||
for (let j = 0; j < mods.length; j++) {
|
for (let j = 0; j < mods.length; j++) {
|
||||||
let modElements = mods[j].split(':');
|
let modElements = mods[j].split(':');
|
||||||
if (modElements[0].match('[0-9]+')) {
|
if (modElements[0].match('[0-9]+')) {
|
||||||
arr[i][Modifications.modifications[modElements[0]]] = Number(modElements[1]);
|
const modification = _.find(Modifications.modifications, function(o) { return o.id === modElements[0]; });
|
||||||
|
if (modification != null) arr[i][modification.name] = Number(modElements[1]);
|
||||||
} else {
|
} else {
|
||||||
arr[i][modElements[0]] = Number(modElements[1]);
|
arr[i][modElements[0]] = Number(modElements[1]);
|
||||||
}
|
}
|
||||||
@@ -1305,17 +1281,24 @@ export default class Ship {
|
|||||||
updateModificationsString() {
|
updateModificationsString() {
|
||||||
// Start off by gathering the information that we need
|
// Start off by gathering the information that we need
|
||||||
let slots = new Array();
|
let slots = new Array();
|
||||||
|
let blueprints = new Array();
|
||||||
|
let specials = new Array();
|
||||||
|
|
||||||
let bulkheadMods = new Array();
|
let bulkheadMods = new Array();
|
||||||
|
let bulkheadBlueprint = null;
|
||||||
|
let bulkheadBlueprintGrade = null;
|
||||||
if (this.bulkheads.m && this.bulkheads.m.mods) {
|
if (this.bulkheads.m && this.bulkheads.m.mods) {
|
||||||
for (let modKey in this.bulkheads.m.mods) {
|
for (let modKey in this.bulkheads.m.mods) {
|
||||||
// Filter out invalid modifications
|
// Filter out invalid modifications
|
||||||
if (Modifications.validity['bh'] && Modifications.validity['bh'].indexOf(modKey) != -1) {
|
if (Modifications.validity['bh'] && Modifications.validity['bh'].indexOf(modKey) != -1) {
|
||||||
bulkheadMods.push({ id: Modifications.modifications.indexOf(modKey), value: this.bulkheads.m.getModValue(modKey) });
|
bulkheadMods.push({ id: Modifications.modifications[modKey].id, value: this.bulkheads.m.getModValue(modKey) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
bulkheadBlueprint = this.bulkheads.m.blueprint;
|
||||||
}
|
}
|
||||||
slots.push(bulkheadMods);
|
slots.push(bulkheadMods);
|
||||||
|
blueprints.push(bulkheadBlueprint);
|
||||||
|
specials.push(bulkheadBlueprint ? bulkheadBlueprint.special : null);
|
||||||
|
|
||||||
for (let slot of this.standard) {
|
for (let slot of this.standard) {
|
||||||
let slotMods = new Array();
|
let slotMods = new Array();
|
||||||
@@ -1323,11 +1306,13 @@ export default class Ship {
|
|||||||
for (let modKey in slot.m.mods) {
|
for (let modKey in slot.m.mods) {
|
||||||
// Filter out invalid modifications
|
// Filter out invalid modifications
|
||||||
if (Modifications.validity[slot.m.grp] && Modifications.validity[slot.m.grp].indexOf(modKey) != -1) {
|
if (Modifications.validity[slot.m.grp] && Modifications.validity[slot.m.grp].indexOf(modKey) != -1) {
|
||||||
slotMods.push({ id: Modifications.modifications.indexOf(modKey), value: slot.m.getModValue(modKey) });
|
slotMods.push({ id: Modifications.modifications[modKey].id, value: slot.m.getModValue(modKey) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
slots.push(slotMods);
|
slots.push(slotMods);
|
||||||
|
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) {
|
for (let slot of this.hardpoints) {
|
||||||
@@ -1336,11 +1321,13 @@ export default class Ship {
|
|||||||
for (let modKey in slot.m.mods) {
|
for (let modKey in slot.m.mods) {
|
||||||
// Filter out invalid modifications
|
// Filter out invalid modifications
|
||||||
if (Modifications.validity[slot.m.grp] && Modifications.validity[slot.m.grp].indexOf(modKey) != -1) {
|
if (Modifications.validity[slot.m.grp] && Modifications.validity[slot.m.grp].indexOf(modKey) != -1) {
|
||||||
slotMods.push({ id: Modifications.modifications.indexOf(modKey), value: slot.m.getModValue(modKey) });
|
slotMods.push({ id: Modifications.modifications[modKey].id, value: slot.m.getModValue(modKey) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
slots.push(slotMods);
|
slots.push(slotMods);
|
||||||
|
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) {
|
for (let slot of this.internal) {
|
||||||
@@ -1349,18 +1336,27 @@ export default class Ship {
|
|||||||
for (let modKey in slot.m.mods) {
|
for (let modKey in slot.m.mods) {
|
||||||
// Filter out invalid modifications
|
// Filter out invalid modifications
|
||||||
if (Modifications.validity[slot.m.grp] && Modifications.validity[slot.m.grp].indexOf(modKey) != -1) {
|
if (Modifications.validity[slot.m.grp] && Modifications.validity[slot.m.grp].indexOf(modKey) != -1) {
|
||||||
slotMods.push({ id: Modifications.modifications.indexOf(modKey), value: slot.m.getModValue(modKey) });
|
slotMods.push({ id: Modifications.modifications[modKey].id, value: slot.m.getModValue(modKey) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
slots.push(slotMods);
|
slots.push(slotMods);
|
||||||
|
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
|
// Now work out the size of the binary buffer from our modifications array
|
||||||
let bufsize = 0;
|
let bufsize = 0;
|
||||||
for (let slot of slots) {
|
for (let slot of slots) {
|
||||||
if (slot.length > 0) {
|
if (slot.length > 0) {
|
||||||
bufsize = bufsize + 1 + (5 * slot.length) + 1;
|
// Length is 1 for the slot ID, 10 for the blueprint name and grade, 5 for each modification, and 1 for the end marker
|
||||||
|
bufsize = bufsize + 1 + 10 + (5 * slot.length) + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let special of specials) {
|
||||||
|
if (special) {
|
||||||
|
// Length is 5 for each special
|
||||||
|
bufsize += 5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1373,18 +1369,37 @@ export default class Ship {
|
|||||||
for (let slot of slots) {
|
for (let slot of slots) {
|
||||||
if (slot.length > 0) {
|
if (slot.length > 0) {
|
||||||
buffer.writeInt8(i, curpos++);
|
buffer.writeInt8(i, curpos++);
|
||||||
for (let slotMod of slot) {
|
if (blueprints[i]) {
|
||||||
buffer.writeInt8(slotMod.id, curpos++);
|
buffer.writeInt8(MODIFICATION_ID_BLUEPRINT, curpos++);
|
||||||
buffer.writeInt32LE(slotMod.value, curpos);
|
buffer.writeInt32LE(blueprints[i].id, curpos);
|
||||||
// console.log('ENCODE Slot ' + i + ': ' + Modifications.modifications[slotMod.id] + ' = ' + slotMod.value);
|
curpos += 4;
|
||||||
|
buffer.writeInt8(MODIFICATION_ID_GRADE, curpos++);
|
||||||
|
buffer.writeInt32LE(blueprints[i].grade, curpos);
|
||||||
curpos += 4;
|
curpos += 4;
|
||||||
}
|
}
|
||||||
buffer.writeInt8(-1, curpos++);
|
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)) {
|
||||||
|
// Need to write the string with exactly four characters, so pad with whitespace
|
||||||
|
buffer.write((' ' + slotMod.value).slice(-4), curpos, 4);
|
||||||
|
} else {
|
||||||
|
buffer.writeInt32LE(slotMod.value, curpos);
|
||||||
|
}
|
||||||
|
// const modification = _.find(Modifications.modifications, function(o) { return o.id === slotMod.id; });
|
||||||
|
// console.log('ENCODE Slot ' + i + ': ' + modification.name + ' = ' + slotMod.value);
|
||||||
|
curpos += 4;
|
||||||
|
}
|
||||||
|
buffer.writeInt8(MODIFICATION_ID_DONE, curpos++);
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
if (curpos > 0) {
|
if (curpos > 0) {
|
||||||
buffer.writeInt8(-1, curpos++);
|
buffer.writeInt8(SLOT_ID_DONE, curpos++);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.serialized.modifications = zlib.gzipSync(buffer).toString('base64');
|
this.serialized.modifications = zlib.gzipSync(buffer).toString('base64');
|
||||||
@@ -1397,23 +1412,42 @@ export default class Ship {
|
|||||||
/**
|
/**
|
||||||
* Populate the modifications array with modification values from the code.
|
* Populate the modifications array with modification values from the code.
|
||||||
* See updateModificationsString() for details of the structure.
|
* See updateModificationsString() for details of the structure.
|
||||||
* @param {String} buffer Buffer holding modification info
|
* @param {String} buffer Buffer holding modification info
|
||||||
* @param {Array} arr Modification array
|
* @param {Array} modArr Modification array
|
||||||
|
* @param {Array} blueprintArr Blueprint array
|
||||||
*/
|
*/
|
||||||
decodeModificationsStruct(buffer, arr) {
|
decodeModificationsStruct(buffer, modArr, blueprintArr) {
|
||||||
let curpos = 0;
|
let curpos = 0;
|
||||||
let slot = buffer.readInt8(curpos++);
|
let slot = buffer.readInt8(curpos++);
|
||||||
while (slot != -1) {
|
while (slot != SLOT_ID_DONE) {
|
||||||
let modifications = {};
|
let modifications = {};
|
||||||
|
let blueprint = {};
|
||||||
let modificationId = buffer.readInt8(curpos++);
|
let modificationId = buffer.readInt8(curpos++);
|
||||||
while (modificationId != -1) {
|
while (modificationId != MODIFICATION_ID_DONE) {
|
||||||
let modificationValue = buffer.readInt32LE(curpos);
|
let modificationValue;
|
||||||
|
if (modificationId === 40) {
|
||||||
|
// Type is special, in that it's a character string
|
||||||
|
modificationValue = buffer.toString('utf8', curpos, curpos + 4).trim();
|
||||||
|
} else {
|
||||||
|
modificationValue = buffer.readInt32LE(curpos);
|
||||||
|
}
|
||||||
curpos += 4;
|
curpos += 4;
|
||||||
// console.log('DECODE Slot ' + slot + ': ' + Modifications.modifications[modificationId] + ' = ' + modificationValue);
|
// There are a number of 'special' modification IDs, check for them here
|
||||||
modifications[Modifications.modifications[modificationId]] = modificationValue;
|
if (modificationId === MODIFICATION_ID_BLUEPRINT) {
|
||||||
|
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);
|
||||||
|
modifications[modification.name] = modificationValue;
|
||||||
|
}
|
||||||
modificationId = buffer.readInt8(curpos++);
|
modificationId = buffer.readInt8(curpos++);
|
||||||
}
|
}
|
||||||
arr[slot] = modifications;
|
modArr[slot] = modifications;
|
||||||
|
blueprintArr[slot] = blueprint;
|
||||||
slot = buffer.readInt8(curpos++);
|
slot = buffer.readInt8(curpos++);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ const SHIP_FD_NAME_TO_CORIOLIS_NAME = {
|
|||||||
'CobraMkIII': 'cobra_mk_iii',
|
'CobraMkIII': 'cobra_mk_iii',
|
||||||
'CobraMkIV': 'cobra_mk_iv',
|
'CobraMkIV': 'cobra_mk_iv',
|
||||||
'Cutter': 'imperial_cutter',
|
'Cutter': 'imperial_cutter',
|
||||||
'DiamondBack': 'diamondback_explorer',
|
'DiamondBackXL': 'diamondback_explorer',
|
||||||
'DiamondBackXL': 'diamondback',
|
'DiamondBack': 'diamondback',
|
||||||
'Eagle': 'eagle',
|
'Eagle': 'eagle',
|
||||||
'Empire_Courier': 'imperial_courier',
|
'Empire_Courier': 'imperial_courier',
|
||||||
'Empire_Eagle': 'imperial_eagle',
|
'Empire_Eagle': 'imperial_eagle',
|
||||||
@@ -149,13 +149,13 @@ export function shipFromJson(json) {
|
|||||||
throw 'Unknown bulkheads "' + armourJson.name + '"';
|
throw 'Unknown bulkheads "' + armourJson.name + '"';
|
||||||
}
|
}
|
||||||
ship.bulkheads.enabled = true;
|
ship.bulkheads.enabled = true;
|
||||||
if (armourJson.modifiers) _addModifications(ship.bulkheads.m, armourJson.modifiers);
|
if (armourJson.modifiers) _addModifications(ship.bulkheads.m, armourJson.modifiers, armourJson.recipeName, armourJson.recipeLevel);
|
||||||
|
|
||||||
// Add the standard modules
|
// Add the standard modules
|
||||||
// Power plant
|
// Power plant
|
||||||
const powerplantJson = json.modules.PowerPlant.module;
|
const powerplantJson = json.modules.PowerPlant.module;
|
||||||
const powerplant = _moduleFromEdId(powerplantJson.id);
|
const powerplant = _moduleFromEdId(powerplantJson.id);
|
||||||
if (powerplantJson.modifiers) _addModifications(powerplant, powerplantJson.modifiers);
|
if (powerplantJson.modifiers) _addModifications(powerplant, powerplantJson.modifiers, powerplantJson.recipeName, powerplantJson.recipeLevel);
|
||||||
ship.use(ship.standard[0], powerplant, true);
|
ship.use(ship.standard[0], powerplant, true);
|
||||||
ship.standard[0].enabled = powerplantJson.on === true;
|
ship.standard[0].enabled = powerplantJson.on === true;
|
||||||
ship.standard[0].priority = powerplantJson.priority;
|
ship.standard[0].priority = powerplantJson.priority;
|
||||||
@@ -163,7 +163,7 @@ export function shipFromJson(json) {
|
|||||||
// Thrusters
|
// Thrusters
|
||||||
const thrustersJson = json.modules.MainEngines.module;
|
const thrustersJson = json.modules.MainEngines.module;
|
||||||
const thrusters = _moduleFromEdId(thrustersJson.id);
|
const thrusters = _moduleFromEdId(thrustersJson.id);
|
||||||
if (thrustersJson.modifiers) _addModifications(thrusters, thrustersJson.modifiers);
|
if (thrustersJson.modifiers) _addModifications(thrusters, thrustersJson.modifiers, thrustersJson.recipeName, thrustersJson.recipeLevel);
|
||||||
ship.use(ship.standard[1], thrusters, true);
|
ship.use(ship.standard[1], thrusters, true);
|
||||||
ship.standard[1].enabled = thrustersJson.on === true;
|
ship.standard[1].enabled = thrustersJson.on === true;
|
||||||
ship.standard[1].priority = thrustersJson.priority;
|
ship.standard[1].priority = thrustersJson.priority;
|
||||||
@@ -171,7 +171,7 @@ export function shipFromJson(json) {
|
|||||||
// FSD
|
// FSD
|
||||||
const frameshiftdriveJson = json.modules.FrameShiftDrive.module;
|
const frameshiftdriveJson = json.modules.FrameShiftDrive.module;
|
||||||
const frameshiftdrive = _moduleFromEdId(frameshiftdriveJson.id);
|
const frameshiftdrive = _moduleFromEdId(frameshiftdriveJson.id);
|
||||||
if (frameshiftdriveJson.modifiers) _addModifications(frameshiftdrive, frameshiftdriveJson.modifiers);
|
if (frameshiftdriveJson.modifiers) _addModifications(frameshiftdrive, frameshiftdriveJson.modifiers, frameshiftdriveJson.recipeName, frameshiftdriveJson.recipeLevel);
|
||||||
ship.use(ship.standard[2], frameshiftdrive, true);
|
ship.use(ship.standard[2], frameshiftdrive, true);
|
||||||
ship.standard[2].enabled = frameshiftdriveJson.on === true;
|
ship.standard[2].enabled = frameshiftdriveJson.on === true;
|
||||||
ship.standard[2].priority = frameshiftdriveJson.priority;
|
ship.standard[2].priority = frameshiftdriveJson.priority;
|
||||||
@@ -179,7 +179,7 @@ export function shipFromJson(json) {
|
|||||||
// Life support
|
// Life support
|
||||||
const lifesupportJson = json.modules.LifeSupport.module;
|
const lifesupportJson = json.modules.LifeSupport.module;
|
||||||
const lifesupport = _moduleFromEdId(lifesupportJson.id);
|
const lifesupport = _moduleFromEdId(lifesupportJson.id);
|
||||||
if (lifesupportJson.modifiers)_addModifications(lifesupport, lifesupportJson.modifiers);
|
if (lifesupportJson.modifiers)_addModifications(lifesupport, lifesupportJson.modifiers, lifesupportJson.recipeName, lifesupportJson.recipeLevel);
|
||||||
ship.use(ship.standard[3], lifesupport, true);
|
ship.use(ship.standard[3], lifesupport, true);
|
||||||
ship.standard[3].enabled = lifesupportJson.on === true;
|
ship.standard[3].enabled = lifesupportJson.on === true;
|
||||||
ship.standard[3].priority = lifesupportJson.priority;
|
ship.standard[3].priority = lifesupportJson.priority;
|
||||||
@@ -187,7 +187,7 @@ export function shipFromJson(json) {
|
|||||||
// Power distributor
|
// Power distributor
|
||||||
const powerdistributorJson = json.modules.PowerDistributor.module;
|
const powerdistributorJson = json.modules.PowerDistributor.module;
|
||||||
const powerdistributor = _moduleFromEdId(powerdistributorJson.id);
|
const powerdistributor = _moduleFromEdId(powerdistributorJson.id);
|
||||||
if (powerdistributorJson.modifiers) _addModifications(powerdistributor, powerdistributorJson.modifiers);
|
if (powerdistributorJson.modifiers) _addModifications(powerdistributor, powerdistributorJson.modifiers, powerdistributorJson.recipeName, powerdistributorJson.recipeLevel);
|
||||||
ship.use(ship.standard[4], powerdistributor, true);
|
ship.use(ship.standard[4], powerdistributor, true);
|
||||||
ship.standard[4].enabled = powerdistributorJson.on === true;
|
ship.standard[4].enabled = powerdistributorJson.on === true;
|
||||||
ship.standard[4].priority = powerdistributorJson.priority;
|
ship.standard[4].priority = powerdistributorJson.priority;
|
||||||
@@ -195,7 +195,7 @@ export function shipFromJson(json) {
|
|||||||
// Sensors
|
// Sensors
|
||||||
const sensorsJson = json.modules.Radar.module;
|
const sensorsJson = json.modules.Radar.module;
|
||||||
const sensors = _moduleFromEdId(sensorsJson.id);
|
const sensors = _moduleFromEdId(sensorsJson.id);
|
||||||
if (sensorsJson.modifiers) _addModifications(sensors, sensorsJson.modifiers);
|
if (sensorsJson.modifiers) _addModifications(sensors, sensorsJson.modifiers, sensorsJson.recipeName, sensorsJson.recipeLevel);
|
||||||
ship.use(ship.standard[5], sensors, true);
|
ship.use(ship.standard[5], sensors, true);
|
||||||
ship.standard[5].enabled = sensorsJson.on === true;
|
ship.standard[5].enabled = sensorsJson.on === true;
|
||||||
ship.standard[5].priority = sensorsJson.priority;
|
ship.standard[5].priority = sensorsJson.priority;
|
||||||
@@ -229,7 +229,7 @@ export function shipFromJson(json) {
|
|||||||
} else {
|
} else {
|
||||||
const hardpointJson = hardpointSlot.module;
|
const hardpointJson = hardpointSlot.module;
|
||||||
const hardpoint = _moduleFromEdId(hardpointJson.id);
|
const hardpoint = _moduleFromEdId(hardpointJson.id);
|
||||||
if (hardpointJson.modifiers) _addModifications(hardpoint, hardpointJson.modifiers);
|
if (hardpointJson.modifiers) _addModifications(hardpoint, hardpointJson.modifiers, hardpointJson.recipeName, hardpointJson.recipeLevel);
|
||||||
ship.use(ship.hardpoints[hardpointArrayNum], hardpoint, true);
|
ship.use(ship.hardpoints[hardpointArrayNum], hardpoint, true);
|
||||||
ship.hardpoints[hardpointArrayNum].enabled = hardpointJson.on === true;
|
ship.hardpoints[hardpointArrayNum].enabled = hardpointJson.on === true;
|
||||||
ship.hardpoints[hardpointArrayNum].priority = hardpointJson.priority;
|
ship.hardpoints[hardpointArrayNum].priority = hardpointJson.priority;
|
||||||
@@ -240,7 +240,7 @@ export function shipFromJson(json) {
|
|||||||
// Add internal compartments
|
// Add internal compartments
|
||||||
let internalSlotNum = 1;
|
let internalSlotNum = 1;
|
||||||
for (let i in shipTemplate.slots.internal) {
|
for (let i in shipTemplate.slots.internal) {
|
||||||
const internalClassNum = shipTemplate.slots.internal[i];
|
const internalClassNum = isNaN(shipTemplate.slots.internal[i]) ? shipTemplate.slots.internal[i].class : shipTemplate.slots.internal[i];
|
||||||
|
|
||||||
let internalSlot = null;
|
let internalSlot = null;
|
||||||
while (internalSlot === null && internalSlotNum < 99) {
|
while (internalSlot === null && internalSlotNum < 99) {
|
||||||
@@ -256,7 +256,7 @@ export function shipFromJson(json) {
|
|||||||
} else {
|
} else {
|
||||||
const internalJson = internalSlot.module;
|
const internalJson = internalSlot.module;
|
||||||
const internal = _moduleFromEdId(internalJson.id);
|
const internal = _moduleFromEdId(internalJson.id);
|
||||||
if (internalJson.modifiers) _addModifications(internal, internalJson.modifiers);
|
if (internalJson.modifiers) _addModifications(internal, internalJson.modifiers, internalJson.recipeName, internalJson.recipeLevel);
|
||||||
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;
|
||||||
@@ -271,26 +271,63 @@ export function shipFromJson(json) {
|
|||||||
* 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 {Object} blueprint the blueprint of the modification
|
||||||
|
* @param {Object} grade the grade of the modification
|
||||||
*/
|
*/
|
||||||
function _addModifications(module, modifiers) {
|
function _addModifications(module, modifiers, blueprint, grade) {
|
||||||
if (!modifiers || !modifiers.modifiers) return;
|
if (!modifiers || !modifiers.modifiers) return;
|
||||||
|
|
||||||
|
let special;
|
||||||
for (const i in modifiers.modifiers) {
|
for (const i in modifiers.modifiers) {
|
||||||
// Look up the modifiers to find what we need to do
|
// Some special modifications
|
||||||
const modifierActions = Modifications.modifierActions[modifiers.modifiers[i].name];
|
if (modifiers.modifiers[i].name === 'mod_weapon_clip_size_override') {
|
||||||
const value = modifiers.modifiers[i].value;
|
// This is a numeric addition to the clip size, but we need to work it out in terms of being a percentage so
|
||||||
|
// that it works the same as other modifications
|
||||||
|
const origClip = module.clip || 1;
|
||||||
|
module.setModValue('clip', ((modifiers.modifiers[i].value - origClip) / origClip) * 10000);
|
||||||
|
} else if (modifiers.modifiers[i].name === 'mod_weapon_burst_size') {
|
||||||
|
// This is an absolute number that acts as an override
|
||||||
|
module.setModValue('burst', modifiers.modifiers[i].value * 100);
|
||||||
|
} else if (modifiers.modifiers[i].name === 'mod_weapon_burst_rof') {
|
||||||
|
// For some reason this is a non-normalised percentage (i.e. 12.23% is 12.23 value rather than 0.1223 as everywhere else), so fix that here
|
||||||
|
module.setModValue('burstrof', modifiers.modifiers[i].value * 100);
|
||||||
|
} else {
|
||||||
|
// Look up the modifiers to find what we need to do
|
||||||
|
const modifierActions = Modifications.modifierActions[modifiers.modifiers[i].name];
|
||||||
|
const value = modifiers.modifiers[i].value;
|
||||||
|
|
||||||
// Carry out the required changes
|
// Carry out the required changes
|
||||||
for (const action in modifierActions) {
|
for (const action in modifierActions) {
|
||||||
const actionValue = modifierActions[action] * value;
|
if (isNaN(modifierActions[action])) {
|
||||||
let mod = module.getModValue(action) / 10000;
|
module.setModValue(action, modifierActions[action]);
|
||||||
if (!mod) {
|
} else {
|
||||||
mod = 0;
|
const actionValue = modifierActions[action] * value;
|
||||||
|
let mod = module.getModValue(action) / 10000;
|
||||||
|
if (!mod) {
|
||||||
|
mod = 0;
|
||||||
|
}
|
||||||
|
module.setModValue(action, ((1 + mod) * (1 + actionValue) - 1) * 10000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
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, grade and special
|
||||||
|
if (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
|
// Need to fix up a few items
|
||||||
|
|
||||||
// Shield boosters are treated internally as straight modifiers, so rather than (for example)
|
// Shield boosters are treated internally as straight modifiers, so rather than (for example)
|
||||||
@@ -355,6 +392,12 @@ function _addModifications(module, modifiers) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Bulkhead boost is based off the inherent boost of the module
|
||||||
|
if (module.grp == 'bh') {
|
||||||
|
const alteredBoost = (1 + module.hullboost) * (1 + module.getModValue('hullboost') / 10000) - 1;
|
||||||
|
module.setModValue('hullboost', (alteredBoost / module.hullboost - 1) * 10000);
|
||||||
|
}
|
||||||
|
|
||||||
// Jitter is an absolute number, so we need to divide it by 100
|
// Jitter is an absolute number, so we need to divide it by 100
|
||||||
if (module.getModValue('jitter')) {
|
if (module.getModValue('jitter')) {
|
||||||
module.setModValue('jitter', module.getModValue('jitter') / 100);
|
module.setModValue('jitter', module.getModValue('jitter') / 100);
|
||||||
|
|||||||
@@ -68,6 +68,7 @@
|
|||||||
"rating": { "$ref": "#/definitions/standardRatings" },
|
"rating": { "$ref": "#/definitions/standardRatings" },
|
||||||
"enabled": { "type": "boolean" },
|
"enabled": { "type": "boolean" },
|
||||||
"priority": { "type": "integer", "minimum": 1, "maximum": 5 },
|
"priority": { "type": "integer", "minimum": 1, "maximum": 5 },
|
||||||
|
"blueprint": { "type": "object" },
|
||||||
"modifications": { "type": "object" }
|
"modifications": { "type": "object" }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -82,6 +83,7 @@
|
|||||||
"description": "The name identifing the thrusters (if applicable), e.g. 'Enhanced Performance'",
|
"description": "The name identifing the thrusters (if applicable), e.g. 'Enhanced Performance'",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"blueprint": { "type": "object" },
|
||||||
"modifications": { "type": "object" }
|
"modifications": { "type": "object" }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -92,6 +94,7 @@
|
|||||||
"rating": { "$ref": "#/definitions/standardRatings" },
|
"rating": { "$ref": "#/definitions/standardRatings" },
|
||||||
"enabled": { "type": "boolean" },
|
"enabled": { "type": "boolean" },
|
||||||
"priority": { "type": "integer", "minimum": 1, "maximum": 5 },
|
"priority": { "type": "integer", "minimum": 1, "maximum": 5 },
|
||||||
|
"blueprint": { "type": "object" },
|
||||||
"modifications": { "type": "object" }
|
"modifications": { "type": "object" }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -102,6 +105,7 @@
|
|||||||
"rating": { "$ref": "#/definitions/standardRatings" },
|
"rating": { "$ref": "#/definitions/standardRatings" },
|
||||||
"enabled": { "type": "boolean" },
|
"enabled": { "type": "boolean" },
|
||||||
"priority": { "type": "integer", "minimum": 1, "maximum": 5 },
|
"priority": { "type": "integer", "minimum": 1, "maximum": 5 },
|
||||||
|
"blueprint": { "type": "object" },
|
||||||
"modifications": { "type": "object" }
|
"modifications": { "type": "object" }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -112,6 +116,7 @@
|
|||||||
"rating": { "$ref": "#/definitions/standardRatings" },
|
"rating": { "$ref": "#/definitions/standardRatings" },
|
||||||
"enabled": { "type": "boolean" },
|
"enabled": { "type": "boolean" },
|
||||||
"priority": { "type": "integer", "minimum": 1, "maximum": 5 },
|
"priority": { "type": "integer", "minimum": 1, "maximum": 5 },
|
||||||
|
"blueprint": { "type": "object" },
|
||||||
"modifications": { "type": "object" }
|
"modifications": { "type": "object" }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -122,6 +127,7 @@
|
|||||||
"rating": { "$ref": "#/definitions/standardRatings" },
|
"rating": { "$ref": "#/definitions/standardRatings" },
|
||||||
"enabled": { "type": "boolean" },
|
"enabled": { "type": "boolean" },
|
||||||
"priority": { "type": "integer", "minimum": 1, "maximum": 5 },
|
"priority": { "type": "integer", "minimum": 1, "maximum": 5 },
|
||||||
|
"blueprint": { "type": "object" },
|
||||||
"modifications": { "type": "object" }
|
"modifications": { "type": "object" }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -132,6 +138,7 @@
|
|||||||
"rating": { "$ref": "#/definitions/standardRatings" },
|
"rating": { "$ref": "#/definitions/standardRatings" },
|
||||||
"enabled": { "type": "boolean" },
|
"enabled": { "type": "boolean" },
|
||||||
"priority": { "type": "integer", "minimum": 1, "maximum": 5 },
|
"priority": { "type": "integer", "minimum": 1, "maximum": 5 },
|
||||||
|
"blueprint": { "type": "object" },
|
||||||
"modifications": { "type": "object" }
|
"modifications": { "type": "object" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -155,6 +162,7 @@
|
|||||||
"description": "The name identifying the component (if applicable), e.g. 'Advance Discovery Scanner', or 'Detailed Surface Scanner'",
|
"description": "The name identifying the component (if applicable), e.g. 'Advance Discovery Scanner', or 'Detailed Surface Scanner'",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"blueprint": { "type": "object" },
|
||||||
"modifications": { "type": "object" }
|
"modifications": { "type": "object" }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -179,6 +187,7 @@
|
|||||||
"description": "The name identifing the component (if applicable), e.g. 'Retributor', or 'Mining Lance'",
|
"description": "The name identifing the component (if applicable), e.g. 'Retributor', or 'Mining Lance'",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"blueprint": { "type": "object" },
|
||||||
"modifications": { "type": "object" }
|
"modifications": { "type": "object" }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -202,6 +211,7 @@
|
|||||||
"description": "The name identifing the component (if applicable), e.g. 'Point Defence', or 'Electronic Countermeasure'",
|
"description": "The name identifing the component (if applicable), e.g. 'Point Defence', or 'Electronic Countermeasure'",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"blueprint": { "type": "object" },
|
||||||
"modifications": { "type": "object" }
|
"modifications": { "type": "object" }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user