There was this question in release topic what exactly changed in bullet physics and why, I hope to provide an answer here. I'll try to make it understandable as it's not exactly rocket science. My apologize if I failed.
This is how soldat physics looks like when drawn:
Handful of other images available
hereThose huge circles you can see surrounding parts of the player, are hitboxes. Their color represent the part of the body they cover, and thus hitbox modifier damage assigned to them.
Blue are legs,
Green is chest and
Red is head.
The red line is a part of bullet's trajectory that was part of the current simulation frame. Each bullet and sprite are simulated 60 times per second, so the red line is the distance a bullet managed to travel in that time (16ms). Basically, each simulation frame, bullet has some starting position and velocity which is a result of it's initial speed, gravity force and damping. Every frame the distance between current bullet's position and it's new position which is old position + current velocity gets checked for sprite and map collisions. If none occurs, bullet's position gets updated to new one and new velocity is calculated.
Once the red bullet line and one of those circles cross, in theory, hit should be registered. Alright, but how does soldat detect that? Especially since they overlap so much with each other?
At first let's look at the old (1.7.0) version did the math. Ugly paint skillz, here we go:
As you can see, I divided bullet trajectory into smaller, even parts (yes, they are supposed to be even). What soldat did, is to check edge points (the hollow circles) and each of those intermediate points in "ascending" order (from old position to new one, aka in direction the bullet is flying) for collisions with every sprite htibox. If any of those points happen to be in any of those hitboxes, hit is registered. The hitboxes are checked from top to bottom, so in case it registered in overlapping area, the higher hitbox wins and the higher damage is applied. However, as said previously, trajectory points were checked in ascending order, so if there was a dot in Green-only area and a dot in Red-Green area, the chest hitbox would ultimately win the race.
This was VERY ineffective. checking each of those midpoints with every hitbox of every sprite in every simulation frame was pretty damn slow.
The new approach (1.7.1) looks like this:
This time, instead of dividing trajectory into smaller parts, current bullet trajectory line equation is calculated. For each hitbox, it's circle equation is calculated. Now, we have to take those two equations, form a set and solve for intersection points. If any is found, hit should be registered.
Again, in case when the line intersects with multiple hitboxes, the tie is broken in favor of the higher one, no change here, yet. The code also still checks every bullet with every hitbox every frame, so there's still plenty of room to optimize things, but the performance boost I achieved was satisfying, hence I stopped working on that code.
What does all that mean?In the old logic, bullet was checked from old position to new, which means while the hitboxes themselves broke the tie in favor of the higher one, the "earlier" dots were checked first, meaning that if there was a dot in both green-only area and a dot in red-green area, it'd be still registered as a chest hit, as the green-only dot was checked earlier and ultimately won the race for hit registration.
Now, since whole line is checked at once, it's much more likely to register damage with higher hitboxes due to the length of the bullet trajectory in every frame. It can "pierce" through your body very deep. So deep in fact, that you're able to register head shot from below, if you're lucky.
This all needs some work, I'd like to bring the shape and size of those hitboxes to something reasonable and replace the tie breaking algorithm with something that takes the closest hitbox, rather than the highest one.
I hope to have it ready before 1.8 is here.