From 588cfc3990dd8707f6c848a750407f0e71157502 Mon Sep 17 00:00:00 2001 From: William Date: Wed, 8 Feb 2017 16:14:34 +1100 Subject: [PATCH 1/9] fix wiki link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 53886504..222e637a 100755 --- a/README.md +++ b/README.md @@ -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 From 24849cee08ed4b68ba54ee9ef7ef5bf022c6e5f1 Mon Sep 17 00:00:00 2001 From: Cmdr McDonald Date: Wed, 8 Feb 2017 10:09:30 +0000 Subject: [PATCH 2/9] Ensure that standard slots are repainted when any component changes --- ChangeLog.md | 3 +++ src/app/components/SlotSection.jsx | 4 ++-- src/app/pages/OutfittingPage.jsx | 5 ++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index ae76de03..c8f817fd 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,3 +1,6 @@ +#2.2.15 + * Ensure that standard slots are repainted when any component changes + #2.2.14 * Ensure that jitter is shown correctly when the result of a special effect * Use restyled blueprint information diff --git a/src/app/components/SlotSection.jsx b/src/app/components/SlotSection.jsx index d0789448..e34607c8 100644 --- a/src/app/components/SlotSection.jsx +++ b/src/app/components/SlotSection.jsx @@ -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 { diff --git a/src/app/pages/OutfittingPage.jsx b/src/app/pages/OutfittingPage.jsx index 95547a95..f0c5f088 100644 --- a/src/app/pages/OutfittingPage.jsx +++ b/src/app/pages/OutfittingPage.jsx @@ -316,7 +316,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 ( @@ -350,12 +349,12 @@ export default class OutfittingPage extends Page { - + - +
From abf65ee436ec9657506e0c1e1fbf0542cc49902f Mon Sep 17 00:00:00 2001 From: Cmdr McDonald Date: Fri, 10 Feb 2017 18:22:39 +0000 Subject: [PATCH 3/9] Reload page if Safari throws a security error --- ChangeLog.md | 1 + package.json | 2 +- src/app/Router.js | 22 ++++++++++++++++++++-- src/app/pages/OutfittingPage.jsx | 12 ++++++------ src/app/pages/Page.jsx | 10 +++++++++- 5 files changed, 37 insertions(+), 10 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index c8f817fd..0a0bdf29 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,5 +1,6 @@ #2.2.15 * Ensure that standard slots are repainted when any component changes + * Reload page if Safari throws a security error #2.2.14 * Ensure that jitter is shown correctly when the result of a special effect diff --git a/package.json b/package.json index 6a7e98fd..47a523c9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "coriolis_shipyard", - "version": "2.2.14", + "version": "2.2.15b", "repository": { "type": "git", "url": "https://github.com/EDCD/coriolis" diff --git a/src/app/Router.js b/src/app/Router.js index acf588c3..6ac0e612 100644 --- a/src/app/Router.js +++ b/src/app/Router.js @@ -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; }; diff --git a/src/app/pages/OutfittingPage.jsx b/src/app/pages/OutfittingPage.jsx index f0c5f088..46401c6b 100644 --- a/src/app/pages/OutfittingPage.jsx +++ b/src/app/pages/OutfittingPage.jsx @@ -348,13 +348,13 @@ export default class OutfittingPage extends Page {
- - + + - - - - + + + +
diff --git a/src/app/pages/Page.jsx b/src/app/pages/Page.jsx index ca1a1d48..7f8b5d31 100644 --- a/src/app/pages/Page.jsx +++ b/src/app/pages/Page.jsx @@ -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(); } -} \ No newline at end of file +} From 7fbcbb75ed286d17af35e1c2f291fc14d5faaa19 Mon Sep 17 00:00:00 2001 From: Cmdr McDonald Date: Sat, 11 Feb 2017 19:45:28 +0000 Subject: [PATCH 4/9] Do not rely on slot sizes being correct --- ChangeLog.md | 1 + .../fixtures/companion-api-import-3.json | 314 ++++++++++++++++++ __tests__/test-import.js | 16 +- src/app/utils/CompanionApiUtils.js | 12 +- 4 files changed, 337 insertions(+), 6 deletions(-) create mode 100644 __tests__/fixtures/companion-api-import-3.json diff --git a/ChangeLog.md b/ChangeLog.md index 0a0bdf29..a3e42176 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,6 +1,7 @@ #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 #2.2.14 * Ensure that jitter is shown correctly when the result of a special effect diff --git a/__tests__/fixtures/companion-api-import-3.json b/__tests__/fixtures/companion-api-import-3.json new file mode 100644 index 00000000..88de0f55 --- /dev/null +++ b/__tests__/fixtures/companion-api-import-3.json @@ -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 + } +} diff --git a/__tests__/test-import.js b/__tests__/test-import.js index 9a069359..19480ad8 100644 --- a/__tests__/test-import.js +++ b/__tests__/test-import.js @@ -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() { diff --git a/src/app/utils/CompanionApiUtils.js b/src/app/utils/CompanionApiUtils.js index 674ef674..c55e334a 100644 --- a/src/app/utils/CompanionApiUtils.js +++ b/src/app/utils/CompanionApiUtils.js @@ -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++; } From 45852db5077fb38587d17c112df84ebabe20b74a Mon Sep 17 00:00:00 2001 From: Cmdr McDonald Date: Sat, 11 Feb 2017 19:57:46 +0000 Subject: [PATCH 5/9] Add 'Extreme' roll --- ChangeLog.md | 1 + src/app/components/ModificationsMenu.jsx | 55 +++++++++++++----------- src/app/i18n/en.js | 3 +- 3 files changed, 33 insertions(+), 26 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index a3e42176..f15a156e 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -2,6 +2,7 @@ * 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) #2.2.14 * Ensure that jitter is shown correctly when the result of a special effect diff --git a/src/app/components/ModificationsMenu.jsx b/src/app/components/ModificationsMenu.jsx index 02267b0e..facdd9c9 100644 --- a/src/app/components/ModificationsMenu.jsx +++ b/src/app/components/ModificationsMenu.jsx @@ -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); } @@ -185,20 +185,6 @@ export default class ModificationsMenu extends TranslatedComponent { this.props.onChange(); } - /** - * Provide an 'average' roll within the information we have - */ - _rollAverage() { - const { m, ship } = this.props; - const features = m.blueprint.grades[m.blueprint.grade].features; - for (const featureName in features) { - let value = (features[featureName][0] + features[featureName][1]) / 2; - this._setRollResult(ship, m, featureName, value); - } - this.setState({ modifications: this._setModifications(this.props) }); - this.props.onChange(); - } - /** * Provide a random roll within the information we have */ @@ -227,6 +213,20 @@ export default class ModificationsMenu extends TranslatedComponent { 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 = Math.abs(features[featureName][0]) < Math.abs(features[featureName][1]) ? features[featureName][1] : features[featureName][0]; + this._setRollResult(ship, m, featureName, value); + } + this.setState({ modifications: this._setModifications(this.props) }); + this.props.onChange(); + } + /** * Reset modification information */ @@ -252,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; @@ -278,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 ( @@ -287,26 +288,30 @@ export default class ModificationsMenu extends TranslatedComponent { onContextMenu={stopCtxPropagation} >
{blueprintLabel}
- { showBlueprintsMenu ? this.state.blueprints : '' } - { showSpecial ?
{specialLabel}
: '' } - { showSpecialsMenu ? this.state.specials : '' } - { showRolls ? + { showBlueprintsMenu ? this.state.blueprints : null } + { showSpecial ?
{specialLabel}
: null } + { showSpecialsMenu ? this.state.specials : null } + { showRolls || showReset ? + { showRolls ? - + - - + : null } + { showReset ? + + + : null } -
{ translate('roll') }: { translate('worst') } { translate('average') } { translate('best') } { translate('extreme') } { translate('random') } { translate('reset') }
{ translate('reset') }
: '' } + : null } { showMods ? { this.state.modifications } - : '' } + : null }
); } diff --git a/src/app/i18n/en.js b/src/app/i18n/en.js index 86b56bf8..e4979ff1 100644 --- a/src/app/i18n/en.js +++ b/src/app/i18n/en.js @@ -31,9 +31,9 @@ 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', @@ -115,6 +115,7 @@ export const terms = { average: 'Average', random: 'Random', best: 'Best', + extreme: 'Extreme', reset: 'Reset', // Weapon, offence, defence and movement From 2620935745aa6e185d32e57b54b1fc5d5b90127e Mon Sep 17 00:00:00 2001 From: Cmdr McDonald Date: Sun, 12 Feb 2017 08:31:09 +0000 Subject: [PATCH 6/9] Add additional explanation for import failures --- ChangeLog.md | 1 + src/app/pages/ErrorDetails.jsx | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/ChangeLog.md b/ChangeLog.md index f15a156e..b8aa5618 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -3,6 +3,7 @@ * 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 #2.2.14 * Ensure that jitter is shown correctly when the result of a special effect diff --git a/src/app/pages/ErrorDetails.jsx b/src/app/pages/ErrorDetails.jsx index c315a87e..507f5b94 100644 --- a/src/app/pages/ErrorDetails.jsx +++ b/src/app/pages/ErrorDetails.jsx @@ -39,10 +39,16 @@ export default class ErrorDetails extends React.Component { ; } + const importerror = ed && ed.scriptUrl && ed.scriptUrl.indexOf('/import') != -1; + return

