The Damage Formula

EDIT 1: Added info regarding pal vs pal damage.

TL;DR

The damage formula is your weapon's damage multiplied by your attack power divided by the target's defense. A ±10% random roll is then applied. Don't know your target's defense? You can get a rough estimate by doing 50 + 6 * level. Alphas and Luckies have separate damage reduction bonuses (approximately -95% for alphas, untested for luckies), and different pal species may or may not have bonuses applied to HP, attack, and/or defense (the highest I've seen is +20%). In addition, there's some point - which I expect is if your attack is higher than their defense - at which your damage is outright doubled.

I haven't tested pal damage yet. It's going to be my next task. I've finished testing pal damage. I'm somewhat confident of this formula, and compared to my data-gathering experiments, it has a margin of error of ±2.6%. The pal vs pal damage formula is as follows:

1.1 x ( ( ( 1.5 x your pal's level ) + 20 ) x the move's power x your pal's attack stat / the target's defense stat ) / 15

Which is a heck of a lot more complicated than the player vs pal formula, but it works, and the numbers make enough sense that I expect it's how the code is written.

The Testing

As with any good science, once we have our question, we need a hypothesis. I was hopeful that the damage formula was a simple and easy one, involving only multiplication. If I were developing the game, I would do something simple, and the player's attack and defense numbers starting at 100 made me think it was probably a multiplicative system. So I actually predicted that the damage formula was going to be the above formula; weapon damage times attack power divided by defense. So, naturally, I set to work testing this theory. I had a character with 100 attack and a crossbow go around killing tiny baby pals. It very quickly became clear that something was missing from my theory; adding a 2x multiplier fixed the issue with the babies, but when i scaled up to larger pals, the 2x multiplier went away. So I went back to the drawing board and tried a variety of different formulae and data gathering methods, but eventually, I did what I probably should have done at the start.

My successful experiment was as follows: I note down my damage and attack power. I also note down the level of my intended target. I then go into battle, with the intent to capture the pal I'm fighting. During the battle, I keep track of my highest and lowest damage numbers, working off of the assumption that the damage range is ±10% based purely on vibes. Once the pal is captured, I take the average of the highest and lowest damages, and check the range of values. If the margin is lower than 5%, I would toss out the data; a narrow damage margin means my calculated average was likely to be too far off from the real average. After getting this data, I noticed they looked strikingly close to the predictions. I'll detail my findings below. I used a crossbow (280 damage) with a character that has 110 attack, so my "base damage" is 308.

Pal Captured Pal Level Pal Defense Lowest Hit Highest Hit Average Damage Damage Range Expected Damage by Formula Margin of Error
Melpaca 13 152 209 241 225 ±7.1% 202.63 -11.03%
Grizzbolt 19 216 134 153 143.5 ±6.6% 142.59 -0.63%
Broncherry 19 211 131 157 144 ±9.0% 145.97 +1.35%
Caprity 11 135 210 234 222 ±5.4% 228.15 +2.69%
Tombat 12 140 200 229 214.5 ±6.7% 220 +2.50%

I don't know what exactly happened with Melpaca, but all of the others are within a margin of error of 3%, so I'm reasonably confident this formula is it. Please feel free to do your own tests and share your data, I'd love to see it.

EDIT: I'm going to include what I did for testing pal damage here as well. Now that I had the player damage formula, I could make some assumptions about the pal formula; firstly, I assumed it would involve the attacker's attack, the defender's defense, and the power of the move. So, I set to work gathering data. This time, however, I remembered the fact that there's a training dummy you can build. So, considering pal damage is so much higher than player damage, I built a training dummy, and started hitting it. My testing partners were five direhowls; levels 6, 9, 10, 10, and 12, with attack stats of 149, 169, 174, 197, and 186. I chose direhowls because they're rideable, so I can consistently and constantly choose the same move, and because they have moves that are very simple.

I used the player damage formula to quickly figure out that the training dummy has a defense of 100, which works well for my testing. So, one by one, I used fierce fang on the training dummy to gather their minimum and maximum damage ranges. At the same time, I used some of the higher level ones to discover that there's a same-type boost of 1.2x. I knew I had the minima and maxima when the resulting range from the average was ±10% (or just shy), and I set to trying to figure out what was going on. It quickly became apparent that level was a factor, because my level 12 direhowl with 186 attack was dealing more damage than my level 10 direhowl with 197 attack. Now, unlike with the player formula, there was a third variable, so I couldn't simply do some kind of interpolation, and had to figure out what was going on. I spent hours and hours trying to work out how they might compare and consistently failed to come up with any leads, until someone suggested I look at the pokemon damage formula, and see if it was just a 1:1 copy.

Obviously, the palworld damage formula is not a 1:1 copy of the pokemon damage formula, but the functional form of it is the same. Power is multiplied onto level with a multiplier as well as to a constant, then divided by another constant, then has multipliers applied. In pokemon, the damage formula is roughly ( ( 2/5 x level ) + 2) x power / 50 and so I started from there, put it into my spreadsheet, and started changing numbers around. I didn't know how to interpolate, so I just manually changed numbers until things looked good. It took a while, but I eventually came upon the winning formula, which had an error margin of ±2.5% with my experimental data, detailed in the tl;dr.

With the formula sorted, I went out to test. I grabbed my lv24 eikthyrdeer and went out to catch a broncherry. Eikthyrdeer has 324 attack, and the broncherry I ended up catching had 188 defense. The formula predicted 297 average damage, and I ended up with a ±7% 293 average from my hits on the broncherry, within a reasonable range, thus confirming the formula. Again, feel free to continue to test this out, more data will always be welcome.

Things I Still Need to Figure Out

Now that I've solved the player damage formula, my next goal is to solve the pal damage formula. I expect it's the same, but with the weapon replaced by the move, possibly with some kind of same-element boost, but I still need to test it to be sure. Pal vs pal formula is solved! oh god now i have to figure out catch rate. I think I'll put that in a separate post, though.

After that, I want to figure out capture rates. It will be a nightmare, I know already. But I have to try.