Merge pull request #386 from EDCD/feature/absolute-mods

Absolute modding
This commit is contained in:
William
2018-09-17 07:30:44 +10:00
committed by GitHub
7 changed files with 347 additions and 198 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,9 @@ 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;
value = Math.max(Math.min(value, 50000), -50000);
ship.setModification(m, name, value, true, true);
this.setState({ value });
}
@@ -75,52 +63,46 @@ 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 onBlur={this._updateFinished.bind(this)} key={name}
className={cn('cb', 'modification-container')}
ref={ modItem => this.props.modItems[name] = modItem }>
<span className={'cb'}>{translate(name, m.grp)}</span>
<span className={'header-adjuster'}></span>
<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>
<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

@@ -73,6 +73,7 @@ export function getLanguage(langCode) {
'°/s': <u>{translate('°/s')}</u>, // Degrees per second
MW: <u>{translate('MW')}</u>, // Mega Watts (same as Mega Joules per second)
mps: <u>{translate('m/s')}</u>, // Metres per second
pct: '%', // Percent
ps: <u>{translate('/s')}</u>, // per second
pm: <u>{translate('/min')}</u>, // per minute
s: <u>{translate('secs')}</u>, // Seconds

View File

@@ -1,7 +1,7 @@
import * as ModuleUtils from './ModuleUtils';
import { Modifications } from 'coriolis-data/dist';
import React from 'react';
import { STATS_FORMATING, SI_PREFIXES } from './StatsFormating';
import { STATS_FORMATTING, SI_PREFIXES } from './StatsFormatting';
/**
* Module - active module in a ship's buildout
@@ -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]) {
@@ -82,6 +76,15 @@ export default class Module {
}
}
// Resistance modding for hull reinforcement packages has additional
// diminishing returns implemented. The mod value gets lowered by
// the amount of base resistance the hrp has.
if (!isNaN(result) && this.grp === 'hr' &&
(name === 'kinres' || name === 'thermres' || name === 'explres')) {
let baseRes = this[name];
result = result * (1 - baseRes);
}
// Sanitise the resultant value to 4dp equivalent
return isNaN(result) ? result : Math.round(result);
}
@@ -141,7 +144,7 @@ export default class Module {
* @param {Number} modified Whether to return the raw or modified value
* @return {Number} The value queried
*/
_getValue(name, modified) {
get(name, modified = true) {
let val;
if (modified) {
val = this._getModifiedValue(name);
@@ -151,6 +154,85 @@ export default class Module {
return isNaN(val) ? null : val;
}
/**
* Sets mod values such that the overall result for the given stat equals value
* @param {String} name The name of the modification
* @param {Number} value The value to effectively set
* @param {Boolean} valueIsWithSpecial True when value includes an special
* effects
*/
set(name, value, valueIsWithSpecial) {
const modification = Modifications.modifications[name];
if (!modification || isNaN(value)) {
// TODO: throw?
return;
}
let baseValue = this[name];
let modValue = 0;
if (modification.method === 'overwrite') {
modValue = value;
} else if (modification.method === 'additive') {
// additive modifications can be given without a base value
if (!baseValue) {
baseValue = 0;
}
modValue = value - baseValue;
if (this.grp === 'hr' &&
(name === 'kinres' || name === 'thermres' || name === 'explres')) {
modValue = modValue / (1 - baseValue);
}
} else if (name === 'shieldboost' || name === 'hullboost') {
modValue = (1 + value) / (1 + baseValue) - 1;
} else { // multiplicative
modValue = value / baseValue - 1;
}
if (modification.type === 'percentage') {
modValue = modValue * 10000;
} else if (modification.type === 'numeric' && name !== 'burst' &&
name !== 'burstrof') {
modValue = modValue * 100;
}
this.setModValue(name, modValue, valueIsWithSpecial);
}
/**
* Returns a value for a given modification in pretty format, i.e. percentages
* are returned as 90 not as 0.9.
* @param {String} name Name of the modification to get the value for
* @param {Boolean} [modified = true] If set to false, the raw value of the
* raw value of the stat is returned
* @param {Number} [places = 2] Number of decimal places to round
* @return {Number} Value for given stat
*/
getPretty(name, modified = true, places = 2) {
const formattingOptions = STATS_FORMATTING[name];
let val = this.get(name, modified) || 0;
if (formattingOptions && formattingOptions.format.startsWith('pct')) {
return 100 * val;
}
// Round to two decimal places
let precisionMult = 10 ** places;
return Math.round(val * precisionMult) / precisionMult;
}
/**
* Same as {@see Module#set} but values expects value that are percentages to
* come in format 90 as opposed to 0.9.
* @param {String} name The name of the modification
* @param {Number} value The value to effectively set
* @param {Boolean} valueIsWithSpecial True when value includes an special
*/
setPretty(name, value, valueIsWithSpecial) {
const formattingOptions = STATS_FORMATTING[name];
if (formattingOptions && formattingOptions.format.startsWith('pct')) {
value = value / 100;
}
this.set(name, value, valueIsWithSpecial);
}
/**
* Helper to obtain a modified value using standard multipliers
* @param {String} name the name of the modifier to obtain
@@ -172,34 +254,27 @@ export default class Module {
modValue = this.getModValue(name);
}
if (modValue) {
if (!result && modification.method === 'additive') {
// If the modification is additive and no value is given by default we
// start at zero
result = 0;
}
if (result !== undefined) {
if (modification.method === 'additive') {
// Resistance modding for hull reinforcement packages has additional
// diminishing returns implemented. The mod value gets lowered by
// the amount of base resistance the hrp has.
if (this.grp === 'hr' &&
(name === 'kinres' || name === 'thermres' || name === 'explres')) {
modValue = modValue * (1 - result);
}
result = result + modValue;
} else if (modification.method === 'overwrite') {
result = modValue;
} else if (name === 'shieldboost' || name === 'hullboost') {
result = (1 + result) * (1 + modValue) - 1;
} else {
result = result * (1 + modValue);
if (!result && modification.method === 'additive') {
// If the modification is additive and no value is given by default we
// start at zero
result = 0;
}
} else if (name === 'burst' || name === 'burstrof') {
// Burst and burst rate of fire are special, as it can not exist but
// have a modification
result = modValue / 100;
}
if (result !== undefined) {
if (modification.method === 'additive') {
result = result + modValue;
} else if (modification.method === 'overwrite') {
result = modValue;
} else if (name === 'shieldboost' || name === 'hullboost') {
result = (1 + result) * (1 + modValue) - 1;
} else {
result = result * (1 + modValue);
}
} else if (name === 'burst' || name === 'burstrof') {
// Burst and burst rate of fire are special, as it can not exist but
// have a modification
result = modValue / 100;
}
}
}
@@ -210,7 +285,7 @@ export default class Module {
* Creates a react element that pretty-prints the queried module value
* @param {String} name The name of the value
* @param {object} language Language object holding formats and util functions
* @param {String} [unit] If unit is given not the stat's default formating
* @param {String} [unit] If unit is given not the stat's default formatting
* unit will be applied but the given one taking into
* account SI-prefixes such as kilo, milli, etc.
* @param {Number} [val] If val is given, not the modules value but given
@@ -218,10 +293,10 @@ export default class Module {
* @returns {React.Component} The formated value as component
*/
formatModifiedValue(name, language, unit, val) {
const formatingOptions = STATS_FORMATING[name];
const formattingOptions = STATS_FORMATTING[name];
if (val === undefined) {
if (formatingOptions && formatingOptions.synthetic) {
val = (this[formatingOptions.synthetic]).call(this, true);
if (formattingOptions && formattingOptions.synthetic) {
val = (this[formattingOptions.synthetic]).call(this, true);
} else {
val = this._getModifiedValue(name);
}
@@ -229,7 +304,7 @@ export default class Module {
val = val || 0;
if (!formatingOptions) {
if (!formattingOptions) {
return (
<span>
{val}
@@ -237,9 +312,9 @@ export default class Module {
);
}
let { format } = formatingOptions;
unit = unit || formatingOptions.unit;
let storedUnit = formatingOptions.storedUnit || formatingOptions.unit;
let { format } = formattingOptions;
unit = unit || formattingOptions.unit;
let storedUnit = formattingOptions.storedUnit || formattingOptions.unit;
let factor = 1;
if (storedUnit && storedUnit !== unit) {
// Find out si prefix of storedUnit and unit as si prefixes can only take
@@ -263,18 +338,88 @@ export default class Module {
return (
<span>
{val}
{formatingOptions.unit && language.units[formatingOptions.unit]}
{formattingOptions.unit && language.units[formattingOptions.unit]}
</span>
);
}
/**
* 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 formattingOptions = STATS_FORMATTING[name];
if (isNaN(val)) {
// Calculate the percentage change for an abstract value
if (formattingOptions && formattingOptions.synthetic) {
const statGetter = this[formattingOptions.synthetic];
let unmodifiedStat = statGetter.call(this, false);
let modifiedStat = statGetter.call(this, true);
result = (modifiedStat / unmodifiedStat - 1) * 10000;
} else {
val = this.getModValue(name);
}
}
if (formattingOptions && formattingOptions.change) {
let changeFormatting = formattingOptions.change;
let baseVal = this[name];
let absVal = this._getModifiedValue(name);
if (changeFormatting === 'additive') {
val = absVal - baseVal;
} else if (changeFormatting === '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 formattingOptions = STATS_FORMATTING[name];
if (!formattingOptions || !formattingOptions.unit) {
if (formattingOptions.format && formattingOptions.format.startsWith('pct')) {
return 'pct';
}
return '';
}
return formattingOptions.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 formattingOptions = STATS_FORMATTING[name];
if (!formattingOptions || !formattingOptions.storedUnit) {
return this.getUnitFor(name);
}
return formattingOptions.storedUnit;
}
/**
* Get the power generation of this module
* @param {Boolean} [modified=true] Whether to take modifications into account
* @return {Number} the power generation of this module
*/
getPowerGeneration(modified = true) {
return this._getValue('pgen', modified);
return this.get('pgen', modified);
}
/**
@@ -283,7 +428,7 @@ export default class Module {
* @return {Number} the power usage of this module
*/
getPowerUsage(modified = true) {
return this._getValue('power', modified);
return this.get('power', modified);
}
/**
@@ -292,7 +437,7 @@ export default class Module {
* @return {Number} the integrity of this module
*/
getIntegrity(modified = true) {
return this._getValue('integrity', modified);
return this.get('integrity', modified);
}
/**
@@ -301,7 +446,7 @@ export default class Module {
* @return {Number} the mass of this module
*/
getMass(modified = true) {
return this._getValue('mass', modified);
return this.get('mass', modified);
}
/**
@@ -310,7 +455,7 @@ export default class Module {
* @return {Number} the thermal efficiency of this module
*/
getThermalEfficiency(modified = true) {
return this._getValue('eff', modified);
return this.get('eff', modified);
}
/**
@@ -319,7 +464,7 @@ export default class Module {
* @return {Number} the maximum fuel per jump of this module
*/
getMaxFuelPerJump(modified = true) {
return this._getValue('maxfuel', modified);
return this.get('maxfuel', modified);
}
/**
@@ -328,7 +473,7 @@ export default class Module {
* @return {Number} the systems capacity of this module
*/
getSystemsCapacity(modified = true) {
return this._getValue('syscap', modified);
return this.get('syscap', modified);
}
/**
@@ -337,7 +482,7 @@ export default class Module {
* @return {Number} the engines capacity of this module
*/
getEnginesCapacity(modified = true) {
return this._getValue('engcap', modified);
return this.get('engcap', modified);
}
/**
@@ -346,7 +491,7 @@ export default class Module {
* @return {Number} the weapons capacity of this module
*/
getWeaponsCapacity(modified = true) {
return this._getValue('wepcap', modified);
return this.get('wepcap', modified);
}
/**
@@ -355,7 +500,7 @@ export default class Module {
* @return {Number} the systems recharge rate of this module
*/
getSystemsRechargeRate(modified = true) {
return this._getValue('sysrate', modified);
return this.get('sysrate', modified);
}
/**
@@ -364,7 +509,7 @@ export default class Module {
* @return {Number} the engines recharge rate of this module
*/
getEnginesRechargeRate(modified = true) {
return this._getValue('engrate', modified);
return this.get('engrate', modified);
}
/**
@@ -373,7 +518,7 @@ export default class Module {
* @return {Number} the weapons recharge rate of this module
*/
getWeaponsRechargeRate(modified = true) {
return this._getValue('weprate', modified);
return this.get('weprate', modified);
}
/**
@@ -382,7 +527,7 @@ export default class Module {
* @return {Number} the kinetic resistance of this module
*/
getKineticResistance(modified = true) {
return this._getValue('kinres', modified);
return this.get('kinres', modified);
}
/**
@@ -391,7 +536,7 @@ export default class Module {
* @return {Number} the thermal resistance of this module
*/
getThermalResistance(modified = true) {
return this._getValue('thermres', modified);
return this.get('thermres', modified);
}
/**
@@ -400,7 +545,7 @@ export default class Module {
* @return {Number} the explosive resistance of this module
*/
getExplosiveResistance(modified = true) {
return this._getValue('explres', modified);
return this.get('explres', modified);
}
/**
@@ -409,7 +554,7 @@ export default class Module {
* @return {Number} the caustic resistance of this module
*/
getCausticResistance(modified = true) {
return this._getValue('causres', modified);
return this.get('causres', modified);
}
/**
@@ -418,7 +563,7 @@ export default class Module {
* @return {Number} the regeneration rate of this module
*/
getRegenerationRate(modified = true) {
return this._getValue('regen', modified);
return this.get('regen', modified);
}
/**
@@ -427,7 +572,7 @@ export default class Module {
* @return {Number} the broken regeneration rate of this module
*/
getBrokenRegenerationRate(modified = true) {
return this._getValue('brokenregen', modified);
return this.get('brokenregen', modified);
}
/**
@@ -436,7 +581,7 @@ export default class Module {
* @return {Number} the range rate of this module
*/
getRange(modified = true) {
return this._getValue('range', modified);
return this.get('range', modified);
}
/**
@@ -447,7 +592,7 @@ export default class Module {
getFalloff(modified = true) {
if (!modified) {
const range = this.getRange(false);
const falloff = this._getValue('falloff', false);
const falloff = this.get('falloff', false);
return (falloff > range ? range : falloff);
}
@@ -473,7 +618,7 @@ export default class Module {
* @return {Number} the range of this module
*/
getRangeT(modified = true) {
return this._getValue('ranget', modified);
return this.get('ranget', modified);
}
/**
@@ -482,7 +627,7 @@ export default class Module {
* @return {Number} the scan time of this module
*/
getScanTime(modified = true) {
return this._getValue('scantime', modified);
return this.get('scantime', modified);
}
/**
@@ -491,7 +636,7 @@ export default class Module {
* @return {Number} the capture arc of this module
*/
getCaptureArc(modified = true) {
return this._getValue('arc', modified);
return this.get('arc', modified);
}
/**
@@ -500,7 +645,7 @@ export default class Module {
* @return {Number} the hull reinforcement of this module
*/
getHullReinforcement(modified = true) {
return this._getValue('hullreinforcement', modified);
return this.get('hullreinforcement', modified);
}
/**
@@ -509,7 +654,7 @@ export default class Module {
* @return {Number} the protection of this module
*/
getProtection(modified = true) {
return this._getValue('protection', modified);
return this.get('protection', modified);
}
/**
@@ -518,7 +663,7 @@ export default class Module {
* @return {Number} the delay of this module
*/
getDelay(modified = true) {
return this._getValue('delay', modified);
return this.get('delay', modified);
}
/**
@@ -527,7 +672,7 @@ export default class Module {
* @return {Number} the duration of this module
*/
getDuration(modified = true) {
return this._getValue('duration', modified);
return this.get('duration', modified);
}
/**
@@ -536,7 +681,7 @@ export default class Module {
* @return {Number} the shield boost of this module
*/
getShieldBoost(modified = true) {
return this._getValue('shieldboost', modified);
return this.get('shieldboost', modified);
}
/**
@@ -563,7 +708,7 @@ export default class Module {
* @return {Number} the optimum mass of this module
*/
getOptMass(modified = true) {
return this._getValue('optmass', modified);
return this.get('optmass', modified);
}
/**
@@ -654,7 +799,7 @@ export default class Module {
* @return {Number} the damage of this module
*/
getDamage(modified = true) {
return this._getValue('damage', modified);
return this.get('damage', modified);
}
/**
@@ -663,7 +808,7 @@ export default class Module {
* @return {Number} the distributor draw of this module
*/
getDistDraw(modified = true) {
return this._getValue('distdraw', modified);
return this.get('distdraw', modified);
}
/**
@@ -672,7 +817,7 @@ export default class Module {
* @return {Number} the thermal load of this module
*/
getThermalLoad(modified = true) {
return this._getValue('thermload', modified);
return this.get('thermload', modified);
}
/**
@@ -681,7 +826,7 @@ export default class Module {
* @return {Number} the rounds per shot of this module
*/
getRoundsPerShot(modified = true) {
return this._getValue('roundspershot', modified);
return this.get('roundspershot', modified);
}
/**
@@ -763,7 +908,7 @@ export default class Module {
*/
getClip(modified = true) {
// Clip size is always rounded up
let result = this._getValue('clip', modified);
let result = this.get('clip', modified);
if (result) { result = Math.ceil(result); }
return result;
}
@@ -774,7 +919,7 @@ export default class Module {
* @return {Number} the ammo size of this module
*/
getAmmo(modified = true) {
return this._getValue('ammo', modified);
return this.get('ammo', modified);
}
/**
@@ -783,7 +928,7 @@ export default class Module {
* @return {Number} the reload time of this module
*/
getReload(modified = true) {
return this._getValue('reload', modified);
return this.get('reload', modified);
}
/**
@@ -792,7 +937,7 @@ export default class Module {
* @return {Number} the burst size of this module
*/
getBurst(modified = true) {
return this._getValue('burst', modified);
return this.get('burst', modified);
}
/**
@@ -801,7 +946,7 @@ export default class Module {
* @return {Number} the burst rate of fire of this module
*/
getBurstRoF(modified = true) {
return this._getValue('burstrof', modified);
return this.get('burstrof', modified);
}
/**
@@ -816,7 +961,7 @@ export default class Module {
getRoF(modified = true) {
const burst = this.getBurst(modified) || 1;
const burstRoF = this.getBurstRoF(modified) || 1;
const intRoF = this._getValue('rof', modified);
const intRoF = this.get('rof', modified);
return burst / (((burst - 1) / burstRoF) + 1 / intRoF);
}
@@ -827,7 +972,7 @@ export default class Module {
* @return {Number} the facing limit for this module
*/
getFacingLimit(modified = true) {
return this._getValue('facinglimit', modified);
return this.get('facinglimit', modified);
}
/**
@@ -836,7 +981,7 @@ export default class Module {
* @return {Number} the hull boost for this module
*/
getHullBoost(modified = true) {
return this._getValue('hullboost', modified);
return this.get('hullboost', modified);
}
/**
@@ -845,7 +990,7 @@ export default class Module {
* @return {Number} the shield reinforcement for this module
*/
getShieldReinforcement(modified = true) {
return this._getValue('shieldreinforcement', modified);
return this.get('shieldreinforcement', modified);
}
/**
@@ -854,7 +999,7 @@ export default class Module {
* @return {Number} the shield addition for this module
*/
getShieldAddition(modified = true) {
return this._getValue('shieldaddition', modified);
return this.get('shieldaddition', modified);
}
/**
@@ -863,7 +1008,7 @@ export default class Module {
* @return {Number} the jump range boost for this module
*/
getJumpBoost(modified = true) {
return this._getValue('jumpboost', modified);
return this.get('jumpboost', modified);
}
/**
@@ -872,7 +1017,7 @@ export default class Module {
* @return {Number} the piercing for this module
*/
getPiercing(modified = true) {
return this._getValue('piercing', modified);
return this.get('piercing', modified);
}
/**
@@ -881,7 +1026,7 @@ export default class Module {
* @return {Number} the bays for this module
*/
getBays(modified) {
return this._getValue('bays', modified);
return this.get('bays', modified);
}
/**
@@ -890,7 +1035,7 @@ export default class Module {
* @return {Number} the rebuilds per bay for this module
*/
getRebuildsPerBay(modified = true) {
return this._getValue('rebuildsperbay', modified);
return this.get('rebuildsperbay', modified);
}
/**
@@ -899,7 +1044,7 @@ export default class Module {
* @return {Number} the jitter for this module
*/
getJitter(modified = true) {
return this._getValue('jitter', modified);
return this.get('jitter', modified);
}
/**
@@ -917,7 +1062,7 @@ export default class Module {
* @return {string} the shot speed for this module
*/
getShotSpeed(modified = true) {
return this._getValue('shotspeed', modified);
return this.get('shotspeed', modified);
}
/**
@@ -926,7 +1071,7 @@ export default class Module {
* @return {string} the spinup for this module
*/
getSpinup(modified = true) {
return this._getValue('spinup', modified);
return this.get('spinup', modified);
}
/**
@@ -935,7 +1080,7 @@ export default class Module {
* @return {string} the time for this module
*/
getTime(modified = true) {
return this._getValue('time', modified);
return this.get('time', modified);
}
/**
@@ -944,7 +1089,7 @@ export default class Module {
* @return {string} the time for this module
*/
getHackTime(modified = true) {
return this._getValue('hacktime', modified);
return this.get('hacktime', modified);
}
}

View File

@@ -7,6 +7,7 @@ import LZString from 'lz-string';
import * as _ from 'lodash';
import isEqual from 'lodash/lang';
import { Ships, Modifications } from 'coriolis-data/dist';
import { chain } from 'lodash';
const zlib = require('zlib');
const UNIQUE_MODULES = ['psg', 'sg', 'bsg', 'rf', 'fs', 'fh', 'gfsb'];
@@ -493,68 +494,62 @@ export default class Ship {
* @param {Object} name The name of the modification to change
* @param {Number} value The new value of the modification. The value of the modification is scaled to provide two decimal places of precision in an integer. For example 1.23% is stored as 123
* @param {bool} sentfromui True if this update was sent from the UI
* @param {bool} isAbsolute True if value is an absolute value and not a
* modification value
*/
setModification(m, name, value, sentfromui) {
setModification(m, name, value, sentfromui, isAbsolute) {
if (isNaN(value)) {
// Value passed is invalid; reset it to 0
value = 0;
}
if (isAbsolute) {
m.setPretty(name, value, sentfromui);
} else {
m.setModValue(name, value, sentfromui);
}
// Handle special cases
if (name === 'pgen') {
// Power generation
m.setModValue(name, value, sentfromui);
this.updatePowerGenerated();
} else if (name === 'power') {
// Power usage
m.setModValue(name, value, sentfromui);
this.updatePowerUsed();
} else if (name === 'mass') {
// Mass
m.setModValue(name, value, sentfromui);
this.recalculateMass();
this.updateMovement();
this.updateJumpStats();
} else if (name === 'maxfuel') {
m.setModValue(name, value, sentfromui);
this.updateJumpStats();
} else if (name === 'optmass') {
m.setModValue(name, value, sentfromui);
// Could be for any of thrusters, FSD or shield
this.updateMovement();
this.updateJumpStats();
this.recalculateShield();
} else if (name === 'optmul') {
m.setModValue(name, value, sentfromui);
// Could be for any of thrusters, FSD or shield
this.updateMovement();
this.updateJumpStats();
this.recalculateShield();
} else if (name === 'shieldboost') {
m.setModValue(name, value, sentfromui);
this.recalculateShield();
} else if (name === 'hullboost' || name === 'hullreinforcement' || name === 'modulereinforcement') {
m.setModValue(name, value, sentfromui);
this.recalculateArmour();
} else if (name === 'shieldreinforcement') {
m.setModValue(name, value, sentfromui);
this.recalculateShieldCells();
} else if (name === 'burst' || name == 'burstrof' || name === 'clip' || name === 'damage' || name === 'distdraw' || name === 'jitter' || name === 'piercing' || name === 'range' || name === 'reload' || name === 'rof' || name === 'thermload') {
m.setModValue(name, value, sentfromui);
this.recalculateDps();
this.recalculateHps();
this.recalculateEps();
} else if (name === 'explres' || name === 'kinres' || name === 'thermres') {
m.setModValue(name, value, sentfromui);
// Could be for shields or armour
this.recalculateArmour();
this.recalculateShield();
} else if (name === 'engcap') {
m.setModValue(name, value, sentfromui);
// Might have resulted in a change in boostability
this.updateMovement();
} else {
// Generic
m.setModValue(name, value, sentfromui);
}
}
@@ -1187,38 +1182,35 @@ export default class Ship {
unladenMass += this.bulkheads.m.getMass();
for (let slotNum in this.standard) {
const slot = this.standard[slotNum];
if (slot.m) {
unladenMass += slot.m.getMass();
if (slot.m.grp === 'ft') {
fuelCapacity += slot.m.fuel;
}
}
}
let slots = this.standard.concat(this.internal, this.hardpoints);
// TODO: create class for slot and also add slot.get
// handle unladen mass
unladenMass += chain(slots)
.map(slot => slot.m ? slot.m.get('mass') : null)
.filter()
.reduce((sum, mass) => sum + mass)
.value();
for (let slotNum in this.internal) {
const slot = this.internal[slotNum];
if (slot.m) {
unladenMass += slot.m.getMass();
if (slot.m.grp === 'ft') {
fuelCapacity += slot.m.fuel;
} else if (slot.m.grp === 'cr') {
cargoCapacity += slot.m.cargo;
} else if (slot.m.grp.slice(0,2) === 'pc') {
if (slot.m.passengers) {
passengerCapacity += slot.m.passengers;
}
}
}
}
// handle fuel capacity
fuelCapacity += chain(slots)
.map(slot => slot.m ? slot.m.get('fuel') : null)
.filter()
.reduce((sum, fuel) => sum + fuel)
.value();
for (let slotNum in this.hardpoints) {
const slot = this.hardpoints[slotNum];
if (slot.m) {
unladenMass += slot.m.getMass();
}
}
// handle cargo capacity
cargoCapacity += chain(slots)
.map(slot => slot.m ? slot.m.get('cargo') : null)
.filter()
.reduce((sum, cargo) => sum + cargo)
.value();
// handle passenger capacity
passengerCapacity += chain(slots)
.map(slot => slot.m ? slot.m.get('passengers') : null)
.filter()
.reduce((sum, passengers) => sum + passengers)
.value();
// Update global stats
this.unladenMass = unladenMass;

View File

@@ -22,7 +22,7 @@ export const SI_PREFIXES = {
'y': 1e-24 // Yokto
};
export const STATS_FORMATING = {
export const STATS_FORMATTING = {
'ammo': { 'format': 'int', },
'boot': { 'format': 'int', 'unit': 'secs' },
'brokenregen': { 'format': 'round1', 'unit': 'ps' },
@@ -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' },
@@ -52,7 +52,7 @@ export const STATS_FORMATING = {
'mass': { 'format': 'round1', 'unit': 'T' },
'maxfuel': { 'format': 'round1', 'unit': 'T' },
'optmass': { 'format': 'int', 'unit': 'T' },
'optmul': { 'format': 'pct' },
'optmul': { 'format': 'pct', 'change': 'additive' },
'pgen': { 'format': 'round1', 'unit': 'MW' },
'piercing': { 'format': 'int' },
'power': { 'format': 'round', 'unit': 'MW' },
@@ -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,35 @@
text-overflow: ellipsis;
}
.modification-container {
@input-container-width: 75%;
td {
width: 100% - @input-container-width;
text-align: center;
}
.input-container {
width: @input-container-width;
text-align: right;
}
input {
width: 80%;
}
.unit-container {
width: 30px;
padding: 3px;
text-align: left;
display: inline-block;
}
.header-adjuster {
width: 100% - @input-container-width;
display: inline-block;
}
}
.cb {
overflow: hidden;
}