Since I don't want to have to type it all out again, here's a discord capture.
Essentially the source of this seems to be that the origin of a puff actor isn't necessarily in the same spot as the exact termination point of a hitscan ray, meaning that the "tracer" actors that can be spawned by A_FireBullets can end up going in wildly different directions than the hitscan attack when fired into a monster up close.
Puff actors not spawning exactly at hitscan line termination
Moderator: GZDoom Developers
Forum rules
Please don't bump threads here if you have a problem - it will often be forgotten about if you do. Instead, make a new thread here.
Please don't bump threads here if you have a problem - it will often be forgotten about if you do. Instead, make a new thread here.
Re: Puff actors not spawning exactly at hitscan line termina
Please post a runnable sample.
- Graf Zahl
- Lead GZDoom+Raze Developer
- Posts: 49073
- Joined: Sat Jul 19, 2003 10:19 am
- Location: Germany
Re: Puff actors not spawning exactly at hitscan line termina
This is intended behavior. The puff's z- coordinate is slightly randomized. This is not intended to be spawned at a possibly significant coordinate so you cannot use it for precise hit detection.
Re: Puff actors not spawning exactly at hitscan line termina
There's an FBF_NORANDOMPUFFZ flag that can be used to disable that Z randomization.
Re: Puff actors not spawning exactly at hitscan line termina
Thanks, I'll try that out and see if it helps. I was hoping this was something that could be remedied with an easy fix like that.
Re: Puff actors not spawning exactly at hitscan line termina
Welp, turns out Nash's fix doesn't work, likely because the Blood actor isn't actually a puff and is therefore not subject to the flag he suggested, or some other reason.
Here is a weapon, use 'give TracerShotgun' and test it out.
https://mega.nz/#!u01zXZjD!6-A_XeC1TP_3 ... 0_kYg4oEl0
Steps to reproduce with near-100% chance:
1.) Use the freeze command
2.) summon a pinky demon
3.) center view and press directly against it
4.) Shoot until it dies
5.) Unfreeze time.
You should then see the trajectories of 20 (30 if you're extremely unlucky) tracers, many of which will be directed upwards at an angle far higher than the aim angle. This behavior is the result of an unsafe assumption being made in the tracer spawn code, which is that a vector from player(+offsets) -> puff is equivalent to, or at least close to, the hitscan line. Obviously it's not when you're extremely close to an enemy, as can be demonstrated here. No need to enable or disable autoaim, it works no matter what. In fact, you can predict the vectors by looking closely at the tracers and the blood actors, then mentally drawing a line that passes through both.
It would be possible to work around this if FBF_PUFFTARGET/FBF_PUFFMASTER/FBF_PUFFTRACER could return pointers to Blood actors (which would allow manual deletion of tracers after they pass their puff), or if it was reasonable to wrap firebullets in a loop which used explicit angles and separately spawned the tracers. Unfortunately one of those is impossible and the other would interfere with autoaim. If there's another workaround that doesn't kill performance, autoaim, or require tearing apart pre-existing weapons I'll be glad to use that.
EDIT: Okay so, firstly my assumption about the source of this issue is dead on, and I do think that maybe there should be a flag to use hitscan angle instead of puff direction if possible. Secondly there is a workaround which does basically just that (while preserving autoaim), and it's this:
In ZScript we can use an incredibly short range dummy puff to get the aim pitch while also accounting for autoaim, then use that along with some other hackery to create the desired effect. There's also a way better way to do this if you don't want autoaim, which is to just use the player's pitch. So far I haven't encountered any issues with this, but it would probably be faster running native.
Here is a weapon, use 'give TracerShotgun' and test it out.
https://mega.nz/#!u01zXZjD!6-A_XeC1TP_3 ... 0_kYg4oEl0
Steps to reproduce with near-100% chance:
1.) Use the freeze command
2.) summon a pinky demon
3.) center view and press directly against it
4.) Shoot until it dies
5.) Unfreeze time.
You should then see the trajectories of 20 (30 if you're extremely unlucky) tracers, many of which will be directed upwards at an angle far higher than the aim angle. This behavior is the result of an unsafe assumption being made in the tracer spawn code, which is that a vector from player(+offsets) -> puff is equivalent to, or at least close to, the hitscan line. Obviously it's not when you're extremely close to an enemy, as can be demonstrated here. No need to enable or disable autoaim, it works no matter what. In fact, you can predict the vectors by looking closely at the tracers and the blood actors, then mentally drawing a line that passes through both.
It would be possible to work around this if FBF_PUFFTARGET/FBF_PUFFMASTER/FBF_PUFFTRACER could return pointers to Blood actors (which would allow manual deletion of tracers after they pass their puff), or if it was reasonable to wrap firebullets in a loop which used explicit angles and separately spawned the tracers. Unfortunately one of those is impossible and the other would interfere with autoaim. If there's another workaround that doesn't kill performance, autoaim, or require tearing apart pre-existing weapons I'll be glad to use that.
EDIT: Okay so, firstly my assumption about the source of this issue is dead on, and I do think that maybe there should be a flag to use hitscan angle instead of puff direction if possible. Secondly there is a workaround which does basically just that (while preserving autoaim), and it's this:
Code: Select all
action void A_FireBulletsProperTracer(double anglex, double angley, int numbullets, int damage, int multiplier=3, string pufftype="PlayerPuff", double range=8192, string missile="", double spawnheight=0, double spawnofs_xy=0)
{
//Declare variables required
let p = players[consoleplayer].mo;
int zoffset = ((p.height/2)+p.AttackZOffset);
double aimPitch, ax, ay;
Vector3 aimVec;
//Determine pitch including autoaim
A_FireBullets(0, 0, 1, 0, "AutoAimPuff", FBF_NORANDOM|FBF_NORANDOMPUFFZ, 1);
AutoAimPuff other = AutoAimPuff(ThinkerIterator.Create("AutoAimPuff").Next()); //We know one will exist because we just spawned it
aimVec = (other.pos.x-p.pos.x, other.pos.y-p.pos.y, other.pos.z-(p.pos.z+zoffset)); //manually create vector to apply offset
aimPitch = -asin(aimVec.z/aimVec.Length()); //hooray trig
//fire bullets, in this case 10 with a 5x5 spread
for(int i = 0; i < 10; i++)
{
ax = frandom(-anglex, anglex);
ay = frandom(-angley, angley);
A_FireBullets(ax, aimPitch+ay, -1, damage * random(1, multiplier), pufftype, FBF_EXPLICITANGLE|FBF_NOPITCH|FBF_NORANDOM, range);
//spawn the tracers in the origin of the hitscan, and move them towards it
p.A_SpawnProjectile (missile, zoffset+spawnheight, spawnofs_xy, p.angle+ax, CMF_AIMDIRECTION|CMF_ABSOLUTEANGLE, aimPitch+ay);
}
}
Last edited by Rachael on Mon Oct 30, 2017 5:43 pm, edited 1 time in total.
Reason: shrank image
Reason: shrank image