Skip to content

Commit

Permalink
Heretic: fix hitscan/missile puffs disappearing in certain areas (#1138)
Browse files Browse the repository at this point in the history
* Fix hitscan/missile puffs disappearing in certain areas

* Fix little typo
  • Loading branch information
JNechaevsky authored Jan 19, 2024
1 parent 48a5819 commit 61cc35e
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 12 deletions.
2 changes: 1 addition & 1 deletion src/doom/p_map.c
Original file line number Diff line number Diff line change
Expand Up @@ -1101,7 +1101,7 @@ boolean PTR_ShootTraverse (intercept_t* in)
}
}

// [crispy] check if the pullet puff's z-coordinate is below of above
// [crispy] check if the bullet puff's z-coordinate is below of above
// its spawning sector's floor or ceiling, respectively, and move its
// coordinates to the point where the trajectory hits the plane
if (aimslope)
Expand Down
6 changes: 6 additions & 0 deletions src/heretic/m_random.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,9 @@ int P_SubRandom (void)
int r = P_Random();
return r - P_Random();
}

int Crispy_SubRandom (void)
{
int r = Crispy_Random();
return r - Crispy_Random();
}
1 change: 1 addition & 0 deletions src/heretic/m_random.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ extern int rndindex;

// Defined version of P_Random() - P_Random()
int P_SubRandom (void);
int Crispy_SubRandom (void);

#endif // HERETIC_M_RANDOM_H

1 change: 1 addition & 0 deletions src/heretic/p_local.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ boolean P_SeekerMissile(mobj_t * actor, angle_t thresh, angle_t turnMax);
void P_MobjThinker(thinker_t *thinker);
void P_BlasterMobjThinker(thinker_t *thinker);
void P_SpawnPuff(fixed_t x, fixed_t y, fixed_t z);
void P_SpawnPuffSafe(fixed_t x, fixed_t y, fixed_t z, boolean safe);
void P_SpawnBlood(fixed_t x, fixed_t y, fixed_t z, int damage);
void P_BloodSplatter(fixed_t x, fixed_t y, fixed_t z, mobj_t * originator);
void P_RipperBlood(mobj_t * mo);
Expand Down
32 changes: 31 additions & 1 deletion src/heretic/p_map.c
Original file line number Diff line number Diff line change
Expand Up @@ -1301,6 +1301,7 @@ boolean PTR_ShootTraverse(intercept_t * in)

if (in->isaline)
{
boolean safe = false;
li = in->d.line;
if (li->special)
P_ShootSpecialLine(shootthing, li);
Expand Down Expand Up @@ -1344,10 +1345,39 @@ boolean PTR_ShootTraverse(intercept_t * in)
if (z > li->frontsector->ceilingheight)
return false; // don't shoot the sky!
if (li->backsector && li->backsector->ceilingpic == skyflatnum)
{
// [crispy] fix hitscan puffs not appearing in outdoor areas
if (li->backsector->ceilingheight < z)
return false; // it's a sky hack wall
else
safe = true;
}
}

P_SpawnPuff(x, y, z);
// [crispy] check if the hitscan puff's z-coordinate is below of above
// its spawning sector's floor or ceiling, respectively, and move its
// coordinates to the point where the trajectory hits the plane
if (aimslope)
{
const int lineside = P_PointOnLineSide(x, y, li);
int side;

if ((side = li->sidenum[lineside]) != NO_INDEX)
{
const sector_t *const sector = sides[side].sector;

if (z < sector->floorheight ||
(z > sector->ceilingheight && sector->ceilingpic != skyflatnum))
{
z = BETWEEN(sector->floorheight, sector->ceilingheight, z);
frac = FixedDiv(z - shootz, FixedMul(aimslope, attackrange));
x = trace.x + FixedMul (trace.dx, frac);
y = trace.y + FixedMul (trace.dy, frac);
}
}
}

P_SpawnPuffSafe(x, y, z, safe);
return false; // don't go any farther
}

Expand Down
74 changes: 64 additions & 10 deletions src/heretic/p_mobj.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,40 @@ boolean P_SetMobjState(mobj_t * mobj, statenum_t state)
return (true);
}

// [crispy] return the latest "safe" state in a state sequence,
// so that no action pointer is ever called
static statenum_t P_LatestSafeState(statenum_t state)
{
statenum_t safestate = S_NULL;
static statenum_t laststate, lastsafestate;

if (state == laststate)
{
return lastsafestate;
}

for (laststate = state; state != S_NULL; state = states[state].nextstate)
{
if (safestate == S_NULL)
{
safestate = state;
}

if (states[state].action)
{
safestate = S_NULL;
}

// [crispy] a state with -1 tics never changes
if (states[state].tics == -1 || state == states[state].nextstate)
{
break;
}
}

return lastsafestate = safestate;
}

