diff --git a/src/app/components/InternalSlot.jsx b/src/app/components/InternalSlot.jsx index ec3c9aa9..c9b5186b 100644 --- a/src/app/components/InternalSlot.jsx +++ b/src/app/components/InternalSlot.jsx @@ -11,7 +11,6 @@ import { blueprintTooltip } from '../utils/BlueprintFunctions'; * Internal Slot */ export default class InternalSlot extends Slot { - /** * Generate the slot contents * @param {Object} m Mounted Module @@ -25,7 +24,6 @@ export default class InternalSlot extends Slot { let classRating = String(m.getSize()) + m.getRating(); let { drag, drop, ship } = this.props; let { termtip, tooltip } = this.context; - let validMods = m.getApplicableBlueprints(); let showModuleResistances = Persist.showModuleResistances(); // Modifications tooltip shows blueprint and grade, if available @@ -50,13 +48,34 @@ export default class InternalSlot extends Slot { const enabled = m.isEnabled(); const className = cn('details', enabled ? '' : 'disabled'); - return
-
-
{classRating} {translate(m.name || m.grp)}{m.mods && Object.keys(m.mods).length > 0 ? : ''}
-
{formats.round(mass)}{u.T}
-
-
- {/* { m.getOptMass() ?
{translate('optmass', 'sg')}: {formats.int(m.getOptMass())}{u.T}
: null } + return ( +
+
+
+ {classRating} {translate(m.readMeta('type'))} + {m.mods && Object.keys(m.mods).length > 0 ? ( + + + + ) : ( + '' + )} +
+
+ {formats.round(mass)} + {u.T} +
+
+
+ {/* { m.getOptMass() ?
{translate('optmass', 'sg')}: {formats.int(m.getOptMass())}{u.T}
: null } { m.getMaxMass() ?
{translate('maxmass', 'sg')}: {formats.int(m.getMaxMass())}{u.T}
: null } { m.bins ?
{m.bins} {translate('bins')}
: null } { m.bays ?
{translate('bays')}: {m.bays}
: null } @@ -90,10 +109,23 @@ export default class InternalSlot extends Slot { { showModuleResistances && m.getCausticResistance() ?
{translate('causres')}: {formats.pct(m.getCausticResistance())}
: null } { m.getHullReinforcement() ?
{translate('armour')}: {formats.int(m.getHullReinforcement() + ship.baseArmour * m.getModValue('hullboost') / 10000)}
: null } { m.getProtection() ?
{translate('protection')}: {formats.rPct(m.getProtection())}
: null } - { m.getIntegrity() ?
{translate('integrity')}: {formats.int(m.getIntegrity())}
: null } - { m && validMods.length > 0 ?
this.modButton = modButton }>
: null } */} + { m.getIntegrity() ?
{translate('integrity')}: {formats.int(m.getIntegrity())}
: null } */} + {(m.getApplicableBlueprints() || []).length > 0 ? ( +
(this.modButton = modButton)} + > + +
+ ) : null} +
-
; + ); } else { return
{translate('empty')}
; } diff --git a/src/app/components/Modification.jsx b/src/app/components/Modification.jsx index 28421a86..0c48beda 100644 --- a/src/app/components/Modification.jsx +++ b/src/app/components/Modification.jsx @@ -3,22 +3,17 @@ import PropTypes from 'prop-types'; import TranslatedComponent from './TranslatedComponent'; import cn from 'classnames'; import NumberEditor from 'react-number-editor'; -import { isChangeValueBeneficial } from '../utils/BlueprintFunctions'; -import { Modifications } from 'coriolis-data/dist'; +import { Module } from 'ed-forge'; /** * Modification */ export default class Modification extends TranslatedComponent { static propTypes = { - ship: PropTypes.object.isRequired, - m: PropTypes.object.isRequired, - name: PropTypes.string.isRequired, - value: PropTypes.number.isRequired, + m: PropTypes.instanceOf(Module).isRequired, + property: PropTypes.string.isRequired, onChange: PropTypes.func.isRequired, - onKeyDown: PropTypes.func.isRequired, - modItems: PropTypes.array.isRequired, - handleModChange: PropTypes.func.isRequired + highlight: PropTypes.bool, }; /** @@ -28,47 +23,22 @@ export default class Modification extends TranslatedComponent { */ constructor(props, context) { super(props); - this.state = {}; - this.state.value = props.value; + const { m, property } = props; + const originalValue = m.get(property); + this.state = { originalValue, value: String(originalValue) }; } /** - * Update modification given a value. - * @param {Number} value The value to set. This comes in as a string and must be stored in state as a string, - * because it needs to allow illegal 'numbers' ('-', '1.', etc) when the user is typing - * in a value by hand - */ - _updateValue(value) { - this.setState({ value }); - let reCast = String(Number(value)); - if (reCast.endsWith(value) || reCast.startsWith(value)) { - let { m, name, ship } = this.props; - value = Math.max(Math.min(value, 50000), -50000); - ship.setModification(m, name, value, true, true); - } - } - - /** - * Triggered when a key is pressed down with focus on the number editor. - * @param {SyntheticEvent} event Key down event - */ - _keyDown(event) { - if (event.key == 'Enter') { - this._updateFinished(); - } - this.props.onKeyDown(event); - } - - /** - * Triggered when an update to slider value is finished i.e. when losing focus - * - * pnellesen (24/05/2018): added value check below - this should prevent experimental effects from being recalculated - * with each onBlur event, even when no change has actually been made to the field. + * Notify listeners that a new value has been entered and commited. */ _updateFinished() { - if (this.props.value != this.state.value) { - this.props.handleModChange(true); + const { m, property } = this.props; + const { value, originalValue } = this.state; + const numValue = Number(value); + if (!isNaN(numValue) && originalValue !== numValue) { + m.set(property, numValue); this.props.onChange(); + this.setState({ originalValue: numValue }); } } @@ -77,53 +47,59 @@ export default class Modification extends TranslatedComponent { * @return {React.Component} modification */ render() { - let { translate, formats, units } = this.context.language; - let { m, name } = this.props; - let modValue = m.getChange(name); - let isOverwrite = Modifications.modifications[name].method === 'overwrite'; + const { translate, formats } = this.context.language; + const { m, property, highlight } = this.props; + const { originalValue, value } = this.state; - if (name === 'damagedist') { - // We don't show damage distribution + // Some features only apply to specific modules; these features will be + // undefined on items that do not belong to the same class. Filter these + // features here + if (originalValue === undefined) { return null; } - let inputClassNames = { - 'cb': true, - 'greyed-out': !this.props.highlight - }; - return ( -
this.props.modItems[name] = modItem }> - {translate(name, m.grp)} - +
+ {translate(property)} + - - +
+ - {this.props.editable ? - : - - } - - {units[m.getStoredUnitFor(name)]} - + { + if (event.key == 'Enter') { + this._updateFinished(); + event.stopPropagation(); + } + }} + onValueChange={(value) => { + if (value.length <= 15) { + this.setState({ value }); + } + }} /> + {/* TODO: support unit */} + {/* unit */} - {formats.f2(modValue / 100) || 0}{isOverwrite ? '' : '%'} - {formats.pct(m.getModifier(property))}
diff --git a/src/app/components/ModificationsMenu.jsx b/src/app/components/ModificationsMenu.jsx index 76a6c7ce..935b14b5 100644 --- a/src/app/components/ModificationsMenu.jsx +++ b/src/app/components/ModificationsMenu.jsx @@ -4,29 +4,22 @@ import * as _ from 'lodash'; import TranslatedComponent from './TranslatedComponent'; import { stopCtxPropagation } from '../utils/UtilityFunctions'; import cn from 'classnames'; -import { Modifications } from 'coriolis-data/dist'; import Modification from './Modification'; import { - getBlueprint, blueprintTooltip, - setPercent, - getPercent, - setRandom, specialToolTip } from '../utils/BlueprintFunctions'; - -const MODIFICATIONS_COMPARATOR = (mod1, mod2) => { - return mod1.props.name.localeCompare(mod2.props.name); -}; +import { getBlueprintInfo, getExperimentalInfo } from 'ed-forge/lib/data/blueprints'; +import { getModuleInfo } from 'ed-forge/lib/data/items'; /** * Modifications menu */ export default class ModificationsMenu extends TranslatedComponent { static propTypes = { + className: PropTypes.string, ship: PropTypes.object.isRequired, m: PropTypes.object.isRequired, - marker: PropTypes.string.isRequired, onChange: PropTypes.func.isRequired, modButton:PropTypes.object }; @@ -41,24 +34,13 @@ export default class ModificationsMenu extends TranslatedComponent { this._toggleBlueprintsMenu = this._toggleBlueprintsMenu.bind(this); this._toggleSpecialsMenu = this._toggleSpecialsMenu.bind(this); - this._rollFifty = this._rollFifty.bind(this); - this._rollRandom = this._rollRandom.bind(this); - this._rollBest = this._rollBest.bind(this); - this._rollWorst = this._rollWorst.bind(this); - this._reset = this._reset.bind(this); - this._keyDown = this._keyDown.bind(this); - this.modItems = [];// Array to hold various element refs (
  • ,
    ,
      , etc.) - this.firstModId = null; - this.firstBPLabel = null;// First item in mod menu - this.lastModId = null; - this.selectedModId = null; - this.selectedSpecialId = null; - this.lastNeId = null;// Last number editor id. Used to set focus to last number editor when shift-tab pressed on first element in mod menu. - this.modValDidChange = false; // used to determine if component update was caused by change in modification value. - this._handleModChange = this._handleModChange.bind(this); + this.selectedModRef = null; + this.selectedSpecialRef = null; + const { m } = props; this.state = { - blueprintMenuOpened: !(props.m.blueprint && props.m.blueprint.name), + blueprintProgress: m.getBlueprintProgress(), + blueprintMenuOpened: !m.getBlueprint(), specialMenuOpened: false }; } @@ -72,92 +54,48 @@ export default class ModificationsMenu extends TranslatedComponent { _renderBlueprints(props, context) { const { m } = props; const { language, tooltip, termtip } = context; - const translate = language.translate; + const { translate } = language; + const blueprints = []; - for (const blueprintName in Modifications.modules[m.grp].blueprints) { - const blueprint = getBlueprint(blueprintName, m); + for (const blueprint of m.getApplicableBlueprints()) { + const info = getBlueprintInfo(blueprint); let blueprintGrades = []; - for (let grade in Modifications.modules[m.grp].blueprints[blueprintName].grades) { + for (let grade in info.features) { // Grade is a string in the JSON so make it a number grade = Number(grade); - const classes = cn('c', { - active: m.blueprint && blueprint.id === m.blueprint.id && grade === m.blueprint.grade - }); - const close = this._blueprintSelected.bind(this, blueprintName, grade); - const key = blueprintName + ':' + grade; - const tooltipContent = blueprintTooltip(translate, blueprint.grades[grade]); - if (classes.indexOf('active') >= 0) this.selectedModId = key; - blueprintGrades.unshift(
    • this.modItems[key] = modItem}>{grade}
    • ); - } - if (blueprintGrades) { - const thisLen = blueprintGrades.length; - if (this.firstModId == null) this.firstModId = blueprintGrades[0].key; - this.lastModId = blueprintGrades[thisLen - 1].key; - blueprints.push(
      {translate(blueprint.name)}
      ); - blueprints.push(
        {blueprintGrades}
      ); + const active = m.getBlueprint() === blueprint && m.getBlueprintGrade() === grade; + const key = blueprint + ':' + grade; + // const tooltipContent = blueprintTooltip(translate, info.features[grade]); + blueprintGrades.unshift( +
    • { + m.setBlueprint(blueprint, grade); + this.setState({ + blueprintMenuOpened: false, + specialMenuOpened: true, + }); + })} + ref={active ? (ref) => { this.selectedModRef = ref; } : undefined} + >{grade}
    • + ); } + + blueprints.push( + [ +
      + {translate(blueprint)} +
      , +
        {blueprintGrades}
      + ], + ); } - return blueprints; + + return [].concat(...blueprints); } - /** - * Key down - select module on Enter key, move to next/previous module on Tab/Shift-Tab, close on Esc - * @param {SyntheticEvent} event Event - * - */ - _keyDown(event) { - let className = null; - let elemId = null; - if (event.currentTarget.attributes['class']) className = event.currentTarget.attributes['class'].value; - if (event.currentTarget.attributes['data-id']) elemId = event.currentTarget.attributes['data-id'].value; - - if (event.key == 'Enter' && className.indexOf('disabled') < 0 && className.indexOf('active') < 0) { - event.stopPropagation(); - if (elemId != null) { - this.modItems[elemId].click(); - } else { - event.currentTarget.click(); - } - return; - } - if (event.key == 'Tab') { - // Shift-Tab - if(event.shiftKey) { - if (elemId == this.firstModId && elemId != null) { - // Initial modification menu - event.preventDefault(); - this.modItems[this.lastModId].focus(); - return; - } else if (event.currentTarget.className.indexOf('button-inline-menu') >= 0 && event.currentTarget.previousElementSibling == null && this.lastNeId != null && this.modItems[this.lastNeId] != null) { - // shift-tab on first element in modifications menu. set focus to last number editor field if open - event.preventDefault(); - this.modItems[this.lastNeId].lastChild.focus(); - return; - } else if (event.currentTarget.className.indexOf('button-inline-menu') >= 0 && event.currentTarget.previousElementSibling == null) { - // shift-tab on button-inline-menu with no number editor - event.preventDefault(); - event.currentTarget.parentElement.lastElementChild.focus(); - } - } else { - if (elemId == this.lastModId && elemId != null) { - // Initial modification menu - event.preventDefault(); - this.modItems[this.firstModId].focus(); - return; - } else if (event.currentTarget.className.indexOf('button-inline-menu') >= 0 && event.currentTarget.nextSibling == null && event.currentTarget.nodeName != 'TD') { - // Experimental menu - event.preventDefault(); - event.currentTarget.parentElement.firstElementChild.focus(); - return; - } else if (event.currentTarget.className == 'cb' && event.currentTarget.parentElement.nextSibling == null) { - event.preventDefault(); - this.modItems[this.firstBPLabel].focus(); - } - } - } - } - - /** * Render the specials * @param {Object} props React component properties @@ -168,200 +106,116 @@ export default class ModificationsMenu extends TranslatedComponent { const { m } = props; const { language, tooltip, termtip } = context; const translate = language.translate; - const specials = []; - const specialsId = m.missile && Modifications.modules[m.grp]['specials_' + m.missile] ? 'specials_' + m.missile : 'specials'; - if (Modifications.modules[m.grp][specialsId] && Modifications.modules[m.grp][specialsId].length > 0) { - const close = this._specialSelected.bind(this, null); - specials.push(
      this.modItems['none'] = modItem}>{translate('PHRASE_NO_SPECIAL')}
      ); - for (const specialName of Modifications.modules[m.grp][specialsId]) { - if (Modifications.specials[specialName].name.search('Legacy') >= 0) { - continue; - } - const classes = cn('button-inline-menu', { - active: m.blueprint && m.blueprint.special && m.blueprint.special.edname == specialName - }); - if (classes.indexOf('active') >= 0) this.selectedSpecialId = specialName; - const close = this._specialSelected.bind(this, specialName); - if (m.blueprint && m.blueprint.name) { - let tmp = {}; - if (m.blueprint.special) { - tmp = m.blueprint.special; - } else { - tmp = undefined; - } - m.blueprint.special = Modifications.specials[specialName]; - let specialTt = specialToolTip(translate, m.blueprint.grades[m.blueprint.grade], m.grp, m, specialName); - m.blueprint.special = tmp; - specials.push(
      this.modItems[specialName] = modItem}>{translate(Modifications.specials[specialName].name)}
      ); - } else { - specials.push(
      this.modItems[specialName] = modItem}>{translate(Modifications.specials[specialName].name)}
      ); - } - } + + const applied = m.getExperimental(); + const experimentals = []; + for (const experimental of m.getApplicableExperimentals()) { + const active = experimental === applied; + // TODO: + // let specialTt = specialToolTip( + // translate, + // m.blueprint.grades[m.blueprint.grade], + // m.grp, m, + // experimental, + // ); + experimentals.push( +
      { this.selectedSpecialRef = ref; } : undefined} + // onMouseOver={termtip.bind(null, specialTt)} + // onMouseOut={tooltip.bind(null, null)} + >{translate(experimental)}
      + ); } - return specials; + + if (experimentals.length) { + experimentals.unshift( +
      { this.selectedSpecialRef = ref; } : undefined} + >{translate('PHRASE_NO_SPECIAL')}
      + ); + } + + return experimentals; + } + + /** + * Create a modification component + */ + _mkModification(property, highlight) { + const { m } = this.props; + return ; } /** * Render the modifications * @param {Object} props React Component properties - * @return {Object} list: Array of React Components + * @return {Array} Array of React Components */ _renderModifications(props) { - const { m, onChange, ship } = props; - const modifiableModifications = []; - const modifications = []; - for (const modName of Modifications.modules[m.grp].modifications) { - if (!Modifications.modifications[modName].hidden) { - const key = modName + (m.getModValue(modName) / 100 || 0); - const editable = modName !== 'fallofffromrange'; - const highlight = m.blueprint.grades[m.blueprint.grade].features[modName]; - this.lastNeId = modName; - (editable && highlight ? modifiableModifications : modifications).push( - - ); - } - } + const { m } = props; - modifiableModifications.sort(MODIFICATIONS_COMPARATOR); - modifications.sort(MODIFICATIONS_COMPARATOR); - return modifiableModifications.concat(modifications); + const blueprintFeatures = getBlueprintInfo(m.getBlueprint()).features[ + m.getBlueprintGrade() + ]; + const blueprintModifications = Object.keys(blueprintFeatures) + .map((feature) => this._mkModification(feature, true)) + .filter(Boolean); + const moduleModifications = Object.keys(getModuleInfo(m.getItem()).props) + .filter((prop) => !blueprintFeatures[prop]) + .map((prop) => this._mkModification(prop, false)); + + return blueprintModifications.concat(moduleModifications); } /** * Toggle the blueprints menu */ _toggleBlueprintsMenu() { - const blueprintMenuOpened = !this.state.blueprintMenuOpened; - this.setState({ blueprintMenuOpened }); + this.setState({ blueprintMenuOpened: !this.state.blueprintMenuOpened }); } /** - * Activated when a blueprint is selected - * @param {int} fdname The Frontier name of the blueprint - * @param {int} grade The grade of the selected blueprint + * Returns a callback that performs an action in form of a callback given as + * arguments and notifiers listeners. + * @param {function} cb Action to perform + * @returns {function} Change callback */ - _blueprintSelected(fdname, grade) { - this.context.tooltip(null); - const { m, ship } = this.props; - const blueprint = getBlueprint(fdname, m); - blueprint.grade = grade; - ship.setModuleBlueprint(m, blueprint); - setPercent(ship, m, 100); - - this.setState({ blueprintMenuOpened: false, specialMenuOpened: true }); - this.props.onChange(); + _change(cb) { + return (...args) => { + this.context.tooltip(null); + if (cb) { + cb(...args); + } + this.props.onChange(); + }; } /** * Toggle the specials menu */ _toggleSpecialsMenu() { - const specialMenuOpened = !this.state.specialMenuOpened; - this.setState({ specialMenuOpened }); + this.setState({ specialMenuOpened: !this.state.specialMenuOpened }); } /** - * Activated when a special is selected - * @param {int} special The name of the selected special + * Creates a callback for when a special effect is being selected + * @param {string} special The name of the selected special + * @returns {function} Callback */ _specialSelected(special) { - this.context.tooltip(null); - const { m, ship } = this.props; - - if (special === null) { - ship.clearModuleSpecial(m); - } else { - ship.setModuleSpecial(m, Modifications.specials[special]); - } - - this.setState({ specialMenuOpened: false }); - this.props.onChange(); - } - - /** - * Provide a '50%' roll within the information we have - */ - _rollFifty() { - const { m, ship } = this.props; - setPercent(ship, m, 50); - - // this will change the values in the modifications. Set modDidChange to true to prevent focus change when component updates - this._handleModChange(true); - - this.props.onChange(); - } - - /** - * Provide a random roll within the information we have - */ - _rollRandom() { - const { m, ship } = this.props; - setRandom(ship, m); - - // this will change the values in the modifications. Set modDidChange to true to prevent focus change when component updates - this._handleModChange(true); - - this.props.onChange(); - } - - /** - * Provide a 'best' roll within the information we have - */ - _rollBest() { - const { m, ship } = this.props; - setPercent(ship, m, 100); - - // this will change the values in the modifications. Set modDidChange to true to prevent focus change when component updates - this._handleModChange(true); - - this.props.onChange(); - } - - /** - * Provide a 'worst' roll within the information we have - */ - _rollWorst() { - const { m, ship } = this.props; - setPercent(ship, m, 0); - // this will change the values in the modifications. Set modDidChange to true to prevent focus change when component updates - this._handleModChange(true); - this.props.onChange(); - } - - /** - * Reset modification information - */ - _reset() { - const { m, ship } = this.props; - ship.clearModifications(m); - ship.clearModuleBlueprint(m); - this.selectedModId = null; - this.selectedSpecialId = null; - this.props.onChange(); - } - - /** - * set mod did change boolean - * @param {boolean} b Boolean to determine if a change has been made to a module - */ - _handleModChange(b) { - this.modValDidChange = b; - } - - /** - * Set focus on first element in modifications menu - * after it first mounts - */ - componentDidMount() { - let firstEleCn = this.modItems['modMainDiv'].children.length > 0 ? this.modItems['modMainDiv'].children[0].className : null; - if (firstEleCn.indexOf('select-group cap') >= 0) { - this.modItems['modMainDiv'].children[1].firstElementChild.focus(); - } else { - this.modItems['modMainDiv'].firstElementChild.focus(); - } + return this._change(() => { + const { m } = this.props; + m.setExperimental(special); + this.setState({ specialMenuOpened: false }); + }); } /** @@ -370,24 +224,12 @@ export default class ModificationsMenu extends TranslatedComponent { * in a modification */ componentDidUpdate() { - if (!this.modValDidChange) { - if (this.modItems['modMainDiv'].children.length > 0) { - if (this.modItems[this.selectedModId]) { - this.modItems[this.selectedModId].focus(); - return; - } else if (this.modItems[this.selectedSpecialId]) { - this.modItems[this.selectedSpecialId].focus(); - return; - } - let firstEleCn = this.modItems['modMainDiv'].children[0].className; - if (firstEleCn.indexOf('button-inline-menu') >= 0) { - this.modItems['modMainDiv'].firstElementChild.focus(); - } else if (firstEleCn.indexOf('select-group cap') >= 0) { - this.modItems['modMainDiv'].children[1].firstElementChild.focus(); - } - } - } else { - this._handleModChange(false);// Need to reset if component update due to value change + if (this.selectedModRef) { + this.selectedModRef.focus(); + return; + } else if (this.selectedSpecialRef) { + this.selectedSpecialRef.focus(); + return; } } /** @@ -407,90 +249,143 @@ export default class ModificationsMenu extends TranslatedComponent { const { language, tooltip, termtip } = this.context; const translate = language.translate; const { m } = this.props; - const { blueprintMenuOpened, specialMenuOpened } = this.state; + const { + blueprintProgress, blueprintMenuOpened, specialMenuOpened, + } = this.state; - const _toggleBlueprintsMenu = this._toggleBlueprintsMenu; - const _toggleSpecialsMenu = this._toggleSpecialsMenu; - const _rollFull = this._rollBest; - const _rollWorst = this._rollWorst; - const _rollFifty = this._rollFifty; - const _rollRandom = this._rollRandom; - const _reset = this._reset; + const appliedBlueprint = m.getBlueprint(); + const appliedExperimental = m.getExperimental(); - let blueprintLabel; - let haveBlueprint = false; - let blueprintTt; - let blueprintCv; - // TODO: Fix this to actually find the correct blueprint. - if (!m.blueprint || !m.blueprint.name || !m.blueprint.fdname || !Modifications.modules[m.grp].blueprints || !Modifications.modules[m.grp].blueprints[m.blueprint.fdname]) { - this.props.ship.clearModuleBlueprint(m); - this.props.ship.clearModuleSpecial(m); - } - if (m.blueprint && m.blueprint.name && Modifications.modules[m.grp].blueprints[m.blueprint.fdname].grades[m.blueprint.grade]) { - blueprintLabel = translate(m.blueprint.name) + ' ' + translate('grade') + ' ' + m.blueprint.grade; - haveBlueprint = true; - blueprintTt = blueprintTooltip(translate, m.blueprint.grades[m.blueprint.grade]); - blueprintCv = getPercent(m); - } + let renderComponents = []; + switch (true) { + case !appliedBlueprint || blueprintMenuOpened: + renderComponents = this._renderBlueprints(this.props, this.context); + break; + case specialMenuOpened: + renderComponents = this._renderSpecials(this.props, this.context); + break; + default: + // Since the first case didn't apply, there is a blueprint applied so + // we render the modifications + // let blueprintTt = blueprintTooltip(translate, m.blueprint.grades[m.blueprint.grade]); - let specialLabel; - let specialTt; - if (m.blueprint && m.blueprint.special) { - specialLabel = m.blueprint.special.name; - specialTt = specialToolTip(translate, m.blueprint.grades[m.blueprint.grade], m.grp, m, m.blueprint.special.edname); - } else { - specialLabel = translate('PHRASE_SELECT_SPECIAL'); - } + renderComponents.push( +
      + {translate(appliedBlueprint)} {translate('grade')} {m.getBlueprintGrade()} +
      + ); - const specials = this._renderSpecials(this.props, this.context); - /** - * pnellesen - 05/28/2018 - added additional checks for specials.length below to ensure menus - * display correctly in cases where there are no specials (ex: AFMUs.) - */ - const showBlueprintsMenu = blueprintMenuOpened; - const showSpecial = haveBlueprint && specials.length && !blueprintMenuOpened; - const showSpecialsMenu = specialMenuOpened && specials.length; - const showRolls = haveBlueprint && !blueprintMenuOpened && (!specialMenuOpened || !specials.length); - const showReset = !blueprintMenuOpened && (!specialMenuOpened || !specials.length) && haveBlueprint; - const showMods = !blueprintMenuOpened && (!specialMenuOpened || !specials.length) && haveBlueprint; - if (haveBlueprint) { - this.firstBPLabel = blueprintLabel; - } else { - this.firstBPLabel = 'selectBP'; - } - return ( -
      e.stopPropagation() } - onContextMenu={stopCtxPropagation} - ref={modItem => this.modItems['modMainDiv'] = modItem} - > - { showBlueprintsMenu | showSpecialsMenu ? '' : haveBlueprint ? -
      this.modItems[this.firstBPLabel] = modItems}>{blueprintLabel}
      : -
      this.modItems[this.firstBPLabel] = modItems}>{translate('PHRASE_SELECT_BLUEPRINT')}
      } - { showBlueprintsMenu ? this._renderBlueprints(this.props, this.context) : null } - { showSpecial & !showSpecialsMenu ?
      {specialLabel}
      : null } - { showSpecialsMenu ? specials : null } - { showReset ?
      { translate('reset') }
      : null } - { showRolls ? + if (m.getApplicableExperimentals().length) { + let specialLabel = translate('PHRASE_SELECT_SPECIAL'); + let specialTt; + if (appliedExperimental) { + specialLabel = appliedExperimental; + // specialTt = specialToolTip(translate, m.blueprint.grades[m.blueprint.grade], m.grp, m, m.blueprint.special.edname); + } + renderComponents.push( +
      {specialLabel}
      + ); + } + renderComponents.push( +
      { + m.resetEngineering(); + this.selectedModRef = null; + this.selectedSpecialRef = null; + })} + onMouseOver={termtip.bind(null, 'PHRASE_BLUEPRINT_RESET')} + onMouseOut={tooltip.bind(null, null)} + >{translate('reset')}
      , - { showRolls ? - - - - - - - : null } + + + + + + + -
      { translate('mroll') }: { translate('0%') } { translate('50%') } { translate('100%') } { translate('random') }
      {translate('mroll')}: { + m.setBlueprintProgress(0); + this.setState({ blueprintProgress: 0 }); + })} + onMouseOver={termtip.bind(null, 'PHRASE_BLUEPRINT_WORST')} + onMouseOut={tooltip.bind(null, null)} + >{translate('0%')} { + m.setBlueprintProgress(0.5); + this.setState({ blueprintProgress: 0.5 }); + })} + onMouseOver={termtip.bind(null, 'PHRASE_BLUEPRINT_FIFTY')} + onMouseOut={tooltip.bind(null, null)} + >{translate('50%')} { + m.setBlueprintProgress(1); + this.setState({ blueprintProgress: 1 }); + })} + onMouseOver={termtip.bind(null, 'PHRASE_BLUEPRINT_BEST')} + onMouseOut={tooltip.bind(null, null)} + >{translate('100%')} { + const blueprintProgress = Math.random(); + m.setBlueprintProgress(blueprintProgress); + this.setState({ blueprintProgress }); + }} + onMouseOver={termtip.bind(null, 'PHRASE_BLUEPRINT_RANDOM')} + onMouseOut={tooltip.bind(null, null)} + >{translate('random')}
      : null } - { showMods ?
      : null } - { showMods ? - - { this._renderModifications(this.props) } - : null } + , +
      , + {this._renderModifications(this.props)} + ); + } + + return ( +
      e.stopPropagation()} + onContextMenu={stopCtxPropagation} + > + {renderComponents}
      ); } diff --git a/src/app/components/Slot.jsx b/src/app/components/Slot.jsx index a7acf9ce..62be06c9 100644 --- a/src/app/components/Slot.jsx +++ b/src/app/components/Slot.jsx @@ -113,32 +113,34 @@ export default class Slot extends TranslatedComponent { } if (selected) { - // if (this._modificationsSelected) { - // menu = ; - // } else { - menu = ; - // } + if (this._modificationsSelected) { + menu = ; + } else { + menu = ; + } } // TODO: implement touch dragging return ( -
      this.slotDiv = slotDiv}> +
      this.slotDiv = slotDiv}>
      {this._getMaxClassLabel(translate)}
      {slotDetails} diff --git a/src/app/components/StandardSlot.jsx b/src/app/components/StandardSlot.jsx index 9120316b..7053d327 100644 --- a/src/app/components/StandardSlot.jsx +++ b/src/app/components/StandardSlot.jsx @@ -89,11 +89,11 @@ export default class StandardSlot extends TranslatedComponent { if (selected) { if (this._modificationsSelected) { menu = ; } else { menu =