Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Weakpoints: Adding Skill To The Hit Chance Equation #51482

Closed
Joshua-Chin opened this issue Sep 9, 2021 · 9 comments
Closed

Weakpoints: Adding Skill To The Hit Chance Equation #51482

Joshua-Chin opened this issue Sep 9, 2021 · 9 comments
Labels
Game: Balance Balancing of (existing) in-game features. Mechanics: Effects / Skills / Stats Effects / Skills / Stats <Suggestion / Discussion> Talk it out before implementing

Comments

@Joshua-Chin
Copy link
Contributor

Summary

We should create a formula for the probability of hitting a weak point. The formula should include the attacker's skills, stats, and proficiencies.

Background

Monsters now have weak points! For example, a zombie's head is less armored than the rest of their body. Currently, the chancing of hitting a weak point is constant. A complete novice has the same chance of hitting the eye as a world-class master.

Scenarios

We should establish a set of reasonable scenarios for balance purposes. In other words, we should be able to fill in the blanks for:

An unskilled fighter has a X% chance of hitting a zombie's eye (unskilled + hard to hit)
An unskilled fighter has a X% chance of hitting a fat zombie's leg (unskilled + easy to hit)
A skilled fighter has a X% chance of hitting a zombie's eye (skilled + hard to hit)
A skilled fighter has a X% chance of hitting a fat zombie's leg (skilled + easy to hit)

Thoughts and Ideas

This section contains several thoughts about implementing a hit chance formula.

Skill factors

The formula should consider the following factors of the attacker:

  • Combat Skill (Melee / Marksmanship)
  • Weapon Skill (Blunt / Shotgun / etc.)
  • Dexterity
  • Perception
  • Proficiency

We can define a single "Effective Skill" as a linear combination of the factors. For example,

Skill = (Combat + Weapon) / 2 + Dex / 8 + Per / 8 + 2 (Basic Prof) + 4 (Prof)

Modifying the Coverage

The hit chance can be a function of the effective skill and base coverage. Here, we propose 3 approaches to modifying the coverage based on the effective skill:

Addition

In this approach, we apply a monotonic function to the skill, and add it to the coverage.

Hit Chance = Coverage + g(Skill)

With this approach, skill has a large impact on the probability of hitting small weakpoints. For example, adding a 5% skill bonus to a 1% coverage weak points yields a 6% hit chance.

Multiplication

In this approach, we apply a monotonic function to the skill, and multiple it with the coverage.

Hit Chance =  Coverage * (1 + g(Skill))

This approach preserves the hit ratios between the weak points. For example, the ratio between eye strikes and face strikes would always be 1:3, regardless of skill level.

Difficulty Parameter

In this approach, we obtain a "difficulty" parameter for each weak point. This can either be derived from the coverage, or specified in the JSON. The "difficulty" parameter would severely dampen the effects of skill, if skill < difficulty. For example

Hit Chance = Coverage + max(0, skill - difficulty)

This approach lets contributors fine tune their weak points, but may require them to specify an additional parameter. Alternatively, we would need to determine a function for difficulty based off coverage.

@Joshua-Chin Joshua-Chin added Game: Balance Balancing of (existing) in-game features. <Suggestion / Discussion> Talk it out before implementing Mechanics: Effects / Skills / Stats Effects / Skills / Stats labels Sep 9, 2021
@Joshua-Chin
Copy link
Contributor Author

Migrated from this discussion for better project tracking.

@I-am-Erk
Copy link
Member

I-am-Erk commented Sep 9, 2021

Some factors I want to consider in a formula include:

  • ranking weak points by how desirable they are to hit, and having your intelligence, perception, and proficiency with this monster downgrade the lower value weak points so you're less likely to hit them, and/or upgrade the juicy ones
  • having your weapon type play a role - melee vs ranged, and for melee, line or point type attack, plus other to-hit factors

@Joshua-Chin
Copy link
Contributor Author

ranking weak points by how desirable they are to hit, and having your intelligence, perception, and proficiency with this monster downgrade the lower value weak points so you're less likely to hit them, and/or upgrade the juicy ones

