mirror of
https://github.com/EDCD/coriolis.git
synced 2025-12-09 06:43:24 +00:00
Implement blueprint tooltips
This commit is contained in:
@@ -63,12 +63,12 @@ export default class ModificationsMenu extends TranslatedComponent {
|
||||
grade = Number(grade);
|
||||
const active = m.getBlueprint() === blueprint && m.getBlueprintGrade() === grade;
|
||||
const key = blueprint + ':' + grade;
|
||||
// const tooltipContent = blueprintTooltip(translate, info.features[grade]);
|
||||
const tooltipContent = blueprintTooltip(language, m, blueprint, grade);
|
||||
blueprintGrades.unshift(
|
||||
<li key={key} data-id={key} className={cn('c', { active })}
|
||||
style={{ width: '2em' }}
|
||||
// onMouseOver={termtip.bind(null, tooltipContent)}
|
||||
// onMouseOut={tooltip.bind(null, null)}
|
||||
onMouseOver={termtip.bind(null, tooltipContent)}
|
||||
onMouseOut={tooltip.bind(null, null)}
|
||||
onClick={() => {
|
||||
m.setBlueprint(blueprint, grade, 1);
|
||||
this.setState({
|
||||
|
||||
@@ -89,20 +89,20 @@ export default class Slot extends TranslatedComponent {
|
||||
// Modifications tooltip shows blueprint and grade, if available
|
||||
let modTT = translate('modified');
|
||||
const blueprint = m.getBlueprint();
|
||||
// const experimental = m.getExperimental();
|
||||
// const grade = m.getGrade();
|
||||
// if (blueprint) {
|
||||
// modTT = translate(blueprint) + ' ' + translate('grade') + ' ' + grade;
|
||||
// if (experimental) {
|
||||
// modTT += ', ' + translate(experimental);
|
||||
// }
|
||||
// modTT = (
|
||||
// <div>
|
||||
// <div>{modTT}</div>
|
||||
// {blueprintTooltip(translate, m.blueprint.grades[m.blueprint.grade], m)}
|
||||
// </div>
|
||||
// );
|
||||
// }
|
||||
const experimental = m.getExperimental();
|
||||
const grade = m.getBlueprintGrade();
|
||||
if (blueprint) {
|
||||
modTT = `${translate(blueprint)} ${translate('grade')}: ${grade}`;
|
||||
if (experimental) {
|
||||
modTT += `, ${translate(experimental)}`;
|
||||
}
|
||||
modTT = (
|
||||
<div>
|
||||
<div>{modTT}</div>
|
||||
{blueprintTooltip(language, m)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
let mass = m.get('mass') || m.get('cargo') || m.get('fuel') || 0;
|
||||
return (
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import React from 'react';
|
||||
import { Modifications } from 'coriolis-data/dist';
|
||||
import { STATS_FORMATTING } from '../shipyard/StatsFormatting';
|
||||
import { Module } from 'ed-forge';
|
||||
import { getBlueprintInfo } from 'ed-forge/lib/data/blueprints';
|
||||
import { keys, uniq } from 'lodash';
|
||||
|
||||
/**
|
||||
* Generate a tooltip with details of a blueprint's specials
|
||||
@@ -63,153 +66,23 @@ export function specialToolTip(translate, blueprint, grp, m, specialName) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 {Object} m The module to compare with
|
||||
* @returns {Object} The react components
|
||||
* Generate a tooltip with details and preview of a blueprint's effects
|
||||
* @param {Object} language The language object
|
||||
* @param {Module} m The module to compare with
|
||||
* @param {string} previewBP Blueprint to preview
|
||||
* @param {number} previewGrade Grade to preview
|
||||
* @returns {Object} The react components
|
||||
*/
|
||||
export function blueprintTooltip(translate, blueprint, m) {
|
||||
const effects = [];
|
||||
if (!blueprint || !blueprint.features) {
|
||||
return undefined;
|
||||
}
|
||||
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(
|
||||
<tr key={feature}>
|
||||
<td style={{ textAlign: 'left' }}>{translate(feature)}</td>
|
||||
<td className={lowerBound === 0 ? '' : lowerIsBeneficial ? 'secondary' : 'warning'} style={{ textAlign: 'right' }}>{lowerBound}{symbol}</td>
|
||||
<td className={current === 0 ? '' : currentIsBeneficial ? 'secondary' : 'warning'} style={{ textAlign: 'right' }}>{current}{symbol}</td>
|
||||
<td className={upperBound === 0 ? '' : upperIsBeneficial ? 'secondary' : 'warning'} style={{ textAlign: 'right' }}>{upperBound}{symbol}</td>
|
||||
</tr>
|
||||
);
|
||||
} else {
|
||||
// We do not have a module, no value
|
||||
effects.push(
|
||||
<tr key={feature}>
|
||||
<td style={{ textAlign: 'left' }}>{translate(feature)}</td>
|
||||
<td className={lowerBound === 0 ? '' : lowerIsBeneficial ? 'secondary' : 'warning'} style={{ textAlign: 'right' }}>{lowerBound}{symbol}</td>
|
||||
<td className={upperBound === 0 ? '' : upperIsBeneficial ? 'secondary' : 'warning'} style={{ textAlign: 'right' }}>{upperBound}{symbol}</td>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
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];
|
||||
if (featureDef && !featureDef.hidden) {
|
||||
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(
|
||||
<tr key={feature}>
|
||||
<td style={{ textAlign: 'left' }}>{translate(feature)}</td>
|
||||
<td> </td>
|
||||
<td className={current === 0 ? '' : currentIsBeneficial ? 'secondary' : 'warning'} style={{ textAlign: 'right' }}>{current}{symbol}</td>
|
||||
<td> </td>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We also add in any benefits from specials that aren't covered above
|
||||
if (m.blueprint && m.blueprint.special) {
|
||||
for (const feature in Modifications.modifierActions[m.blueprint.special.edname]) {
|
||||
if (!blueprint.features[feature] && !m.mods.feature) {
|
||||
const featureDef = Modifications.modifications[feature];
|
||||
if (featureDef && !featureDef.hidden) {
|
||||
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(
|
||||
<tr key={feature}>
|
||||
<td style={{ textAlign: 'left' }}>{translate(feature)}</td>
|
||||
<td> </td>
|
||||
<td className={current === 0 ? '' : currentIsBeneficial ? 'secondary' : 'warning'} style={{ textAlign: 'right' }}>{current}{symbol}</td>
|
||||
<td> </td>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
export function blueprintTooltip(language, m, previewBP, previewGrade) {
|
||||
const { translate, formats } = language;
|
||||
const blueprint = previewBP || m.getBlueprint();
|
||||
const grade = previewGrade || m.getBlueprintGrade();
|
||||
if (!blueprint) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let components;
|
||||
if (!m) {
|
||||
components = [];
|
||||
for (const component in blueprint.components) {
|
||||
components.push(
|
||||
<tr key={component}>
|
||||
<td style={{ textAlign: 'left' }}>{translate(component)}</td>
|
||||
<td style={{ textAlign: 'right' }}>{blueprint.components[component]}</td>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let engineersList = [];
|
||||
// TODO:
|
||||
// if (engineers) {
|
||||
// engineersList = [];
|
||||
// for (const engineer of engineers) {
|
||||
// engineersList.push(
|
||||
// <tr key={engineer}>
|
||||
// <td style={{ textAlign: 'left' }}>{engineer}</td>
|
||||
// </tr>
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
const bpFeatures = getBlueprintInfo(blueprint).features[grade];
|
||||
const features = uniq(m.getModifiedProperties().concat(keys(bpFeatures)));
|
||||
|
||||
return (
|
||||
<div>
|
||||
@@ -218,35 +91,37 @@ export function blueprintTooltip(translate, blueprint, m) {
|
||||
<tr>
|
||||
<td>{translate('feature')}</td>
|
||||
<td>{translate('worst')}</td>
|
||||
{m ? <td>{translate('current')}</td> : null }
|
||||
<td>{translate('current')}</td>
|
||||
<td>{translate('best')}</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{effects}
|
||||
{features.map((prop) => {
|
||||
const { value, unit, beneficial } = m.getModifierFormatted(prop);
|
||||
if (!bpFeatures[prop] && !value) {
|
||||
// Can happen for exported synthetics
|
||||
return null;
|
||||
}
|
||||
const { min, max } = bpFeatures[prop] || {};
|
||||
// If the product of value and min/max is positive, both values
|
||||
// point into the same direction, i.e. positive/negative.
|
||||
const minBeneficial = (value * min) > 0 === beneficial;
|
||||
const maxBeneficial = (value * max) > 0 === beneficial;
|
||||
return (<tr key={prop}>
|
||||
<td style={{ textAlign: 'left' }}>{translate(prop)}</td>
|
||||
<td className={!min ? '' : minBeneficial ? 'secondary' : 'warning'} style={{ textAlign: 'right' }}>
|
||||
{!isNaN(min) && formats.round(min * 100)}{!isNaN(min) && unit}
|
||||
</td>
|
||||
<td className={!value ? '' : beneficial ? 'secondary' : 'warning'} style={{ textAlign: 'right' }}>
|
||||
{formats.round(value || 0)}{unit}
|
||||
</td>
|
||||
<td className={!max ? '' : maxBeneficial ? 'secondary' : 'warning'} style={{ textAlign: 'right' }}>
|
||||
{!isNaN(max) && formats.round(max * 100)}{!isNaN(max) && unit}
|
||||
</td>
|
||||
</tr>);
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
{ components ? <table width='100%'>
|
||||
<thead>
|
||||
<tr>
|
||||
<td>{translate('component')}</td>
|
||||
<td>{translate('amount')}</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{components}
|
||||
</tbody>
|
||||
</table> : null }
|
||||
{ engineersList ? <table width='100%'>
|
||||
<thead>
|
||||
<tr>
|
||||
<td>{translate('engineers')}</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{engineersList}
|
||||
</tbody>
|
||||
</table> : null }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user