import React from 'react'; import { Modifications } from 'coriolis-data/dist'; /** * Generate a tooltip with details of a blueprint's effects * @param {Object} translate The translate object * @param {Object} blueprint The blueprint at the required grade * @param {Array} engineers The engineers supplying this blueprint * @param {string} grp The group of the module * @param {Object} m The module to compare with * @returns {Object} The react components */ export function blueprintTooltip(translate, blueprint, engineers, grp, m) { const effects = []; for (const feature in blueprint.features) { const featureIsBeneficial = isBeneficial(feature, blueprint.features[feature]); const featureDef = Modifications.modifications[feature]; if (!featureDef.hidden) { let symbol = ''; if (feature === 'jitter') { symbol = '°'; } else if (featureDef.type === 'percentage') { symbol = '%'; } let lowerBound = blueprint.features[feature][0]; let upperBound = blueprint.features[feature][1]; if (featureDef.type === 'percentage') { lowerBound = Math.round(lowerBound * 1000) / 10; upperBound = Math.round(upperBound * 1000) / 10; } const lowerIsBeneficial = isValueBeneficial(feature, lowerBound); const upperIsBeneficial = isValueBeneficial(feature, upperBound); if (m) { // We have a module - add in the current value let current = m.getModValue(feature); if (featureDef.type === 'percentage' || featureDef.name === 'burst' || featureDef.name === 'burstrof') { current = Math.round(current / 10) / 10; } else if (featureDef.type === 'numeric') { current /= 100; } const currentIsBeneficial = isValueBeneficial(feature, current); effects.push( {translate(feature, grp)} {lowerBound}{symbol} {current}{symbol} {upperBound}{symbol} ); } else { // We do not have a module, no value effects.push( {translate(feature, grp)} {lowerBound}{symbol} {upperBound}{symbol} ); } } } if (m) { // Because we have a module add in any benefits that aren't part of the primary blueprint for (const feature in m.mods) { if (!blueprint.features[feature]) { const featureDef = Modifications.modifications[feature]; let symbol = ''; if (feature === 'jitter') { symbol = '°'; } else if (featureDef.type === 'percentage') { symbol = '%'; } let current = m.getModValue(feature); if (featureDef.type === 'percentage' || featureDef.name === 'burst' || featureDef.name === 'burstrof') { current = Math.round(current / 10) / 10; } else if (featureDef.type === 'numeric') { current /= 100; } const currentIsBeneficial = isValueBeneficial(feature, current); effects.push( {translate(feature, grp)}   {current}{symbol}   ); } } } let components; if (!m) { components = []; for (const component in blueprint.components) { components.push( {translate(component)} {blueprint.components[component]} ); } } let engineersList; if (engineers) { engineersList = []; for (const engineer of engineers) { engineersList.push( {engineer} ); } } return (
{m ? : null } {effects}
{translate('feature')} {translate('worst')}{translate('current')}{translate('best')}
{ components ? {components}
{translate('component')} {translate('amount')}
: null } { engineersList ? {engineersList}
{translate('engineers')}
: null }
); } /** * Is this blueprint feature beneficial? * @param {string} feature The name of the feature * @param {array} values The value of the feature * @returns {boolean} True if this feature is beneficial */ export function isBeneficial(feature, values) { const fact = (values[0] < 0 || (values[0] === 0 && values[1] < 0)); if (Modifications.modifications[feature].higherbetter) { return !fact; } else { return fact; } } /** * Is this feature value beneficial? * @param {string} feature The name of the feature * @param {number} value The value of the feature * @returns {boolean} True if this value is beneficial */ export function isValueBeneficial(feature, value) { if (Modifications.modifications[feature].higherbetter) { return value > 0; } else { return value < 0; } } /** * Get a blueprint with a given name and an optional module * @param {string} name The name of the blueprint * @param {Object} module The module for which to obtain this blueprint * @returns {Object} The matching blueprint */ export function getBlueprint(name, module) { // Start with a copy of the blueprint const blueprint = JSON.parse(JSON.stringify(Modifications.blueprints[name])); if (module) { if (module.grp === 'bh' || module.grp === 'hr' || module.grp === 'sg' || module.grp === 'psg' || module.grp === 'bsg') { // Bulkheads, hull reinforcements and shield generators need to have their resistances altered by the base values for (const grade in blueprint.grades) { for (const feature in blueprint.grades[grade].features) { if (feature === 'explres') { blueprint.grades[grade].features[feature][0] *= (1 - module.explres); blueprint.grades[grade].features[feature][1] *= (1 - module.explres); } if (feature === 'kinres') { blueprint.grades[grade].features[feature][0] *= (1 - module.kinres); blueprint.grades[grade].features[feature][1] *= (1 - module.kinres); } if (feature === 'thermres') { blueprint.grades[grade].features[feature][0] *= (1 - module.thermres); blueprint.grades[grade].features[feature][1] *= (1 - module.thermres); } } } } if (module.grp === 'sb') { // Shield boosters are treated internally as straight modifiers, so rather than (for example) // being a 4% boost they are a 104% multiplier. We need to fix the values here so that they look // accurate as per the information in Elite for (const grade in blueprint.grades) { for (const feature in blueprint.grades[grade].features) { if (feature === 'shieldboost') { blueprint.grades[grade].features[feature][0] = ((1 + blueprint.grades[grade].features[feature][0]) * (1 + module.shieldboost) - 1) / module.shieldboost - 1; blueprint.grades[grade].features[feature][1] = ((1 + blueprint.grades[grade].features[feature][1]) * (1 + module.shieldboost) - 1) / module.shieldboost - 1; } } } } } 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); } }