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.