A_Tracer() and gametic

I just teleported behind the rocket and it turned around just fine.

Share this post


Link to post

Yup, that's indeed the case. Even if someone theoretically does a perfect teleportation with the exact opposite course of the rocket, it will still make a turn. I guess that "dodging" is yet another case of confirmation bias, then: "I dodged them, they didn't come for me again (reason unknown/don't care), hence they must have 'lost' me".

 

Still, none of this really explains the A_Tracer savegame bug.

 

Edit: TBQH, I don't get where in the code the decision to fire either a homing or non-homing missile is made, and, save for actually altering the newly spawned object's state, I don't see how the game could distinguish between a homing and non-homing rocket, nor how this distinction could survive a savegame. There's no clear-cut flag saying "homing", after all. Could it be that there's no such deliberate distinction at all, and it's only caused by a glitch with gametics? Or maybe it's lost in the released source code? Many other versions of Doom don't have such a distinction at all, that could be a hint...

 


//

// A_SkelMissile

//

void A_SkelMissile (mobj_t* actor)

{

mobj_t* mo;

if (!actor->target)

return;

A_FaceTarget (actor);

actor->z += 16*FRACUNIT; // so missile spawns higher

mo = P_SpawnMissile (actor, actor->target, MT_TRACER);

actor->z -= 16*FRACUNIT; // back to normal

mo->x += mo->momx;

mo->y += mo->momy;

mo->tracer = actor->target;

}

 

Craptacular test map: tracer.zip

Edited by Maes

Share this post


Link to post
34 minutes ago, Maes said:

Edit: TBQH, I don't get where in the code the decision to fire either a homing or non-homing missile is made, and, save for actually altering the newly spawned object's state, I don't see how the game could distinguish between a homing and non-homing rocket, nor how this distinction could survive a savegame. There's no clear-cut flag saying "homing", after all. Could it be that there's no such deliberate distinction at all, and it's only caused by a glitch with gametics? Or maybe it's lost in the released source code? Many other versions of Doom don't have such a distinction at all, that could be a hint...

The distinction is indeed only in the "gametic & 3" check inside A_Tracer. Revenant missile calls A_Tracer every 2 tics. If the missile gets fired in an odd tic, "gametic & 3" will always be equal to either 1 or 3, therefore A_Tracer will never do anything. If the missile gets fired in an even tic, "gametic & 3" will always be equal to either 0 or 2, therefore A_Tracer will do something only every other call (when it's 0). All of this so far was probably done by design. But, if the odd/even-ness of the current gametic changes after loading a savegame while the missile is in air, the missile would certainly toggle its (non)homing-ness, and that's the glitch.

Edited by scifista42

Share this post


Link to post

So, the only way for player input (or lack thereof) to affect the "gender" of an already fired rocket, would be for it to somehow affect the value of gametic? Or it depends purely on the value of gametic the moment one loads a game?

Edited by Maes

Share this post


Link to post

Yes and yes. :P

Edited by scifista42

Share this post


Link to post

So the only way to load a vanilla savegame consistently (but not necessarily correctly) would be to load it directly from the command line (as that would at least guarantee an initial gametic value of 0 every time). Of course, that might not work right for the particular situation at hand...so this falls purely under bug emulation. But hey, at least you have 1/4th change to get it right if the rocket is supposed to be a tracer, and 3/4ths if it's not ;-)

Edited by Maes

Share this post


Link to post
8 hours ago, scifista42 said:

The distinction is indeed only in the "gametic & 3" check inside A_Tracer. Revenant missile calls A_Tracer every 2 tics. If the missile gets fired in an odd tic, "gametic & 3" will always be equal to either 1 or 3, therefore A_Tracer will never do anything. If the missile gets fired in an even tic, "gametic & 3" will always be equal to either 0 or 2, therefore A_Tracer will do something only every other call (when it's 0). All of this so far was probably done by design. But, if the odd/even-ness of the current gametic changes after loading a savegame while the missile is in air, the missile would certainly toggle its (non)homing-ness, and that's the glitch.

That is an amazing analysis! How long did it take you to figure this out? In fact, I would not bet the farm that this was done intentionally: It was only done for this one monster, it was added in a hurry for Doom II - a rushed product, and it's broken for demos. If I had to guess, I'd say it was a happy mistake. Great question to ask Romero!

 

By the way, Boom fixes it like this:

if ((gametic - basetic) & 3)
    return;

with this in G_DoNewGame() and G_PlayDemo():

basetic = gametic;

And, for the save game, the tracer field (target) is stored, and basetic/gametic are stored as follows:

// killough 11/98: save revenant tracer state
*save_p++ = (gametic - basetic) & 255;

Upon loading, you have this:

// killough 11/98: load revenant tracer state
basetic = gametic - (int) *save_p++;

And, finally, to handle pauses in demo playback, you have this in G_Ticker():

if (paused && demoplayback)
{
    // For revenant tracers and RNG -- we must maintain sync
    basetic++;
}

So, it's a fairly complicated bug, to nail down in all places.

 

Edited by kb1
1 person likes this

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now