I'm putting together a fun wad with a bunch of custom items from here for my cousin and I to play using Zandronum. Most of the weapon wads we will be pairing are from our old Skulltag days. Needless to say, with most of the modding activity now being focused toward developing under GZDoom and its features, I knew going into this that some compatibility edits would be required (I'm actually quite surprised at the amount of really high quality wads on here that are cross compatible!).

Item and Reason for Discovery

Perhaps my absolute favorite custom item so far has been Quantum_Dranger's
Bullet Ant Venom
. My jaw literally dropped when I saw the syringe actually STICK onto the monsters then MOVE around with them AND change angles until they fall off!! Unfortunately, Zandronum (3.0.18242.1) didn't like a particular argument header for the A_JumpIfHealthLower() function (I don't know if the definition containing the optional actor pointer has been intentionally removed/ ignored by the Zandronum authors or whatever the case may be) so I implemented a little work around (if interested in adding compatibility for current Zandronum, I'll elaborate on my particular solution at your request).

The Issue

While testing my edit, I came across an annoying artifact (which I double checked using the original version of this wad [before my edit] in Zandronum and the latest GZDoom) which causes syringes to freeze in midair and remain frozen, detached from their tracer until they run out of juice and fall to the ground.

Easiest Way to Produce the Bug

Simply run forward toward a monster (you can ensure they don't stray from your path by cornering them but this isn't required); while moving forward and colliding with your target, simply use the item. It will cause a pain reaction and the monsters can freely walk away from the now frozen syringe at will. It will not hurt them unless they wander back within the syringe's radius.

The Cause (I THINK)

I ran some tests to determine the exact circumstances of this bug (thank goodness for A_Log()). I noticed that when this bug happens, the message I left in the syringe's Spawn state never printed. Never entering Spawn? That doesn't make sense! What I've surmised is that somewhere, in the ZDoom source code there is some "special case" in the native function backing A_FireCustomMissile(), something to the effect of "if(the missile spawns inside of or past another actor) just go straight to xdeath". Perhaps this is to avoid missiles tunneling past monsters because of tics spent in Spawn frames... Anywho, this seems to completely break the tracer functionality. The game definitely knows something got hit, but AAPTR_TRACER was never initialized so A_Warp() was always working with an invalid pointer.

Possible Solutions

Xdeath: A_CheckFlag("ISMONSTER", "realxdeath", AAPTR_TRACER) goto death, where "realxdeath" is simply your original xdeath code in a new state. Unfortunately, your syringe will still be spent but you could always make them retrievable!

Add the +HITTRACER flag to the projectile definition to make it so AAPTR_TRACER is set to the actor that caused it to go into xdeath. Obviously this solution requires the least work! xD

A Few Notes

For some reason, whether XF_HURTSOURCE is true or false in A_Explode(), the floating syringes still hurt the player... I think this is because the default "source" being placed in the Syringe's AAPTR_TARGET pointer is the ItemSyringe that spawned it, NOT the Player. There seems to be no way to transfer pointers using A_FireCustomMissile() so I'm not sure how that could be fixed without using an alternative damage delivery altogether (which I did for my cousin and I's wad setup).

Speaking of alternative damage delivery methods... you may want to consider one if you want the damage to be more consistent with the item itself. As it is currently, Cyberdemons and Spidermasterminds aren't affected by the syringe since they make use of the NORADIUSDMG flag. I mean, it would make sense if you chose to keep it the way it is since maybe bosses should be a little tougher! Of course, for my purposes I changed it to inflict direct damage.

Anywho, I just wanted to bring this to your attention because I freaking love this item and I thought maybe addressing the freezing thing might help to make it even greater!

A-Bomb wrote: What I've surmised is that somewhere, in the ZDoom source code there is some "special case" in the native function backing A_FireCustomMissile(), something to the effect of "if(the missile spawns inside of or past another actor) just go straight to xdeath".

The engine explodes the missile immediately if it fails the room check. In such a case, A_FireCustomMissile will not set the tracer field of the missile (among other things).

Add the +HITTRACER flag to the projectile definition to make it so AAPTR_TRACER is set to the actor that caused it to go into xdeath. Obviously this solution requires the least work! xD

Yes, removing SEEKERMISSILE and using that flag instead should solve the problem easily.

For some reason, whether XF_HURTSOURCE is true or false in A_Explode(), the floating syringes still hurt the player... I think this is because the default "source" being placed in the Syringe's AAPTR_TARGET pointer is the ItemSyringe that spawned it, NOT the Player.

The player is correctly considered the source/shooter. It's just there's an error in the code. The flag parameter of A_Explode should've been set to 0, not -XF_HURTSOURCE.

Thinking about it, all of these little issues would've been avoided had
my suggestions
at the time been taken into consideration.