Jameson, we have a problem..

{error.message}

+
+ {importerror ?
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.
: null } +
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.
+
{content}
; } From f011f1f4d57aa40c98beb749d2e9bbb7e95eff97 Mon Sep 17 00:00:00 2001 From: Cmdr McDonald Date: Mon, 13 Feb 2017 07:59:29 +0000 Subject: [PATCH 7/9] Add ability to export module list to EDDB to find where they can be purchased --- ChangeLog.md | 1 + src/app/components/SvgIcons.jsx | 20 ++++++++++++++++++++ src/app/i18n/en.js | 1 + src/app/pages/OutfittingPage.jsx | 19 ++++++++++++++++++- 4 files changed, 40 insertions(+), 1 deletion(-) diff --git a/ChangeLog.md b/ChangeLog.md index b8aa5618..88719997 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -4,6 +4,7 @@ * 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 #2.2.14 * Ensure that jitter is shown correctly when the result of a special effect diff --git a/src/app/components/SvgIcons.jsx b/src/app/components/SvgIcons.jsx index 34d84118..af119679 100644 --- a/src/app/components/SvgIcons.jsx +++ b/src/app/components/SvgIcons.jsx @@ -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 + + ; + } +} + /** * No Power - Lightning bolt + no entry */ diff --git a/src/app/i18n/en.js b/src/app/i18n/en.js index e4979ff1..ce9d4436 100644 --- a/src/app/i18n/en.js +++ b/src/app/i18n/en.js @@ -37,6 +37,7 @@ export const terms = { 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', diff --git a/src/app/pages/OutfittingPage.jsx b/src/app/pages/OutfittingPage.jsx index 46401c6b..9fdd86cb 100644 --- a/src/app/pages/OutfittingPage.jsx +++ b/src/app/pages/OutfittingPage.jsx @@ -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'; @@ -284,6 +284,20 @@ export default class OutfittingPage extends Page { this.context.showModal(); } + /** + * 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 @@ -342,6 +356,9 @@ export default class OutfittingPage extends Page { + From cbac650b9ec23b0b5ce6a5dd7aec82c64ddea059 Mon Sep 17 00:00:00 2001 From: Cmdr McDonald Date: Mon, 13 Feb 2017 08:07:35 +0000 Subject: [PATCH 8/9] Added miner and shielded miner roles --- ChangeLog.md | 1 + src/app/components/StandardSlotSection.jsx | 12 +++ src/app/i18n/en.js | 2 + src/app/shipyard/ShipRoles.js | 101 +++++++++++++++++++++ 4 files changed, 116 insertions(+) diff --git a/ChangeLog.md b/ChangeLog.md index 88719997..9979ea3a 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -5,6 +5,7 @@ * 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 #2.2.14 * Ensure that jitter is shown correctly when the result of a special effect diff --git a/src/app/components/StandardSlotSection.jsx b/src/app/components/StandardSlotSection.jsx index e319f524..23fe2b63 100644 --- a/src/app/components/StandardSlotSection.jsx +++ b/src/app/components/StandardSlotSection.jsx @@ -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 {
  • {translate('Shielded Trader')}
  • {translate('Explorer')}
  • {translate('Planetary Explorer')}
  • +
  • {translate('Miner')}
  • +
  • {translate('Shielded Miner')}
  • ; } diff --git a/src/app/i18n/en.js b/src/app/i18n/en.js index ce9d4436..a296c55f 100644 --- a/src/app/i18n/en.js +++ b/src/app/i18n/en.js @@ -228,6 +228,8 @@ To remove a module from a slot right-click on the module.

    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.

    +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).

    +

    Power Management

    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.

    diff --git a/src/app/shipyard/ShipRoles.js b/src/app/shipyard/ShipRoles.js index 0ebbf0d7..79b3ee9e 100644 --- a/src/app/shipyard/ShipRoles.js +++ b/src/app/shipyard/ShipRoles.js @@ -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); +} From 15a14dc2802f3fd9bd6b69bed9c5181205aab84a Mon Sep 17 00:00:00 2001 From: Cmdr McDonald Date: Mon, 13 Feb 2017 19:50:47 +0000 Subject: [PATCH 9/9] Package version --- ChangeLog.md | 4 ++++ package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog.md b/ChangeLog.md index 9979ea3a..c1ae7c71 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -6,6 +6,10 @@ * 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 diff --git a/package.json b/package.json index 47a523c9..5c876bef 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "coriolis_shipyard", - "version": "2.2.15b", + "version": "2.2.15", "repository": { "type": "git", "url": "https://github.com/EDCD/coriolis"