diff --git a/ChangeLog.md b/ChangeLog.md
index 0f7dda9b..ab1cf2b1 100644
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,3 +1,9 @@
+#2.3.3
+ * Remove unused blueprint when hitting reset
+ * Add 'purchase module' external link to EDDB for refit items
+ * Use coriolis-data 2.3.3:
+ * Add Felicity Farseer to list of engineers that supply sensor and detailed surface scanner modifications
+
#2.3.2
* Use scan range for DSS rather than scan time
* Fix companion API import of Dolphin
diff --git a/package.json b/package.json
index f9851ca5..f2047f42 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "coriolis_shipyard",
- "version": "2.3.2",
+ "version": "2.3.3",
"repository": {
"type": "git",
"url": "https://github.com/EDCD/coriolis"
diff --git a/src/app/components/CostSection.jsx b/src/app/components/CostSection.jsx
index 302dd5c8..0da51961 100644
--- a/src/app/components/CostSection.jsx
+++ b/src/app/components/CostSection.jsx
@@ -6,6 +6,7 @@ import Ship from '../shipyard/Ship';
import { Insurance } from '../shipyard/Constants';
import { slotName, slotComparator } from '../utils/SlotFunctions';
import TranslatedComponent from './TranslatedComponent';
+import { ShoppingIcon } from '../components/SvgIcons';
/**
* Cost Section
@@ -31,6 +32,7 @@ export default class CostSection extends TranslatedComponent {
this._buildRetrofitShip = this._buildRetrofitShip.bind(this);
this._onBaseRetrofitChange = this._onBaseRetrofitChange.bind(this);
this._defaultRetrofitName = this._defaultRetrofitName.bind(this);
+ this._eddbShoppingList = this._eddbShoppingList.bind(this);
let data = Ships[props.ship.id]; // Retrieve the basic ship properties, slots and defaults
let retrofitName = this._defaultRetrofitName(props.ship.id, props.buildName);
@@ -325,12 +327,27 @@ export default class CostSection extends TranslatedComponent {
;
}
+ /**
+ * Open up a window for EDDB with a shopping list of our retrofit components
+ */
+ _eddbShoppingList() {
+ const { retrofitCosts } = this.state;
+ const { ship } = this.props;
+
+ // Provide unique list of non-PP module EDDB IDs to buy
+ const modIds = retrofitCosts.filter(item => item.retroItem.incCost && item.buyId && !item.buyPp).map(item => item.buyId).filter((v, i, a) => a.indexOf(v) === i);
+
+ // Open up the relevant URL
+ window.open('https://eddb.io/station?m=' + modIds.join(','));
+ }
+
/**
* Render the retofit tab
* @return {React.Component} Tab contents
*/
_retrofitTab() {
let { retrofitTotal, retrofitCosts, moduleDiscount, retrofitName } = this.state;
+ const { termtip, tooltip } = this.context;
let { translate, formats, units } = this.context.language;
let int = formats.int;
let rows = [], options = [];
@@ -370,7 +387,8 @@ export default class CostSection extends TranslatedComponent {
{rows}
- | {translate('cost')} |
+ |
+ {translate('cost')} |
0 ? 'warning' : 'secondary-disabled')} style={{ borderBottom:'none' }}>
{int(retrofitTotal)}{units.CR}
|
@@ -403,6 +421,8 @@ export default class CostSection extends TranslatedComponent {
if (ship.bulkheads.m.index != retrofitShip.bulkheads.m.index) {
item = {
buyClassRating: ship.bulkheads.m.class + ship.bulkheads.m.rating,
+ buyId: ship.bulkheads.m.eddbID,
+ buyPp: ship.bulkheads.m.pp,
buyName: ship.bulkheads.m.name,
sellClassRating: retrofitShip.bulkheads.m.class + retrofitShip.bulkheads.m.rating,
sellName: retrofitShip.bulkheads.m.name,
@@ -424,6 +444,8 @@ export default class CostSection extends TranslatedComponent {
if (modId != retroModId) {
item = { netCost: 0, retroItem: retroSlotGroup[i] };
if (slotGroup[i].m) {
+ item.buyId = slotGroup[i].m.eddbID,
+ item.buyPp = slotGroup[i].m.pp,
item.buyName = slotGroup[i].m.name || slotGroup[i].m.grp;
item.buyClassRating = slotGroup[i].m.class + slotGroup[i].m.rating;
item.netCost = slotGroup[i].discountedCost;
diff --git a/src/app/components/ModificationsMenu.jsx b/src/app/components/ModificationsMenu.jsx
index 1e657e79..5e040613 100644
--- a/src/app/components/ModificationsMenu.jsx
+++ b/src/app/components/ModificationsMenu.jsx
@@ -130,10 +130,10 @@ export default class ModificationsMenu extends TranslatedComponent {
*/
_blueprintSelected(fdname, grade) {
this.context.tooltip(null);
- const { m } = this.props;
+ const { m, ship } = this.props;
const blueprint = getBlueprint(fdname, m);
blueprint.grade = grade;
- m.blueprint = blueprint;
+ ship.setModuleBlueprint(m, blueprint);
this.setState({ blueprintMenuOpened: false });
this.props.onChange();
@@ -155,15 +155,10 @@ export default class ModificationsMenu extends TranslatedComponent {
this.context.tooltip(null);
const { m, ship } = this.props;
- if (m.blueprint) {
- if (special === null) {
- m.blueprint.special = null;
- } else {
- m.blueprint.special = Modifications.specials[special];
- }
- ship.recalculateDps();
- ship.recalculateHps();
- ship.recalculateEps();
+ if (special === null) {
+ ship.clearModuelSpecial(m);
+ } else {
+ ship.setModuleSpecial(m, Modifications.specials[special]);
}
this.setState({ specialMenuOpened: false });
@@ -268,7 +263,7 @@ export default class ModificationsMenu extends TranslatedComponent {
_reset() {
const { m, ship } = this.props;
ship.clearModifications(m);
- ship.clearBlueprint(m);
+ ship.clearModuleBlueprint(m);
this.props.onChange();
}
@@ -294,7 +289,7 @@ export default class ModificationsMenu extends TranslatedComponent {
let blueprintLabel;
let haveBlueprint = false;
let blueprintTt;
- if (m.blueprint && !isEmpty(m.blueprint)) {
+ if (m.blueprint && m.blueprint.name) {
blueprintLabel = translate(m.blueprint.name) + ' ' + translate('grade') + ' ' + m.blueprint.grade;
haveBlueprint = true;
blueprintTt = blueprintTooltip(translate, m.blueprint.grades[m.blueprint.grade], Modifications.modules[m.grp].blueprints[m.blueprint.fdname].grades[m.blueprint.grade].engineers, m.grp);
diff --git a/src/app/i18n/en.js b/src/app/i18n/en.js
index b154cae4..5ef042f3 100644
--- a/src/app/i18n/en.js
+++ b/src/app/i18n/en.js
@@ -38,6 +38,7 @@ export const terms = {
PHRASE_SELECT_SPECIAL: 'Click to select an experimental effect',
PHRASE_NO_SPECIAL: 'No experimental effect',
PHRASE_SHOPPING_LIST: 'Stations that sell this build',
+ PHRASE_REFIT_SHOPPING_LIST: 'Stations that sell required modules',
PHRASE_TOTAL_EFFECTIVE_SHIELD: 'Total amount of damage that can be taken from each damage type, if using all shield cells',
PHRASE_TIME_TO_LOSE_SHIELDS: 'Shields will hold for',
PHRASE_TIME_TO_RECOVER_SHIELDS: 'Shields will recover in',
diff --git a/src/app/shipyard/Ship.js b/src/app/shipyard/Ship.js
index 0de8b2ef..99dcd23d 100755
--- a/src/app/shipyard/Ship.js
+++ b/src/app/shipyard/Ship.js
@@ -429,11 +429,45 @@ export default class Ship {
}
/**
- * Clear blueprint for a module
- * @param {Number} m The module for which to clear the modifications
+ * Set blueprint for a module
+ * @param {Object} m The module for which to set the blueprint
+ * @param {Object} bp The blueprint
*/
- clearBlueprint(m) {
+ setModuleBlueprint(m, bp) {
+ m.blueprint = bp;
+ this.updateModificationsString();
+ }
+
+ /**
+ * Clear blueprint for a module
+ * @param {Object} m The module for which to clear the blueprint
+ */
+ clearModuleBlueprint(m) {
m.blueprint = {};
+ this.updateModificationsString();
+ }
+
+ /**
+ * Set special for a module
+ * @param {Object} m The module for which to set the blueprint
+ * @param {Object} special The special
+ */
+ setModuleSpecial(m, special) {
+ if (m.blueprint) {
+ m.blueprint.special = special;
+ }
+ this.recalculateDps().recalculateHps().recalculateEps();
+ }
+
+ /**
+ * Clear special for a module
+ * @param {Object} m The module for which to clear the blueprint
+ */
+ clearModuleSpecial(m) {
+ if (m.blueprint) {
+ m.blueprint.special = null;
+ }
+ this.recalculateDps().recalculateHps().recalculateEps();
}
/**
@@ -1445,16 +1479,20 @@ export default class Ship {
// Now work out the size of the binary buffer from our modifications array
let bufsize = 0;
- for (let slot of slots) {
- if (slot.length > 0) {
- // Length is 1 for the slot ID, 10 for the blueprint name and grade, 5 for each modification, and 1 for the end marker
- bufsize = bufsize + 1 + 10 + (5 * slot.length) + 1;
- }
- }
- for (let special of specials) {
- if (special) {
- // Length is 5 for each special
- bufsize += 5;
+ for (let i = 0; i < slots.length; i++) {
+ if (slots[i].length > 0 || (blueprints[i] && blueprints[i].id)) {
+ // Length is 1 for the slot ID, 5 for each modification, and 1 for the end marker
+ bufsize = bufsize + 1 + (5 * slots[i].length) + 1;
+
+ if (blueprints[i] && blueprints[i].id) {
+ // Additional 10 for the blueprint and grade
+ bufsize += 10;
+ }
+
+ if (specials[i]) {
+ // Additional 5 for each special
+ bufsize += 5;
+ }
}
}
@@ -1465,7 +1503,7 @@ export default class Ship {
let curpos = 0;
let i = 0;
for (let slot of slots) {
- if (slot.length > 0) {
+ if (slot.length > 0 || (blueprints[i] && blueprints[i].id)) {
buffer.writeInt8(i, curpos++);
if (blueprints[i] && blueprints[i].id) {
buffer.writeInt8(MODIFICATION_ID_BLUEPRINT, curpos++);