How about every X points in effective skill lets you re-roll on the weak points table and take the best result. For example, if X=2 and the attacker has 6 skill, then they roll 3 times on the weak points table.

Their probability of hitting the eye (which covers the range [0, 0.01]) would be
1 - (1 - 0.01)^3 = ~3%.

Their probability of hitting the leg (which covers the range [0.1, 0.2]) would be

(1 - (1 - 0.2)^3) - (1 - (1 - 0.1)^3)= ~22%

It's straight forward to extend this to support fractional tries. Harder to hit weak points could be preferred to easier weak points.

having your weapon type play a role - melee vs ranged, and for melee, line or point type attack, plus other to-hit factors

For the melee vs ranged, it could be handled via independent "coverage_melee" and "coverage_ranged" values. Line / point attacks are included in the to-hit factors, which should be added to the effective skill.

The cut/blunt split should also impact the "small enough to hit" calculation. For example, blunt weapons can't hit weakpoints with less than 8% base coverage, and cutting weapons can't hit weakpoints with less than 3% base coverage.

@I-am-Erk
Copy link
Member

I-am-Erk commented Sep 9, 2021

That is a very clever solution I hadn't thought of at all. I would suggest we do a separate variable to count rerolls though, because it should be based on some different stuff.

Number of weak point rolls = (std::round((int-8)/4) + (per-8)/2)) + 1 per applicable proficiency), min. 1

The idea here is that your dexterity and perception and skill determine if you can hit a weak point at all, but it is your wits and knowledge that let you know that hitting the leg in this particular creature isn't as desirable as taking that shot for the elbow joint. IE, the physical ability/speed determines whether or not you can hit a weak point, your mental abilities determine if you're quick thinking enough to choose the best one out of the options you're capable of hitting.

For the melee vs ranged, it could be handled via independent "coverage_melee" and "coverage_ranged" values. Line / point attacks are included in the to-hit factors, which should be added to the effective skill.

The cut/blunt split should also impact the "small enough to hit" calculation. For example, blunt weapons can't hit weakpoints with less than 8% base coverage, and cutting weapons can't hit weakpoints with less than 3% base coverage.

I think our best bet is to have both difficulty and coverage as stats, and have difficulty be the one split by melee, range, and weapon shape. So, coverage determines how much of the enemy the weakpoint covers, which in turn helps us decide using randomness if that part of the enemy is targetable at all. Then, difficulty is used to determine if the tool you have and the skills you have are up to the task of hitting it. An armpit is much easier to hit with a dagger than with a quarterstaff or bow.

I'd suggest we accept the following inputs.

"difficulty": { "default": 4, "melee_point": 3, "ranged": 5 }

So a melee weapon without a defined to_hit line or point will have difficulty 4, all ranged weapons have difficulty 5, line weapons have 4 and point weapons have 3. Ideally we'd allow you to just say difficulty: 4 and have them all the same too, to avoid too much repetition for simpler weak points.

I don't really like the idea of having coverage determine this mysefl.

Also, may I add that I'm glad you joined me on this? It's a real pleasure working with you.

@I-am-Erk
Copy link
Member

I-am-Erk commented Sep 9, 2021

I'm going to give some more focused replies now as I might have a few minutes to finish this off.

We should establish a set of reasonable scenarios for balance purposes. In other words, we should be able to fill in the blanks for:

An unskilled fighter has a X% chance of hitting a zombie's eye (unskilled + hard to hit)
An unskilled fighter has a X% chance of hitting a fat zombie's leg (unskilled + easy to hit)
A skilled fighter has a X% chance of hitting a zombie's eye (skilled + hard to hit)
A skilled fighter has a X% chance of hitting a fat zombie's leg (skilled + easy to hit)

Agree, and I think our new info will require us to add a case for skilled/unskilled character with a weapon appropriate to hit the weak spot and inappropriate to hit it, too, eg hitting a zombie's eye with a dagger, arrow, and quarterstaff.

calculations

I would suggest that we do a calculation like you have specified for skill. However I think we should account for the possibility that coverage might end up exceeding 100%, and create a weighted coverage stat at hit-time, like this:

