Auto Aim logic error in P_PreFireHitscan
There's a logic error in P_PreFireHitscan in player.cpp where the player's auto aim setting is not checked at the right time, causing it to essentially do nothing when shooting the pistol (specifically shooting SHOTSPARK1) and GROWSPARK.
https://www.youtube.com/watch?v=NQCYrQJwX4o
You can see this behavior on display in this test, running the current version as of this post, r10118. You can see I have auto aim fully disabled, but the pistol and Expander both still use it. I didn't capture it in this video but other hitscan weapons (shotgun, ripper) do not behave in this way.
In A_ShootHardcoded, the 3 bullet weapons are fired using this line. This only affects the pistol because the pistol is defined as "SHOTSPARK1", causing the 2nd to last condition to always return 0 for the shotgun and ripper:
P_PreFireHitscan(spriteNum, playerNum, projecTile, &startPos, &Zvel, &shootAng, projecTile == SHOTSPARK1__STATIC && !WW2GI, 1);
And the Expander is fired using this line:
P_PreFireHitscan(spriteNum, playerNum, projecTile, &startPos, &Zvel, &shootAng, 1, 1);
Note that custom projectiles are fired when checking for the appropriate auto aim flags, and are also susceptible to this behavior:
P_PreFireHitscan(spriteNum, playerNum, projecTile, startPos, &zvel, &shootAng, pProj->workslike & PROJECTILE_ACCURATE_AUTOAIM, !(pProj->workslike & PROJECTILE_ACCURATE));
The bullet weapon bug could be fixed checking for the other 2 tiles, some thing like:
P_PreFireHitscan(spriteNum, playerNum, projecTile, &startPos, &Zvel, &shootAng, (projecTile == SHOTSPARK1__STATIC || projecTile == SHOTGUN__STATIC || projecTile == CHAINGUN__STATIC) && !WW2GI, 1);
But the real problem is up in P_PreFireHitscan, paraphrased here for readability:
static void P_PreFireHitscan(int spriteNum, int playerNum, int projecTile, vec3_t *srcVect, int32_t *zvel, int *shootAng,
int accurateAim, int doSpread)
[. . .]
if (accurateAim)
{
if (!pPlayer->auto_aim)
{
[. . .]
}
if (aimSprite == -1)
goto notarget;
}
else
{
if (aimSprite == -1) // no target
{
notarget:
*zvel = fix16_to_int(F16(100)-pPlayer->q16horiz-pPlayer->q16horizoff)<<5;
}
Proj_MaybeAddSpread(doSpread, zvel, shootAng, zRange, angRange);
}
If accurateAim is 1, the code enters the if statement to perform auto aim. But because the player's auto aim setting is 0 (fully disabled), the auto aim code is skipped, but so is the later code where the weapon spread is applied using Proj_MaybeAddSpread.
The simplest solution should be something like modifying this line:
if (aimSprite == -1 || !pPlayer->auto_aim)
goto notarget;