Merge pull request #329 from felixlinker/resistance-stacking

Caps for resistances introduced
This commit is contained in:
William
2018-07-22 07:36:46 +10:00
committed by GitHub
4 changed files with 84 additions and 111 deletions

View File

@@ -102,11 +102,11 @@ export default class Defence extends TranslatedComponent {
// Add effective shield from resistances
const rawMj = shield.generator + shield.boosters + shield.cells;
const explosiveMj = rawMj / (shield.explosive.generator * shield.explosive.boosters) - rawMj;
const explosiveMj = rawMj / shield.explosive.total - rawMj;
if (explosiveMj != 0) effectiveShieldExplosiveTt.push(<div key='resistance'>{translate('resistance') + ' ' + formats.int(explosiveMj)}{units.MJ}</div>);
const kineticMj = rawMj / (shield.kinetic.generator * shield.kinetic.boosters) - rawMj;
const kineticMj = rawMj / shield.kinetic.total - rawMj;
if (kineticMj != 0) effectiveShieldKineticTt.push(<div key='resistance'>{translate('resistance') + ' ' + formats.int(kineticMj)}{units.MJ}</div>);
const thermalMj = rawMj / (shield.thermal.generator * shield.thermal.boosters) - rawMj;
const thermalMj = rawMj / shield.thermal.total - rawMj;
if (thermalMj != 0) effectiveShieldThermalTt.push(<div key='resistance'>{translate('resistance') + ' ' + formats.int(thermalMj)}{units.MJ}</div>);
// Add effective shield from power distributor SYS pips
@@ -184,17 +184,17 @@ export default class Defence extends TranslatedComponent {
const armourDamageTakenExplosiveTt = [];
armourDamageTakenExplosiveTt.push(<div key='bulkheads'>{translate('bulkheads') + ' ' + formats.pct1(armour.explosive.bulkheads)}</div>);
armourDamageTakenExplosiveTt.push(<div key='reinforcement'>{translate('reinforcement') + ' ' + formats.pct1(armour.explosive.reinforcement)}</div>);
if (armour.explosive.bulkheads * armour.explosive.reinforcement != 1) effectiveArmourExplosiveTt.push(<div key='resistance'>{translate('resistance') + ' ' + formats.int(rawArmour / (armour.explosive.bulkheads * armour.explosive.reinforcement) - rawArmour)}</div>);
if (armour.explosive.total != 1) effectiveArmourExplosiveTt.push(<div key='resistance'>{translate('resistance') + ' ' + formats.int(rawArmour / armour.explosive.total - rawArmour)}</div>);
const armourDamageTakenKineticTt = [];
armourDamageTakenKineticTt.push(<div key='bulkheads'>{translate('bulkheads') + ' ' + formats.pct1(armour.kinetic.bulkheads)}</div>);
armourDamageTakenKineticTt.push(<div key='reinforcement'>{translate('reinforcement') + ' ' + formats.pct1(armour.kinetic.reinforcement)}</div>);
if (armour.kinetic.bulkheads * armour.kinetic.reinforcement != 1) effectiveArmourKineticTt.push(<div key='resistance'>{translate('resistance') + ' ' + formats.int(rawArmour / (armour.kinetic.bulkheads * armour.kinetic.reinforcement) - rawArmour)}</div>);
if (armour.kinetic.total != 1) effectiveArmourKineticTt.push(<div key='resistance'>{translate('resistance') + ' ' + formats.int(rawArmour / armour.kinetic.total - rawArmour)}</div>);
const armourDamageTakenThermalTt = [];
armourDamageTakenThermalTt.push(<div key='bulkheads'>{translate('bulkheads') + ' ' + formats.pct1(armour.thermal.bulkheads)}</div>);
armourDamageTakenThermalTt.push(<div key='reinforcement'>{translate('reinforcement') + ' ' + formats.pct1(armour.thermal.reinforcement)}</div>);
if (armour.thermal.bulkheads * armour.thermal.reinforcement != 1) effectiveArmourThermalTt.push(<div key='resistance'>{translate('resistance') + ' ' + formats.int(rawArmour / (armour.thermal.bulkheads * armour.thermal.reinforcement) - rawArmour)}</div>);
if (armour.thermal.total != 1) effectiveArmourThermalTt.push(<div key='resistance'>{translate('resistance') + ' ' + formats.int(rawArmour / armour.thermal.total - rawArmour)}</div>);
const effectiveArmourData = [];
const effectiveAbsoluteArmour = armour.total / armour.absolute.total;

View File

@@ -397,11 +397,6 @@ export function shieldMetrics(ship, sys) {
// res.kin = kinDim + overage;
// boosterKinDmg = kinDim + overage;
// }
// Apply diminishing returns
// boosterExplDmg = boosterExplDmg > 0.7 ? boosterExplDmg : 0.7 - (0.7 - boosterExplDmg) / 2;
// boosterKinDmg = boosterKinDmg > 0.7 ? boosterKinDmg : 0.7 - (0.7 - boosterKinDmg) / 2;
// boosterThermDmg = boosterThermDmg > 0.7 ? boosterThermDmg : 0.7 - (0.7 - boosterThermDmg) / 2;
// res.therm = res.therm > 0.7 ? res.therm : 0.7 - (0.7 - res.therm) / 2;
let shieldAddition = 0;
if (ship) {
for (const module of ship.internal) {
@@ -485,31 +480,37 @@ export function shieldMetrics(ship, sys) {
max: 1 - maxSysResistance
};
let sgExplosiveDmg = 1 - shieldGenerator.getExplosiveResistance();
let sgSbExplosiveDmg = diminishDamageMult(sgExplosiveDmg * 0.7, (1 - shieldGenerator.getExplosiveResistance()) * boosterExplDmg);
shield.explosive = {
generator: 1 - shieldGenerator.getExplosiveResistance(),
boosters: boosterExplDmg,
generator: sgExplosiveDmg,
boosters: sgSbExplosiveDmg - sgExplosiveDmg,
sys: (1 - sysResistance),
total: (1 - shieldGenerator.getExplosiveResistance()) * boosterExplDmg * (1 - sysResistance),
max: (1 - shieldGenerator.getExplosiveResistance()) * boosterExplDmg * (1 - maxSysResistance),
res: 1 - boosterExplDmg
total: sgSbExplosiveDmg * (1 - sysResistance),
max: sgSbExplosiveDmg * (1 - maxSysResistance),
res: 1 - sgSbExplosiveDmg
};
let sgKineticDmg = 1 - shieldGenerator.getKineticResistance();
let sgSbKineticDmg = diminishDamageMult(sgKineticDmg * 0.7, (1 - shieldGenerator.getKineticResistance()) * boosterKinDmg);
shield.kinetic = {
generator: 1 - shieldGenerator.getKineticResistance(),
boosters: boosterKinDmg,
generator: sgKineticDmg,
boosters: sgSbKineticDmg - sgKineticDmg,
sys: (1 - sysResistance),
total: (1 - shieldGenerator.getKineticResistance()) * boosterKinDmg * (1 - sysResistance),
max: (1 - shieldGenerator.getKineticResistance()) * boosterKinDmg * (1 - maxSysResistance),
res: 1 - boosterKinDmg
total: sgSbKineticDmg * (1 - sysResistance),
max: sgSbKineticDmg * (1 - maxSysResistance),
res: 1 - sgSbKineticDmg
};
let sgThermalDmg = 1 - shieldGenerator.getThermalResistance();
let sgSbThermalDmg = diminishDamageMult(sgThermalDmg * 0.7, (1 - shieldGenerator.getThermalResistance()) * boosterThermDmg);
shield.thermal = {
generator: 1 - shieldGenerator.getThermalResistance(),
boosters: boosterThermDmg,
generator: sgThermalDmg,
boosters: sgSbThermalDmg - sgThermalDmg,
sys: (1 - sysResistance),
total: (1 - shieldGenerator.getThermalResistance()) * boosterThermDmg * (1 - sysResistance),
max: (1 - shieldGenerator.getThermalResistance()) * boosterThermDmg * (1 - maxSysResistance),
res: 1 - boosterThermDmg
total: sgSbThermalDmg * (1 - sysResistance),
max: sgSbThermalDmg * (1 - maxSysResistance),
res: 1 - sgSbThermalDmg
};
}
return shield;
@@ -545,22 +546,21 @@ export function armourMetrics(ship) {
let hullKinDmg = 1;
let hullThermDmg = 1;
// const dimReturnLine = (res) => 1 - (1 - res) * 0.7;
let res = {
kin: 0,
therm: 0,
expl: 0
};
// let res = {
// kin: 0,
// therm: 0,
// expl: 0
// };
// Armour from HRPs and module armour from MRPs
for (let slot of ship.internal) {
if (slot.m && (slot.m.grp === 'hr' || slot.m.grp === 'ghrp')) {
armourReinforcement += slot.m.getHullReinforcement();
// Hull boost for HRPs is applied against the ship's base armour
armourReinforcement += ship.baseArmour * slot.m.getModValue('hullboost') / 10000;
res.expl += slot.m.getExplosiveResistance();
res.kin += slot.m.getKineticResistance();
res.therm += slot.m.getThermalResistance();
// res.expl += slot.m.getExplosiveResistance();
// res.kin += slot.m.getKineticResistance();
// res.therm += slot.m.getThermalResistance();
hullExplDmg = hullExplDmg * (1 - slot.m.getExplosiveResistance());
hullKinDmg = hullKinDmg * (1 - slot.m.getKineticResistance());
hullThermDmg = hullThermDmg * (1 - slot.m.getThermalResistance());
}
@@ -592,11 +592,6 @@ export function armourMetrics(ship) {
// hullKinDmg = kinDim + overage;
// }
// Apply diminishing returns
// hullExplDmg = hullExplDmg > 0.7 ? hullExplDmg : 0.7 - (0.7 - hullExplDmg) / 2;
// hullKinDmg = hullKinDmg > 0.7 ? hullKinDmg : 0.7 - (0.7 - hullKinDmg) / 2;
// hullThermDmg = hullThermDmg > 0.7 ? hullThermDmg : 0.7 - (0.7 - hullThermDmg) / 2;
const armour = {
bulkheads: armourBulkheads,
reinforcement: armourReinforcement,
@@ -613,25 +608,31 @@ export function armourMetrics(ship) {
total: 1
};
let armourExplDmg = diminishDamageMult(0.7, 1 - ship.bulkheads.m.getExplosiveResistance());
let armourReinforcedExplDmg = diminishDamageMult(0.7, (1 - ship.bulkheads.m.getExplosiveResistance()) * hullExplDmg);
armour.explosive = {
bulkheads: 1 - ship.bulkheads.m.getExplosiveResistance(),
reinforcement: hullExplDmg,
total: (1 - ship.bulkheads.m.getExplosiveResistance()) * hullExplDmg,
res: 1 - hullExplDmg
bulkheads: armourExplDmg,
reinforcement: armourReinforcedExplDmg - armourExplDmg,
total: armourReinforcedExplDmg,
res: 1 - armourReinforcedExplDmg
};
let armourKinDmg = diminishDamageMult(0.7, 1 - ship.bulkheads.m.getKineticResistance());
let armourReinforcedKinDmg = diminishDamageMult(0.7, (1 - ship.bulkheads.m.getKineticResistance()) * hullKinDmg);
armour.kinetic = {
bulkheads: 1 - ship.bulkheads.m.getKineticResistance(),
reinforcement: hullKinDmg,
total: (1 - ship.bulkheads.m.getKineticResistance()) * hullKinDmg,
res: 1 - hullKinDmg
bulkheads: armourKinDmg,
reinforcement: armourReinforcedKinDmg - armourKinDmg,
total: armourReinforcedKinDmg,
res: 1 - armourReinforcedKinDmg
};
let armourThermDmg = diminishDamageMult(0.7, 1 - ship.bulkheads.m.getThermalResistance());
let armourReinforcedThermDmg = diminishDamageMult(0.7, (1 - ship.bulkheads.m.getThermalResistance()) * hullThermDmg);
armour.thermal = {
bulkheads: 1 - ship.bulkheads.m.getThermalResistance(),
reinforcement: hullThermDmg,
total: (1 - ship.bulkheads.m.getThermalResistance()) * hullThermDmg,
res: 1 - hullThermDmg
bulkheads: armourThermDmg,
reinforcement: armourReinforcedThermDmg - armourThermDmg,
total: armourReinforcedThermDmg,
res: 1 - armourReinforcedThermDmg
};
return armour;
}
@@ -959,3 +960,17 @@ export function timeToDeplete(amount, dps, eps, capacity, recharge) {
}
}
}
/**
* Applies diminishing returns to resistances.
* @param {number} baseDamageMult The base resistance up to which no diminishing returns are applied.
* @param {number} damageMult Resistance as damage multiplier
* @returns {number} Actual damage multiplier
*/
export function diminishDamageMult(diminishFrom, damageMult) {
if (damageMult > diminishFrom) {
return damageMult;
} else {
return (diminishFrom / 2) + 0.5 * damageMult;
}
}

View File

@@ -47,7 +47,16 @@ export default class Module {
if (modifierActions && modifierActions[name]) {
// this special effect modifies our returned value
const modification = Modifications.modifications[name];
if (modification.method === 'additive') {
const multiplier = modification.type === 'percentage' ? 10000 : 100;
if (name === 'explres' || name === 'kinres' || name === 'thermres') {
// Resistance modifications in itself are additive, however their
// special effects are multiplicative. They affect the overall result
// by (special effect resistance) * (damage mult after modification),
// i. e. we need to apply the special effect as a multiplier to the
// overall result and then calculate the difference.
let baseMult = this[name] ? 1 - this[name] : 1;
result = (baseMult - (baseMult - result / multiplier) * (1 - modifierActions[name] / 100)) * multiplier;
} else if (modification.method === 'additive') {
result = result + modifierActions[name] * 100;
} else if (modification.method === 'overwrite') {
result = modifierActions[name];
@@ -59,7 +68,6 @@ export default class Module {
} else {
mod = modifierActions[name];
}
const multiplier = modification.type === 'percentage' ? 10000 : 100;
result = (((1 + result / multiplier) * (1 + mod)) - 1) * multiplier;
}
}

View File

@@ -996,25 +996,6 @@ export default class Ship {
return this;
}
/**
* Calculate diminishing returns value, where values below a given limit are returned
* as-is, and values between the lower and upper limit of the diminishing returns are
* given at half value.
* Commonly used for resistances.
* @param {Number} val The value
* @param {Number} drll The lower limit for diminishing returns
* @param {Number} drul The upper limit for diminishing returns
* @return {this} The ship instance (for chaining operations)
*/
diminishingReturns(val, drll, drul) {
if (val < drll) {
val = drll;
} else if (val < drul) {
val = drul - (drul - val) / 2;
}
return val;
}
/**
* Calculate damage per second and related items for weapons
* @return {this} The ship instance (for chaining operations)
@@ -1306,45 +1287,14 @@ export default class Ship {
*/
recalculateArmour() {
// Armour from bulkheads
let bulkhead = this.bulkheads.m;
let armour = this.baseArmour + (this.baseArmour * bulkhead.getHullBoost());
let modulearmour = 0;
let moduleprotection = 1;
let hullExplRes = 1 - bulkhead.getExplosiveResistance();
const hullExplResDRStart = hullExplRes * 0.7;
const hullExplResDREnd = hullExplRes * 0;
let hullKinRes = 1 - bulkhead.getKineticResistance();
const hullKinResDRStart = hullKinRes * 0.7;
const hullKinResDREnd = hullKinRes * 0;
let hullThermRes = 1 - bulkhead.getThermalResistance();
const hullThermResDRStart = hullThermRes * 0.7;
const hullThermResDREnd = hullThermRes * 0;
// Armour from HRPs and module armour from MRPs
for (let slot of this.internal) {
if (slot.m && (slot.m.grp === 'hr' || slot.m.grp === 'ghrp')) {
armour += slot.m.getHullReinforcement();
// Hull boost for HRPs is applied against the ship's base armour
armour += this.baseArmour * slot.m.getModValue('hullboost') / 10000;
hullExplRes *= (1 - slot.m.getExplosiveResistance());
hullKinRes *= (1 - slot.m.getKineticResistance());
hullThermRes *= (1 - slot.m.getThermalResistance());
}
if (slot.m && slot.m.grp == 'mrp') {
modulearmour += slot.m.getIntegrity();
moduleprotection = moduleprotection * (1 - slot.m.getProtection());
}
}
moduleprotection = 1 - moduleprotection;
this.armour = armour;
this.modulearmour = modulearmour;
this.moduleprotection = moduleprotection;
this.hullExplRes = 1 - this.diminishingReturns(hullExplRes, hullExplResDREnd, hullExplResDRStart);
this.hullKinRes = 1 - this.diminishingReturns(hullKinRes, hullKinResDREnd, hullKinResDRStart);
this.hullThermRes = 1 - this.diminishingReturns(hullThermRes, hullThermResDREnd, hullThermResDRStart);
let metrics = Calc.armourMetrics(this);
this.armour = metrics.total ? metrics.total : 0;
this.modulearmour = metrics.modulearmour;
this.moduleprotection = metrics.moduleprotection;
this.hullExplRes = 1 - metrics.explosive.total;
this.hullKinRes = 1 - metrics.kinetic.total;
this.hullThermRes = 1 - metrics.thermal.total;
return this;
}