Source-1-Games icon indicating copy to clipboard operation
Source-1-Games copied to clipboard

[TF2] Huntsman headshots are inconsistent depending on victim's world space orientation

Open wgetJane opened this issue 1 year ago • 6 comments

spy with yaw of 180 degrees

image image

spy with yaw of 0 degrees (notice the wall in the background)

image image

wgetJane avatar Apr 24 '24 10:04 wgetJane

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

wgetJane avatar Apr 24 '24 10:04 wgetJane

I've always disliked how forgiving the huntsman hitboxes are, anything to make them more accurate is appreciated.

gdfsgdfg avatar Apr 25 '24 14:04 gdfsgdfg

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.

bakugo avatar Apr 25 '24 20:04 bakugo

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

wgetJane avatar Apr 26 '24 07:04 wgetJane

i think i figured it out

so here's how huntsman arrows pick a hitbox:

  1. 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)
  2. if the line trace hits a hitbox, then that hitbox is chosen, early return
  3. otherwise, loop through each hitbox
  4. for each hitbox, trace from the arrow's position (and offset 16 units forwards) to the bone origin of the hitbox
  5. 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: image gif

wgetJane avatar Apr 26 '24 22:04 wgetJane

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 );

wgetJane avatar Apr 27 '24 12:04 wgetJane