Fix segfault when calling P_RemoveMobj from MobjCollide hook

This commit is contained in:
Gustaf Alhäll 2023-07-07 21:35:41 +02:00
parent d7a84b967c
commit ecf0c4b45a
No known key found for this signature in database
GPG key ID: 6C1F67D690CDEDFD

View file

@ -4005,131 +4005,135 @@ void P_BounceMove(mobj_t *mo)
slidemo = mo; slidemo = mo;
hitcount = 0; hitcount = 0;
retry: do
if (++hitcount == 3) {
goto bounceback; // don't loop forever if (++hitcount == 3)
goto bounceback; // don't loop forever
if (mo->player) if (mo->player)
{
mmomx = mo->player->rmomx;
mmomy = mo->player->rmomy;
}
else
{
mmomx = mo->momx;
mmomy = mo->momy;
}
// trace along the three leading corners
if (mo->momx > 0)
{
leadx = mo->x + mo->radius;
trailx = mo->x - mo->radius;
}
else
{
leadx = mo->x - mo->radius;
trailx = mo->x + mo->radius;
}
if (mo->momy > 0)
{
leady = mo->y + mo->radius;
traily = mo->y - mo->radius;
}
else
{
leady = mo->y - mo->radius;
traily = mo->y + mo->radius;
}
bestslidefrac = FRACUNIT + 1;
P_PathTraverse(leadx, leady, leadx + mmomx, leady + mmomy, PT_ADDLINES, PTR_SlideTraverse);
P_PathTraverse(trailx, leady, trailx + mmomx, leady + mmomy, PT_ADDLINES, PTR_SlideTraverse);
P_PathTraverse(leadx, traily, leadx + mmomx, traily + mmomy, PT_ADDLINES, PTR_SlideTraverse);
// move up to the wall
if (bestslidefrac == FRACUNIT + 1)
{
// the move must have hit the middle, so bounce straight back
bounceback:
if (P_TryMove(mo, mo->x - mmomx, mo->y - mmomy, true))
{ {
mo->momx *= -1; mmomx = mo->player->rmomx;
mo->momy *= -1; mmomy = mo->player->rmomy;
mo->momx = FixedMul(mo->momx, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3))); }
mo->momy = FixedMul(mo->momy, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3))); else
{
mmomx = mo->momx;
mmomy = mo->momy;
}
if (mo->player) // trace along the three leading corners
if (mo->momx > 0)
{
leadx = mo->x + mo->radius;
trailx = mo->x - mo->radius;
}
else
{
leadx = mo->x - mo->radius;
trailx = mo->x + mo->radius;
}
if (mo->momy > 0)
{
leady = mo->y + mo->radius;
traily = mo->y - mo->radius;
}
else
{
leady = mo->y - mo->radius;
traily = mo->y + mo->radius;
}
bestslidefrac = FRACUNIT + 1;
P_PathTraverse(leadx, leady, leadx + mmomx, leady + mmomy, PT_ADDLINES, PTR_SlideTraverse);
P_PathTraverse(trailx, leady, trailx + mmomx, leady + mmomy, PT_ADDLINES, PTR_SlideTraverse);
P_PathTraverse(leadx, traily, leadx + mmomx, traily + mmomy, PT_ADDLINES, PTR_SlideTraverse);
// move up to the wall
if (bestslidefrac == FRACUNIT + 1)
{
// the move must have hit the middle, so bounce straight back
bounceback:
if (P_TryMove(mo, mo->x - mmomx, mo->y - mmomy, true))
{ {
mo->player->cmomx *= -1; mo->momx *= -1;
mo->player->cmomy *= -1; mo->momy *= -1;
mo->player->cmomx = FixedMul(mo->player->cmomx, mo->momx = FixedMul(mo->momx, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3)));
(FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3))); mo->momy = FixedMul(mo->momy, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3)));
mo->player->cmomy = FixedMul(mo->player->cmomy,
(FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3))); if (mo->player)
{
mo->player->cmomx *= -1;
mo->player->cmomy *= -1;
mo->player->cmomx = FixedMul(mo->player->cmomx,
(FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3)));
mo->player->cmomy = FixedMul(mo->player->cmomy,
(FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3)));
}
}
return;
}
// fudge a bit to make sure it doesn't hit
bestslidefrac -= 0x800;
if (bestslidefrac > 0)
{
newx = FixedMul(mmomx, bestslidefrac);
newy = FixedMul(mmomy, bestslidefrac);
if (!P_TryMove(mo, mo->x + newx, mo->y + newy, true))
{
if (P_MobjWasRemoved(mo))
return;
goto bounceback;
} }
} }
return;
// Now continue along the wall.
// First calculate remainder.
bestslidefrac = FRACUNIT - bestslidefrac;
if (bestslidefrac > FRACUNIT)
bestslidefrac = FRACUNIT;
if (bestslidefrac <= 0)
return;
if (mo->type == MT_SHELL)
{
tmxmove = mmomx;
tmymove = mmomy;
}
else if (mo->type == MT_THROWNBOUNCE)
{
tmxmove = FixedMul(mmomx, (FRACUNIT - (FRACUNIT>>6) - (FRACUNIT>>5)));
tmymove = FixedMul(mmomy, (FRACUNIT - (FRACUNIT>>6) - (FRACUNIT>>5)));
}
else if (mo->type == MT_THROWNGRENADE || mo->type == MT_CYBRAKDEMON_NAPALM_BOMB_LARGE)
{
// Quickly decay speed as it bounces
tmxmove = FixedDiv(mmomx, 2*FRACUNIT);
tmymove = FixedDiv(mmomy, 2*FRACUNIT);
}
else
{
tmxmove = FixedMul(mmomx, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3)));
tmymove = FixedMul(mmomy, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3)));
}
P_HitBounceLine(bestslideline); // clip the moves
mo->momx = tmxmove;
mo->momy = tmymove;
if (mo->player)
{
mo->player->cmomx = tmxmove;
mo->player->cmomy = tmymove;
}
} }
while (!P_TryMove(mo, mo->x + tmxmove, mo->y + tmymove, true) && !P_MobjWasRemoved(mo));
// fudge a bit to make sure it doesn't hit
bestslidefrac -= 0x800;
if (bestslidefrac > 0)
{
newx = FixedMul(mmomx, bestslidefrac);
newy = FixedMul(mmomy, bestslidefrac);
if (!P_TryMove(mo, mo->x + newx, mo->y + newy, true))
goto bounceback;
}
// Now continue along the wall.
// First calculate remainder.
bestslidefrac = FRACUNIT - bestslidefrac;
if (bestslidefrac > FRACUNIT)
bestslidefrac = FRACUNIT;
if (bestslidefrac <= 0)
return;
if (mo->type == MT_SHELL)
{
tmxmove = mmomx;
tmymove = mmomy;
}
else if (mo->type == MT_THROWNBOUNCE)
{
tmxmove = FixedMul(mmomx, (FRACUNIT - (FRACUNIT>>6) - (FRACUNIT>>5)));
tmymove = FixedMul(mmomy, (FRACUNIT - (FRACUNIT>>6) - (FRACUNIT>>5)));
}
else if (mo->type == MT_THROWNGRENADE || mo->type == MT_CYBRAKDEMON_NAPALM_BOMB_LARGE)
{
// Quickly decay speed as it bounces
tmxmove = FixedDiv(mmomx, 2*FRACUNIT);
tmymove = FixedDiv(mmomy, 2*FRACUNIT);
}
else
{
tmxmove = FixedMul(mmomx, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3)));
tmymove = FixedMul(mmomy, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3)));
}
P_HitBounceLine(bestslideline); // clip the moves
mo->momx = tmxmove;
mo->momy = tmymove;
if (mo->player)
{
mo->player->cmomx = tmxmove;
mo->player->cmomy = tmymove;
}
if (!P_TryMove(mo, mo->x + tmxmove, mo->y + tmymove, true))
goto retry;
} }
// //