Various fixes; allow direct import from URL

This commit is contained in:
Cmdr McDonald
2016-11-13 16:42:59 +00:00
parent 7d4c534956
commit a65dae1631
8 changed files with 103 additions and 33 deletions

View File

@@ -16,4 +16,5 @@
* Enable boost display even if power distributor is disabled * Enable boost display even if power distributor is disabled
* Calculate breakdown of ship offensive and defensive stats * Calculate breakdown of ship offensive and defensive stats
* Add 'Offence summary' and 'Defence summary' components * Add 'Offence summary' and 'Defence summary' components
* Add ability to import directly from companion API output * Add ability to import from companion API output through import feature
* Add ability to import from companion API output through URL

View File

@@ -7,6 +7,8 @@ import Persist from './stores/Persist';
import Header from './components/Header'; import Header from './components/Header';
import Tooltip from './components/Tooltip'; import Tooltip from './components/Tooltip';
import ModalImport from './components/ModalImport'; import ModalImport from './components/ModalImport';
import * as CompanionApiUtils from './utils/CompanionApiUtils';
import * as Utils from './utils/UtilityFunctions';
import AboutPage from './pages/AboutPage'; import AboutPage from './pages/AboutPage';
import NotFoundPage from './pages/NotFoundPage'; import NotFoundPage from './pages/NotFoundPage';
@@ -15,6 +17,8 @@ import ComparisonPage from './pages/ComparisonPage';
import ShipyardPage from './pages/ShipyardPage'; import ShipyardPage from './pages/ShipyardPage';
import ErrorDetails from './pages/ErrorDetails'; import ErrorDetails from './pages/ErrorDetails';
const zlib = require('zlib');
/** /**
* Coriolis App * Coriolis App
*/ */
@@ -52,6 +56,7 @@ export default class Coriolis extends React.Component {
this._onLanguageChange = this._onLanguageChange.bind(this); this._onLanguageChange = this._onLanguageChange.bind(this);
this._onSizeRatioChange = this._onSizeRatioChange.bind(this); this._onSizeRatioChange = this._onSizeRatioChange.bind(this);
this._keyDown = this._keyDown.bind(this); this._keyDown = this._keyDown.bind(this);
this._importBuild = this._importBuild.bind(this);
this.emitter = new EventEmitter(); this.emitter = new EventEmitter();
this.state = { this.state = {
@@ -63,6 +68,7 @@ export default class Coriolis extends React.Component {
}; };
Router('', (r) => this._setPage(ShipyardPage, r)); Router('', (r) => this._setPage(ShipyardPage, r));
Router('/import/:data', (r) => this._importBuild(r));
Router('/outfit/:ship/:code?', (r) => this._setPage(OutfittingPage, r)); Router('/outfit/:ship/:code?', (r) => this._setPage(OutfittingPage, r));
Router('/compare/:name?', (r) => this._setPage(ComparisonPage, r)); Router('/compare/:name?', (r) => this._setPage(ComparisonPage, r));
Router('/comparison/:code', (r) => this._setPage(ComparisonPage, r)); Router('/comparison/:code', (r) => this._setPage(ComparisonPage, r));
@@ -70,6 +76,23 @@ export default class Coriolis extends React.Component {
Router('*', (r) => this._setPage(null, r)); Router('*', (r) => this._setPage(null, r));
} }
/**
* Import a build directly
*/
_importBuild(r) {
try {
// Need to decode and gunzip the data
const data = zlib.gunzipSync(new Buffer(Utils.fromUrlSafe(r.params.data), 'base64'))
const json = JSON.parse(data);
const ship = CompanionApiUtils.shipFromJson(json);
r.params.ship = ship.id;
r.params.code = ship.toString();
this._setPage(OutfittingPage, r);
} catch (err) {
this.setState({ error: err });
}
}
/** /**
* Updates / Sets the page and route context * Updates / Sets the page and route context
* @param {[type]} page The page to be shown * @param {[type]} page The page to be shown

View File

@@ -64,7 +64,7 @@ export default class HardpointSlot extends Slot {
{ m.getHps() ? <div className={'l'} onMouseOver={termtip.bind(null, m.getClip() ? 'hpsshps' : 'hps')} onMouseOut={tooltip.bind(null, null)}>{translate('HPS')}: {formats.round1(m.getHps())} { m.getClip() ? <span>({formats.round1((m.getClip() * m.getHps() / m.getRoF()) / ((m.getClip() / m.getRoF()) + m.getReload())) })</span> : null }</div> : null } { m.getHps() ? <div className={'l'} onMouseOver={termtip.bind(null, m.getClip() ? 'hpsshps' : 'hps')} onMouseOut={tooltip.bind(null, null)}>{translate('HPS')}: {formats.round1(m.getHps())} { m.getClip() ? <span>({formats.round1((m.getClip() * m.getHps() / m.getRoF()) / ((m.getClip() / m.getRoF()) + m.getReload())) })</span> : null }</div> : null }
{ m.getDps() && m.getEps() ? <div className={'l'} onMouseOver={termtip.bind(null, 'dpe')} onMouseOut={tooltip.bind(null, null)}>{translate('DPE')}: {formats.f1(m.getDps() / m.getEps())}</div> : null } { m.getDps() && m.getEps() ? <div className={'l'} onMouseOver={termtip.bind(null, 'dpe')} onMouseOut={tooltip.bind(null, null)}>{translate('DPE')}: {formats.f1(m.getDps() / m.getEps())}</div> : null }
{ m.getRoF() ? <div className={'l'} onMouseOver={termtip.bind(null, 'rof')} onMouseOut={tooltip.bind(null, null)}>{translate('ROF')}: {formats.f1(m.getRoF())}{u.ps}</div> : null } { m.getRoF() ? <div className={'l'} onMouseOver={termtip.bind(null, 'rof')} onMouseOut={tooltip.bind(null, null)}>{translate('ROF')}: {formats.f1(m.getRoF())}{u.ps}</div> : null }
{ m.getRange() && !m.getDps() ? <div className={'l'}>{translate('Range')} : {formats.round(m.getRange() / 1000)}{u.km}</div> : null } { m.getRange() ? <div className={'l'}>{translate('range')} {formats.f1(m.getRange() / 1000)}{u.km}</div> : null }
{ m.getShieldBoost() ? <div className={'l'}>+{formats.pct1(m.getShieldBoost())}</div> : null } { m.getShieldBoost() ? <div className={'l'}>+{formats.pct1(m.getShieldBoost())}</div> : null }
{ m.getAmmo() ? <div className={'l'}>{translate('ammunition')}: {formats.int(m.getClip())}/{formats.int(m.getAmmo())}</div> : null } { m.getAmmo() ? <div className={'l'}>{translate('ammunition')}: {formats.int(m.getClip())}/{formats.int(m.getAmmo())}</div> : null }
{ showModuleResistances && m.getExplosiveResistance() ? <div className='l'>{translate('explres')}: {formats.pct(m.getExplosiveResistance())}</div> : null } { showModuleResistances && m.getExplosiveResistance() ? <div className='l'>{translate('explres')}: {formats.pct(m.getExplosiveResistance())}</div> : null }

View File

@@ -40,7 +40,7 @@ export default class InternalSlot extends Slot {
{ m.rate ? <div className={'l'}>{translate('rate')}: {m.rate}{u.kgs}&nbsp;&nbsp;&nbsp;{translate('refuel time')}: {formats.time(this.props.fuel * 1000 / m.rate)}</div> : null } { m.rate ? <div className={'l'}>{translate('rate')}: {m.rate}{u.kgs}&nbsp;&nbsp;&nbsp;{translate('refuel time')}: {formats.time(this.props.fuel * 1000 / m.rate)}</div> : null }
{ m.getAmmo() ? <div className={'l'}>{translate('ammunition')}: {formats.gen(m.getAmmo())}</div> : null } { m.getAmmo() ? <div className={'l'}>{translate('ammunition')}: {formats.gen(m.getAmmo())}</div> : null }
{ m.cells ? <div className={'l'}>{translate('cells')}: {m.cells}</div> : null } { m.cells ? <div className={'l'}>{translate('cells')}: {m.cells}</div> : null }
{ m.recharge ? <div className={'l'}>{translate('recharge')}: {m.recharge} <u>MJ</u>&nbsp;&nbsp;&nbsp;{translate('total')}: {m.cells * m.recharge}{u.MJ}</div> : null } { m.shieldreinforcement ? <div className={'l'}>{translate('shieldreinforcement')}: {formats.int(m.getShieldReinforcement())} <u>MJ</u>&nbsp;&nbsp;&nbsp;{translate('total')}: {formats.int(m.cells * m.getShieldReinforcement())}{u.MJ}</div> : null }
{ m.repair ? <div className={'l'}>{translate('repair')}: {m.repair}</div> : null } { m.repair ? <div className={'l'}>{translate('repair')}: {m.repair}</div> : null }
{ m.getFacingLimit() ? <div className={'l'}>{translate('facinglimit')} {formats.f1(m.getFacingLimit())}°</div> : null } { m.getFacingLimit() ? <div className={'l'}>{translate('facinglimit')} {formats.f1(m.getFacingLimit())}°</div> : null }
{ m.getRange() ? <div className={'l'}>{translate('range')} {formats.f2(m.getRange())}{u.km}</div> : null } { m.getRange() ? <div className={'l'}>{translate('range')} {formats.f2(m.getRange())}{u.km}</div> : null }

View File

@@ -2,6 +2,7 @@ import { ModuleGroupToName, MountMap, BulkheadNames } from './Constants';
import { Ships } from 'coriolis-data/dist'; import { Ships } from 'coriolis-data/dist';
import Ship from './Ship'; import Ship from './Ship';
import * as ModuleUtils from './ModuleUtils'; import * as ModuleUtils from './ModuleUtils';
import * as Utils from '../utils/UtilityFunctions';
import LZString from 'lz-string'; import LZString from 'lz-string';
const STANDARD = ['powerPlant', 'thrusters', 'frameShiftDrive', 'lifeSupport', 'powerDistributor', 'sensors', 'fuelTank']; const STANDARD = ['powerPlant', 'thrusters', 'frameShiftDrive', 'lifeSupport', 'powerDistributor', 'sensors', 'fuelTank'];
@@ -209,13 +210,13 @@ export function toDetailedExport(builds) {
* @return {string} Zipped Base 64 encoded JSON * @return {string} Zipped Base 64 encoded JSON
*/ */
export function fromComparison(name, builds, facets, predicate, desc) { export function fromComparison(name, builds, facets, predicate, desc) {
return LZString.compressToBase64(JSON.stringify({ return Utils.toUrlSafe(LZString.compressToBase64(JSON.stringify({
n: name, n: name,
b: builds.map((b) => { return { s: b.id, n: b.buildName, c: b.toString() }; }), b: builds.map((b) => { return { s: b.id, n: b.buildName, c: b.toString() }; }),
f: facets, f: facets,
p: predicate, p: predicate,
d: desc ? 1 : 0 d: desc ? 1 : 0
})).replace(/\//g, '-'); })));
}; };
/** /**
@@ -224,5 +225,5 @@ export function fromComparison(name, builds, facets, predicate, desc) {
* @return {Object} Comparison data object * @return {Object} Comparison data object
*/ */
export function toComparison(code) { export function toComparison(code) {
return JSON.parse(LZString.decompressFromBase64(code.replace(/-/g, '/'))); return JSON.parse(LZString.decompressFromBase64(Utils.fromUrlSafe(code)));
}; };

View File

@@ -1,5 +1,6 @@
import * as Calc from './Calculations'; import * as Calc from './Calculations';
import * as ModuleUtils from './ModuleUtils'; import * as ModuleUtils from './ModuleUtils';
import * as Utils from '../utils/UtilityFunctions';
import Module from './Module'; import Module from './Module';
import LZString from 'lz-string'; import LZString from 'lz-string';
import isEqual from 'lodash/lang'; import isEqual from 'lodash/lang';
@@ -601,15 +602,15 @@ export default class Ship {
code = parts[0]; code = parts[0];
if (parts[1]) { if (parts[1]) {
enabled = LZString.decompressFromBase64(parts[1].replace(/-/g, '/')).split(''); enabled = Utils.fromUrlSafe(LZString.decompressFromBase64(parts[1])).split('');
} }
if (parts[2]) { if (parts[2]) {
priorities = LZString.decompressFromBase64(parts[2].replace(/-/g, '/')).split(''); priorities = Utils.fromUrlSafe(LZString.decompressFromBase64(parts[2])).split('');
} }
if (parts[3]) { if (parts[3]) {
const modstr = parts[3].replace(/-/g, '/'); const modstr = Utils.fromUrlSafe(parts[3]);
if (modstr.match(':')) { if (modstr.match(':')) {
this.decodeModificationsString(modstr, modifications); this.decodeModificationsString(modstr, modifications);
} else { } else {
@@ -1198,7 +1199,7 @@ export default class Ship {
priorities.push(slot.priority); priorities.push(slot.priority);
} }
this.serialized.priorities = LZString.compressToBase64(priorities.join('')).replace(/\//g, '-'); this.serialized.priorities = Utils.toUrlSafe(LZString.compressToBase64(priorities.join('')));
return this; return this;
} }
@@ -1219,7 +1220,7 @@ export default class Ship {
enabled.push(slot.enabled ? 1 : 0); enabled.push(slot.enabled ? 1 : 0);
} }
this.serialized.enabled = LZString.compressToBase64(enabled.join('')).replace(/\//g, '-'); this.serialized.enabled = Utils.toUrlSafe(LZString.compressToBase64(enabled.join('')));
return this; return this;
} }
@@ -1265,7 +1266,7 @@ export default class Ship {
} }
allMods.push(slotMods.join(';')); allMods.push(slotMods.join(';'));
} }
this.serialized.modifications = LZString.compressToBase64(allMods.join(',').replace(/,+$/, '')).replace(/\//g, '-'); this.serialized.modifications = Utils.toUrlSafe(LZString.compressToBase64(allMods.join(',').replace(/,+$/, '')));
return this; return this;
} }
@@ -1386,7 +1387,7 @@ export default class Ship {
buffer.writeInt8(-1, curpos++); buffer.writeInt8(-1, curpos++);
} }
this.serialized.modifications = zlib.gzipSync(buffer).toString('base64').replace(/\//g, '-'); this.serialized.modifications = Utils.toUrlSafe(zlib.gzipSync(buffer).toString('base64'));
} else { } else {
this.serialized.modifications = null; this.serialized.modifications = null;
} }

View File

@@ -151,6 +151,7 @@ export function shipFromJson(json) {
throw 'Unknown bulkheads "' + armourJson.name + '"'; throw 'Unknown bulkheads "' + armourJson.name + '"';
} }
ship.bulkheads.enabled = true; ship.bulkheads.enabled = true;
if (armourJson.modifiers) _addModifications(ship.bulkheads.m, armourJson.modifiers);
// Add the standard modules // Add the standard modules
// Power plant // Power plant
@@ -159,7 +160,7 @@ export function shipFromJson(json) {
if (powerplantJson.modifiers) _addModifications(powerplant, powerplantJson.modifiers); if (powerplantJson.modifiers) _addModifications(powerplant, powerplantJson.modifiers);
ship.use(ship.standard[0], powerplant, true); ship.use(ship.standard[0], powerplant, true);
ship.standard[0].enabled = powerplantJson.on === true; ship.standard[0].enabled = powerplantJson.on === true;
ship.standard[0].priority = powerplantJson.priority + 1; ship.standard[0].priority = powerplantJson.priority;
// Thrusters // Thrusters
const thrustersJson = json.modules.MainEngines.module; const thrustersJson = json.modules.MainEngines.module;
@@ -167,7 +168,7 @@ export function shipFromJson(json) {
if (thrustersJson.modifiers) _addModifications(thrusters, thrustersJson.modifiers); if (thrustersJson.modifiers) _addModifications(thrusters, thrustersJson.modifiers);
ship.use(ship.standard[1], thrusters, true); ship.use(ship.standard[1], thrusters, true);
ship.standard[1].enabled = thrustersJson.on === true; ship.standard[1].enabled = thrustersJson.on === true;
ship.standard[1].priority = thrustersJson.priority + 1; ship.standard[1].priority = thrustersJson.priority;
// FSD // FSD
const frameshiftdriveJson = json.modules.FrameShiftDrive.module; const frameshiftdriveJson = json.modules.FrameShiftDrive.module;
@@ -175,7 +176,7 @@ export function shipFromJson(json) {
if (frameshiftdriveJson.modifiers) _addModifications(frameshiftdrive, frameshiftdriveJson.modifiers); if (frameshiftdriveJson.modifiers) _addModifications(frameshiftdrive, frameshiftdriveJson.modifiers);
ship.use(ship.standard[2], frameshiftdrive, true); ship.use(ship.standard[2], frameshiftdrive, true);
ship.standard[2].enabled = frameshiftdriveJson.on === true; ship.standard[2].enabled = frameshiftdriveJson.on === true;
ship.standard[2].priority = frameshiftdriveJson.priority + 1; ship.standard[2].priority = frameshiftdriveJson.priority;
// Life support // Life support
const lifesupportJson = json.modules.LifeSupport.module; const lifesupportJson = json.modules.LifeSupport.module;
@@ -183,7 +184,7 @@ export function shipFromJson(json) {
if (lifesupportJson.modifiers)_addModifications(lifesupport, lifesupportJson.modifiers); if (lifesupportJson.modifiers)_addModifications(lifesupport, lifesupportJson.modifiers);
ship.use(ship.standard[3], lifesupport, true); ship.use(ship.standard[3], lifesupport, true);
ship.standard[3].enabled = lifesupportJson.on === true; ship.standard[3].enabled = lifesupportJson.on === true;
ship.standard[3].priority = lifesupportJson.priority + 1; ship.standard[3].priority = lifesupportJson.priority;
// Power distributor // Power distributor
const powerdistributorJson = json.modules.PowerDistributor.module; const powerdistributorJson = json.modules.PowerDistributor.module;
@@ -191,7 +192,7 @@ export function shipFromJson(json) {
if (powerdistributorJson.modifiers) _addModifications(powerdistributor, powerdistributorJson.modifiers); if (powerdistributorJson.modifiers) _addModifications(powerdistributor, powerdistributorJson.modifiers);
ship.use(ship.standard[4], powerdistributor, true); ship.use(ship.standard[4], powerdistributor, true);
ship.standard[4].enabled = powerdistributorJson.on === true; ship.standard[4].enabled = powerdistributorJson.on === true;
ship.standard[4].priority = powerdistributorJson.priority + 1; ship.standard[4].priority = powerdistributorJson.priority;
// Sensors // Sensors
const sensorsJson = json.modules.Radar.module; const sensorsJson = json.modules.Radar.module;
@@ -199,14 +200,14 @@ export function shipFromJson(json) {
if (sensorsJson.modifiers) _addModifications(sensors, sensorsJson.modifiers); if (sensorsJson.modifiers) _addModifications(sensors, sensorsJson.modifiers);
ship.use(ship.standard[5], sensors, true); ship.use(ship.standard[5], sensors, true);
ship.standard[5].enabled = sensorsJson.on === true; ship.standard[5].enabled = sensorsJson.on === true;
ship.standard[5].priority = sensorsJson.priority + 1; ship.standard[5].priority = sensorsJson.priority;
// Fuel tank // Fuel tank
const fueltankJson = json.modules.FuelTank.module; const fueltankJson = json.modules.FuelTank.module;
const fueltank = _moduleFromEdId(fueltankJson.id); const fueltank = _moduleFromEdId(fueltankJson.id);
ship.use(ship.standard[6], fueltank, true); ship.use(ship.standard[6], fueltank, true);
ship.standard[6].enabled = true; ship.standard[6].enabled = true;
ship.standard[6].priority = 1; ship.standard[6].priority = 0;
// Add hardpoints // Add hardpoints
let hardpointClassNum = -1; let hardpointClassNum = -1;
@@ -285,11 +286,11 @@ function _addModifications(module, modifiers) {
// Carry out the required changes // Carry out the required changes
for (const action in modifierActions) { for (const action in modifierActions) {
const actionValue = modifierActions[action] * value; const actionValue = modifierActions[action] * value;
let mod = module.getModValue(action); let mod = module.getModValue(action) / 10000;
if (!mod) { if (!mod) {
mod = 0; mod = 0;
} }
module.setModValue(action, ((1 + mod / 10000) * (1 + actionValue) - 1) * 10000); module.setModValue(action, ((1 + mod) * (1 + actionValue) - 1) * 10000);
} }
} }
@@ -299,20 +300,20 @@ function _addModifications(module, modifiers) {
// being a 4% boost they are a 104% multiplier. Unfortunately this means that our % modification // being a 4% boost they are a 104% multiplier. Unfortunately this means that our % modification
// is incorrect so we fix it // is incorrect so we fix it
if (module.grp === 'sb' && module.getModValue('shieldboost')) { if (module.grp === 'sb' && module.getModValue('shieldboost')) {
const alteredBoost = (1 + module.shieldboost) * (module.getModValue('shieldboost')); const alteredBoost = (1 + module.shieldboost) * (module.getModValue('shieldboost') / 10000);
module.setModValue('shieldboost', alteredBoost / module.shieldboost); module.setModValue('shieldboost', alteredBoost * 10000 / module.shieldboost);
} }
// Shield booster resistance is actually a damage modifier, so needs to be inverted. // Shield booster resistance is actually a damage modifier, so needs to be inverted.
if (module.grp === 'sb') { if (module.grp === 'sb') {
if (module.getModValue('explres')) { if (module.getModValue('explres')) {
module.setModValue('explres', module.getModValue('explres') * -1); module.setModValue('explres', ((module.getModValue('explres') / 10000) * -1) * 10000);
} }
if (module.getModValue('kinres')) { if (module.getModValue('kinres')) {
module.setModValue('kinres', module.getModValue('kinres') * -1); module.setModValue('kinres', ((module.getModValue('kinres') / 10000) * -1) * 10000);
} }
if (module.getModValue('thermres')) { if (module.getModValue('thermres')) {
module.setModValue('thermres', module.getModValue('thermres') * -1); module.setModValue('thermres', ((module.getModValue('thermres') / 10000) * -1) * 10000);
} }
} }
@@ -320,17 +321,43 @@ function _addModifications(module, modifiers) {
// In addition, the modification is based off the inherent resistance of the module // In addition, the modification is based off the inherent resistance of the module
if (module.isShieldGenerator()) { if (module.isShieldGenerator()) {
if (module.getModValue('explres')) { if (module.getModValue('explres')) {
module.setModValue('explres', (1 - (1 - module.explres) * (1 + module.getModValue('explres'))) - module.explres); module.setModValue('explres', ((1 - (1 - module.explres) * (1 + module.getModValue('explres') / 10000)) - module.explres) * 10000);
} }
if (module.getModValue('kinres')) { if (module.getModValue('kinres')) {
module.setModValue('kinres', (1 - (1 - module.kinres) * (1 + module.getModValue('kinres')))- module.kinres); module.setModValue('kinres', ((1 - (1 - module.kinres) * (1 + module.getModValue('kinres') / 10000)) - module.kinres) * 10000);
} }
if (module.getModValue('thermres')) { if (module.getModValue('thermres')) {
module.setModValue('thermres', (1 - (1 - module.thermres) * (1 + module.getModValue('thermres'))) - module.thermres); module.setModValue('thermres', ((1 - (1 - module.thermres) * (1 + module.getModValue('thermres') / 10000)) - module.thermres) * 10000);
}
}
// Hull reinforcement package resistance is actually a damage modifier, so needs to be inverted.
if (module.grp === 'hr') {
if (module.getModValue('explres')) {
module.setModValue('explres', ((module.getModValue('explres') / 10000) * -1) * 10000);
}
if (module.getModValue('kinres')) {
module.setModValue('kinres', ((module.getModValue('kinres') / 10000) * -1) * 10000);
}
if (module.getModValue('thermres')) {
module.setModValue('thermres', ((module.getModValue('thermres') / 10000) * -1) * 10000);
}
}
// Bulkhead resistance is actually a damage modifier, so needs to be inverted.
// In addition, the modification is based off the inherent resistance of the module
if (module.grp == 'bh') {
if (module.getModValue('explres')) {
module.setModValue('explres', ((1 - (1 - module.explres) * (1 + module.getModValue('explres') / 10000)) - module.explres) * 10000);
}
if (module.getModValue('kinres')) {
module.setModValue('kinres', ((1 - (1 - module.kinres) * (1 + module.getModValue('kinres') / 10000)) - module.kinres) * 10000);
}
if (module.getModValue('thermres')) {
module.setModValue('thermres', ((1 - (1 - module.thermres) * (1 + module.getModValue('thermres') / 10000)) - module.thermres) * 10000);
} }
} }
//TODO do this for armour resistances as well ?
// Jitter is in degrees not % so need to divide it by 100 to obtain the correct number // Jitter is in degrees not % so need to divide it by 100 to obtain the correct number
if (module.getModValue('jitter')) { if (module.getModValue('jitter')) {
@@ -339,7 +366,6 @@ function _addModifications(module, modifiers) {
// FD uses interval between bursts internally, so we need to translate this to a real rate of fire // FD uses interval between bursts internally, so we need to translate this to a real rate of fire
if (module.getModValue('rof')) { if (module.getModValue('rof')) {
module.setModValue('rof', (1 / (1 + module.getModValue('jitter'))) - 1); module.setModValue('rof', ((1 / (1 + module.getModValue('rof') / 10000)) - 1) * 10000);
} }
} }

View File

@@ -58,3 +58,21 @@ export function shallowEqual(objA, objB) {
return true; return true;
} }
/**
* Turn a base-64 encoded string in to a URL-safe version
* @param {string} data the string
* @return {string} the converted string
*/
export function toUrlSafe(data) {
return data.replace(/\\/g, '-').replace(/\+/g, '_');
}
/**
* Turn a URL-safe base-64 encoded string in to a normal version
* @param {string} data the string
* @return {string} the converted string
*/
export function fromUrlSafe(data) {
return data.replace(/-/g, '/').replace(/_/g, '+');
}