If you go to the “New Formula” tab, columns C-J have the basic numbers about the weapon, K-N calculate the hit_roll and crit values, and O-P calculate the average damage per attack per armor, crits, and rapid strikes.
If you look at src/melee.cpp and related bits of code (and no, there’s no synopsis, I’m afraid), you’ll see that a hit occurs when a randomly generated number on a normal distribution with a standard deviation of 25 and a mean value of 5 * (hit_roll - target's dodge) is greater than 0. Column S calculated the number of hits per 1000 attempts against the monster with the Dodge value in S4. Column T is the % of hits that are criticals, and columns U and V are damage per hit for non-critical and critical hits. Column W is the number of hits that are rapid strikes (assuming that rapid strikes occur 3/4ths of the time with a weapon with no other techniques, and (3+number of techs)/(4+number of techs) for weapons with more than 1 technique. Columns X and Y are rapid strike and rapid strike critical damage. Finally, Column Z
calculates average damage per 100 moves by multiplying the number of non-rapid strikes by the critical adjusted non-rapid strike damage and adding product of the number of rapid strikes and the critical adjusted rapid strike damage and dividing by the total number of moves used to perform all strikes, and then multiplying the results by 100 to get the average injury per 100 strikes.
Columns AB-AI and AK-AR repeat the process for survivor and smoker zombies, respectively. Column A averages the damage of the three targets, and multiplies by a fudge factor for the weapon’s reach: 1.5 for reach 2 or 1.75 for reach 3.
Any suggestions for improvement would be appreciated, as well as ways to refine it.
Please take my lack of feedback as, “you’ve put more thought into this than I have now”, rather than a lack of approval
To the extent that I’ve reviewed the spreadsheet it looks rational and more nuanced than the existing function, my main thing is I want to wedge some sanity checks into the unit tests to avoid future regressions, which I’ll happily base on what you come up with.
Ok, the cpp’s look pretty easy to read through and the combat math isn’t generally too crazy, so creating a discrete analysis function in a spreadsheet that would boil a weapon’s stats down to an expected damage/move against a given target dodge/armor profile doesn’t look too hard?
Made some progress last night - To hit wasn’t a problem, but we’ll see where damage goes. Can maybe get something together this evening - as long as I focus on just melee and ignore most of the special cases. Would like to find a solution that doesn’t require building and maintaining tables.
Oh, I do almost all my work in spreadsheets, for exactly that reason. I’m not really much of a coder - enough to read and putter around - but I do a lot of excel and google sheets.
When I say I don’t want to maintain tables, I mean I don’t want whatever analysis function we end up with to rely on big lookup tables unless it really needs it.
For my part I’ll have oodles of tables just to amuse myself.
Wow. Google sheets doesn’t support sorting or filtering named ranges. That’s disappointing.
Ah well. Anyway, I looked over your sheets and given what they’re trying to accomplish they seem quite sufficient if you want to plug fixed comparitive values into weapons and have NPC’s wield the ‘best’ one - probably with a bit of extra weighting for the NPC’s skills tacked on to prefer weapons they are already competent with.
The other approach you could take altogether would be to write an ‘evaluation’ path alongside the core attack logic that lets the NPC execute an imaginary attack with a weapon they are considering against an enemy, with a flag to prevent anything from actually happening.
Aside from preventing effects you’d want to convert a few of the results along the way into %'s and Averages rather than hard outcomes and then spit out the final value of that - much like you’re doing in the spreadsheet, but with live values.
This has the advantage of being built into the game at a fundamental level so that NPC’s can always evaluate weapons on their own as they are added to the game, AND they can specifically choose weapons that are appropriate to both their own stats and condition, as well as those of the enemy they are fighting - but it adds a base layer of complexity to the main combat resolution path because you need to maintain the evaluation functions alongside the main outcome functions.
The actual process cost of doing this sort of evaluation shouldn’t really be that high, as long as the NPC’s don’t spam it unnecessarily, and stick to only evaluating actual melee weapons - unless they have none, in which case they may have to fall back to evaluating their pasta extruders and such…
All that being said, the current charts you’re working with seem to present a reasonably straightforward evaluation, and they are useful for doing game balance work as well, so I’d go with that as the first solution and think about a live combat path evaluation function for the future.
We already have 90% of the live evaluation code and I plan to add the rest at some point. Weapons are going to be approximately balanced based on the spreadsheet, so we can look at the numbers have not have vast discrepancies between similar weapons, but in play, an NPC is going to evaluate a weapon based on their own stats and skills - so a ST 5 NPC might not that think a lucern hammer is all that good and prefer a combat knife.
My real concern remains: is average damage per 100 moves against a zombie soldier, a zombie survivor, and a zombie smoker a good measure of a weapon’s general utility?
My second concern remains: should a weapon’s BLOCK ability count for it’s rating, or is effective damage the only concern?
This is just my 2 cents, for whatever it may be worth, but I’d think damage only is the way to go. Granted some weapons were built with defense in mind, but for the most part they’re designed for ease of use and the destruction they can dole out. Anything defense related is secondary. Otherwise you’ll have to start figuring for spiked shields or those pointy German helmets etc.
As we sort of discussed before I think block shouldn’t be factored in at this time. I don’t feel it appreciably benefits the user in combat over other weapons that lack it.
If for example we did a “live test” and the damage on the weapons were the same, I doubt the block of the weapon would be the difference between living and dying against a zombie soldier, since the far more important factor is if you can actually damage it in turn, otherwise it just takes slightly longer to kill you.
Currently NPCs favor attacks over tactical retreats as well, so with that in mind the damage, ability to hit, and armor penetration are the main things that are going to make a difference in their armaments.
The moment you start trying to take defense into account, you kind of go into a much more extensive form of evaluation where you have an NPC trying to judge Time To Kill vs. Time To Survive, and that’s much more complex - especially when in order for that evaluation to be useful, it would have to take into account not just your own stats, or one opponent, but the general field.
You could give a weapon some generic flat bonus for having medium or high block, but I’d weight it lightly, given that block is a modest benefit currently - just so that given two nearly equivalent weapons the NPC will prefer one with block over one without.
Another week or two of hammering at the spreadsheet and I’ve got this proposal for rebalancing one-handed swords:
Item Name
Item ID
OVal
Acc
Moves
Bash
Cut
Stab
NVal
Acc
Moves
Bash
Cut
Stab
NVal
arming sword (fake)
arming_sword_fake
18.09
2
108
14
2
0
11.39
2
108
13
2
0
10.65
arming sword (inferior)
arming_sword_inferior
25.13
1
142
12
25
0
16.34
1
142
25
8
0
15.39
arming sword
arming_sword
34.33
1
119
14
31
0
25.48
2
119
10
30
0
24.20
blade
blade
5.00
-2
86
6
8
0
5.58
-1
86
6
8
0
7.03
broadsword
broadsword
40.67
2
111
8
35
0
29.12
2
111
8
29
0
23.69
broadsword (inferior)
broadsword_inferior
35.61
2
111
7
29
0
23.14
1
111
23
7
0
17.81
broadsword (fake)
broadsword_fake
17.42
2
105
10
2
0
8.67
2
105
12
2
0
9.64
cavalry saber (fake)
cavalry_sabre_fake
17.42
2
95
4
2
0
5.45
1
95
9
2
0
7.93
cavalry saber (inferior)
cavalry_sabre_inferior
5.00
2
95
4
2
0
5.45
0
95
18
7
0
14.78
cavalry saber
cavalry_sabre
41.62
2
100
2
26
0
19.64
1
100
6
28
0
22.03
crude sword
sword_crude
11.78
-1
115
6
14
0
7.70
1
115
6
18
0
12.53
cutlass
cutlass
36.94
2
100
7
27
0
23.68
1
100
8
27
0
22.20
cutlass (fake)
cutlass_fake
16.49
2
103
8
2
0
7.38
1
103
12
1
0
9.43
cutlass (inferior)
cutlass_inferior
34.69
2
100
6
25
0
21.06
0
100
23
7
0
17.39
dao
dao
27.56
2
107
6
18
0
14.78
0
107
7
28
0
18.56
fencing epee
fencing_epee
21.03
2
95
3
0
7
7.18
0
95
3
0
7
5.45
fencing foil
fencing_foil
14.72
2
92
1
0
2
3.73
0
92
1
0
2
2.71
fencing saber
fencing_sabre
18.95
2
91
1
0
6
5.64
0
91
1
0
6
4.21
firebrand (off)
broadfire_off
33.60
1
125
8
35
0
23.77
1
125
8
29
0
19.26
firebrand (on)
broadfire_on
33.60
1
125
8
35
0
23.77
3
125
8
29
0
22.60
jian
jian
36.90
2
110
8
30
0
24.82
2
110
5
31
0
24.07
jian (fake)
jian_fake
16.49
2
103
8
2
0
7.38
2
103
11
2
0
9.00
jian (inferior)
jian_inferior
31.84
2
110
7
24
0
19.02
1
110
21
8
0
17.16
khopesh
khopesh
26.22
1
105
7
19
0
14.90
0
105
16
27
0
23.58
kukri
kukri
37.53
1
84
2
20
0
16.15
0
84
7
26
0
21.60
machete
machete
33.91
2
89
6
20
0
19.45
1
89
6
21
0
18.50
makeshift machete
makeshift_machete
20.21
1
106
4
14
0
10.04
0
106
5
16
0
10.19
makeshift macuahuitl
glass_macuahuitl
20.24
1
116
7
14
0
10.61
0
116
7
14
0
9.17
monomolecular blade
bio_blade_weapon
53.44
3
78
0
36
0
39.51
1
78
0
33
0
30.45
nailboard
nailboard
14.25
1
108
10
0
3
7.32
1
108
10
0
3
0.00
No. 9 (On)
firemachete_on
23.66
1
119
6
20
0
13.26
2
119
6
21
0
15.18
No. 9 (Off)
firemachete_off
23.66
1
119
6
20
0
13.26
0
119
6
21
0
12.06
pair of butterfly swords
butterfly_swords
31.00
2
118
6
26
0
18.70
1
118
7
32
0
22.32
rapier (fake)
rapier_fake
16.76
2
100
4
2
0
5.18
2
100
9
0
2
8.24
rapier (inferior)
rapier_inferior
5.00
2
100
4
2
0
5.18
0
100
18
0
8
14.74
rapier
rapier
38.04
2
105
2
0
29
15.50
1
105
2
0
33
24.33
scimitar (fake)
scimitar_fake
11.89
1
106
6
2
0
5.45
1
106
12
2
0
9.21
scimitar
scimitar
31.66
1
115
6
30
0
20.79
1
115
6
34
0
24.06
scimitar (inferior)
scimitar_inferior
26.79
1
115
5
24
0
15.63
0
115
23
8
0
15.58
scythe blade
blade_scythe
5.00
-2
105
6
8
0
4.57
-1
105
6
8
0
5.76
shishkebab (off)
shishkebab_off
13.74
0
133
4
14
0
6.90
0
133
4
14
0
6.90
shishkebab (on)
shishkebab_on
13.74
0
133
4
14
0
6.90
2
133
4
14
0
6.90
survivor machete
survivor_machete
41.73
2
90
6
20
0
19.24
1
90
6
21
0
18.30
sword bayonet
sword_bayonet
39.07
1
108
8
25
0
18.82
1
108
7
29
0
21.78
sword cane
sword_cane
5.00
0
94
2
0
25
10.13
0
94
2
0
25
17.02
wakizashi (fake)
wakizashi_fake
19.33
2
98
7
2
0
7.14
1
98
8
2
0
7.02
wakizashi
wakizashi
36.38
1
102
3
24
0
16.54
1
102
2
30
0
21.27
wakizashi (inferior)
wakizashi_inferior
35.20
2
102
3
20
0
15.19
0
102
17
7
0
13.10
xiphos
sword_xiphos
29.35
2
110
8
20
0
16.84
110
8
28
0
21.04
OVal is the current NPC evaluation function, and the first set of columns are the weapon’s current stats, ending with NVal, which is the current weapon’s stats using my new NPC evaluation formula.
The second set of stats is what I’m proposing to use, along with the NVals for the new stats.
A couple of notes here: I’ve gone through and broken down the grip, length, striking surface, and balance for every weapon in the game and recalculated accuracy from that. Most “real” swords have linear striking surfaces and good balance, but their flaming variants have “every” striking surface when on and neutral balance at all times to account for the balance of the gasoline system. Fake and inferior weapons have neutral balance, and fake weapons upgrade to “any” strike surface because they’re actually fancy clubs. Asian weapons do roughly equivalent damage as European weapons, but Asian weapons are more cutting and European weapons are more bashing - this is not strictly accurate, but it does differentiate them a little.
The target value for 1 handed swords was 24, and 22 for shortswords. Makeshift or improvised weapons were generally set to be roughly equivalent to inferior variants of real weapons. Inferior weapons get 1/2 of the real weapon’s Cut or Stab damage added to their bash damage and the cut or stab damage reduced to 25% of normal; fake weapons have half the bash damage of inferior weapons and their cut or stab damage is reduced to 25% of the inferior weapon. A little arbitrary, but it’s consistent.
The “Comparison” tab of the spreadsheet has all of this color coded to show numbers that were increased or decreased, and the “Raw” tab has the values I used to calculate accuracy if anyone wants to double-check my work.
So much of the discussion that is going on here is both far better researched and in depth than I could meaningfully contribute to, though there is one facet I’m curious about being brought up. Having watched a few ‘pop-culture medieval’ videos, one aspect of curved blades in particular I’ve seen is the concept of ‘edge-alignment’ being much easier to achieve with a curved weapon. As in, the curve of the blade and the motion of slashing makes an accurate cute more attainable by someone with less practice.
This seems to me like it would be attractive to a survivor with low skills, rather than using a straight edged weapon that could (according to some) more easily roll during the swing and hit with a less aligned edge. Once sufficient skill with a weapon is attained, that advantage obviously matters very little, but it was something that I didn’t notice being brought up in the discussion thus far.
RE: Block rating and the value calculation, perhaps damage per 100 turn should be calculated in both directions. I’d even go so far as to make damage taken weight more than damage dealt, unless the character can reasonably expect to one-shot regular zombies.
I guess what I’m saying is that in all these NPC decision making calculations, you probably wouldn’t go wrong to lean towards a preference for survivability over literally any other factor. Block certainly improves your survivability, especially if you don’t really want to fight (I’d assume most people wouldn’t).
edit RE: test fights, I’d add a small mob of zombies, 3 to 5. How often do you fight a single zombie?
That’s going to be below the level of resolution in the game. The accuracy categories are very broad and don’t account for marginal differences like that.
An NPC’s damage taken is going to depend on armor and Dodge. There’s a place for evaluating Turns to Kill and Delta Turns Till Death (see https://github.com/CleverRaven/Cataclysm-DDA/issues/25687) but it’s going to really complicate weapon evaluation. Maybe it’s reasonable that you prefer knives if you’re unarmored and sledgehammers if you’re in plate, but it works out to 45 scenarios:
high armor zombie, mixed dodge/armor zombie, high dodge zombie
high accuracy and high damage zombie, low accuracy and high damage zombie, middle accuracy and middle damage zombie, high accuracy and low damage zombie, low accuracy and low damage zombie
high armor NPC, mixed armor and dodge NPC, unarmored but dodgy NPC
Very fair, just thought it was worth asking about.
On the whole offensive vs survivable side of things, I don’t think that offensive ability contributing to defensive play can be understated. A zombie that’s ‘dead’ again can’t keep attacking, and given how NPCs don’t take terrain advantages into account, killing something, especially one of a group of zeds, keeps the incoming damage down.
Perhaps for that reason biasing the value towards particularly tough to kill enemies would be more useful? A high dodge/low armor enemy will eventually be put down with enough attacks against it no matter what, but if you can’t get past the armor of a tanky one you’re gonna die unless you run, especially if you’re wasting attacks on armor when getting swarmed. Like being the giant spider who goes up against a properly armored survivor.
Significantly curved blades can actually be quite awkward for a novice user. While Its true that it remains clear where the edge of the blade is, the problem is that the blade is much more likely to roll due to impacts, especially if it’s not well balanced for combat (such as a makeshift blade might be).
Basically there’s just a lot more physics that can happen with a curved blade in the chaos of melee, and a novice will have a harder time keeping the blade straight, or even keeping their grip on it due to these forces.
The grip on a regular sword is generally not round, it’s oval, and in such a manner that the ‘natural’ grip and swing will tend to bring the edge of the blade to bear. No guarantee, but as a rule I’d start a novice with a relatively short, straight blade, or perhaps gently curved one, such as a katana - but not a dramatically swept blade such as a Scimitar.
Also, it’s important to note that straight blades are usually double edged, which allows a wider range of swing motions, and you can’t get your grip ‘backwards’ - curved blades are always single edged, which is another limitation and potential thing for a novice to get screwed up with in a fight.
Ultimately if you’re looking for NPC behavior that effectively compliments the player character, that’s only really going to work if the player can directly equip and define an NPC follower’s behaviors at a relatively detailed level. The ability to yell commands in battle or to force-equip them with specific armor and weapons in order to complement whatever their role in combat is intended to be.
If the goal is really just about NPC personal effectiveness and survival, their movement behaviors are going to be FAR more important than whether they choose to use a katana or a longsword (as long as they don’t charge into battle with a pasta extruder…). Simply choosing correctly when you’re in a position to stick and fight or when to re-position or run is the deciding survival factor about 95% of the time.