mirror of
https://github.com/EDCD/coriolis.git
synced 2025-12-10 15:15:34 +00:00
Add and use range when calculating weapon effectiveness for damage dealt
This commit is contained in:
@@ -1,6 +1,8 @@
|
|||||||
#2.2.9
|
#2.2.9
|
||||||
* Use SSL-enabled server for shortlinks
|
* Use SSL-enabled server for shortlinks
|
||||||
* Add falloff for weapons
|
* Add falloff for weapons
|
||||||
|
* Use falloff when calculating weapon effectiveness in damage dealt
|
||||||
|
* Add engagement range slider to allow user to see change in weapon effectiveness with range
|
||||||
|
|
||||||
#2.2.8
|
#2.2.8
|
||||||
* Fix issue where filling all internals with cargo racks would include restricted slots
|
* Fix issue where filling all internals with cargo racks would include restricted slots
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { Ships } from 'coriolis-data/dist';
|
|||||||
import ShipSelector from './ShipSelector';
|
import ShipSelector from './ShipSelector';
|
||||||
import { nameComparator } from '../utils/SlotFunctions';
|
import { nameComparator } from '../utils/SlotFunctions';
|
||||||
import { CollapseSection, ExpandSection, MountFixed, MountGimballed, MountTurret } from './SvgIcons';
|
import { CollapseSection, ExpandSection, MountFixed, MountGimballed, MountTurret } from './SvgIcons';
|
||||||
|
import Slider from '../components/Slider';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates an internationalization friendly weapon comparator that will
|
* Generates an internationalization friendly weapon comparator that will
|
||||||
@@ -66,7 +67,9 @@ export default class DamageDealt extends TranslatedComponent {
|
|||||||
predicate: 'n',
|
predicate: 'n',
|
||||||
desc: true,
|
desc: true,
|
||||||
against: DamageDealt.DEFAULT_AGAINST,
|
against: DamageDealt.DEFAULT_AGAINST,
|
||||||
expanded: false
|
expanded: false,
|
||||||
|
range: 0.1667,
|
||||||
|
maxRange: 6000
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +77,7 @@ export default class DamageDealt extends TranslatedComponent {
|
|||||||
* Set the initial weapons state
|
* Set the initial weapons state
|
||||||
*/
|
*/
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
const weapons = this._calcWeapons(this.props.ship, this.state.against);
|
const weapons = this._calcWeapons(this.props.ship, this.state.against, this.state.range * this.state.maxRange);
|
||||||
this.setState({ weapons });
|
this.setState({ weapons });
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,7 +89,7 @@ export default class DamageDealt extends TranslatedComponent {
|
|||||||
*/
|
*/
|
||||||
componentWillReceiveProps(nextProps, nextContext) {
|
componentWillReceiveProps(nextProps, nextContext) {
|
||||||
if (nextProps.code != this.props.code) {
|
if (nextProps.code != this.props.code) {
|
||||||
const weapons = this._calcWeapons(this.props.ship, this.state.against);
|
const weapons = this._calcWeapons(this.props.ship, this.state.against, this.state.range * this.state.maxRange);
|
||||||
this.setState({ weapons });
|
this.setState({ weapons });
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -96,19 +99,37 @@ export default class DamageDealt extends TranslatedComponent {
|
|||||||
* Calculate the damage dealt by a ship
|
* Calculate the damage dealt by a ship
|
||||||
* @param {Object} ship The ship which will deal the damage
|
* @param {Object} ship The ship which will deal the damage
|
||||||
* @param {Object} against The ship against which damage will be dealt
|
* @param {Object} against The ship against which damage will be dealt
|
||||||
|
* @param {Object} range The engagement range
|
||||||
* @return {boolean} Returns the per-weapon damage
|
* @return {boolean} Returns the per-weapon damage
|
||||||
*/
|
*/
|
||||||
_calcWeapons(ship, against) {
|
_calcWeapons(ship, against, range) {
|
||||||
let weapons = [];
|
// Tidy up the range so that it's to 4 decimal places
|
||||||
|
range = Math.round(10000 * range) / 10000;
|
||||||
|
|
||||||
|
let weapons = [];
|
||||||
for (let i = 0; i < ship.hardpoints.length; i++) {
|
for (let i = 0; i < ship.hardpoints.length; i++) {
|
||||||
if (ship.hardpoints[i].m) {
|
if (ship.hardpoints[i].m) {
|
||||||
const m = ship.hardpoints[i].m;
|
const m = ship.hardpoints[i].m;
|
||||||
if (m.getDamage() && m.grp !== 'po') {
|
if (m.getDamage() && m.grp !== 'po') {
|
||||||
|
let dropoff = 1;
|
||||||
|
if (m.getFalloff()) {
|
||||||
|
// Calculate the dropoff % due to range
|
||||||
|
if (range > m.getRange()) {
|
||||||
|
// Weapon is out of range
|
||||||
|
dropoff = 0;
|
||||||
|
} else {
|
||||||
|
const falloff = m.getFalloff();
|
||||||
|
if (range > falloff) {
|
||||||
|
const dropoffRange = m.getRange() - falloff;
|
||||||
|
// Assuming straight-line falloff
|
||||||
|
dropoff = 1 - (range - falloff) / dropoffRange;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
const classRating = `${m.class}${m.rating}${m.missile ? '/' + m.missile : ''}`;
|
const classRating = `${m.class}${m.rating}${m.missile ? '/' + m.missile : ''}`;
|
||||||
const effectiveness = m.getPiercing() >= against.properties.hardness ? 1 : m.getPiercing() / against.properties.hardness;
|
const effectiveness = (m.getPiercing() >= against.properties.hardness ? 1 : m.getPiercing() / against.properties.hardness) * dropoff;
|
||||||
const effectiveDps = m.getDps() * effectiveness;
|
const effectiveDps = m.getDps() * effectiveness * dropoff;
|
||||||
const effectiveSDps = m.getClip() ? (m.getClip() * m.getDps() / m.getRoF()) / ((m.getClip() / m.getRoF()) + m.getReload()) * effectiveness : effectiveDps;
|
const effectiveSDps = (m.getClip() ? (m.getClip() * m.getDps() / m.getRoF()) / ((m.getClip() / m.getRoF()) + m.getReload()) * effectiveness : effectiveDps) * dropoff;
|
||||||
|
|
||||||
weapons.push({ id: i,
|
weapons.push({ id: i,
|
||||||
mount: m.mount,
|
mount: m.mount,
|
||||||
@@ -210,14 +231,23 @@ export default class DamageDealt extends TranslatedComponent {
|
|||||||
return rows;
|
return rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update current range
|
||||||
|
* @param {number} range Range 0-1
|
||||||
|
*/
|
||||||
|
_rangeChange(range) {
|
||||||
|
const weapons = this._calcWeapons(this.props.ship, this.state.against, this.state.range * this.state.maxRange);
|
||||||
|
this.setState({ range, weapons });
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render damage dealt
|
* Render damage dealt
|
||||||
* @return {React.Component} contents
|
* @return {React.Component} contents
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
const { language, tooltip, termtip } = this.context;
|
const { language, onWindowResize, sizeRatio, tooltip, termtip } = this.context;
|
||||||
const { formats, translate } = language;
|
const { formats, translate, units } = language;
|
||||||
const { expanded } = this.state;
|
const { expanded, maxRange, range } = this.state;
|
||||||
|
|
||||||
const sortOrder = this._sortOrder;
|
const sortOrder = this._sortOrder;
|
||||||
const onCollapseExpand = this._onCollapseExpand;
|
const onCollapseExpand = this._onCollapseExpand;
|
||||||
@@ -239,6 +269,27 @@ export default class DamageDealt extends TranslatedComponent {
|
|||||||
<tbody>
|
<tbody>
|
||||||
{this._renderRows(translate, formats)}
|
{this._renderRows(translate, formats)}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<table style={{ width: '80%', lineHeight: '1em', backgroundColor: 'transparent', margin: 'auto' }}>
|
||||||
|
<tbody >
|
||||||
|
<tr>
|
||||||
|
<td style={{ verticalAlign: 'top', padding: 0, width: '2.5em' }} onMouseEnter={termtip.bind(null, 'PHRASE_ENGAGEMENT_RANGE')} onMouseLeave={tooltip.bind(null, null)}>{translate('engagement range')}</td>
|
||||||
|
<td>
|
||||||
|
<Slider
|
||||||
|
axis={true}
|
||||||
|
onChange={this._rangeChange.bind(this)}
|
||||||
|
axisUnit={translate('m')}
|
||||||
|
percent={range}
|
||||||
|
max={maxRange}
|
||||||
|
scale={sizeRatio}
|
||||||
|
onResize={onWindowResize}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
<td className='primary' style={{ width: '10em', verticalAlign: 'top', fontSize: '0.9em', textAlign: 'left' }}>
|
||||||
|
{formats.f2(range * maxRange / 1000)}{units.km}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
</table></span> : null }
|
</table></span> : null }
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ export const terms = {
|
|||||||
PHRASE_SG_RECOVER: 'Recovery (to 50%) after collapse',
|
PHRASE_SG_RECOVER: 'Recovery (to 50%) after collapse',
|
||||||
PHRASE_UNLADEN: 'Ship mass excluding fuel and cargo',
|
PHRASE_UNLADEN: 'Ship mass excluding fuel and cargo',
|
||||||
PHRASE_UPDATE_RDY: 'Update Available! Click to refresh',
|
PHRASE_UPDATE_RDY: 'Update Available! Click to refresh',
|
||||||
|
PHRASE_ENGAGEMENT_RANGE: 'The distance between your ship and its target',
|
||||||
|
|
||||||
HELP_MODIFICATIONS_MENU: 'Click on a number to enter a new value, or drag along the bar for small changes',
|
HELP_MODIFICATIONS_MENU: 'Click on a number to enter a new value, or drag along the bar for small changes',
|
||||||
|
|
||||||
@@ -123,6 +124,7 @@ export const terms = {
|
|||||||
'yaw': 'Yaw',
|
'yaw': 'Yaw',
|
||||||
'internal protection': 'Internal protection',
|
'internal protection': 'Internal protection',
|
||||||
'external protection': 'External protection',
|
'external protection': 'External protection',
|
||||||
|
'engagement range': 'Engagement range',
|
||||||
|
|
||||||
// Modifications
|
// Modifications
|
||||||
ammo: 'Ammunition maximum',
|
ammo: 'Ammunition maximum',
|
||||||
|
|||||||
Reference in New Issue
Block a user