//----------------------------------------------------------------------------
//
// FUNC P_SetMobjStateNF
Expand Down Expand Up @@ -110,7 +144,7 @@ boolean P_SetMobjStateNF(mobj_t * mobj, statenum_t state)
//
//----------------------------------------------------------------------------

void P_ExplodeMissile(mobj_t * mo)
static void P_ExplodeMissileSafe(mobj_t * mo, boolean safe)
{
if (mo->type == MT_WHIRLWIND)
{
Expand All @@ -120,7 +154,7 @@ void P_ExplodeMissile(mobj_t * mo)
}
}
mo->momx = mo->momy = mo->momz = 0;
P_SetMobjState(mo, mobjinfo[mo->type].deathstate);
P_SetMobjState(mo, safe ? P_LatestSafeState(mobjinfo[mo->type].deathstate) : (statenum_t)mobjinfo[mo->type].deathstate);
//mo->tics -= P_Random()&3;
mo->flags &= ~MF_MISSILE;
if (mo->info->deathsound)
Expand All @@ -129,6 +163,11 @@ void P_ExplodeMissile(mobj_t * mo)
}
}

void P_ExplodeMissile(mobj_t * mo)
{
P_ExplodeMissileSafe(mo, false);
}

//----------------------------------------------------------------------------
//
// PROC P_FloorBounceMissile
Expand Down Expand Up @@ -361,6 +400,7 @@ void P_XYMovement(mobj_t * mo)
}
else if (mo->flags & MF_MISSILE)
{ // Explode a missile
boolean safe = false;
if (ceilingline && ceilingline->backsector
&& ceilingline->backsector->ceilingpic == skyflatnum)
{ // Hack to prevent missiles exploding against the sky
Expand All @@ -369,13 +409,17 @@ void P_XYMovement(mobj_t * mo)
mo->momx = mo->momy = 0;
mo->momz = -FRACUNIT;
}
else
if (mo->z > ceilingline->backsector->ceilingheight)
{
P_RemoveMobj(mo);
return;
}
else
{
safe = true;
}
return;
}
P_ExplodeMissile(mo);
P_ExplodeMissileSafe(mo, safe);
}
//else if(mo->info->crashstate)
//{
Expand Down Expand Up @@ -872,7 +916,7 @@ void P_MobjThinker(thinker_t *thinker)
===============
*/

mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
static mobj_t *P_SpawnMobjSafe(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, boolean safe)
{
mobj_t *mobj;
state_t *st;
Expand All @@ -896,12 +940,12 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
{
mobj->reactiontime = info->reactiontime;
}
mobj->lastlook = P_Random() % MAXPLAYERS;
mobj->lastlook = safe ? Crispy_Random () % MAXPLAYERS : P_Random () % MAXPLAYERS;

// Set the state, but do not use P_SetMobjState, because action
// routines can't be called yet. If the spawnstate has an action
// routine, it will not be called.
st = &states[info->spawnstate];
st = &states[safe ? P_LatestSafeState(info->spawnstate) : (statenum_t)info->spawnstate];
mobj->state = st;
mobj->tics = st->tics;
mobj->sprite = st->sprite;
Expand Down Expand Up @@ -962,6 +1006,11 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
return (mobj);
}

mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
{
return P_SpawnMobjSafe(x, y, z, type, false);
}

/*
===============
=
Expand Down Expand Up @@ -1226,11 +1275,11 @@ void P_SpawnMapThing(mapthing_t * mthing)
//---------------------------------------------------------------------------


void P_SpawnPuff(fixed_t x, fixed_t y, fixed_t z)
void P_SpawnPuffSafe(fixed_t x, fixed_t y, fixed_t z, boolean safe)
{
mobj_t *puff;

z += (P_SubRandom() << 10);
z += safe ? (Crispy_SubRandom() << 10) : (P_SubRandom() << 10);
puff = P_SpawnMobj(x, y, z, PuffType);
if (puff->info->attacksound)
{
Expand All @@ -1252,6 +1301,11 @@ void P_SpawnPuff(fixed_t x, fixed_t y, fixed_t z)
puff->interp = -1;
}

void P_SpawnPuff(fixed_t x, fixed_t y, fixed_t z)
{
P_SpawnPuffSafe(x, y, z, false);
}

/*
================
=
Expand Down

0 comments on commit 61cc35e

Please sign in to comment.