BEX patch is being frustrating (PRBoom+)

Currently having some Dehacked-related troubles with a project of mine. Here is a link to the current file: https://dl.dropbox.com/u/76650/project%20files/ww-oldie-test2.7z

The issue I am having is this: to save on frames, I've redirected all weapons' muzzle flash codes to a generic, invisible flash frame (frames 1-3 at the beginning of the states table). On ALL other existing weapons, this works just fine, but for the Chaingun replacement, it inexplicably makes the Doom fist appear over the gun on the latest prboom-plus. However, testing it in other Boom-supporting ports (a recent-ish ZDoom SVN and EDGE 1.35) does not produce any such glitch. I've tried other methods, like reverting the original Chaingun muzzle flash frames and using those, but where ZDoom and EDGE work just fine and produce no glitches whatsoever, prboom-plus just flat-out crashes, with nothing useful in stderr or stdout.

I am really stuck here. Either this is my own danged fault, and I've encountered some bizarre undefined DEH behavior, or prboom-plus has an actual bug in it.

Share this post


Link to post

The chaingun's firing action A_FireCGun has a hardcoded element in Vanilla Doom.

If the weapon it's attached to has a flash state, the weapons first attack state must be called CHAIN1.

Not every port has changed this behaviour.

Share this post


Link to post
Vermil said:

The flash state of Doom's chaingun in Vanilla Doom is hardcoded to expect the firing states of the weapon to be called CHAIN1 and CHAIN2.

Not every port has changed this behaviour.

Okay, uh...I guess I'll need to figure out how to do this myself? Maybe create two blank frames for CHGFA0 and CHGFB0?

Share this post


Link to post

Or just define no flash state for the weapon?

Here's the source code btw:

//
// A_FireCGun
//
void C_DECL A_FireCGun(player_t *player, pspdef_t * psp)
{
S_StartSound(sfx_pistol, player->plr->mo);

/*if(!player->ammo[weaponinfo[player->readyweapon].ammo])
return; */

P_SetMobjState(player->plr->mo, S_PLAY_ATK2);
//player->ammo[weaponinfo[player->readyweapon].ammo]--;
P_ShotAmmo(player);

P_SetPsprite(player, ps_flash,
weaponinfo[player->readyweapon].flashstate + psp->state -
&states[S_CHAIN1]);

player->update |= PSF_AMMO;
if(IS_CLIENT)
return;

P_BulletSlope(player->plr->mo);

P_GunShot(player->plr->mo, !player->refire);
}

Share this post


Link to post
Vermil said:

Or just define no flash state for the weapon?

I've tried setting the Chaingun's Muzzle Flash frame to 0. This unfortunately seems to spawn the same behavior, where a fist appears over the weapon for no reason. And again, still works just fine in ZDoom and EDGE. =P

Share this post


Link to post

Ok.

That worked in Doomsday,which also retains this hardcoded behaviour. Though I did use Dday's own weapon info ded defs.

Share this post


Link to post

Vanilla code:

//
// A_FireCGun
//
void
A_FireCGun
( player_t*	player,
  pspdef_t*	psp ) 
{
    S_StartSound (player->mo, sfx_pistol);

    if (!player->ammo[weaponinfo[player->readyweapon].ammo])
	return;
		
    P_SetMobjState (player->mo, S_PLAY_ATK2);
    player->ammo[weaponinfo[player->readyweapon].ammo]--;

    P_SetPsprite (player,
		  ps_flash,
		  weaponinfo[player->readyweapon].flashstate
		  + psp->state
		  - &states[S_CHAIN1] );

    P_BulletSlope (player->mo);
	
    P_GunShot (player->mo, !player->refire);
}
The important part here is this:
    P_SetPsprite (player,
		  ps_flash,
		  weaponinfo[player->readyweapon].flashstate
		  + psp->state
		  - &states[S_CHAIN1] );
The function's prototype:
P_SetPsprite
( player_t*	player,
  int		position,
  statenum_t	stnum ) 
What is a statenum? It's an enum, that is to say, an integer. Here's an excerpt:
typedef enum
{
    S_NULL,
    S_LIGHTDONE,
    S_PUNCH,
    S_PUNCHDOWN,
    S_PUNCHUP,
    S_PUNCH1,
    S_PUNCH2,
    S_PUNCH3,
    S_PUNCH4,
    S_PUNCH5,
    S_PISTOL,
    S_PISTOLDOWN,
    S_PISTOLUP,
    S_PISTOL1,
    S_PISTOL2,
    S_PISTOL3,
    S_PISTOL4,
    S_PISTOLFLASH,
<snip shotgun states>
    S_CHAIN,
    S_CHAINDOWN,
    S_CHAINUP,
    S_CHAIN1,
    S_CHAIN2,
    S_CHAIN3,
    S_CHAINFLASH1,
    S_CHAINFLASH2,
<snip a ton of stuff>
    S_BRAINSTEM,
    S_TECHLAMP,
    S_TECHLAMP2,
    S_TECHLAMP3,
    S_TECHLAMP4,
    S_TECH2LAMP,
    S_TECH2LAMP2,
    S_TECH2LAMP3,
    S_TECH2LAMP4,
    NUMSTATES
} statenum_t;

