mirror of
https://github.com/EDCD/coriolis.git
synced 2025-12-08 22:33:24 +00:00
Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
230351b959 | ||
|
|
4ee5c03cd1 | ||
|
|
d8e9733170 | ||
|
|
aba2abe507 | ||
|
|
45e6b71ec9 | ||
|
|
15a14dc280 | ||
|
|
cbac650b9e | ||
|
|
f011f1f4d5 | ||
|
|
d467ad5f7c | ||
|
|
b56ac177d9 | ||
|
|
5b13d64a1d | ||
|
|
2620935745 | ||
|
|
45852db507 | ||
|
|
7fbcbb75ed | ||
|
|
abf65ee436 | ||
|
|
24849cee08 | ||
|
|
9e5efe50dc | ||
|
|
39e9a38068 | ||
|
|
73d5915b3a | ||
|
|
b06d2d1f72 | ||
|
|
6e71f5e6db | ||
|
|
588cfc3990 | ||
|
|
191e31ff18 | ||
|
|
c655b65779 | ||
|
|
3e168a3e5f |
28
ChangeLog.md
28
ChangeLog.md
@@ -1,3 +1,31 @@
|
||||
#2.2.16
|
||||
* Fix 'Extreme' blueprint roll where some incorrect ranges were chosen
|
||||
* Use coriolis-data 2.2.16:
|
||||
* Fix incorrect thermal load modifiers for dirty drives
|
||||
* Provide explicit information about if values are higher numeric value == better or not
|
||||
|
||||
#2.2.15
|
||||
* Ensure that standard slots are repainted when any component changes
|
||||
* Reload page if Safari throws a security error
|
||||
* Handle import of ships with incorrectly-sized slots
|
||||
* Add 'Extreme' blueprint roll: best beneficial and worst detrimental outcome (in place of 'Average' roll)
|
||||
* Display information about Microsoft browser issues when an import fails
|
||||
* Add 'purchase this build' icon link to EDDB
|
||||
* Add 'miner' and 'shielded miner' ship roles
|
||||
* Use coriolis-data 2.2.15:
|
||||
* Fix location of initial cargo rack for Vulture
|
||||
* Fix broken regeneration rate for 6B shield generators
|
||||
* Tidy up breach damage values
|
||||
|
||||
#2.2.14
|
||||
* Ensure that jitter is shown correctly when the result of a special effect
|
||||
* Use restyled blueprint information
|
||||
* Use the ship name (if available) rather than the ship model for the window title
|
||||
* Use coriolis-data 2.2.14:
|
||||
* Alter blueprint structure to combine components and features
|
||||
* Make hidden value of modifications its own attribute
|
||||
* Fix incorrect ED ID for class 6 passenger cabins
|
||||
|
||||
#2.2.13
|
||||
* Add 'time to drain' summary value. This is the time to drain the WEP capacitor if firing all enabled weapons
|
||||
* Do not include utility slot DPS/EPS/HPS in summary information
|
||||
|
||||
@@ -16,7 +16,7 @@ Chat to us on [Discord](https://discord.gg/0uwCh6R62aPRjk9w)!
|
||||
|
||||
## Development
|
||||
|
||||
See the [Developer's Guide](https://github.com/cmmcleod/coriolis/wiki/Developer's-Guide) in the wiki.
|
||||
See the [Developer's Guide](https://github.com/EDCD/coriolis/wiki/Developing-for-Coriolis) in the wiki.
|
||||
|
||||
|
||||
### Ship and Module Database
|
||||
|
||||
314
__tests__/fixtures/companion-api-import-3.json
Normal file
314
__tests__/fixtures/companion-api-import-3.json
Normal file
@@ -0,0 +1,314 @@
|
||||
{
|
||||
"cargo": {
|
||||
"capacity": 264
|
||||
},
|
||||
"free": false,
|
||||
"fuel": {
|
||||
"main": {
|
||||
"capacity": 32
|
||||
},
|
||||
"reserve": {
|
||||
"capacity": 0.52
|
||||
}
|
||||
},
|
||||
"id": 4,
|
||||
"modules": {
|
||||
"Armour": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128049298,
|
||||
"name": "Type7_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": 128667746,
|
||||
"name": "Decal_Trade_Dealer",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"unloaned": 0,
|
||||
"value": 0
|
||||
}
|
||||
},
|
||||
"Decal2": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128667738,
|
||||
"name": "Decal_Combat_Competent",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"unloaned": 0,
|
||||
"value": 0
|
||||
}
|
||||
},
|
||||
"Decal3": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128667753,
|
||||
"name": "Decal_Explorer_Scout",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"unloaned": 0,
|
||||
"value": 0
|
||||
}
|
||||
},
|
||||
"EngineColour": [],
|
||||
"FrameShiftDrive": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128064122,
|
||||
"name": "Int_Hyperdrive_Size5_Class5",
|
||||
"on": true,
|
||||
"priority": 0,
|
||||
"unloaned": 0,
|
||||
"value": 5103953
|
||||
}
|
||||
},
|
||||
"FuelTank": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128064350,
|
||||
"name": "Int_FuelTank_Size5_Class3",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"unloaned": 97754,
|
||||
"value": 97754
|
||||
}
|
||||
},
|
||||
"LifeSupport": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128064154,
|
||||
"name": "Int_LifeSupport_Size4_Class2",
|
||||
"on": true,
|
||||
"priority": 0,
|
||||
"unloaned": 0,
|
||||
"value": 28373
|
||||
}
|
||||
},
|
||||
"MainEngines": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128064087,
|
||||
"name": "Int_Engine_Size5_Class5",
|
||||
"on": true,
|
||||
"priority": 0,
|
||||
"unloaned": 0,
|
||||
"value": 5103953
|
||||
}
|
||||
},
|
||||
"PaintJob": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128671422,
|
||||
"name": "PaintJob_Type7_Tactical_White",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"unloaned": 0,
|
||||
"value": 0
|
||||
}
|
||||
},
|
||||
"PlanetaryApproachSuite": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128672317,
|
||||
"name": "Int_PlanetApproachSuite",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"unloaned": 500,
|
||||
"value": 500
|
||||
}
|
||||
},
|
||||
"PowerDistributor": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128064192,
|
||||
"name": "Int_PowerDistributor_Size3_Class5",
|
||||
"on": true,
|
||||
"priority": 0,
|
||||
"unloaned": 0,
|
||||
"value": 158331
|
||||
}
|
||||
},
|
||||
"PowerPlant": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128064047,
|
||||
"name": "Int_Powerplant_Size4_Class5",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"unloaned": 0,
|
||||
"value": 1610080
|
||||
}
|
||||
},
|
||||
"Radar": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128064229,
|
||||
"name": "Int_Sensors_Size3_Class2",
|
||||
"on": true,
|
||||
"priority": 0,
|
||||
"unloaned": 0,
|
||||
"value": 10133
|
||||
}
|
||||
},
|
||||
"Slot01_Size6": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128064343,
|
||||
"name": "Int_CargoRack_Size6_Class1",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"unloaned": 0,
|
||||
"value": 362591
|
||||
}
|
||||
},
|
||||
"Slot02_Size6": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128064343,
|
||||
"name": "Int_CargoRack_Size6_Class1",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"unloaned": 0,
|
||||
"value": 362591
|
||||
}
|
||||
},
|
||||
"Slot03_Size5": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128064343,
|
||||
"name": "Int_CargoRack_Size6_Class1",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"unloaned": 0,
|
||||
"value": 362591
|
||||
}
|
||||
},
|
||||
"Slot04_Size5": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128064342,
|
||||
"name": "Int_CargoRack_Size5_Class1",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"unloaned": 111566,
|
||||
"value": 111566
|
||||
}
|
||||
},
|
||||
"Slot05_Size4": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128064342,
|
||||
"name": "Int_CargoRack_Size5_Class1",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"unloaned": 111566,
|
||||
"value": 111566
|
||||
}
|
||||
},
|
||||
"Slot06_Size4": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128064279,
|
||||
"name": "Int_ShieldGenerator_Size5_Class2",
|
||||
"on": true,
|
||||
"priority": 0,
|
||||
"unloaned": 0,
|
||||
"value": 189035
|
||||
}
|
||||
},
|
||||
"Slot07_Size2": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128049549,
|
||||
"name": "Int_DockingComputer_Standard",
|
||||
"on": true,
|
||||
"priority": 0,
|
||||
"unloaned": 0,
|
||||
"value": 4500
|
||||
}
|
||||
},
|
||||
"Slot08_Size2": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128064340,
|
||||
"name": "Int_CargoRack_Size3_Class1",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"unloaned": 0,
|
||||
"value": 10563
|
||||
}
|
||||
},
|
||||
"SmallHardpoint1": [],
|
||||
"SmallHardpoint2": [],
|
||||
"SmallHardpoint3": [],
|
||||
"SmallHardpoint4": [],
|
||||
"TinyHardpoint1": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128668536,
|
||||
"name": "Hpt_ShieldBooster_Size0_Class5",
|
||||
"on": true,
|
||||
"priority": 0,
|
||||
"unloaned": 0,
|
||||
"value": 281000
|
||||
}
|
||||
},
|
||||
"TinyHardpoint2": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128668536,
|
||||
"name": "Hpt_ShieldBooster_Size0_Class5",
|
||||
"on": true,
|
||||
"priority": 0,
|
||||
"unloaned": 0,
|
||||
"value": 281000
|
||||
}
|
||||
},
|
||||
"TinyHardpoint3": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128668536,
|
||||
"name": "Hpt_ShieldBooster_Size0_Class5",
|
||||
"on": true,
|
||||
"priority": 0,
|
||||
"unloaned": 0,
|
||||
"value": 281000
|
||||
}
|
||||
},
|
||||
"TinyHardpoint4": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128049513,
|
||||
"name": "Hpt_ChaffLauncher_Tiny",
|
||||
"on": true,
|
||||
"priority": 0,
|
||||
"unloaned": 0,
|
||||
"value": 8500
|
||||
}
|
||||
},
|
||||
"WeaponColour": []
|
||||
},
|
||||
"name": "Type7",
|
||||
"value": {
|
||||
"hull": 16780009,
|
||||
"modules": 14479580,
|
||||
"unloaned": 321386
|
||||
}
|
||||
}
|
||||
@@ -229,7 +229,7 @@ describe('Import Modal', function() {
|
||||
|
||||
beforeEach(reset);
|
||||
|
||||
it('imports a valid v4 build', function() {
|
||||
it('imports a valid companion API build', function() {
|
||||
const importData = require('./fixtures/companion-api-import-1');
|
||||
pasteText(JSON.stringify(importData));
|
||||
|
||||
@@ -241,7 +241,7 @@ describe('Import Modal', function() {
|
||||
expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/federal_corvette?code=A2putsFklndzsxf50x0x7l28281919040404040402020l06p05sf63c5ifr--v66g2f.AwRj4zNaqA%3D%3D.CwRgDBldUExuBiIlUA%3D%3D.H4sIAAAAAAAAA02SPy9DURjG3%2F65vW1v47TXVbeqqF7EQtIIBomRJswsYmISH8BgkFhqFZ9AwlALMYitkXQyEF2k4SMYJNK0dV7PK7nc5ck55%2Fm9z%2FnznpBeJqLvECQbM4hUjZnjO5hyWGfFikAGGjGiku0QuddhQCNdZmdWM9snsDmih4REOdlnNvz9DrPrJIicPdSwoZf8pAnTIpq8x7DYADS%2Bi5DERY85%2BYqpmkc6x%2FWGf6beKCR3YBIZFZCxCgrtczjuOmo4qTf94F4KYuxhz5jjEhXmUJNexFrpIUo02ALN1j9u1JMgD%2FMga1GfbMNRd9iHUwGy%2BpspZF3IBSGvMFJluS%2FuR24FJ2KlV%2Fxju6sQq4lhRsQTUVUJTgegLtS6EUjEE1HPAmUC0KdAjwKJeCKqD8zoURx72gHyDW9nvQhJGHkyUscS1x%2BAZnAlqwU%2FI%2BKJKEvextXrf93eQrR1KUlS5HWwGC61mfOn0oN3IM4OHoBzuuIHj33hS5jT8KeamIYa0sjhgH%2BLfplP4kcwD5Xl3xR1wfeHtqWzBHHX8I9SH9Je%2FgGvXxeungIAAA%3D%3D&bn=Imported%20Federal%20Corvette');
|
||||
});
|
||||
|
||||
it('imports a valid v4 build', function() {
|
||||
it('imports a valid companion API build', function() {
|
||||
const importData = require('./fixtures/companion-api-import-2');
|
||||
pasteText(JSON.stringify(importData));
|
||||
|
||||
@@ -252,6 +252,18 @@ describe('Import Modal', function() {
|
||||
expect(MockRouter.go.mock.calls.length).toBe(1);
|
||||
expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/beluga?code=A0pktsFplCdpsnf70t0t2727270004040404043c4fmimlmm04mc0iv62i2f.AwRj4yukg%3D%3D%3D.CwRgDBldHi8IUA%3D%3D.H4sIAAAAAAAAA2P8Z8%2FAwPCXEUiIKTMxMPCv%2F%2Ff%2FP8cFIPGf6Z8YTEr0GjMDg%2FJWICERBOTzn%2Fn7%2F7%2FIO5Ai5n9SIEWsQEIoSxAolfbt%2F3%2BJPk4GBhE7YQYGYVmgcuVnf4Aq%2FwMAIrEcGGsAAAA%3D&bn=Imported%20Beluga%20Liner');
|
||||
});
|
||||
|
||||
it('imports a valid companion API build', function() {
|
||||
const importData = require('./fixtures/companion-api-import-3');
|
||||
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/type_7_transport?code=A0patfFflidasdf5----0404040005050504044d2402.AwRj4yrI.CwRgDBlVK7EiA%3D%3D%3D.&bn=Imported%20Type-7%20Transporter');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Import E:D Shipyard Builds', function() {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "coriolis_shipyard",
|
||||
"version": "2.2.13",
|
||||
"version": "2.2.16",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/EDCD/coriolis"
|
||||
|
||||
@@ -76,7 +76,16 @@ Router.go = function(path, state) {
|
||||
if (isStandAlone()) {
|
||||
Persist.setState(ctx);
|
||||
}
|
||||
history.pushState(ctx.state, ctx.title, ctx.canonicalPath);
|
||||
try {
|
||||
history.pushState(ctx.state, ctx.title, ctx.canonicalPath);
|
||||
} catch (ex) {
|
||||
sessionStorage.setItem('__safari_history_fix', JSON.stringify({
|
||||
state: ctx.state,
|
||||
title: ctx.title,
|
||||
path: ctx.canonicalPath
|
||||
}));
|
||||
location.reload();
|
||||
}
|
||||
}
|
||||
return ctx;
|
||||
};
|
||||
@@ -99,7 +108,16 @@ Router.replace = function(path, state, dispatch) {
|
||||
if (isStandAlone()) {
|
||||
Persist.setState(ctx);
|
||||
}
|
||||
history.replaceState(ctx.state, ctx.title, ctx.canonicalPath);
|
||||
try {
|
||||
history.replaceState(ctx.state, ctx.title, ctx.canonicalPath);
|
||||
} catch (ex) {
|
||||
sessionStorage.setItem('__safari_history_fix', JSON.stringify({
|
||||
state: ctx.state,
|
||||
title: ctx.title,
|
||||
path: ctx.canonicalPath
|
||||
}));
|
||||
location.reload();
|
||||
}
|
||||
return ctx;
|
||||
};
|
||||
|
||||
|
||||
@@ -32,8 +32,8 @@ export default class ModificationsMenu extends TranslatedComponent {
|
||||
this._toggleSpecialsMenu = this._toggleSpecialsMenu.bind(this);
|
||||
this._rollWorst = this._rollWorst.bind(this);
|
||||
this._rollRandom = this._rollRandom.bind(this);
|
||||
this._rollAverage = this._rollAverage.bind(this);
|
||||
this._rollBest = this._rollBest.bind(this);
|
||||
this._rollExtreme = this._rollExtreme.bind(this);
|
||||
this._reset = this._reset.bind(this);
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ export default class ModificationsMenu extends TranslatedComponent {
|
||||
const { m, onChange, ship } = props;
|
||||
let modifications = [];
|
||||
for (const modName of Modifications.modules[m.grp].modifications) {
|
||||
if (Modifications.modifications[modName].type === 'percentage' || Modifications.modifications[modName].type === 'numeric') {
|
||||
if (!Modifications.modifications[modName].hidden) {
|
||||
const key = modName + (m.getModValue(modName) / 100 || 0);
|
||||
modifications.push(<Modification key={ key } ship={ ship } m={ m } name={ modName } value={ m.getModValue(modName) / 100 || 0 } onChange={ onChange }/>);
|
||||
}
|
||||
@@ -147,58 +147,40 @@ export default class ModificationsMenu extends TranslatedComponent {
|
||||
this.props.onChange();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the result of a roll
|
||||
* @param {object} ship The ship to which the roll applies
|
||||
* @param {object} m The module to which the roll applies
|
||||
* @param {string} featureName The modification feature to which the roll applies
|
||||
* @param {number} value The value of the roll
|
||||
*/
|
||||
_setRollResult(ship, m, featureName, value) {
|
||||
if (Modifications.modifications[featureName].method !== 'overwrite') {
|
||||
if (m.grp == 'sb' && featureName == 'shieldboost') {
|
||||
// Shield boosters are a special case. Their boost is dependent on their base so we need to calculate the value here
|
||||
value = ((1 + m.shieldboost) * (1 + value) - 1) / m.shieldboost - 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (Modifications.modifications[featureName].type == 'percentage') {
|
||||
ship.setModification(m, featureName, value * 10000);
|
||||
} else if (Modifications.modifications[featureName].type == 'numeric') {
|
||||
ship.setModification(m, featureName, value * 100);
|
||||
} else {
|
||||
ship.setModification(m, featureName, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a 'worst' roll within the information we have
|
||||
*/
|
||||
_rollWorst() {
|
||||
const { m, ship } = this.props;
|
||||
const features = m.blueprint.features[m.blueprint.grade];
|
||||
const features = m.blueprint.grades[m.blueprint.grade].features;
|
||||
for (const featureName in features) {
|
||||
if (Modifications.modifications[featureName].method == 'overwrite') {
|
||||
ship.setModification(m, featureName, features[featureName][1]);
|
||||
} else {
|
||||
let value = features[featureName][0];
|
||||
if (m.grp == 'sb' && featureName == 'shieldboost') {
|
||||
// Shield boosters are a special case. Their boost is dependent on their base so we need to calculate the value here
|
||||
value = ((1 + m.shieldboost) * (1 + value) - 1) / m.shieldboost - 1;
|
||||
}
|
||||
|
||||
if (Modifications.modifications[featureName].type == 'percentage') {
|
||||
ship.setModification(m, featureName, value * 10000);
|
||||
} else if (Modifications.modifications[featureName].type == 'numeric') {
|
||||
ship.setModification(m, featureName, value * 100);
|
||||
}
|
||||
}
|
||||
let value = features[featureName][0];
|
||||
this._setRollResult(ship, m, featureName, value);
|
||||
}
|
||||
|
||||
this.setState({ modifications: this._setModifications(this.props) });
|
||||
this.props.onChange();
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide an 'average' roll within the information we have
|
||||
*/
|
||||
_rollAverage() {
|
||||
const { m, ship } = this.props;
|
||||
const features = m.blueprint.features[m.blueprint.grade];
|
||||
for (const featureName in features) {
|
||||
if (Modifications.modifications[featureName].method == 'overwrite') {
|
||||
ship.setModification(m, featureName, (features[featureName][0] + features[featureName][1]) / 2);
|
||||
} else {
|
||||
let value = (features[featureName][0] + features[featureName][1]) / 2;
|
||||
if (m.grp == 'sb' && featureName == 'shieldboost') {
|
||||
// Shield boosters are a special case. Their boost is dependent on their base so we need to calculate the value here
|
||||
value = ((1 + m.shieldboost) * (1 + value) - 1) / m.shieldboost - 1;
|
||||
}
|
||||
|
||||
if (Modifications.modifications[featureName].type == 'percentage') {
|
||||
ship.setModification(m, featureName, value * 10000);
|
||||
} else if (Modifications.modifications[featureName].type == 'numeric') {
|
||||
ship.setModification(m, featureName, value * 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({ modifications: this._setModifications(this.props) });
|
||||
this.props.onChange();
|
||||
}
|
||||
@@ -208,25 +190,11 @@ export default class ModificationsMenu extends TranslatedComponent {
|
||||
*/
|
||||
_rollRandom() {
|
||||
const { m, ship } = this.props;
|
||||
const features = m.blueprint.features[m.blueprint.grade];
|
||||
const features = m.blueprint.grades[m.blueprint.grade].features;
|
||||
for (const featureName in features) {
|
||||
if (Modifications.modifications[featureName].method == 'overwrite') {
|
||||
ship.setModification(m, featureName, features[featureName][1]);
|
||||
} else {
|
||||
let value = features[featureName][0] + (Math.random() * (features[featureName][1] - features[featureName][0]));
|
||||
if (m.grp == 'sb' && featureName == 'shieldboost') {
|
||||
// Shield boosters are a special case. Their boost is dependent on their base so we need to calculate the value here
|
||||
value = ((1 + m.shieldboost) * (1 + value) - 1) / m.shieldboost - 1;
|
||||
}
|
||||
|
||||
if (Modifications.modifications[featureName].type == 'percentage') {
|
||||
ship.setModification(m, featureName, value * 10000);
|
||||
} else if (Modifications.modifications[featureName].type == 'numeric') {
|
||||
ship.setModification(m, featureName, value * 100);
|
||||
}
|
||||
}
|
||||
let value = features[featureName][0] + (Math.random() * (features[featureName][1] - features[featureName][0]));
|
||||
this._setRollResult(ship, m, featureName, value);
|
||||
}
|
||||
|
||||
this.setState({ modifications: this._setModifications(this.props) });
|
||||
this.props.onChange();
|
||||
}
|
||||
@@ -236,25 +204,25 @@ export default class ModificationsMenu extends TranslatedComponent {
|
||||
*/
|
||||
_rollBest() {
|
||||
const { m, ship } = this.props;
|
||||
const features = m.blueprint.features[m.blueprint.grade];
|
||||
const features = m.blueprint.grades[m.blueprint.grade].features;
|
||||
for (const featureName in features) {
|
||||
if (Modifications.modifications[featureName].method == 'overwrite') {
|
||||
ship.setModification(m, featureName, features[featureName][1]);
|
||||
} else {
|
||||
let value = features[featureName][1];
|
||||
if (m.grp == 'sb' && featureName == 'shieldboost') {
|
||||
// Shield boosters are a special case. Their boost is dependent on their base so we need to calculate the value here
|
||||
value = ((1 + m.shieldboost) * (1 + value) - 1) / m.shieldboost - 1;
|
||||
}
|
||||
|
||||
if (Modifications.modifications[featureName].type == 'percentage') {
|
||||
ship.setModification(m, featureName, value * 10000);
|
||||
} else if (Modifications.modifications[featureName].type == 'numeric') {
|
||||
ship.setModification(m, featureName, value * 100);
|
||||
}
|
||||
}
|
||||
let value = features[featureName][1];
|
||||
this._setRollResult(ship, m, featureName, value);
|
||||
}
|
||||
this.setState({ modifications: this._setModifications(this.props) });
|
||||
this.props.onChange();
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide an 'extreme' roll within the information we have
|
||||
*/
|
||||
_rollExtreme() {
|
||||
const { m, ship } = this.props;
|
||||
const features = m.blueprint.grades[m.blueprint.grade].features;
|
||||
for (const featureName in features) {
|
||||
const value = Modifications.modifications[featureName].higherbetter ? features[featureName][1] : features[featureName][0];
|
||||
this._setRollResult(ship, m, featureName, value);
|
||||
}
|
||||
this.setState({ modifications: this._setModifications(this.props) });
|
||||
this.props.onChange();
|
||||
}
|
||||
@@ -284,8 +252,8 @@ export default class ModificationsMenu extends TranslatedComponent {
|
||||
const _toggleBlueprintsMenu = this._toggleBlueprintsMenu;
|
||||
const _toggleSpecialsMenu = this._toggleSpecialsMenu;
|
||||
const _rollBest = this._rollBest;
|
||||
const _rollExtreme = this._rollExtreme;
|
||||
const _rollWorst = this._rollWorst;
|
||||
const _rollAverage = this._rollAverage;
|
||||
const _rollRandom = this._rollRandom;
|
||||
const _reset = this._reset;
|
||||
|
||||
@@ -310,6 +278,7 @@ export default class ModificationsMenu extends TranslatedComponent {
|
||||
const showSpecial = haveBlueprint && this.state.specials.length > 0;
|
||||
const showSpecialsMenu = specialMenuOpened;
|
||||
const showRolls = haveBlueprint && !blueprintMenuOpened && !specialMenuOpened;
|
||||
const showReset = !blueprintMenuOpened && !specialMenuOpened;
|
||||
const showMods = !blueprintMenuOpened && !specialMenuOpened;
|
||||
|
||||
return (
|
||||
@@ -319,26 +288,30 @@ export default class ModificationsMenu extends TranslatedComponent {
|
||||
onContextMenu={stopCtxPropagation}
|
||||
>
|
||||
<div className={ cn('section-menu', { selected: blueprintMenuOpened })} style={{ cursor: 'pointer' }} onClick={_toggleBlueprintsMenu}>{blueprintLabel}</div>
|
||||
{ showBlueprintsMenu ? this.state.blueprints : '' }
|
||||
{ showSpecial ? <div className={ cn('section-menu', { selected: specialMenuOpened })} style={{ cursor: 'pointer' }} onClick={_toggleSpecialsMenu}>{specialLabel}</div> : '' }
|
||||
{ showSpecialsMenu ? this.state.specials : '' }
|
||||
{ showRolls ?
|
||||
{ showBlueprintsMenu ? this.state.blueprints : null }
|
||||
{ showSpecial ? <div className={ cn('section-menu', { selected: specialMenuOpened })} style={{ cursor: 'pointer' }} onClick={_toggleSpecialsMenu}>{specialLabel}</div> : null }
|
||||
{ showSpecialsMenu ? this.state.specials : null }
|
||||
{ showRolls || showReset ?
|
||||
<table style={{ width: '100%', backgroundColor: 'transparent' }}>
|
||||
<tbody>
|
||||
{ showRolls ?
|
||||
<tr>
|
||||
<td> { translate('roll') }: </td>
|
||||
<td style={{ cursor: 'pointer' }} onClick={_rollWorst} onMouseOver={termtip.bind(null, 'PHRASE_BLUEPRINT_WORST')} onMouseOut={tooltip.bind(null, null)}> { translate('worst') } </td>
|
||||
<td style={{ cursor: 'pointer' }} onClick={_rollAverage}onMouseOver={termtip.bind(null, 'PHRASE_BLUEPRINT_AVERAGE')} onMouseOut={tooltip.bind(null, null)}> { translate('average') } </td>
|
||||
<td style={{ cursor: 'pointer' }} onClick={_rollBest}onMouseOver={termtip.bind(null, 'PHRASE_BLUEPRINT_BEST')} onMouseOut={tooltip.bind(null, null)}> { translate('best') } </td>
|
||||
<td style={{ cursor: 'pointer' }} onClick={_rollExtreme}onMouseOver={termtip.bind(null, 'PHRASE_BLUEPRINT_EXTREME')} onMouseOut={tooltip.bind(null, null)}> { translate('extreme') } </td>
|
||||
<td style={{ cursor: 'pointer' }} onClick={_rollRandom} onMouseOver={termtip.bind(null, 'PHRASE_BLUEPRINT_RANDOM')} onMouseOut={tooltip.bind(null, null)}> { translate('random') } </td>
|
||||
<td style={{ cursor: 'pointer' }} onClick={_reset}onMouseOver={termtip.bind(null, 'PHRASE_BLUEPRINT_RESET')} onMouseOut={tooltip.bind(null, null)}> { translate('reset') } </td>
|
||||
</tr>
|
||||
</tr> : null }
|
||||
{ showReset ?
|
||||
<tr>
|
||||
<td colSpan={'5'} style={{ cursor: 'pointer' }} onClick={_reset}onMouseOver={termtip.bind(null, 'PHRASE_BLUEPRINT_RESET')} onMouseOut={tooltip.bind(null, null)}> { translate('reset') } </td>
|
||||
</tr> : null }
|
||||
</tbody>
|
||||
</table> : '' }
|
||||
</table> : null }
|
||||
{ showMods ?
|
||||
<span onMouseOver={termtip.bind(null, 'HELP_MODIFICATIONS_MENU')} onMouseOut={tooltip.bind(null, null)} >
|
||||
{ this.state.modifications }
|
||||
</span> : '' }
|
||||
</span> : null }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ export default class SlotSection extends TranslatedComponent {
|
||||
* @param {Object} m Selected module
|
||||
*/
|
||||
_selectModule(slot, m) {
|
||||
this.props.ship.use(slot, m);
|
||||
this.props.ship.use(slot, m, false);
|
||||
this.props.onChange();
|
||||
this._close();
|
||||
}
|
||||
@@ -123,7 +123,7 @@ export default class SlotSection extends TranslatedComponent {
|
||||
// We want to copy the module in to the target slot
|
||||
if (targetSlot && canMount(this.props.ship, targetSlot, m.grp, m.class)) {
|
||||
const mCopy = m.clone();
|
||||
this.props.ship.use(targetSlot, mCopy);
|
||||
this.props.ship.use(targetSlot, mCopy, false);
|
||||
this.props.onChange();
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -53,6 +53,16 @@ export default class StandardSlotSection extends SlotSection {
|
||||
this._close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Miner Build
|
||||
* @param {Boolean} shielded True if shield generator should be included
|
||||
*/
|
||||
_optimizeMiner(shielded) {
|
||||
ShipRoles.miner(this.props.ship, shielded);
|
||||
this.props.onChange();
|
||||
this._close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Explorer role
|
||||
* @param {Boolean} planetary True if Planetary Vehicle Hangar (PVH) should be included
|
||||
@@ -209,6 +219,8 @@ export default class StandardSlotSection extends SlotSection {
|
||||
<li className='lc' onClick={this._optimizeCargo.bind(this, true)}>{translate('Shielded Trader')}</li>
|
||||
<li className='lc' onClick={this._optimizeExplorer.bind(this, false)}>{translate('Explorer')}</li>
|
||||
<li className={cn('lc', { disabled: planetaryDisabled })} onClick={!planetaryDisabled && this._optimizeExplorer.bind(this, true)}>{translate('Planetary Explorer')}</li>
|
||||
<li className='lc' onClick={this._optimizeMiner.bind(this, false)}>{translate('Miner')}</li>
|
||||
<li className='lc' onClick={this._optimizeMiner.bind(this, true)}>{translate('Shielded Miner')}</li>
|
||||
</ul>
|
||||
</div>;
|
||||
}
|
||||
|
||||
@@ -227,6 +227,26 @@ export class LinkIcon extends SvgIcon {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shopping icon (dollar sign)
|
||||
*/
|
||||
export class ShoppingIcon extends SvgIcon {
|
||||
/**
|
||||
* Overriden view box
|
||||
* @return {String} view box
|
||||
*/
|
||||
viewBox() { return '0 0 200 200'; }
|
||||
/**
|
||||
* Generate the SVG
|
||||
* @return {React.Component} SVG Contents
|
||||
*/
|
||||
svg() {
|
||||
return <g>
|
||||
<path d='M94 188v-17c-9-1-16-3-21-6-6-3-11-7-15-14-4-6-6-14-6-23l17-3c2 9 4 16 7 21 5 6 11 9 18 10v-56c-7-1-14-4-22-8-6-3-10-8-13-13-3-6-4-12-4-19 0-13 4-23 13-31 6-5 15-8 26-9v-8h11v8c10 1 18 4 24 9 8 6 12 15 14 26l-18 3c-1-7-4-12-7-16s-8-6-13-7v50l17 6c6 2 10 5 13 8 4 4 7 8 8 13 2 4 3 10 3 15 0 12-4 22-11 31-8 8-18 12-30 13v17H94zm0-153c-7 1-12 3-16 8-4 4-6 9-6 15s2 11 5 16c4 4 9 7 17 9V35zm11 121a28 28 0 0 0 24-28c-1-6-2-11-6-15-3-4-9-7-18-10v53z'/>
|
||||
</g>;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* No Power - Lightning bolt + no entry
|
||||
*/
|
||||
|
||||
@@ -31,12 +31,13 @@ export const terms = {
|
||||
PHRASE_ENGAGEMENT_RANGE: 'The distance between your ship and its target',
|
||||
PHRASE_SELECT_BLUEPRINT: 'Click to select a blueprint',
|
||||
PHRASE_BLUEPRINT_WORST: 'Worst primary values for this blueprint',
|
||||
PHRASE_BLUEPRINT_AVERAGE: 'Average primary values for this blueprint',
|
||||
PHRASE_BLUEPRINT_RANDOM: 'Random selection between worst and best primary values for this blueprint',
|
||||
PHRASE_BLUEPRINT_BEST: 'Best primary values for this blueprint',
|
||||
PHRASE_BLUEPRINT_EXTREME: 'Best beneficial and worst detrimental primary values for this blueprint',
|
||||
PHRASE_BLUEPRINT_RESET: 'Remove all modifications and blueprint',
|
||||
PHRASE_SELECT_SPECIAL: 'Click to select an experimental effect',
|
||||
PHRASE_NO_SPECIAL: 'No experimental effect',
|
||||
PHRASE_SHOPPING_LIST: 'Stations that sell this build',
|
||||
|
||||
HELP_MODIFICATIONS_MENU: 'Click on a number to enter a new value, or drag along the bar for small changes',
|
||||
|
||||
@@ -115,6 +116,7 @@ export const terms = {
|
||||
average: 'Average',
|
||||
random: 'Random',
|
||||
best: 'Best',
|
||||
extreme: 'Extreme',
|
||||
reset: 'Reset',
|
||||
|
||||
// Weapon, offence, defence and movement
|
||||
@@ -226,6 +228,8 @@ To remove a module from a slot right-click on the module. </p>
|
||||
|
||||
To move a module from one slot to another drag it. If you instead want to copy the module drag it whilst holding down the 'Alt' key. </p>
|
||||
|
||||
Clicking on the headings for each set of modules gives you the ability to either select an overall role for your ship (when clicking the core internal header) or a specific module with which you want to fill all applicable slots (when clicking the other headers). </p>
|
||||
|
||||
<h2>Power Management</h2>
|
||||
The power management panel provides information about power usage and priorities. It allows you to enable and disable individual modules, as well as set power priorities for each module.</p>
|
||||
|
||||
|
||||
@@ -39,10 +39,16 @@ export default class ErrorDetails extends React.Component {
|
||||
</div>;
|
||||
}
|
||||
|
||||
const importerror = ed && ed.scriptUrl && ed.scriptUrl.indexOf('/import') != -1;
|
||||
|
||||
return <div className='error'>
|
||||
<h1>Jameson, we have a problem..</h1>
|
||||
<h1><small>{error.message}</small></h1>
|
||||
<br/>
|
||||
{importerror ? <div>If you are attempting to import a ship from EDDI or EDMC and are seeing a 'Z_BUF_ERROR' it means that the URL has not been provided correctly. This is a common problem when using Microsoft Internet Explorer or Microsoft Edge, and you should use another browser instead.</div> : null }
|
||||
<br/>
|
||||
<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>
|
||||
<br/>
|
||||
{content}
|
||||
</div>;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import Persist from '../stores/Persist';
|
||||
import Ship from '../shipyard/Ship';
|
||||
import { toDetailedBuild } from '../shipyard/Serializer';
|
||||
import { outfitURL } from '../utils/UrlGenerators';
|
||||
import { FloppyDisk, Bin, Switch, Download, Reload, Fuel, LinkIcon } from '../components/SvgIcons';
|
||||
import { FloppyDisk, Bin, Switch, Download, Reload, Fuel, LinkIcon, ShoppingIcon } from '../components/SvgIcons';
|
||||
import ShipSummaryTable from '../components/ShipSummaryTable';
|
||||
import StandardSlotSection from '../components/StandardSlotSection';
|
||||
import HardpointsSlotSection from '../components/HardpointsSlotSection';
|
||||
@@ -36,7 +36,7 @@ const SPEED_COLORS = ['#0088d2', '#ff8c0d', '#D26D00', '#c06400'];
|
||||
* @return {String} Document title
|
||||
*/
|
||||
function getTitle(shipName, buildName) {
|
||||
return `${shipName}${buildName ? ` - ${buildName}` : ''}`;
|
||||
return buildName ? buildName : shipName;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -284,6 +284,20 @@ export default class OutfittingPage extends Page {
|
||||
this.context.showModal(<ModalPermalink url={window.location.href}/>);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open up a window for EDDB with a shopping list of our components
|
||||
*/
|
||||
_eddbShoppingList() {
|
||||
const ship = this.state.ship;
|
||||
|
||||
const shipId = Ships[ship.id].eddbID;
|
||||
// Provide unique list of non-PP module EDDB IDs
|
||||
const modIds = ship.internal.concat(ship.bulkheads, ship.standard, ship.hardpoints).filter(slot => slot !== null && slot.m !== null && !slot.m.pp).map(slot => slot.m.eddbID).filter((v, i, a) => a.indexOf(v) === i);
|
||||
|
||||
// Open up the relevant URL
|
||||
window.open('https://eddb.io/station?s=' + shipId + '&m=' + modIds.join(','));
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Key Down
|
||||
* @param {Event} e Keyboard Event
|
||||
@@ -316,7 +330,6 @@ export default class OutfittingPage extends Page {
|
||||
canRename = buildName && newBuildName && buildName != newBuildName,
|
||||
canReload = savedCode && canSave,
|
||||
hStr = ship.getHardpointsString() + '.' + ship.getModificationsString(),
|
||||
sStr = ship.getStandardString() + '.' + ship.getModificationsString(),
|
||||
iStr = ship.getInternalString() + '.' + ship.getModificationsString();
|
||||
|
||||
return (
|
||||
@@ -343,19 +356,22 @@ export default class OutfittingPage extends Page {
|
||||
<button onClick={buildName && this._exportBuild} disabled={!buildName} onMouseOver={termtip.bind(null, 'export')} onMouseOut={hide}>
|
||||
<Download className='lg'/>
|
||||
</button>
|
||||
<button onClick={this._eddbShoppingList} onMouseOver={termtip.bind(null, 'PHRASE_SHOPPING_LIST')} onMouseOut={hide}>
|
||||
<ShoppingIcon className='lg' />
|
||||
</button>
|
||||
<button onClick={this._genShortlink} onMouseOver={termtip.bind(null, 'shortlink')} onMouseOut={hide}>
|
||||
<LinkIcon className='lg' />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ShipSummaryTable ship={ship} code={code} />
|
||||
<StandardSlotSection ship={ship} code={sStr} onChange={shipUpdated} currentMenu={menu} />
|
||||
<ShipSummaryTable ship={ship} code={code || ''} />
|
||||
<StandardSlotSection ship={ship} code={code || ''} onChange={shipUpdated} currentMenu={menu} />
|
||||
<InternalSlotSection ship={ship} code={iStr} onChange={shipUpdated} currentMenu={menu} />
|
||||
<HardpointsSlotSection ship={ship} code={hStr} onChange={shipUpdated} currentMenu={menu} />
|
||||
<UtilitySlotSection ship={ship} code={hStr} onChange={shipUpdated} currentMenu={menu} />
|
||||
<PowerManagement ship={ship} code={code} onChange={shipUpdated} />
|
||||
<CostSection ship={ship} buildName={buildName} code={sStr + hStr + iStr} />
|
||||
<HardpointsSlotSection ship={ship} code={hStr || ''} onChange={shipUpdated} currentMenu={menu} />
|
||||
<UtilitySlotSection ship={ship} code={hStr || ''} onChange={shipUpdated} currentMenu={menu} />
|
||||
<PowerManagement ship={ship} code={code || ''} onChange={shipUpdated} />
|
||||
<CostSection ship={ship} buildName={buildName} code={code || ''} />
|
||||
|
||||
<div className='group third'>
|
||||
<OffenceSummary ship={ship} code={code}/>
|
||||
|
||||
@@ -39,6 +39,14 @@ export default class Page extends React.Component {
|
||||
this[prop] = this[prop].bind(this);
|
||||
}
|
||||
});
|
||||
|
||||
let fix = sessionStorage.getItem('__safari_history_fix');
|
||||
sessionStorage.removeItem('__safari_history_fix');
|
||||
if (fix) {
|
||||
fix = JSON.parse(fix);
|
||||
history.replaceState(history.state, document.title, location.href);
|
||||
history.pushState(fix.state, fix.title, fix.path);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -82,4 +90,4 @@ export default class Page extends React.Component {
|
||||
return this.renderPage();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +60,8 @@ export default class Module {
|
||||
} else {
|
||||
mod = modifierActions[name];
|
||||
}
|
||||
result = (((1 + result / 10000) * (1 + mod)) - 1) * 10000;
|
||||
const multiplier = modification.type === 'percentage' ? 10000 : 100;
|
||||
result = (((1 + result / multiplier) * (1 + mod)) - 1) * multiplier;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -897,6 +897,7 @@ export default class Ship {
|
||||
}
|
||||
if (epsChanged) {
|
||||
this.recalculateEps();
|
||||
this.recalculateTtd();
|
||||
}
|
||||
if (hpsChanged) {
|
||||
this.recalculateHps();
|
||||
|
||||
@@ -126,3 +126,104 @@ export function explorer(ship, planetary) {
|
||||
|
||||
ship.useLightestStandard(standardOpts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Miner Role
|
||||
* @param {Ship} ship Ship instance
|
||||
* @param {Boolean} shielded True if shield generator should be included
|
||||
*/
|
||||
export function miner(ship, shielded) {
|
||||
let standardOpts = { ppRating: 'A' },
|
||||
miningLaserCount = 2,
|
||||
usedSlots = [],
|
||||
sg = ship.getAvailableModules().lightestShieldGenerator(ship.hullMass);
|
||||
|
||||
// Cargo hatch should be enabled
|
||||
ship.setSlotEnabled(ship.cargoHatch, true);
|
||||
|
||||
// 4A or largest possible refinery
|
||||
const refineryOrder = [4, 5, 6, 7, 8, 3, 2, 1];
|
||||
const refineryInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1)
|
||||
.filter(a => (!a.eligible) || a.eligible.rf)
|
||||
.sort((a,b) => refineryOrder.indexOf(a.maxClass) - refineryOrder.indexOf(b.maxClass));
|
||||
for (let i = 0; i < refineryInternals.length; i++) {
|
||||
if (canMount(ship, refineryInternals[i], 'rf')) {
|
||||
ship.use(refineryInternals[i], ModuleUtils.findInternal('rf', refineryInternals[i].maxClass, 'A'));
|
||||
usedSlots.push(refineryInternals[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Prospector limpet controller - 3A if possible
|
||||
const prospectorOrder = [3, 4, 5, 6, 7, 8, 2, 1];
|
||||
const prospectorInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1)
|
||||
.filter(a => (!a.eligible) || a.eligible.pc)
|
||||
.sort((a,b) => prospectorOrder.indexOf(a.maxClass) - prospectorOrder.indexOf(b.maxClass));
|
||||
for (let i = 0; i < prospectorInternals.length; i++) {
|
||||
if (canMount(ship, prospectorInternals[i], 'pc')) {
|
||||
// Prospector only has odd classes
|
||||
const prospectorClass = prospectorInternals[i].maxClass % 2 === 0 ? prospectorInternals[i].maxClass - 1 : prospectorInternals[i].maxClass;
|
||||
ship.use(prospectorInternals[i], ModuleUtils.findInternal('pc', prospectorClass, 'A'));
|
||||
usedSlots.push(prospectorInternals[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Shield generator if required
|
||||
if (shielded) {
|
||||
const shieldOrder = [1, 2, 3, 4, 5, 6, 7, 8];
|
||||
const shieldInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1)
|
||||
.filter(a => (!a.eligible) || a.eligible.pc)
|
||||
.filter(a => a.maxClass >= sg.class)
|
||||
.sort((a,b) => shieldOrder.indexOf(a.maxClass) - shieldOrder.indexOf(b.maxClass));
|
||||
for (let i = 0; i < shieldInternals.length; i++) {
|
||||
if (canMount(ship, shieldInternals[i], 'sg')) {
|
||||
ship.use(shieldInternals[i], sg);
|
||||
usedSlots.push(shieldInternals[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Collector limpet controller if there are enough internals left
|
||||
let collectorLimpetsRequired = Math.max(ship.internal.filter(a => (!a.eligible) || a.eligible.cr).length - 6, 0);
|
||||
if (collectorLimpetsRequired > 0) {
|
||||
const collectorOrder = [1, 2, 3, 4, 5, 6, 7, 8];
|
||||
const collectorInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1)
|
||||
.filter(a => (!a.eligible) || a.eligible.cc)
|
||||
.sort((a,b) => collectorOrder.indexOf(a.maxClass) - collectorOrder.indexOf(b.maxClass));
|
||||
for (let i = 0; i < collectorInternals.length && collectorLimpetsRequired > 0; i++) {
|
||||
if (canMount(ship, collectorInternals[i], 'cc')) {
|
||||
// Collector only has odd classes
|
||||
const collectorClass = collectorInternals[i].maxClass % 2 === 0 ? collectorInternals[i].maxClass - 1 : collectorInternals[i].maxClass;
|
||||
ship.use(collectorInternals[i], ModuleUtils.findInternal('cc', collectorClass, 'A'));
|
||||
usedSlots.push(collectorInternals[i]);
|
||||
collectorLimpetsRequired -= collectorInternals[i].m.maximum;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Dual mining lasers of highest possible class; remove anything else
|
||||
const miningLaserOrder = [2, 3, 4, 1, 0];
|
||||
const miningLaserHardpoints = ship.hardpoints.concat().sort(function(a,b) {
|
||||
return miningLaserOrder.indexOf(a.maxClass) - miningLaserOrder.indexOf(b.maxClass);
|
||||
});
|
||||
for (let s of miningLaserHardpoints) {
|
||||
if (s.maxClass >= 1 && miningLaserCount) {
|
||||
ship.use(s, ModuleUtils.hardpoints(s.maxClass >= 2 ? '2m' : '2l'));
|
||||
miningLaserCount--;
|
||||
} else {
|
||||
ship.use(s, null);
|
||||
}
|
||||
}
|
||||
|
||||
// Fill the empty internals with cargo racks
|
||||
for (let i = ship.internal.length; i--;) {
|
||||
let slot = ship.internal[i];
|
||||
if (usedSlots.indexOf(slot) == -1 && canMount(ship, slot, 'cr')) {
|
||||
ship.use(slot, ModuleUtils.findInternal('cr', slot.maxClass, 'E'));
|
||||
}
|
||||
}
|
||||
|
||||
ship.useLightestStandard(standardOpts);
|
||||
}
|
||||
|
||||
@@ -253,11 +253,15 @@ export function shipFromJson(json) {
|
||||
internalSlot = json.modules[internalName];
|
||||
militarySlotNum++;
|
||||
} else {
|
||||
// Slot numbers are not contiguous so handle skips.
|
||||
while (internalSlot === null && internalSlotNum < 99) {
|
||||
// Slot numbers are not contiguous so handle skips
|
||||
const internalName = 'Slot' + (internalSlotNum <= 9 ? '0' : '') + internalSlotNum + '_Size' + internalClassNum;
|
||||
if (json.modules[internalName]) {
|
||||
internalSlot = json.modules[internalName];
|
||||
// Slot sizes have no relationship to the actual size, either, so check all possibilities
|
||||
for (let slotsize = 0; slotsize < 9; slotsize++) {
|
||||
const internalName = 'Slot' + (internalSlotNum <= 9 ? '0' : '') + internalSlotNum + '_Size' + slotsize;
|
||||
if (json.modules[internalName]) {
|
||||
internalSlot = json.modules[internalName];
|
||||
break;
|
||||
}
|
||||
}
|
||||
internalSlotNum++;
|
||||
}
|
||||
|
||||
@@ -22,24 +22,24 @@
|
||||
<meta name="msapplication-TileImage" content="/mstile-144x144.png">
|
||||
<meta name="msapplication-config" content="/browserconfig.xml">
|
||||
<meta name="theme-color" content="#000000">
|
||||
</head>
|
||||
<body style="background-color:#000;">
|
||||
<section id="coriolis"></section>
|
||||
|
||||
<script>
|
||||
window.CORIOLIS_GAPI_KEY = '{%= o.htmlWebpackPlugin.options.gapiKey %}';
|
||||
window.CORIOLIS_VERSION = '{%= o.htmlWebpackPlugin.options.version %}';
|
||||
window.CORIOLIS_DATE = '{%= new Date().toISOString().slice(0, 10) %}';
|
||||
</script>
|
||||
{% if (o.htmlWebpackPlugin.options.uaTracking) { %}
|
||||
<script>
|
||||
window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
|
||||
ga('create', '{%= o.htmlWebpackPlugin.options.uaTracking %}', 'auto');
|
||||
ga('send', 'pageview');
|
||||
</script>
|
||||
<script async src='https://www.google-analytics.com/analytics.js'></script>
|
||||
{% } %}
|
||||
</head>
|
||||
<body style="background-color:#000;">
|
||||
<section id="coriolis"></section>
|
||||
<script src="{%= o.htmlWebpackPlugin.files.chunks.lib.entry %}" charset="utf-8" crossorigin="anonymous"></script>
|
||||
<script src="{%= o.htmlWebpackPlugin.files.chunks.app.entry %}" charset="utf-8" crossorigin="anonymous"></script>
|
||||
<script>
|
||||
{% if (o.htmlWebpackPlugin.options.uaTracking) { %}
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||
ga('create', '{%= o.htmlWebpackPlugin.options.uaTracking %}', 'auto');
|
||||
{% } %}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user