Merge branch 'feature/fixes' into develop

This commit is contained in:
Cmdr McDonald
2017-02-12 11:11:10 +00:00
13 changed files with 420 additions and 46 deletions

View File

@@ -1,3 +1,10 @@
#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
#2.2.14 #2.2.14
* Ensure that jitter is shown correctly when the result of a special effect * Ensure that jitter is shown correctly when the result of a special effect
* Use restyled blueprint information * Use restyled blueprint information

View File

@@ -16,7 +16,7 @@ Chat to us on [Discord](https://discord.gg/0uwCh6R62aPRjk9w)!
## Development ## 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 ### Ship and Module Database

View 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
}
}

View File

@@ -229,7 +229,7 @@ describe('Import Modal', function() {
beforeEach(reset); 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'); const importData = require('./fixtures/companion-api-import-1');
pasteText(JSON.stringify(importData)); 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'); 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'); const importData = require('./fixtures/companion-api-import-2');
pasteText(JSON.stringify(importData)); 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.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'); 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() { describe('Import E:D Shipyard Builds', function() {

View File

@@ -1,6 +1,6 @@
{ {
"name": "coriolis_shipyard", "name": "coriolis_shipyard",
"version": "2.2.14", "version": "2.2.15b",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/EDCD/coriolis" "url": "https://github.com/EDCD/coriolis"

View File

@@ -76,7 +76,16 @@ Router.go = function(path, state) {
if (isStandAlone()) { if (isStandAlone()) {
Persist.setState(ctx); 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; return ctx;
}; };
@@ -99,7 +108,16 @@ Router.replace = function(path, state, dispatch) {
if (isStandAlone()) { if (isStandAlone()) {
Persist.setState(ctx); 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; return ctx;
}; };

View File

@@ -32,8 +32,8 @@ export default class ModificationsMenu extends TranslatedComponent {
this._toggleSpecialsMenu = this._toggleSpecialsMenu.bind(this); this._toggleSpecialsMenu = this._toggleSpecialsMenu.bind(this);
this._rollWorst = this._rollWorst.bind(this); this._rollWorst = this._rollWorst.bind(this);
this._rollRandom = this._rollRandom.bind(this); this._rollRandom = this._rollRandom.bind(this);
this._rollAverage = this._rollAverage.bind(this);
this._rollBest = this._rollBest.bind(this); this._rollBest = this._rollBest.bind(this);
this._rollExtreme = this._rollExtreme.bind(this);
this._reset = this._reset.bind(this); this._reset = this._reset.bind(this);
} }
@@ -185,20 +185,6 @@ export default class ModificationsMenu extends TranslatedComponent {
this.props.onChange(); 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 * Provide a random roll within the information we have
*/ */
@@ -227,6 +213,20 @@ export default class ModificationsMenu extends TranslatedComponent {
this.props.onChange(); 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 * Reset modification information
*/ */
@@ -252,8 +252,8 @@ export default class ModificationsMenu extends TranslatedComponent {
const _toggleBlueprintsMenu = this._toggleBlueprintsMenu; const _toggleBlueprintsMenu = this._toggleBlueprintsMenu;
const _toggleSpecialsMenu = this._toggleSpecialsMenu; const _toggleSpecialsMenu = this._toggleSpecialsMenu;
const _rollBest = this._rollBest; const _rollBest = this._rollBest;
const _rollExtreme = this._rollExtreme;
const _rollWorst = this._rollWorst; const _rollWorst = this._rollWorst;
const _rollAverage = this._rollAverage;
const _rollRandom = this._rollRandom; const _rollRandom = this._rollRandom;
const _reset = this._reset; const _reset = this._reset;
@@ -278,6 +278,7 @@ export default class ModificationsMenu extends TranslatedComponent {
const showSpecial = haveBlueprint && this.state.specials.length > 0; const showSpecial = haveBlueprint && this.state.specials.length > 0;
const showSpecialsMenu = specialMenuOpened; const showSpecialsMenu = specialMenuOpened;
const showRolls = haveBlueprint && !blueprintMenuOpened && !specialMenuOpened; const showRolls = haveBlueprint && !blueprintMenuOpened && !specialMenuOpened;
const showReset = !blueprintMenuOpened && !specialMenuOpened;
const showMods = !blueprintMenuOpened && !specialMenuOpened; const showMods = !blueprintMenuOpened && !specialMenuOpened;
return ( return (
@@ -287,26 +288,30 @@ export default class ModificationsMenu extends TranslatedComponent {
onContextMenu={stopCtxPropagation} onContextMenu={stopCtxPropagation}
> >
<div className={ cn('section-menu', { selected: blueprintMenuOpened })} style={{ cursor: 'pointer' }} onClick={_toggleBlueprintsMenu}>{blueprintLabel}</div> <div className={ cn('section-menu', { selected: blueprintMenuOpened })} style={{ cursor: 'pointer' }} onClick={_toggleBlueprintsMenu}>{blueprintLabel}</div>
{ showBlueprintsMenu ? this.state.blueprints : '' } { showBlueprintsMenu ? this.state.blueprints : null }
{ showSpecial ? <div className={ cn('section-menu', { selected: specialMenuOpened })} style={{ cursor: 'pointer' }} onClick={_toggleSpecialsMenu}>{specialLabel}</div> : '' } { showSpecial ? <div className={ cn('section-menu', { selected: specialMenuOpened })} style={{ cursor: 'pointer' }} onClick={_toggleSpecialsMenu}>{specialLabel}</div> : null }
{ showSpecialsMenu ? this.state.specials : '' } { showSpecialsMenu ? this.state.specials : null }
{ showRolls ? { showRolls || showReset ?
<table style={{ width: '100%', backgroundColor: 'transparent' }}> <table style={{ width: '100%', backgroundColor: 'transparent' }}>
<tbody> <tbody>
{ showRolls ?
<tr> <tr>
<td> { translate('roll') }: </td> <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={_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={_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={_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> : null }
</tr> { 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> </tbody>
</table> : '' } </table> : null }
{ showMods ? { showMods ?
<span onMouseOver={termtip.bind(null, 'HELP_MODIFICATIONS_MENU')} onMouseOut={tooltip.bind(null, null)} > <span onMouseOver={termtip.bind(null, 'HELP_MODIFICATIONS_MENU')} onMouseOut={tooltip.bind(null, null)} >
{ this.state.modifications } { this.state.modifications }
</span> : '' } </span> : null }
</div> </div>
); );
} }

View File

@@ -64,7 +64,7 @@ export default class SlotSection extends TranslatedComponent {
* @param {Object} m Selected module * @param {Object} m Selected module
*/ */
_selectModule(slot, m) { _selectModule(slot, m) {
this.props.ship.use(slot, m); this.props.ship.use(slot, m, false);
this.props.onChange(); this.props.onChange();
this._close(); this._close();
} }
@@ -123,7 +123,7 @@ export default class SlotSection extends TranslatedComponent {
// We want to copy the module in to the target slot // We want to copy the module in to the target slot
if (targetSlot && canMount(this.props.ship, targetSlot, m.grp, m.class)) { if (targetSlot && canMount(this.props.ship, targetSlot, m.grp, m.class)) {
const mCopy = m.clone(); const mCopy = m.clone();
this.props.ship.use(targetSlot, mCopy); this.props.ship.use(targetSlot, mCopy, false);
this.props.onChange(); this.props.onChange();
} }
} else { } else {

View File

@@ -31,9 +31,9 @@ export const terms = {
PHRASE_ENGAGEMENT_RANGE: 'The distance between your ship and its target', PHRASE_ENGAGEMENT_RANGE: 'The distance between your ship and its target',
PHRASE_SELECT_BLUEPRINT: 'Click to select a blueprint', PHRASE_SELECT_BLUEPRINT: 'Click to select a blueprint',
PHRASE_BLUEPRINT_WORST: 'Worst primary values for this 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_RANDOM: 'Random selection between worst and best primary values for this blueprint',
PHRASE_BLUEPRINT_BEST: '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_BLUEPRINT_RESET: 'Remove all modifications and blueprint',
PHRASE_SELECT_SPECIAL: 'Click to select an experimental effect', PHRASE_SELECT_SPECIAL: 'Click to select an experimental effect',
PHRASE_NO_SPECIAL: 'No experimental effect', PHRASE_NO_SPECIAL: 'No experimental effect',
@@ -115,6 +115,7 @@ export const terms = {
average: 'Average', average: 'Average',
random: 'Random', random: 'Random',
best: 'Best', best: 'Best',
extreme: 'Extreme',
reset: 'Reset', reset: 'Reset',
// Weapon, offence, defence and movement // Weapon, offence, defence and movement

View File

@@ -39,10 +39,16 @@ export default class ErrorDetails extends React.Component {
</div>; </div>;
} }
const importerror = ed && ed.scriptUrl && ed.scriptUrl.indexOf('/import') != -1;
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>
<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> <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} {content}
</div>; </div>;
} }

View File

@@ -316,7 +316,6 @@ export default class OutfittingPage extends Page {
canRename = buildName && newBuildName && buildName != newBuildName, canRename = buildName && newBuildName && buildName != newBuildName,
canReload = savedCode && canSave, canReload = savedCode && canSave,
hStr = ship.getHardpointsString() + '.' + ship.getModificationsString(), hStr = ship.getHardpointsString() + '.' + ship.getModificationsString(),
sStr = ship.getStandardString() + '.' + ship.getModificationsString(),
iStr = ship.getInternalString() + '.' + ship.getModificationsString(); iStr = ship.getInternalString() + '.' + ship.getModificationsString();
return ( return (
@@ -349,13 +348,13 @@ export default class OutfittingPage extends Page {
</div> </div>
</div> </div>
<ShipSummaryTable ship={ship} code={code} /> <ShipSummaryTable ship={ship} code={code || ''} />
<StandardSlotSection ship={ship} code={sStr} onChange={shipUpdated} currentMenu={menu} /> <StandardSlotSection ship={ship} code={code || ''} onChange={shipUpdated} currentMenu={menu} />
<InternalSlotSection ship={ship} code={iStr} onChange={shipUpdated} currentMenu={menu} /> <InternalSlotSection ship={ship} code={iStr} onChange={shipUpdated} currentMenu={menu} />
<HardpointsSlotSection ship={ship} code={hStr} onChange={shipUpdated} currentMenu={menu} /> <HardpointsSlotSection ship={ship} code={hStr || ''} onChange={shipUpdated} currentMenu={menu} />
<UtilitySlotSection ship={ship} code={hStr} onChange={shipUpdated} currentMenu={menu} /> <UtilitySlotSection ship={ship} code={hStr || ''} onChange={shipUpdated} currentMenu={menu} />
<PowerManagement ship={ship} code={code} onChange={shipUpdated} /> <PowerManagement ship={ship} code={code || ''} onChange={shipUpdated} />
<CostSection ship={ship} buildName={buildName} code={sStr + hStr + iStr} /> <CostSection ship={ship} buildName={buildName} code={code || ''} />
<div className='group third'> <div className='group third'>
<OffenceSummary ship={ship} code={code}/> <OffenceSummary ship={ship} code={code}/>

View File

@@ -39,6 +39,14 @@ export default class Page extends React.Component {
this[prop] = this[prop].bind(this); 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(); return this.renderPage();
} }
} }

View File

@@ -253,11 +253,15 @@ export function shipFromJson(json) {
internalSlot = json.modules[internalName]; internalSlot = json.modules[internalName];
militarySlotNum++; militarySlotNum++;
} else { } else {
// Slot numbers are not contiguous so handle skips.
while (internalSlot === null && internalSlotNum < 99) { while (internalSlot === null && internalSlotNum < 99) {
// Slot numbers are not contiguous so handle skips // Slot sizes have no relationship to the actual size, either, so check all possibilities
const internalName = 'Slot' + (internalSlotNum <= 9 ? '0' : '') + internalSlotNum + '_Size' + internalClassNum; for (let slotsize = 0; slotsize < 9; slotsize++) {
if (json.modules[internalName]) { const internalName = 'Slot' + (internalSlotNum <= 9 ? '0' : '') + internalSlotNum + '_Size' + slotsize;
internalSlot = json.modules[internalName]; if (json.modules[internalName]) {
internalSlot = json.modules[internalName];
break;
}
} }
internalSlotNum++; internalSlotNum++;
} }