[Modding Tool] Rimworld Weapons Balancer

Started by Bog, August 12, 2014, 05:38:11 PM

Previous topic - Next topic

Bog

What is this?:
This is a little python script made by my genius brother to help me balance weapons in my mods faster.


What exactly does it do?:
You just have to point it to the weapon's .hml file file and it will automatically examine the weapon's stats and do a bunch of calculations for you, then pump out some more useful stats so you can see how the weapon is performing.


What sort of stats?:
Here's an example of what it puts out when targeted at a .hml file with only the Vanilla M-16 in it:

Reading xml file: VanillaWeapon-M-16Rifle.xml
cooldownTicks:    40.0
DamageAmountBase: 7.0
basePrice:        325.0
warmupTicks:      108.0
range:            32.0
accuracyTouch:    0.96
accuracyShort:    0.87
accuracyMedium:   0.77
accuracyLong:     0.64
burstShotCount:   3.0
ticksbetweenburstshots:7.0

Ticks per shot:   56.333333333333336
Shots per second: 1.0650887573964496
Damage per second:7.455621301775147
Power Rating before accuracy: 238.5798816568047

Power Rating: 229.0366863905325
Suggested Silver Value: 458.073372781065


So as you can see, it first of all shows all the basic stats that are visible, cooldown, damage, price, warmup, range, accuracy, and burst fire information.

Then it does some calculations and shows you some extra stuff.

Ticks per shot is found by multiplying the burst shot count by the ticks between burst shots, then adding that figure to the warmup and cooldown, then dividing by the burst shot count. Now you don't have to do all that though, it does it for you.

Shots per second is found by taking 60 and dividing it by the ticks per shot.

Damage per second is found by taking the shots per second and multiplying it by the damage amount base.

Power Rating before accuracy basically just takes the damage per second and multiplies it by the range.

Power rating takes the power rating before accuracy and multiplies it by the largest accuracy figure.

Suggested silver value just multiplies the power rating by 2. Might not be ideal for everybody, but it's about where I want things for my mod. You can always do whatever you want with all this infromation, of course.


How does this balance play out?:

Well here's all the non-incendiary/explosive vanilla Alpha 5 weapon's power ratings:

Thrown Stones: 25
Pila: 74
Short Bow: 78
Great Bow: 109
Pistol: 124
Shotgun: 124
Uzi: 145
Lee-Enfield: 172
Charge Lance: 190
M-16: 229
M24: 240
LMG-15: 264
R4: 312

Minigun: 369
Heavy Charge Blaster: 380

The Minigun and Heavy Charge Blaster both have an extra stat "forced miss radius" that isn't taken into account by the formula because I don't know how it works, exactly.

For the sake of this list I've taken the accuracy value, divided it by the forced miss radius, then multiplied it by the power rating before accuracy value.

Result:

Minigun:
Power Rating without forced miss: 887 (I think this is inaccurate stat in this case)
Power Rating before accuracy: 1123
Accuracy: .79
Forced miss radius: 2.4
Accuracy divided by forced miss: 0.3291666666666667
Power rating with forced miss radius: 369.6541666666667

Heavy Charge Blaster:
Power Rating without forced miss: 1103 (I think this is an inaccurate stat in this case)
Power Rating before accuracy: 1186
Accuracy: .93
Forced miss radius: 2.9
Accuracy divided by forced miss: 0.3206896551724138
Power rating with forced miss radius: 380.3379310344828




Overall I think that's a pretty accurate assessment, but it does change from situation to situation. For example the pistol and shotgun have the same rating, but they're very different weapons. The Shotgun has about half again more DPS but the pistol has about half again more range.

In close quarters combat the shotgun is a lot better, but in an open skirmish I personally actually prefer the pistol because the range is so much better.

Likewise the M16 and M24 have a similar power rating. In some situations (such as attacking siege bases) the M24 is a lot better, but in base defense I generally prefer the M16 because it has more then adequate range for that situation and has slightly better DPS.

Also, the accuracy stats are a little funny. Right now the formula only uses the highest accuracy stat. I chose that because then it assumes that the player is using the weapon to it's greatest potential, carefully choosing the range that will best complement it.