Little digression about the chaingun states:
    {
	// chaingun
	am_clip,	//   ammo/amunition type
	S_CHAINUP,	//  upstate
	S_CHAINDOWN,	//  downstate
	S_CHAIN,	// readystate
	S_CHAIN1,	// atkstate, i.e. attack/fire/hit frame
	S_CHAINFLASH1	// flashstate, muzzle flash
    },

Now let's look at the stnum value here:
  • weaponinfo[player->readyweapon].flashstate => this is the state you defined, which can be NULL. In vanilla, it is S_CHAINFLASH1.
  • + psp->state => this is the current player sprite state on the weapon position; in vanilla it's going to be CHAIN1 or CHAIN2.
  • - &states[S_CHAIN1] => we subtract the chaingun attack state (note: not the chaingun flash state).
The result? If we currently are in CHAIN1, it'll be flash state + CHAIN1 - CHAIN1, or flash state. If we currently are in CHAIN2, it'll be flash state + CHAIN2 - CHAIN1, or flash state + 1.

Now what if we are in a totally different state from what vanilla expect? What if our attack state is PISTOL? Then it'll be flash state + 10 - 52, or flash state -42. Your flash state is 0? Yeah, don't expect things to work well.

Or, what if it's something different in the other way around? Your attack state somehow is BRAINSTEM. Flash state + 958 - 52 = flash state + 906. Your flash state is 0? Then, now, it's STALAGTITE. (Blame Id for the misspelling.)

Anyway, the only way you can have things working correctly is if you keep as many flash states as you have attack states with A_FireCGun, and you keep in mind that the offset between your attack state and S_CHAIN1, whatever that is, will be used as the offset between the weapon's flash state and the state actually used for the muzzle flash.

For instance, looking at your BEX code, I see A_FireCGun is used in frame 58. 58-52=6. Firing frame is 1. 1 + 6 = 7. What is state 7? Why, it just happens to be PUNCH3!



Incidentally, why does it work as you expected it in ZDoom? Simple:
//
// A_FireCGun
//
DEFINE_ACTION_FUNCTION(AActor, A_FireCGun)
{
	player_t *player;

	if (self == NULL || NULL == (player = self->player))
	{
		return;
	}

	AWeapon *weapon = player->ReadyWeapon;
	if (weapon != NULL)
	{
		if (!weapon->DepleteAmmo (weapon->bAltFire, true, 1))
			return;
		
		S_Sound (self, CHAN_WEAPON, "weapons/chngun", 1, ATTN_NORM);

		FState *flash = weapon->FindState(NAME_Flash);
		if (flash != NULL)
		{
			// [RH] Fix for Sparky's messed-up Dehacked patch! Blargh!
			FState * atk = weapon->FindState(NAME_Fire);

			int theflash = clamp (int(player->psprites[ps_weapon].state - atk), 0, 1);

			if (flash[theflash].sprite != flash->sprite)
			{
				theflash = 0;
			}

			P_SetSafeFlash (weapon, player, flash, theflash);
		}

	}
	player->mo->PlayAttacking2 ();

	P_GunShot (self, !player->refire, PClass::FindClass(NAME_BulletPuff), P_BulletSlope (self));
}
As you can see, there's a fix for Sparky's messed up Dehacked patch, blargh! A consequence of this is that ZDoom will not accept an offset between flash state and actual flash greater than 1. So if you make something which rely on having an offset of 7, ZDoom will clamp it to an offset of 1. That means that it'll be broken in ZDoom...

Conclusion: if you want your dehacked to work in both ZDoom and PrBoom/Choco, you need to make sure that you use the same chaingun attack states as the chaingun itself. You can use only one of them, or both, or none; but you cannot use, say, a rocket launcher frame for A_FireCGun.

Share this post


Link to post

Most interesting. I might use this information to make a wad that doesn't work in ZDoom.

Share this post


Link to post

Well, many thanks for the help I've received with this chaingun issue, but I've run across an entirely different and similarly frustrating issue with my new rocket launcher.

Relevant link: https://dl.dropbox.com/u/76650/project%20files/ww-oldie-test5.7z

The rocket launcher will not select on PRBoom/GLBoom. The previous weapon lowers, and then...never comes back. On ZDoom, the weapon selects, and even fires, but selection happens instantaneously (despite having a duration of 1 for both Raise and Lower states), and selecting away from the weapon will crash ZDoom.

I'm pretty sure this is something to do with a similar issue to the chaingun, likely to do with the fact that I'm actually repurposing the (now unused) Chaingunner frames to allow for more weapon frames. As usual, help is appreciated.

[[edit]] Never mind, turns out I had the Raise and Lower frames backwards again.

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