[TF2] Huntsman headshots are inconsistent depending on victim's world space orientation
spy with yaw of 180 degrees
spy with yaw of 0 degrees (notice the wall in the background)
btw this means that point-symmetrical maps are actually biased towards one of the teams, because landing huntsman headshots will be easier on one side than on the opposite
I've always disliked how forgiving the huntsman hitboxes are, anything to make them more accurate is appreciated.
The entire huntsman headshot detection system has desperately needed a rework since the day it was added. It's understandable why extra logic was added beyond direct collisions with a hitbox, because projectiles are much harder to aim, but the current "find the closest hitbox" approach has hilariously bad results in some situations.
I've experimented with this, and the best approach I could come up with was to simply define a larger radius (sphere) around the player's head hitbox and check if the arrow's trajectory intersects that radius.
I've always disliked how forgiving the huntsman hitboxes are, anything to make them more accurate is appreciated.
this issue isn't about nerfing the huntsman
in fact, if this issue were to be hypothetically fixed, then it would probably have even more forgiving headshots
the result in the more forgiving angle (at 180 yaw) is most likely to be more correct
the result in the less forgiving angle (at 0 yaw) is most likely to be incorrect, considering that you can't land a headshot even at the corner of the box where the head hitbox is definitely the closest hitbox
i think i figured it out
so here's how huntsman arrows pick a hitbox:
- upon hitting a player's collision hull, perform a line trace to a point from the arrow's position + impact velocity * server tick interval (basically just keep going forward for a little bit)
- if the line trace hits a hitbox, then that hitbox is chosen, early return
- otherwise, loop through each hitbox
- for each hitbox, trace from the arrow's position (and offset 16 units forwards) to the bone origin of the hitbox
- the hitbox with the shortest resulting trace distance is chosen
the issue with inconsistent headshots based on world space orientation is caused by a part of this code:
from CTFProjectile_Arrow::ArrowTouch
// Locate the hitbox closest to our point of impact on the collision box.
Vector position, start, forward;
QAngle angles;
float closest_dist = 99999;
// Intense, but extremely accurate:
AngleVectors( GetAbsAngles(), &forward );
start = GetAbsOrigin() + forward*16;
for ( int i = 0; i < set->numhitboxes; i++ )
{
mstudiobbox_t *pbox = set->pHitbox( i );
pAnimOther->GetBonePosition( pbox->bone, position, angles );
Ray_t ray;
ray.Init( start, position );
trace_t tr;
IntersectRayWithBox( ray, position+pbox->bbmin, position+pbox->bbmax, 0.f, &tr );
float dist = tr.endpos.DistTo( start );
if ( dist < closest_dist )
{
closest_dist = dist;
closest_box = pbox;
}
}
if you didn't notice, it's because the hitboxes are treated as AABBs, the angles variable is not used at all
visualisation:
this can be fixed by replacing this line:
IntersectRayWithBox( ray, position+pbox->bbmin, position+pbox->bbmax, 0.f, &tr );
with this:
IntersectRayWithOBB( ray, position, angles, pbox->bbmin, pbox->bbmax, 0.f, &tr );