# Latest experimental features: tangent and new feature discussion

**URL:** <https://discourse.cataclysmdda.org/t/latest-experimental-features-tangent-and-new-feature-discussion/12750>\
**Category:** The Bunker\
**Created:** [August 2, 2016, 10:18am UTC](https://discourse.cataclysmdda.org/t/latest-experimental-features-tangent-and-new-feature-discussion/12750 "2016-08-02T10:18:05Z")\
**Posts on this page:** 1\
**Showing post:** 48

<div class="post-metadata">

**Author:** ![BorkBorkGoesTheCode](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.cataclysmdda.org/borkborkgoesthecode/32/2343_2.png) [@BorkBorkGoesTheCode](https://discourse.cataclysmdda.org/u/BorkBorkGoesTheCode)\
**Post date:** [September 22, 2016, 4:59am UTC](https://discourse.cataclysmdda.org/t/latest-experimental-features-tangent-and-new-feature-discussion/12750/48 "2016-09-22T04:59:16Z")

</div>

> [@Latest experimental features](https://discourse.cataclysmdda.org/t/latest-experimental-features/5582/1018):
>
> Looks like the guns have been heavily nerfed. My survivor-carbine doesn’t even seem to hit a hulk which is 20 tiles away.

Until calculations are fixed, all guns have a hardcoded 30 tile max range. If you can solve this math problem, please PR a fix on GitHub as soon as possible, it is badly needed. If you can fix the technical problem that forces a hard cap of 60 due to the reality bubble, that would also be needed. The discussions around these subjects are archived in the links; Please refrain from posting complaints, as a technical solution carries more weight:

> <https://github.com/CleverRaven/Cataclysm-DDA/issues/18299>
>
> Known and all, but I'm just leaving it out as a reminder that arbitrary hard cap… isn't the right way to do it.
> A reality bubble cap is necessary, 30 tiles cap isn't.
> 
> Ideas:
> \- Add a deterministic penalty that scales with range. Essentially a cap on accuracy. If high, it would prevent getting hits near cap. If low, it could still allow guaranteed headshots for overpowered characters.
> \- Add a hard low cap on dispersion.
> \- Revise dispersion calculations to prevent near-0 dispersion guns naturally, then nerf all 0 dispersion guns and give them something sensible. Most important parts would be to add some "soft cap" on json dispersion (as in adding a note that "not even futuristic guns should have less than 60 dispersion") and then revising how gunmods affect dispersion. Most likely by making gunmods apply multipliers rather than additions/subtractions. Would also require getting rid (or nerfing) of "accurizing".
> \- Some range-dependent special case. For example, dispersion penalty that is 0 until soft range cap and then rises with range.
> \- Generate \`missed\_by\` with a normal distribution rng.

> <https://github.com/CleverRaven/Cataclysm-DDA/pull/18020>
>
> Our current aiming formula uses total dispersion σ (arc minutes) to calculate th…e tangent of an isoceles triangle formed by the player, intended target and actual target. The relationship is expontential:
> 
> !\[range\](https://cloud.githubusercontent.com/assets/12238606/17642715/acf021e6-6148-11e6-83be-3b9654ebdc1e.png)
> 
> Effective range is defined as the length of either equal side for triangle with vertex angle θ = σ and with a tangent of 0.25 (derived from 50% chance of \`accuracy\_goodhit\`).
> 
> Total dispersion is calculated as \`σ = W + P + R\` where:
> \- \`W\` is the constant sum of the weapon and ammo values
> \- \`P\` is determined from player skill
> \- \`R\` is current effective recoil
> 
> If we intend for \`MAX\_RANGE\` of 30 the usable values for constant \`W\` fall within the range \[100,600\]:
> 
> !\[scaled\](https://cloud.githubusercontent.com/assets/12238606/17642722/2c1d8576-6149-11e6-84da-965ef2a21570.png)
> 
> Aiming reduces \`R\` so the distance between \`MIN\_RECOIL\` and effective \`sight\_dispersion\` controls how much range improves with aiming (how far left you move on the above graph).
> 
> The current range of \`P\` is \[0-250\] dependent both upon \`marksmanship\` and relevant weapon skill. Reducing \`P\` also results in moving left on the graph with the effects dependent upon σ from other sources: low \`P\` has much more effect if \`W\` is also low.
> 
> In other words player skill (P) is only relevant for already accurate weapons and should be balanced around these:
> 
> | item | W + Rmin (MoA) | Range at P0 | Range at P5 |
> | --- | --- | --- | --- |
> | Glock 19 | 360 + 90 = 450 | 5 | 6 |
> | R700+scope | 30 + 0 = 30 | 12 | 22 |
> 
> If we change \`P\` to be dependent only upon \`marksmanship\` (in linear proportion) we can decide on the range \[P0,P10\] based upon \`Rmin\` and \`W\`.
> 
> Currently \`Rmin\` is zero when using the the \`rifle\_scope\` after maximum aiming at \`PER 10\` and there is no reason to change this. We can also presume P10 (maximum \`marksmanship\`) is zero.
> 
> Knowing this we define an accurate rifle as \`W=120\` which at \`P10\` and \`Rmin\` gives an effective range of 29. If we remove the scope and use iron sights we might expect a reduction in range of at least 50% - this would be \`σ=240\` based on an increase from \`Rmin=0\` to \`R=120\`.
> 
> If we then define a typical rifle as \`W=180\` the following applies:
> 
> | Item | Iron sights (120) | Rifle scope (0) |
> | --- | --- | --- |
> | Typical rifle (180) | 12 | 19 |
> | Accurate rifle (120) | 14 | 29 |
> 
> These values are reasonable - adding a better sight to a typical rifle helps but the combination cannot be used as an alternative to the pairing of an accurate rifle with good sights.
> 
> We need to ensure that the above relationship holds true for all values of P. If we propose a linear range for P of \[0,100\] then the following apply:
> 
> | Item | P0 | P5 | P10 |
> | --- | --- | --- | --- |
> | Typical rifle + iron sights (300) | 12 | 10 | 9 |
> | Accurate rifle + iron sights (240) | 14 | 12 | 10 |
> | Typical rifle + rifle scope (180) | 19 | 15 | 12 |
> | Accurate rifle + rifle scope (120) | 29 | 20 | 16 |
> 
> We now arrive at the following definitions:
> \- \`marksmanship\` is the ability to use accurate weapons and sights
> \- The range of levels is \[0,10\] with P having the inversely proportional range \[100,0\]
> \- default sights are iron sights with \`Rmin=120\`

> <https://github.com/CleverRaven/Cataclysm-DDA/pull/17962>
>
> \### Overview
> 
> Subset of #17712 that provides:
> \- A unit test validating \`player::…gun\_engagement\_range\`
> \- R script for producing aiming graphs
> \- Initial algorithm changes
> 
> The below is produced using the R graphing script:
> \- Uses the \`S1\` definition for a survivor (all stats 8, all skills 4) wearing light survivor gloves + mask.
> \- Weapons are loaded with default ammunition (\`9mm\`, \`223\` and \`270\`)
> \- \_Effective range\_ is defined as 50% chance of \`accuracy\_goodhit\`
> \- Chance and accuracy scale linearly with range (at half the range you have twice the accuracy)
> \### Initial status
> \- \*\*Aiming is irrelevant\*\* (slope of curve)
> a rifle scope reaches full aim after 2 turns and gains you only a single extra tile
> \- \*\*Weapon dispersion is irrelevant\*\* (y-intercept)
> a highly accurate rifle (σ=30) and an inaccurate pistol have (σ=380) differ by only two tiles
> \- \*\*Maximum range is both too low and too uniform\*\* (zenith of slopes)
> rifle with scope is only 50% better than pistol and both are useless apart from at point-blank range
> 
> !\[output\](https://cloud.githubusercontent.com/assets/12238606/17466245/3c5b01ce-5d03-11e6-8a14-e93e1fa4e1bc.png)
> \### Increase effect of aiming
> \- A 400% increase in \`MIN\_RECOIL\`to 600 results in a proportional increase in aiming time
> \_eg.\_ turns required to achieve maximum aim with \`ar\_15\` increases by 450% from 1 to 4
> \- Initial range (y-intercept) is worse, maximum range (slope zenith) is unaffected
> \- \*\*Weapon \`aim\_speed\` is irrelevant\*\*
> \`glock\_19\` has half the \`aim\_speed\` (4) of \`ar15\` (8) but their curves are identical
> 
> !\[output\](https://cloud.githubusercontent.com/assets/12238606/17466252/805fad0c-5d03-11e6-9862-4412e1ed9bff.png)
> \### Aim speed differs by weapon
> 
> \`aim\_speed\` has only trivial effect in \`Character::aim\_per\_time\`. The following implementation is both simpler and produces much better results.
> 
> \`\`\`
> int Character::aim\_per\_time( const item& gun, int recoil ) const {
> int aim = std::max( 1, 10 - gun.aim\_speed( recoil ) ) \* 3.2;
> return std::max( std::min( aim, recoil - gun.sight\_dispersion( recoil ) ), 0 )
> }
> \`\`\`
> \- Pistols and SMG's now aim faster than rifles
> \- Further improvements would require \`JSON\` changes (probably rescaling \`aim\_speed\`)
> 
> !\[output\](https://cloud.githubusercontent.com/assets/12238606/17466274/1255681e-5d04-11e6-80e9-068fd1bc46ec.png)
> \### Increase effect of weapon stats
> \- \*\*Player skills have too much effect\*\*
> from nil to maximum skill is Δσ=600, whereas from a pistol to a rifle is typically Δσ=300.
> \- \*\*\`markmanship\` has too little effect\*\*
> only 25% of player dispersion results from \`marksmanship\`
> 
> Considering few players will reach \`marksmanship 10\` and even fewer will max out a ranged skill we need to reduce the effect whilst still granting a bonus for each successive level. The following works well reducing both the overall effect and making \`marksmanship\` twice as important as weapon skill:
> 
> \`\`\`
> int Character::skill\_dispersion( const item& gun ) const
> {
> if( weapon\_lvl \< 10 ) {
> dispersion += 5 \* ( 10 - lvl );
> }
> if( marksmanship\_lvl \< 10 ) {
> dispersion += 10 \* ( 10 - marksmanship\_lvl );
> }
> }
> \`\`\`
> 
> !\[output\](https://cloud.githubusercontent.com/assets/12238606/17466284/6171cba4-5d04-11e6-9e9e-169c40abe3f0.png)
> \### Drop excessive penalty from stats
> \- Stat penalties via \`ranged\_dex\_mod()\` and \`ranged\_per\_mod()\` were implemented when character generation encouraged Min-Maxing and most characters had stats of 12
> \- Currently an average survivor has a penalty of σ=120 with the lowest possible penalty being σ=90
> \- If we drop the penalty level to 8 a typical players doesn't receive a penalty \*\*except\*\* when subject to pain or other stat modifying effects.
> \- Later we could consider applying a non-uniform penalty so more difficult shots required better stats
> 
> !\[output\](https://cloud.githubusercontent.com/assets/12238606/17466288/7f56faae-5d04-11e6-87af-75bfedb50a49.png)
> \### Summary
> \- Although later JSON changes will be required the major problem is the algorithms. Fortunately the above fixes are not especially intrusive and significant gains can be made \*\*without\*\* rewriting the aiming subsystem.
> \- Rescaling of JSON data can be done once the above changes are made and after further unit tests are devised. These should specify the expected range for suitable test items under specific circumstances. \*\*Suggestions as to such tests are welcomed\*\*

> <https://github.com/CleverRaven/Cataclysm-DDA/issues/17643>
>
> \### Summary
> 
> \*\*Effective range of guns is too low and unaffected by weapon type,… skill, gunmods or aiming\*\*
> 
> If we define effective range as a 50% chance of a \_good hit\_ on the first shot then effective range for the following guns used at different stages of the game is:
> 
> | item | early | mid | late |
> | --- | --- | --- | --- |
> | Glock 19 | 3 | 3 | 3 |
> | MP5 | 3 | 3 | 3 |
> | AR-15 | 4 | 4 | 4 |
> 
> This explains why in DDA everyone walks around with a shotgun and a big handgun and engages targets at point-blank range. Rifles in particularly are especially useless.
> 
> The algorithm (with code sources) is set out below or otherwise skip to \*\*Plan\*\*.
> \### Proof
> 
> Dispersion (σ) is expressed in minutes of arc and is the sum of penalties from
> the player and their weapon. Player penalties are calculated as follows:
> 
> \`\`\`
> \# Weapon and marksmanship skill 
> (10 - WEAP) \* 45 # Character::skill\_dispersion()
> (10 - GUN ) \* 15 # Character::skill\_dispersion()
> 
> \# Player stats
> (12 - DEX) \* 15 # Character::ranged\_dex\_mod()
> (12 - PER) \* 15 # Character::ranged\_per\_mod()
> 
> \# Clothing encumbrance
> EYES \* 6 # player::get\_weapon\_dispersion()
> HANDS \* 6 # player::get\_weapon\_dispersion()
> \`\`\`
> 
> An additional penalty applies for recoil. The default is \`MIN\_RECOIL\` of 150
> with lower values achieved by aiming and higher values resulting from recoil.
> 
> We can calculate player dispersion (σ) for some typical survivors:
> 
> | | description | GUN | WEAP | DEX | PER | EYES\* | HANDS^ | Pσ |
> | --- | --- | --- | --- | --- | --- | --- | --- | --- |
> | S1 | early game | 2 | 2 | 8 | 8 | 5 | 0 | 630 |
> | S2 | mid game | 4 | 4 | 8 | 8 | 10 | 5 | 570 |
> | S3 | late game | 6 | 6 | 9 | 9 | 15 | 10 | 510 |
> 
> \`\*\` safety goggles, light survivor mask, heavy survivor mask
> \`^\` fingerless leather gloves, light survivor gloves, survivor gloves
> 
> Weapon dispersion (Wσ) is simply the sum of the gun and ammo dispersion:
> 
> | | description | GUN | AMMO | Wσ |
> | --- | --- | --- | --- | --- |
> | G1 | Glock 19 | 240 | 140 | 380 |
> | G2 | MP5 | 150 | 140 | 290 |
> | G3 | AR-15 | 5 | 80 | 85 |
> | G4 | 700NX + scope | 60 | 15 | 75 |
> 
> Chance to hit (k) is calculated in \`Creature::projectile\_attack\` as:
> 
> \`\`\`
> σ = Pσ + Wσ + recoil 
> t = π / 180 / 60 \* 0.745
> k = range \* σ \* t
> \`\`\`
> 
> Excluding monster dodges this is applied in \`Creature::deal\_projectile\_attack\`:
> 
> | k | result | multiplier |
> | --- | --- | --- |
> | \< 0.1 | headshot | 2.45 - 3.35 |
> | \< 0.2 | critical | 1.75 - 2.30 |
> | \< 0.4 | good hit | 1.00 - 1.50 |
> | \< 0.6 | | 0.50 - 1.00 |
> | \< 0.8 | grazing | 0.00 - 0.25 |
> 
> Dispersion is applied randomly so resuming an even distribution the typical
> effective dispersion (x̄σ) will be half and is calculated as follows:
> 
> \`\`\`
> x̄σ = ( Pσ + Wσ + recoil ) / 2
> \`\`\`
> 
> The below shows average dispersion (x̄σ) for some combinations:
> 
> | | description | Wσ | recoil\* | S1 | S2 | S3 |
> | --- | --- | --- | --- | --- | --- | --- |
> | G1 | Glock 19 | 380 | 150 | 579 | 550 | 525 |
> | G2 | MP5 | 290 | 150 | 536 | 506 | 476 |
> | G3 | AR-15 | 85 | 150 | 432 | 402 | 372 |
> | G4 | 700NX + scope | 75 | 0 | 352 | 322 | 292 |
> 
> \`\*\` G1-G3 \_'from the hip'\_ whereas G4 is after maximum aiming
> 
> If we define effective range as a 50% chance to yield a good hit (k\<0.4) on the
> first shot each of the following combinations has the following effective ranges:
> 
> | | description | S1 | S2 | S3 |
> | --- | --- | --- | --- | --- |
> | G1 | Glock 19 | 3 | 3 | 3 |
> | G2 | MP5 | 3 | 3 | 3 |
> | G3 | AR-15 | 4 | 4 | 4 |
> | G4 | 700NX + scope | 5 | 5 | 6 |
> 
> These values are of course all (much) lower on subsequent shots due to the effects of \`recoil\`. I've included \`G4\` as it illustrates both gunmods and aiming having very little overall effect.
> \### Plan
> 
> Comments as to the following or alternative suggestions:
> \- \`pistol\` and \`shotgun\` are already well balanced having both limited range and being reasonably controllable in \`semi-auto\` mode.
> \- \`smg\` needs a small increase in range and a meaningful ability to use \`auto\` mode within this range.
> \- \`rifle\` needs an increase in range relative to all of the other groups
> \- Additional \`sights\` need to have more of an effect.
> \- Skill should provide more of an effect than just offsetting the inevitably better (and usually higher encumbrance) clothing that a player wears.
> \### Implementation
> 
> TODO

> <https://github.com/CleverRaven/Cataclysm-DDA/pull/17656>
>
> Follows #17643 and intentionally does \*\*not\*\* adjust balance but provides a fram…ework for doing so.
> 
> Firstly some minor refactoring of the code to use standard trigonometric functions (ad7bc2b). We seem to use varying definitions of the accuracy levels so a start is made in 33d46b7 to standardise these. There is one behavioral change in that the full range \[0-1\] is now considered a hit.
> 
> With one exception (corrected in 79617ca) effective recoil is uniformly distributed from 0 to maximum and this is exploited to allow the inverse calculation in \`player::gun\_effective\_range\`. This function allows you to determine at what \`range\` a player has a given \`chance\` of achieving a degree of \`accuracy\`.
> 
> The skeleton of a unit test is provided with the intention of extending it to include cases along the lines of \_9mm pistol should have a 50% chance of a good hit at 3 tiles after 1 turn of aiming\_.
> 
> The stats dumper can now export various effective ranges for addressing future overall balance and finding outliers. The definition of a standard survivor is contained there (8/8/8/8 stats, 4/4 skills with relevant kit) and is supposed to represent the typical mid-game survivor. I don't think it needs much adjustment but if anyone feels strongly that could be done.
> 
> Less well defined is effective range displayed to the player. I've dropped the previous \`range\` field from \`item::info\` as its useless to the point of completely misleading. For example an AR-15 does not have a range of even close to 36.
> 
> Instead I've defined effective range as \_50% chance of good hit spanning from nil to maximum aim\_ which is a much more useful metric. Support is included for comparing between weapons and the debug menu provides a useful way of determining how various factors affect it. For example adding adding a scope, increasing marksmanship etc.
> 
> Note this isn't the maximum absolute range (although it is constrained by it) and it isn't to say guns aren't usable beyond their effective range. It does however provide a good indication where you have at least a better than average chance of scoring a hit. It is my intention to update turrets and NPCs to consider effective range as both will spam ammo at targets they have no realistic chance of hitting.
> 
> EDIT: Note \`player::gun\_effective\_range\` was later renamed \`\`player::gun\_engagement\_range\`

---

_[View the full topic](https://discourse.cataclysmdda.org/t/latest-experimental-features-tangent-and-new-feature-discussion/12750)._
