diff --git a/ChangeLog.md b/ChangeLog.md
index a5f43e51..316b3f0e 100644
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,6 +1,7 @@
#2.3.4
* Fix crash when removing the special effect from a module
* Ensure comparisons with saved stock ships work correctly
+ * Add 'Racer' role
#2.3.3
* Remove unused blueprint when hitting reset
diff --git a/src/app/components/ModificationsMenu.jsx b/src/app/components/ModificationsMenu.jsx
index 6380aad5..4ffe0c9f 100644
--- a/src/app/components/ModificationsMenu.jsx
+++ b/src/app/components/ModificationsMenu.jsx
@@ -5,7 +5,7 @@ import { isEmpty, stopCtxPropagation } from '../utils/UtilityFunctions';
import cn from 'classnames';
import { Modifications } from 'coriolis-data/dist';
import Modification from './Modification';
-import { getBlueprint, blueprintTooltip } from '../utils/BlueprintFunctions';
+import { getBlueprint, blueprintTooltip, setWorst, setBest, setExtreme, setRandom } from '../utils/BlueprintFunctions';
/**
* Modifications menu
@@ -165,35 +165,12 @@ 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].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;
- ship.clearModifications(m);
- const features = m.blueprint.grades[m.blueprint.grade].features;
- for (const featureName in features) {
- let value = features[featureName][0];
- this._setRollResult(ship, m, featureName, value);
- }
-
+ setWorst(ship, m);
this.props.onChange();
}
@@ -202,13 +179,7 @@ export default class ModificationsMenu extends TranslatedComponent {
*/
_rollRandom() {
const { m, ship } = this.props;
- ship.clearModifications(m);
- const features = m.blueprint.grades[m.blueprint.grade].features;
- for (const featureName in features) {
- let value = features[featureName][0] + (Math.random() * (features[featureName][1] - features[featureName][0]));
- this._setRollResult(ship, m, featureName, value);
- }
-
+ setRandom(ship, m);
this.props.onChange();
}
@@ -217,12 +188,7 @@ export default class ModificationsMenu extends TranslatedComponent {
*/
_rollBest() {
const { m, ship } = this.props;
- const features = m.blueprint.grades[m.blueprint.grade].features;
- for (const featureName in features) {
- let value = features[featureName][1];
- this._setRollResult(ship, m, featureName, value);
- }
-
+ setBest(ship, m);
this.props.onChange();
}
@@ -231,29 +197,7 @@ export default class ModificationsMenu extends TranslatedComponent {
*/
_rollExtreme() {
const { m, ship } = this.props;
- ship.clearModifications(m);
- const features = m.blueprint.grades[m.blueprint.grade].features;
- for (const featureName in features) {
- let value;
- if (Modifications.modifications[featureName].higherbetter) {
- // Higher is better, but is this making it better or worse?
- if (features[featureName][0] < 0 || (features[featureName][0] === 0 && features[featureName][1] < 0)) {
- value = features[featureName][0];
- } else {
- value = features[featureName][1];
- }
- } else {
- // Higher is worse, but is this making it better or worse?
- if (features[featureName][0] < 0 || (features[featureName][0] === 0 && features[featureName][1] < 0)) {
- value = features[featureName][1];
- } else {
- value = features[featureName][0];
- }
- }
-
- this._setRollResult(ship, m, featureName, value);
- }
-
+ setExtreme(ship, m);
this.props.onChange();
}
diff --git a/src/app/components/StandardSlotSection.jsx b/src/app/components/StandardSlotSection.jsx
index f57edd90..30b4ff66 100644
--- a/src/app/components/StandardSlotSection.jsx
+++ b/src/app/components/StandardSlotSection.jsx
@@ -72,6 +72,15 @@ export default class StandardSlotSection extends SlotSection {
this._close();
}
+ /**
+ * Racer role
+ */
+ _optimizeRacer() {
+ ShipRoles.racer(this.props.ship);
+ this.props.onChange();
+ this._close();
+ }
+
/**
* Use the specified bulkhead
* @param {Object} bulkhead Bulkhead module details
@@ -220,6 +229,7 @@ export default class StandardSlotSection extends SlotSection {
{translate('Planetary Explorer')}
{translate('Miner')}
{translate('Shielded Miner')}
+ {translate('Racer')}
;
}
diff --git a/src/app/shipyard/ModuleSet.js b/src/app/shipyard/ModuleSet.js
index 1e1f3982..c792bccd 100755
--- a/src/app/shipyard/ModuleSet.js
+++ b/src/app/shipyard/ModuleSet.js
@@ -119,12 +119,11 @@ export default class ModuleSet {
/**
* Find the lightest Power Distributor that provides sufficient
* energy to boost.
- * @param {number} boostEnergy [description]
+ * @param {number} boostEnergy The energy that is required to boost
* @return {Object} Power Distributor
*/
lightestPowerDist(boostEnergy) {
let pd = this.standard[4][0];
-
for (let p of this.standard[4]) {
if (p.mass < pd.mass && p.engcap > boostEnergy) {
pd = p;
diff --git a/src/app/shipyard/Ship.js b/src/app/shipyard/Ship.js
index 902ba096..421504f5 100755
--- a/src/app/shipyard/Ship.js
+++ b/src/app/shipyard/Ship.js
@@ -1718,6 +1718,11 @@ export default class Ship {
.use(standard[4], pd) // Power Distributor
.use(standard[6], ft); // Fuel Tank
+ // Turn off nearly everything
+ if (m.fsdDisabled) this.setSlotEnabled(this.standard[2], false);
+ if (m.pdDisabled) this.setSlotEnabled(this.standard[4], false);
+ if (m.sDisabled) this.setSlotEnabled(this.standard[5], false);
+
// Thrusters and Powerplant must be determined after all other ModuleUtils are mounted
// Loop at least once to determine absolute lightest PD and TH
do {
diff --git a/src/app/shipyard/ShipRoles.js b/src/app/shipyard/ShipRoles.js
index 4ddf91fc..84b15f55 100644
--- a/src/app/shipyard/ShipRoles.js
+++ b/src/app/shipyard/ShipRoles.js
@@ -294,3 +294,88 @@ export function miner(ship, shielded) {
ship.useLightestStandard(standardOpts);
}
+
+/**
+ * Racer Role
+ * @param {Ship} ship Ship instance
+ */
+export function racer(ship) {
+ let standardOpts = {},
+ usedSlots = [],
+ sgSlot,
+ sg = ship.getAvailableModules().lightestShieldGenerator(ship.hullMass);
+
+ // Cargo hatch can be disabled
+ ship.setSlotEnabled(ship.cargoHatch, false);
+
+ // Shield generator
+ 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.sg)
+ .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]);
+ sgSlot = shieldInternals[i];
+ break;
+ }
+ }
+
+ // Empty the hardpoints
+ for (let s of ship.hardpoints) {
+ ship.use(s, null);
+ }
+
+ // Empty the internals
+ for (let i = ship.internal.length; i--;) {
+ let slot = ship.internal[i];
+ if (usedSlots.indexOf(slot) == -1) {
+ ship.use(slot, null);
+ }
+ }
+
+ // Best thrusters
+ if (ship.standard[1].maxClass === 3) {
+ standardOpts.th = 'tz';
+ } else if (ship.standard[1].maxClass === 2) {
+ standardOpts.th = 'u0';
+ } else {
+ standardOpts.th = ship.standard[1].maxClass + 'A';
+ }
+
+ // Best power distributor for more boosting
+ standardOpts.pd = ship.standard[4].maxClass + 'A';
+
+ // Smallest possible FSD drive
+ standardOpts.fsd = '2D';
+ // Minimal fuel tank
+ standardOpts.ft = '1C';
+
+ // Disable nearly everything
+ standardOpts.fsdDisabled = true;
+ standardOpts.sDisabled = true;
+ standardOpts.pdDisabled = true;
+ standardOpts.lsDisabled = true;
+
+ ship.useLightestStandard(standardOpts);
+
+ // Apply engineering to each module
+ // ship.standard[1].m.blueprint = getBlueprint('Engine_Dirty', ship.standard[0]);
+ // ship.standard[1].m.blueprint.grade = 5;
+ // setBest(ship, ship.standard[1].m);
+
+ // ship.standard[3].m.blueprint = getBlueprint('LifeSupport_LightWeight', ship.standard[3]);
+ // ship.standard[3].m.blueprint.grade = 4;
+ // setBest(ship, ship.standard[3].m);
+
+ // ship.standard[4].m.blueprint = getBlueprint('PowerDistributor_PriorityEngines', ship.standard[4]);
+ // ship.standard[4].m.blueprint.grade = 3;
+ // setBest(ship, ship.standard[4].m);
+
+ // ship.standard[5].m.blueprint = getBlueprint('Sensor_Sensor_LightWeight', ship.standard[5]);
+ // ship.standard[5].m.blueprint.grade = 5;
+ // setBest(ship, ship.standard[5].m);
+}
+
diff --git a/src/app/utils/BlueprintFunctions.js b/src/app/utils/BlueprintFunctions.js
index eaaffaec..dd22bec3 100644
--- a/src/app/utils/BlueprintFunctions.js
+++ b/src/app/utils/BlueprintFunctions.js
@@ -227,3 +227,110 @@ export function getBlueprint(name, module) {
}
return blueprint;
}
+
+/**
+ * Provide 'worst' primary modifications
+ * @param {Object} ship The ship for which to perform the modifications
+ * @param {Object} m The module for which to perform the modifications
+ */
+export function setWorst(ship, m) {
+ ship.clearModifications(m);
+ const features = m.blueprint.grades[m.blueprint.grade].features;
+ for (const featureName in features) {
+ const value = features[featureName][0];
+ _setValue(ship, m, featureName, value);
+ }
+}
+
+/**
+ * Provide 'best' primary modifications
+ * @param {Object} ship The ship for which to perform the modifications
+ * @param {Object} m The module for which to perform the modifications
+ */
+export function setBest(ship, m) {
+ ship.clearModifications(m);
+ const features = m.blueprint.grades[m.blueprint.grade].features;
+ for (const featureName in features) {
+ const value = features[featureName][1];
+ _setValue(ship, m, featureName, value);
+ }
+}
+
+/**
+ * Provide 'extreme' primary modifications
+ * @param {Object} ship The ship for which to perform the modifications
+ * @param {Object} m The module for which to perform the modifications
+ */
+export function setExtreme(ship, m) {
+ ship.clearModifications(m);
+ const features = m.blueprint.grades[m.blueprint.grade].features;
+ for (const featureName in features) {
+ let value;
+ if (Modifications.modifications[featureName].higherbetter) {
+ // Higher is better, but is this making it better or worse?
+ if (features[featureName][0] < 0 || (features[featureName][0] === 0 && features[featureName][1] < 0)) {
+ value = features[featureName][0];
+ } else {
+ value = features[featureName][1];
+ }
+ } else {
+ // Higher is worse, but is this making it better or worse?
+ if (features[featureName][0] < 0 || (features[featureName][0] === 0 && features[featureName][1] < 0)) {
+ value = features[featureName][1];
+ } else {
+ value = features[featureName][0];
+ }
+ }
+
+ _setValue(ship, m, featureName, value);
+ }
+}
+
+/**
+ * Provide 'random' primary modifications
+ * @param {Object} ship The ship for which to perform the modifications
+ * @param {Object} m The module for which to perform the modifications
+ */
+export function setRandom(ship, m) {
+ ship.clearModifications(m);
+ // Pick a single value for our randomness
+ const mult = Math.random();
+ const features = m.blueprint.grades[m.blueprint.grade].features;
+ for (const featureName in features) {
+ let value;
+ if (Modifications.modifications[featureName].higherbetter) {
+ // Higher is better, but is this making it better or worse?
+ if (features[featureName][0] < 0 || (features[featureName][0] === 0 && features[featureName][1] < 0)) {
+ value = features[featureName][1] + ((features[featureName][0] - features[featureName][1]) * mult);
+ } else {
+ value = features[featureName][0] + ((features[featureName][1] - features[featureName][0]) * mult);
+ }
+ } else {
+ // Higher is worse, but is this making it better or worse?
+ if (features[featureName][0] < 0 || (features[featureName][0] === 0 && features[featureName][1] < 0)) {
+ value = features[featureName][0] + ((features[featureName][1] - features[featureName][0]) * mult);
+ } else {
+ value = features[featureName][1] + ((features[featureName][0] - features[featureName][1]) * mult);
+ }
+ }
+
+ _setValue(ship, m, featureName, value);
+ }
+}
+
+/**
+ * Set a modification feature value
+ * @param {Object} ship The ship for which to perform the modifications
+ * @param {Object} m The module for which to perform the modifications
+ * @param {string} featureName The feature being set
+ * @param {number} value The value being set for the feature
+ */
+function _setValue(ship, m, featureName, value) {
+ 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);
+ }
+}