From ecf0c4b45a756039ccde6ffd1845c0232220952d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= <gustaf@hanicef.me> Date: Fri, 7 Jul 2023 21:35:41 +0200 Subject: [PATCH] Fix segfault when calling P_RemoveMobj from MobjCollide hook --- src/p_map.c | 214 ++++++++++++++++++++++++++-------------------------- 1 file changed, 109 insertions(+), 105 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index 0021fe450c..0221fbc11b 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -4005,131 +4005,135 @@ void P_BounceMove(mobj_t *mo) slidemo = mo; hitcount = 0; -retry: - if (++hitcount == 3) - goto bounceback; // don't loop forever - - if (mo->player) - { - mmomx = mo->player->rmomx; - mmomy = mo->player->rmomy; - } - else + do { - mmomx = mo->momx; - mmomy = mo->momy; - } + if (++hitcount == 3) + goto bounceback; // don't loop forever - // 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->player) + { + mmomx = mo->player->rmomx; + mmomy = mo->player->rmomy; + } + else + { + mmomx = mo->momx; + mmomy = mo->momy; + } - 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; - } + // 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; + 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); + 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)) + // move up to the wall + if (bestslidefrac == FRACUNIT + 1) { - mo->momx *= -1; - mo->momy *= -1; - mo->momx = FixedMul(mo->momx, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3))); - mo->momy = FixedMul(mo->momy, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3))); - - if (mo->player) + // 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->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))); + mo->momx *= -1; + mo->momy *= -1; + mo->momx = FixedMul(mo->momx, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3))); + mo->momy = FixedMul(mo->momy, (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; } - return; - } - // fudge a bit to make sure it doesn't hit - bestslidefrac -= 0x800; - if (bestslidefrac > 0) - { - newx = FixedMul(mmomx, bestslidefrac); - newy = FixedMul(mmomy, bestslidefrac); + // 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; - } + if (!P_TryMove(mo, mo->x + newx, mo->y + newy, true)) + { + if (P_MobjWasRemoved(mo)) + return; + goto bounceback; + } + } - // Now continue along the wall. - // First calculate remainder. - bestslidefrac = FRACUNIT - bestslidefrac; + // Now continue along the wall. + // First calculate remainder. + bestslidefrac = FRACUNIT - bestslidefrac; - if (bestslidefrac > FRACUNIT) - bestslidefrac = FRACUNIT; + if (bestslidefrac > FRACUNIT) + bestslidefrac = FRACUNIT; - if (bestslidefrac <= 0) - return; + 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))); - } + 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 + P_HitBounceLine(bestslideline); // clip the moves - mo->momx = tmxmove; - mo->momy = tmymove; + mo->momx = tmxmove; + mo->momy = tmymove; - if (mo->player) - { - mo->player->cmomx = tmxmove; - mo->player->cmomy = 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; + while (!P_TryMove(mo, mo->x + tmxmove, mo->y + tmymove, true) && !P_MobjWasRemoved(mo)); } // -- GitLab