weighted_coverage = (this_weakpoint_coverage) /  sum( all_weakpoint_coverages ) * 100

where "no_weakpoint" is considered in the calculation as well and has a base coverage of 100%.

Example zombie has weakpoints: eye (cov 1) and head (cov 5).
head weighted_coverage = 5/106 = 4.7%
eye weighted_coverage = 1/106 0.9%
no_weakpoint weighted_coverage = 100/106 94.3%

This has the disadvantage of makign coverage a little counterintuitive when we have large weakpoints, like zombie soldiers and their legs, so we could get more robust and have no_weakpoint start at 100, subtract the value of other weakpoints, but have a minimum 50% or something. I don't think that's really necessary but I am open to debate it... I think the addition of skill and difficulty will smooth that out and I don't want to wind up with a situation where sufficiently skilled archers shoot every single zombie in the eye.

With that, I'd run difficulty like this:

Hit Chance =  [ weighted_coverage * (1 + g(Skill) - Difficulty) ], min 1

except the hit chance for no_weakpoint, which just remains equal to its weighted_coverage.

Then we create a list of hit chances, and roll a random number from 0 to the sum of all hit chances, and whatever it comes to is what you hit.

EDIT: for the rerolls option above, too, we should only allow rerolls if the first hit is to a weakpoint. If the first hit goes to no_weakpoint, no rerolls. After the first roll we drop that rule and treat no_weakpoint the same as a weakpoint, so it would get evaluated for possibly being optimal. This is just to stop the rerolls from boosting your chance to hit a weakpoint at all, which they should not do.

IE: Character with 3 rerolls:

roll 1: eye
roll 2: no-weakpoint
roll 3: head
--> evaluate each of these three for effect and pick the best one
roll1: no_weakpoint
break

@I-am-Erk
Copy link
Member

Another thought that only tangentially relates to this and is probably for another pass, but at some point I'd like to be able to toggle an "aim for weakpoints" option in the Aim menu, and possibly while making melee attacks as well. I would suggest that in the paradigm I outlined above, this would apply a penalty to your to-hit roll, and if you hit, would reduce the weight of no_weakpoint by half and give you another reroll on which weakpoint you hit.

@Joshua-Chin
Copy link
Contributor Author

We're certainly on the right track, but I think there are a few small improvements we can make.

Properties

There are several properties that the hit chance algorithm should satisfy:

  1. The probability of hitting the N "best" weakpoints increases as skill increases, for all values of N.
  2. The chance of hitting any particular weak point is nonzero, regardless of skill. This includes no_weakpoint.
  3. Adding or removing a weak point does not effect the hit chance of "better" weak points. (E.G. Adding a large gash to a zombie's armor should not reduce the chance of hitting its head.)

The current proposal satisfies properties (1) and (2), but violates (3) in the weighed_coverage step.

Calculations

the physical ability/speed determines whether or not you can hit a weak point, your mental abilities determine if you're quick thinking enough to choose the best one out of the options you're capable of hitting.

I agree that quick thinking should play a role in the calculation. However, I'm not sure if have two separate steps is the best way. A dexterous character with no idea what to hit won't do better than random chance. Likewise, a knowledge character with minimal dexterity will do little better than random chance (if they manage to hit in the first place). Instead, we can either multiply or add the physical and mental abilities together. Then, we proceed with making N roll (based on the combined skill) and taking the highest.

The value skill - difficulty could still be a multiplier for the base coverage. However f(skill - difficulty) would be restricted to the range [0, 1]. In other words, the difficulty value represents the monster's ability to defend/protect a particular weak point from harm, reducing its base coverage.

@I-am-Erk
Copy link
Member

I don't mind this closing but we do still need at least some differentiation between "chance" and "difficulty"at some point.

@Joshua-Chin
Copy link
Contributor Author

This discussion focused on the skilled-based portion of the formula. To keep things organized, I opened a separate discussion for monster defenses, like difficulty (#51915).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Game: Balance Balancing of (existing) in-game features. Mechanics: Effects / Skills / Stats Effects / Skills / Stats <Suggestion / Discussion> Talk it out before implementing
Projects
None yet
Development

No branches or pull requests

2 participants