If I instead made the formula average together all the accuracy values together then you get some funny results. For example a shotgun has low enough range that it basically only uses the touch and short range stats, and the medium and long range stats will basically just confuse the formula and make the weapon seem worse then it actually is.

In the end, if you don't like the accuracy system I've used, or even the entire power rating system the script will still put out stats like DPS and power rating before accuracy, so it'll still speed up whatever formula modifications you want to use.

So take it with a grain of salt, but at the very least I think it gives people a good starting point for their weapon's balance. At the most I'm planning on using this formula exclusively for my new mod.

Bullet speed isn't taken into account because it has such a small effect on combat that it's not worth taking into account in my opinion. (And yes, it does have an effect on combat. If you want to know what it is ask and I'll post the long explanation, and show that it does make a difference but it's so small that it doesn't matter 99% of the time.)


How do I get this?:

First of all you'll need python. It's a free download and can be found here. I'm using 3.4, you should probably try to get the same version, unless you know a lot about python and can fix it as you go along.

Second of all you'll need to download my brother's script.

You should hopefully be able to download it from File Dropper here.

If that download doesn't seem to be working then either post here or send me a PM or something so I know it's not functioning, I've not used a free upload/download site before. On that note, I'm very open to suggestions of which free site to use and could upload it again.

Alternatively you could send me a private message saying you want it with your e-mail address and I can send it to you in an attachment.


How do I use it?:

Okay, put the rwb.py file somewhere that you'll remember.

I've put it in my Python34 folder, which I installed right into C:. So if I want to find it, it's in:

c:\python34\

Go into your mod and hold down shift then rightclick on the folder that has all your weapon .hml files in it. In the popdown menu there should be the option: "Open Command Window Here". Press that.

It should open command prompt, which looks a lot like MS/DOS if you're old enough to remember what that is.

It'll show a text line that has your mod file directory in it.

Mine looks like this:

C:\RimWorldAlpha5Win\RimWorld492Win\Mods\ProjectArmoury211\Defs\ThingDefs>

This is because I'm looking at the ThingDefs folder in the Project Armoury mod.

Now you should type in:

python (rwb.py with it's directory here) (.hml filename you want it to check here)

On my computer it looks like this:

python c:\python34\rwb.py PA_MedievalWeapon-Crossbow.hml

If I hit enter, then it'll pop out all the Crossbow's stats, like this:


C:\RimWorldAlpha5Win\RimWorld492Win\Mods\ProjectArmory211\Defs\ThingDefs>python
c:\python34\rwb.py PA_MedievalWeapon-Crossbow.xml
Reading xml file: PA_MedievalWeapon-Crossbow.xml
cooldownTicks:    40.0
DamageAmountBase: 18.0
basePrice:        220.0
warmupTicks:      280.0
range:            38.0
accuracyTouch:    0.96
accuracyShort:    0.87
accuracyMedium:   0.77
accuracyLong:     0.64
burstShotCount:   None
ticksbetweenburstshots:None

Ticks per shot:   320.0
Shots per second: 0.1875
Damage per second:3.375
Power Rating before accuracy: 128.25

Power Rating: 123.11999999999999
Suggested Silver Value: 246.23999999999998


Hopefully that makes sense to you. :P


Extra important bugfixing stuff:
Python is case sensitive. If you type "RWB.py" instead of "rwb.py" it won't work.

This especially applies for stuff inside of .hml files. One of the stats it's looking at is the <DamageAmountBase> </DamageAmountBase> figure. For whatever reason about half of Tynan's weapons have the "D" capitalized, and the rest have it in lower case. The script doesn't recognize the lower case ones, so you have to go through your files and make sure that "D" is capitalized it to make it work.

.hml files can't have the same stat in it twice. The script will collect data from one and ignore the other. (and not tell you that it did so) So you need to have all the weapons in their own .hml files, not all bundled together. If you look in the Core mod's weapons they're all bundled together. It won't work on them unless you separate them all into their own files. If you look at Project Armoury's weapons you'll notice that almost all of them are in their own files, which will work.

This also applies in some cases where the stat shows up twice. In the upper "BaseGun" section of a weapon's .hml file is a "CooldownTicks" stat, usually it's at 40. Some guns have a replacement "CooldownTicks" stat which will overwrite the upper one in the game. This python script will only read the top one though, so you'll want to replace the top one's stat with the bottom one's stat. (which is totally fine if there's only 1 gun in the file. If there's more than 1 gun in the file it'll change the stats on all the guns, so split them apart first)

Also, sometimes modded guns have special duplicate stats. For example mrofa's boomerang uses 2 projectiles, each with their own stats which will confuse the python script. For these guns I suggest either doing the formula by hand, or copying the weapon file then removing the second bullet on the copy and running that one through the script to see how the weapon works.

It doesn't take into account fire or explosive stuff, so just use it on "normal" weapons for now. Grenades, mortars, and Molotov Cocktails won't work.

If you run into other problems, please say so and post any errors or anything that comes up.


Credits:

Formula: By me. (though I ended up being happy with it in it's simplest form, so didn't have to do anything fancy)

Coding: By my brother who shall remain anonymous.
Divergence of Civilization Lead Developer (in this case that's the fancy way of saying "Only Developer")

Project Armoury Developer (New huge 2.13 Release now live!)

Architect

Veeeeeeeeeeeeeeeerrry nice :D It looks like it still needs a little refining to me, but otherwise I will definitely use this if the need arises. Using the same version can be very important, 3.2 and 3.4 handle lists very differently for example so I would be wary there.
Check out BetterPower+ and all its derivatives by clicking the picture below.

It adds many new methods of power generation and uses for it, as well as other things such as incidents.


Bog

Quote from: Architect on August 12, 2014, 06:40:57 PM
Veeeeeeeeeeeeeeeerrry nice :D It looks like it still needs a little refining to me, but otherwise I will definitely use this if the need arises.
I'm open to suggestions on how to make it better, then we can banter back in forth about what the best sort of formula modifications would be, then once I'm happy I may try to recruit my brother to change it around a bit.

Quote from: Architect on August 12, 2014, 06:40:57 PMUsing the same version can be very important, 3.2 and 3.4 handle lists very differently for example so I would be wary there.
Good to know, I'll update the post.
Divergence of Civilization Lead Developer (in this case that's the fancy way of saying "Only Developer")

Project Armoury Developer (New huge 2.13 Release now live!)

Tynan

This is really cool. Hell, I should start using this thing!
Tynan Sylvester - @TynanSylvester - Tynan's Blog

Bog

#4
Quote from: Tynan on August 12, 2014, 11:11:44 PM
This is really cool.
;D


...

So, could you explain to me how the ForcedMissRadius works? Then maybe I could come up with a good way to take it into account and coerce my brother into coding it so this thing gets a little better. :)
Divergence of Civilization Lead Developer (in this case that's the fancy way of saying "Only Developer")

Project Armoury Developer (New huge 2.13 Release now live!)

Tynan

Quote from: Bog on August 12, 2014, 11:48:14 PM
So, could you explain to me how the ForcedMissRadius works? Then maybe I could come up with a good way to take it into account and coerce my brother into coding it so this thing gets a little better. :)

If forcedMissRadius > 0, the game chooses a random miss distance d where 0 < d < forcedMissRadius. It then chooses a random angle. It then determines the square at that distance and angle away from the target center square. If it is in the same square as the target center square, all proceeds as normal. If not, the shot is fired at that square instead.

It's used for making weapons that spray shots over a wide area.
Tynan Sylvester - @TynanSylvester - Tynan's Blog

Bog

Quote from: Tynan on August 13, 2014, 12:07:42 AM
If forcedMissRadius > 0, the game chooses a random miss distance d where 0 < d < forcedMissRadius. It then chooses a random angle. It then determines the square at that distance and angle away from the target center square. If it is in the same square as the target center square, all proceeds as normal. If not, the shot is fired at that square instead.

It's used for making weapons that spray shots over a wide area.
Okay, cool. I'll probably mull that one over for a few days and do a bit of experimentation with it.

Thanks.
Divergence of Civilization Lead Developer (in this case that's the fancy way of saying "Only Developer")

Project Armoury Developer (New huge 2.13 Release now live!)

ZestyLemons

This is a pretty great tool, but it should really take time to kill (TTK) into consideration.

Sure, guns like the Lee Enfield have good accuracy, but are totally outclassed by the fire rate of a pistol mostly because of the low damage/high warmup.
Help out with the wiki!

Steam: http://steamcommunity.com/id/Divaya/
Wiki: http://rimworldwiki.com/wiki/User:Zesty

Feel free to contact me about wiki questions or wiki admin stuff.

Bog

#8
Quote from: ZestyLemons on August 13, 2014, 03:18:33 AM
This is a pretty great tool, but it should really take time to kill (TTK) into consideration.

Sure, guns like the Lee Enfield have good accuracy, but are totally outclassed by the fire rate of a pistol mostly because of the low damage/high warmup.
Well luckily for you we can look at all the stats easily now. ;D

Reading xml file: LeeEnfield.xml
cooldownTicks:    40.0
DamageAmountBase: 18.0
basePrice:        190.0
warmupTicks:      182.0
range:            37.0
accuracyTouch:    0.96
accuracyShort:    0.96
accuracyMedium:   0.92
accuracyLong:     0.88
burstShotCount:   None
ticksbetweenburstshots:None

Ticks per shot:   222.0
Shots per second: 0.2702702702702703
Damage per second:4.864864864864865
Power Rating before accuracy: 180.0

Power Rating: 172.79999999999998
Suggested Silver Value: 345.59999999999997


Reading xml file: Pistol.xml
cooldownTicks:    40.0
DamageAmountBase: 10.0
basePrice:        60.0
warmupTicks:      68.0
range:            24.0
accuracyTouch:    0.91
accuracyShort:    0.71
accuracyMedium:   0.5
accuracyLong:     0.32
burstShotCount:   None
ticksbetweenburstshots:None

Ticks per shot:   108.0
Shots per second: 0.5555555555555556
Damage per second:5.555555555555555
Power Rating before accuracy: 133.33333333333331

Power Rating: 121.33333333333331
Suggested Silver Value: 242.66666666666663



The DPS stats show that the LE has 4.86 and the pistol has 5.5. So yes, the pistol will kill a target faster if it hits with every bullet.

If we take the touch accuracy into account (by manually multiplying the accuracy and the DPS with a calculator) we get:

LE: 4.67
Pistol: 5.05

So, yes, the pistol still has a higher "true" DPS at close range.

So we could fairly easily add a new stat where DPS is combined with accuracy but doesn't take range into account. I don't really know what to call it. (Maybe "True DPS" or "stopping power" or something) Would that be good enough for you?

Calculating TTK is a different story though. It'd be easy enough to make the system automatically figure how how many shots a gun needs to remove 100 hitpoints then compare that to the bullets per second to see how many seconds it takes to put a standard unarmoured human down, but that system will go obsolete very soon because in the upcoming now released Alpha 6 the character health system is changing has changed a lot.
Divergence of Civilization Lead Developer (in this case that's the fancy way of saying "Only Developer")

Project Armoury Developer (New huge 2.13 Release now live!)

Tynan

Why not just output separate DPS for each range?
Tynan Sylvester - @TynanSylvester - Tynan's Blog

Bog

#10
Quote from: Tynan on August 13, 2014, 12:27:03 PM
Why not just output separate DPS for each range?
Could do that too. ;D Good idea.

So I'd probably change "DPS" to "Base DPS" then add touch/short/medium/long DPS stats.

I'll see if I can get together with my brother tonight so we can get it updated.

Any other suggestions in the mean time?
Divergence of Civilization Lead Developer (in this case that's the fancy way of saying "Only Developer")

Project Armoury Developer (New huge 2.13 Release now live!)

Bog

#11
Here's an example of what the tool can do.

I measured the power rating of all the weapons in the upcoming Project Armoury Release. (which we want to balance, because it's bad in some areas... look at the strongest vanilla weapon and then look even further down if you don't believe me) Overall, it took me less than an hour and a half to make this list. Can you imagine how long it would have taken me to run through the formula by hand on each of these? And can you imagine how many errors I would have made as my mind turned to mush, throwing the balance off?


Thrown Stones: 25 (Vanilla Weapon)
Flintlock Folwer Shot: 51.31
Dragon: 52.89
M1911: 54.30
LeMat Revolver: 57.07
British Bulldog: 61.14
Apache: 65.84
Laspistol: 69.65
Pila: 74 (Vanilla Weapon) (Weakest weapon avalible to the player in the vanilla version)
Kentucky Long Rifle: 74.35
Lupara: 75.09
Flintlock Fowler Ball: 75.40
Short Bow: 78 (Vanilla Weapon)
Walther PPK (S): 78.85
LeMat Carbine: 79.91
Woomera: 80.08
British Apache: 82.01
Franchi SPAS-12: 84.02
Steyr-Mannlicher M1894: 86.45
Walther PPK: 86.74
I. Pulase Ventor: 88.45
Webley-Fosbery: 90.79
Webley Revolver: 93.42
Atlatl: 95.00
Colt Police Positive: 95.90
Nambu: 96.05
Steyr-Mannlicher M1901: 96.06
Roth-Steyr M1907: 96.06
Star M1914: 96.06
Lebel M1888: 96.84
Moonraker Pistol: 98.74
Sawed-off Browning A5: 102.24
Lasgun: 106.67
Great Bow: 109 (Vanilla Weapon)
Steyr M1912: 109.77
Luger P08: 109.78
Mossberg 500: 110.98
Browning Auto 5: 120.65
Mauser C96: 120.9
Crossbow: 123.11
Pistol: 124 (Vanilla Weapon)
Shotgun: 124 (Vanilla Weapon)
Yew Longbow: 125.07
I. Ventor: 126.35
S&W Model 29: 130.33
Sjögren Shotgun: 130.8
Mateba Autorevolver: 132.20
Lebman M1911: 135.38
USAS-12: 138.58
Sjögren Rifle: 139.65
Sarcos K-11: 140.14
Uzi: 145 (Vanilla Weapon)
E-11 Blaster Rifle: 147.84
N64 Moonraker Laser: 148.11
Pancor Jackhammer: 148.8
AA-12: 150.26
Saiga-12 152.30
Moonraker Laser: 155.52
Desert Eagle Mk.1: 157.73
Winchester M1907: 160.94
Mateba Grifone: 170.84
Lee-Enfield: 172 (Vanilla Weapon)
SCAR-L Mk.16 Standard: 177.14
vz58P: 178.43
vz58V: 178.43
Charge Lance: 190 (Vanilla Weapon)
FN P90: 190.08
CS19: 193.53
Steyr M1912 MP: 197.17
Bolt Pistol: 199.38
BRX-A1: 200
BRX-A2: 200
Steyr AUGA1 204.58
SA58 Tactical 206.37
M4A1: 206.67
H&K G11: 210.16
M30 Luftwaffe Drilling: 210.96
SG552Commando: 212.21
Mac 10: 213.6
L58A1: 216.63
Vera: 218.4
Carcano M91: 218.88
H&K UMP.45: 219.37
MP-18: 219.70
ASval: 220.13
Lebman M1907: 220.60
Ross Rifle: 221.42
Steyr-Mannlicher M1895: 221.76
MP-40: 224.26
M-16: 229 (Vanilla Weapon)
Morita Mk.1 Carbine: 232.99
Glock 18: 236.60
T2 Plasma Rifle: 238.53
M24: 240 (Vanilla Weapon)
CM901: 245.18
H&K G36C: 247.65
Colt Monitor: 248.05
FN FAL: 248.92
M-14 EBR: 250.68
AK-47: 251.58
AKs-74U: 251.58
M8 Avenger: 252.0
D3 Plasma Gun: 255.07
FAMAS G2: 261.93
LMG-15: 264 (Vanilla Weapon)
Madsen-Rasmussen M1896: 266.8
BAR M1918: 268.8
TRW Plasma Sniper: 282.06
Chauchat: 284.40
MP5A2: 286.94
Huot: 298.93
R4: 312 (Vanilla Weapon)
M-14: 324.27
KRISS Vector: 326.7
Winchester Model 70: 334.12
MA5DICWS: 350.15
Morita Mk.1 AR: 350.3
M2 Browning (again): 355.22
Minigun: 369 (Vanilla Weapon) (Strongest weapon avalible to the play in the vanilla version)
M-81 Pulse Rifle: 379.82
Heavy Charge Blaster: 380 (Vanilla Weapon)
M60: 381.93
Thompson M1928A1: 390.23
M249: 393.47
M25: 412.29
Boys AT Rifle: 413.95
VSS Vintorez: 427.76
Walther WA2000: 451.44
Thompson M1920: 452.31
McMillan_Tac-50: 483.84
BarrettM82: 495.38
BarrettM107: 508.42
DragunovSVD: 512
Bren: 515.58
Bolter: 536.28
Accuracy Int. AWM: 553.41
M2 Browning: (Again) 598.66
M2 Browning: (Again) 598.66
PK: 718.48
RPD: 718.48
M4A1 Pulse Rifle: 758.71


That's over 150 weapons, in case you were wondering. ;D And that time included bug fixing. (about a quarter of the weapons needed the "d" capitalized in their .hml files, and there was a few other things)
Divergence of Civilization Lead Developer (in this case that's the fancy way of saying "Only Developer")

Project Armoury Developer (New huge 2.13 Release now live!)

Tynan

Bog: I suggest you do some math to have the tool reduce its power estimate for overkill. E.g. a weapon that does 1000 damage isn't 10x better than a 100-damage weapon because once a body part is destroyed the rest of the damage is wasted. You can bias the results in favor of smaller damage amounts per shot to capture this effect.
Tynan Sylvester - @TynanSylvester - Tynan's Blog

Bog

#13
Quote from: Tynan on August 14, 2014, 08:06:02 PM
Bog: I suggest you do some math to have the tool reduce its power estimate for overkill. E.g. a weapon that does 1000 damage isn't 10x better than a 100-damage weapon because once a body part is destroyed the rest of the damage is wasted. You can bias the results in favor of smaller damage amounts per shot to capture this effect.
Thanks for the input. I didn't think of that. In fact I've actually been contemplating the opposite effect, ie:

If a gun does too little damage (Thrown Stones, Uzi) it won't do enough damage to any given body part before "going on" and damaging the next body part, so a target might end up with a lot of very minor survivable wounds instead of a few strong ones. On the other hand a gun with high damage (M24) might take out any body part it touches with the first shot it fires, giving it a much higher chance to kill or severely cripple someone right off the bat. (and a shot that instantly permanently cripples a colonist is a lot worse for players then a bunch of weak shots that can be potentially recovered from, so in their eyes it's more dangerous, and so also "more powerful".)

So I was previously thinking about making the formula value higher damage weapons more. :P

I think I might have to come up with a way to do both at the same time, valuing damage to a point and then not counting it with the same weight because of the overkill. Of course I'll probably have to set it up for a regular humanpawn vs. humanpawn battle as that'll be the most common battle and the upper damage threshold is probably a lot higher on a centipede, which throws things off again. (assuming centipede's body parts have more health than human. I haven't specifically checked.)

Hopefully sometime this week I'll have the time to systematically figure out where the system evens out. Is a pistol that only has 1 damage but shoots 10x as fast better? Or would it be better to shoot 1/5th as fast but deal out 50 damage a shot? Or is it best as-is?

I'll probably answer those questions through a lot of trial and error by spawning colonists and making them shoot each other to death. ::)

.....

By the way, how does the "death threshold " work? Do people just die when a vital part (heart, brain, blood loss, etc.) reach 0? Or can they still be killed though damage volume if it doesn't finish off a vital part? That'd make a huge difference to my thoughts.

Also, how is blood loss measured? Does any damage contribute to it making it like the old health system?

Never mind, found a good thread on it. ;D
Divergence of Civilization Lead Developer (in this case that's the fancy way of saying "Only Developer")

Project Armoury Developer (New huge 2.13 Release now live!)

ison

#14
QuoteHopefully sometime this week I'll have the time to systematically figure out where the system evens out. Is a pistol that only has 1 damage but shoots 10x as fast better? Or would it be better to shoot 1/5th as fast but deal out 50 damage a shot? Or is it best as-is?

Assuming that losing a limb is something that you want to avoid, then pistol that deals 1 damage but shoots 10x as fast is less deadly than one with higher damage but normal shooting rate, because damage is then equally distributed among all body parts.
For example if someone's body consists only of 3 parts with 50 health each (all with 33.(3)% coverage), then one 50hp bullet = 100% chance to lose a limb, while 50 1hp bullets would usually lead to ~16 damage per body part.