Change module modding to have absolute values entered

This commit is contained in:
Felix Linker
2018-09-15 00:40:19 +02:00
parent f86ce62c27
commit 2456ce330b
5 changed files with 125 additions and 60 deletions

View File

@@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
import TranslatedComponent from './TranslatedComponent';
import cn from 'classnames';
import NumberEditor from 'react-number-editor';
import { isValueBeneficial } from '../utils/BlueprintFunctions';
/**
* Modification
@@ -38,22 +39,8 @@ export default class Modification extends TranslatedComponent {
* in a value by hand
*/
_updateValue(value) {
const name = this.props.name;
let scaledValue = Math.round(Number(value) * 100);
// Limit to +1000% / -99.99%
if (scaledValue > 100000) {
scaledValue = 100000;
value = 1000;
}
if (scaledValue < -9999) {
scaledValue = -9999;
value = -99.99;
}
let m = this.props.m;
let ship = this.props.ship;
ship.setModification(m, name, scaledValue, true);
let { m, name, ship } = this.props;
ship.setModification(m, name, value, true, true);
this.setState({ value });
}
@@ -75,52 +62,43 @@ export default class Modification extends TranslatedComponent {
* @return {React.Component} modification
*/
render() {
let translate = this.context.language.translate;
let formats = this.context.language.formats;
let { translate, formats, units } = this.context.language;
let { m, name } = this.props;
let modValue = m.getChange(name);
if (name === 'damagedist') {
// We don't show damage distribution
return null;
}
let symbol;
if (name === 'jitter') {
symbol = '°';
} else if (name !== 'burst' && name != 'burstrof') {
symbol = '%';
}
if (symbol) {
symbol = ' (' + symbol + ')';
}
return (
<div onBlur={this._updateFinished.bind(this)} className={'cb'} key={name} ref={ modItem => this.props.modItems[name] = modItem }>
<div className={'cb'}>{translate(name, m.grp)}{symbol}</div>
<div className={'cb'}>{translate(name, m.grp)}</div>
<table style={{ width: '100%' }}>
<tbody>
<tr>
<td style={{ width: '50%' }}>
{/* thermload doesn't have any values set therefore we ignore it */}
<div>{this.props.name !== 'thermload' &&
this.props.m.formatModifiedValue(
this.props.name,
this.context.language
)
}</div>
</td>
<td style={{ width: '50%' }}>
{this.props.editable ?
<NumberEditor className={'cb'} value={this.state.value}
style={{ textAlign: 'center' }}
step={0.01} stepModifier={1} decimals={2}
onValueChange={this._updateValue.bind(this)}
onKeyDown={ this.props.onKeyDown } /> :
<div>
<tr className={'modification-container'}>
<td className={'input-container'}>
<span>
{this.props.editable ?
<NumberEditor className={'cb'} value={this.state.value}
decimals={2} style={{ textAlign: 'right' }} step={0.01}
stepModifier={1} onKeyDown={ this.props.onKeyDown }
onValueChange={this._updateValue.bind(this)} /> :
<input type="text" value={formats.f2(this.state.value)}
disabled style={{ textAlign: 'center', cursor: 'inherit' }}/>
</div>
}
disabled className={'number-editor'}
style={{ textAlign: 'right', cursor: 'inherit' }}/>
}
<span className={'unit-container'}>
{units[m.getStoredUnitFor(name)]}
</span>
</span>
</td>
<td style={{ textAlign: 'center' }} className={
modValue ?
isValueBeneficial(name, modValue) ? 'secondary': 'warning':
''
}>
{formats.f2(modValue / 100) || 0}%
</td>
</tr>
</tbody>

View File

@@ -219,7 +219,7 @@ export default class ModificationsMenu extends TranslatedComponent {
this.lastNeId = modName;
(editable ? modifiableModifications : modifications).push(
<Modification key={ key } ship={ ship } m={ m }
value={m.getModValue(modName) / 100 || 0} modItems={this.modItems}
value={m.getPretty(modName) || 0} modItems={this.modItems}
onChange={onChange} onKeyDown={this._keyDown} name={modName}
editable={editable} handleModChange = {this._handleModChange} />
);

View File

@@ -44,13 +44,7 @@ export default class Module {
getModValue(name, raw) {
let result = this.mods && this.mods[name] ? this.mods[name] : null;
// Calculate the percentage change for a synthetic value
if (STATS_FORMATING[name] && STATS_FORMATING[name].synthetic) {
const statGetter = this[STATS_FORMATING[name].synthetic];
let unmodifiedStat = statGetter.call(this, false);
let modifiedStat = statGetter.call(this, true);
result = (modifiedStat / unmodifiedStat - 1) * 10000;
} else if ((!raw) && this.blueprint && this.blueprint.special) {
if ((!raw) && this.blueprint && this.blueprint.special) {
// This module has a special effect, see if we need to alter our returned value
const modifierActions = Modifications.modifierActions[this.blueprint.special.edname];
if (modifierActions && modifierActions[name]) {
@@ -339,6 +333,76 @@ export default class Module {
);
}
/**
* Returns the change rate in percentage of a given stat. Change rate can
* differ from return value of {@see Module#getModValue} when formatting
* options are given.
* @param {String} name Name of the value to get the change for
* @param {Number} [val] If given not the modules value but this one will be
* taken as new value
* @return {Number} Change rate of the stat according to formatting options
*/
getChange(name, val) {
const formatingOptions = STATS_FORMATING[name];
if (isNaN(val)) {
// Calculate the percentage change for an abstract value
if (formatingOptions && formatingOptions.synthetic) {
const statGetter = this[formatingOptions.synthetic];
let unmodifiedStat = statGetter.call(this, false);
let modifiedStat = statGetter.call(this, true);
result = (modifiedStat / unmodifiedStat - 1) * 10000;
} else {
val = this.getModValue(name);
}
}
if (formatingOptions && formatingOptions.change) {
let changeFormating = formatingOptions.change;
let baseVal = this[name];
let absVal = this._getModifiedValue(name);
if (changeFormating === 'additive') {
val = absVal - baseVal;
} else if (changeFormating === 'multiplicative') {
val = absVal / baseVal - 1;
}
val *= 10000;
}
return val;
}
/**
* Returns the the unit key for a given stat. For example '%' for 'kinres'.
* @param {String} name Name of the stat
* @return {String} Unit key
*/
getUnitFor(name) {
const formatingOptions = STATS_FORMATING[name];
if (!formatingOptions || !formatingOptions.unit) {
if (formatingOptions.format && formatingOptions.format.startsWith('pct')) {
return 'pct';
}
return '';
}
return formatingOptions.unit;
}
/**
* Same as {@see Module#getUnitFor} but returns the unit in which the stat is
* stored. For example 'm' for 'range' as opposed to 'km' which is the unit
* 'range' is usually displayed.
* @param {String} name Name of the stat
* @return {String} Unit key
*/
getStoredUnitFor(name) {
const formatingOptions = STATS_FORMATING[name];
if (!formatingOptions || !formatingOptions.storedUnit) {
return this.getUnitFor(name);
}
return formatingOptions.storedUnit;
}
/**
* Get the power generation of this module
* @param {Boolean} [modified=true] Whether to take modifications into account

View File

@@ -44,7 +44,7 @@ export const STATS_FORMATING = {
'falloff': { 'format': 'round', 'unit': 'km', 'storedUnit': 'm' },
'fallofffromrange': { 'format': 'round', 'unit': 'km', 'storedUnit': 'm', 'synthetic': 'getFalloff' },
'hps': { 'format': 'round', 'units': 'ps', 'synthetic': 'getHps' },
'hullboost': { 'format': 'pct1' },
'hullboost': { 'format': 'pct1', 'change': 'additive' },
'hullreinforcement': { 'format': 'int' },
'integrity': { 'format': 'round1' },
'jitter': { 'format': 'round', 'unit': 'ang' },
@@ -68,7 +68,7 @@ export const STATS_FORMATING = {
'sdps': { 'format': 'round1', 'units': 'ps', 'synthetic': 'getSDps' },
'shield': { 'format': 'int', 'unit': 'MJ' },
'shieldaddition': { 'format': 'round1', 'unit': 'MJ' },
'shieldboost': { 'format': 'pct1' },
'shieldboost': { 'format': 'pct1', 'change': 'additive' },
'shieldreinforcement': { 'format': 'round1', 'unit': 'MJ' },
'shotspeed': { 'format': 'int', 'unit': 'm/s' },
'spinup': { 'format': 'round1', 'unit': 's' },

View File

@@ -37,6 +37,29 @@
text-overflow: ellipsis;
}
.modification-container {
td {
width: 35%;
text-align: center;
}
.input-container {
width: 65%;
text-align: right;
}
input {
width: 70%;
}
.unit-container {
width: 30px;
padding: 3px;
text-align: left;
display: inline-block;
}
}
.cb {
overflow: hidden;
}