From 76f00131ff545fa2ab296580a77d2bd0bb40df0c Mon Sep 17 00:00:00 2001 From: MajorCooke Date: Sun, 10 Apr 2016 11:51:40 -0500 Subject: [PATCH] - Fixed: A_CheckBlock's dropoff check ignored the specifications of NOACTORS and NOLINES due to P_CheckMove blindly failing if P_CheckPosition failed. This lead to false positives such as blocking actors being detected when they shouldn't be. --- src/p_local.h | 9 +++++++-- src/p_map.cpp | 18 +++++++++++++++--- src/thingdef/thingdef_codeptr.cpp | 12 ++++++++++-- 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/src/p_local.h b/src/p_local.h index 82f4580b9..45b02e8ea 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -186,7 +186,12 @@ enum WARPF WARPF_COPYPITCH = 0x8000, }; - +enum PCM +{ + PCM_DROPOFF = 1, + PCM_NOACTORS = 1 << 1, + PCM_NOLINES = 1 << 2, +}; AActor *P_BlockmapSearch (AActor *mo, int distance, AActor *(*check)(AActor*, int, void *), void *params = NULL); @@ -221,7 +226,7 @@ void P_FakeZMovement (AActor *mo); bool P_TryMove(AActor* thing, const DVector2 &pos, int dropoff, const secplane_t * onfloor, FCheckPosition &tm, bool missileCheck = false); bool P_TryMove(AActor* thing, const DVector2 &pos, int dropoff, const secplane_t * onfloor = NULL); -bool P_CheckMove(AActor *thing, const DVector2 &pos, bool dropoff = false); +bool P_CheckMove(AActor *thing, const DVector2 &pos, int flags = 0); void P_ApplyTorque(AActor *mo); bool P_TeleportMove(AActor* thing, const DVector3 &pos, bool telefrag, bool modifyactor = true); // [RH] Added z and telefrag parameters diff --git a/src/p_map.cpp b/src/p_map.cpp index 73aa3f73f..a1ef28cc4 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -2410,14 +2410,26 @@ bool P_TryMove(AActor *thing, const DVector2 &pos, // //========================================================================== -bool P_CheckMove(AActor *thing, const DVector2 &pos, bool dropoff) +bool P_CheckMove(AActor *thing, const DVector2 &pos, int flags) { FCheckPosition tm; double newz = thing->Z(); if (!P_CheckPosition(thing, pos, tm)) { - return false; + // Ignore PCM_DROPOFF. Not necessary here: a little later it is. + if (!flags || (!(flags & PCM_NOACTORS) && !(flags & PCM_NOLINES))) + { + return false; + } + if (!(flags & PCM_NOACTORS) && thing->BlockingMobj) + { + return false; + } + if (!(flags & PCM_NOLINES) && thing->BlockingLine) + { + return false; + } } if (thing->flags3 & MF3_FLOORHUGGER) @@ -2469,7 +2481,7 @@ bool P_CheckMove(AActor *thing, const DVector2 &pos, bool dropoff) return false; } } - else if (dropoff) + else if (flags & PCM_DROPOFF) { const DVector3 oldpos = thing->Pos(); thing->SetOrigin(pos.X, pos.Y, newz, true); diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index cc4ffd33b..53685c43b 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -6706,8 +6706,16 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckBlock) bool checker = false; if (flags & CBF_DROPOFF) { + // Unfortunately, whenever P_CheckMove returned false, that means it could + // ignore a variety of flags mainly because of P_CheckPosition. This + // results in picking up false positives due to actors or lines being in the way + // when they clearly should not be. + + int fpass = PCM_DROPOFF; + if (flags & CBF_NOACTORS) fpass |= PCM_NOACTORS; + if (flags & CBF_NOLINES) fpass |= PCM_NOLINES; mobj->SetZ(pos.Z); - checker = P_CheckMove(mobj, pos, true); + checker = P_CheckMove(mobj, pos, fpass); mobj->SetZ(oldpos.Z); } else @@ -6743,7 +6751,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckBlock) //[MC] I don't know why I let myself be persuaded not to include a flag. //If an actor is loaded with pointers, they don't really have any options to spare. //Also, fail if a dropoff or a step is too great to pass over when checking for dropoffs. - + if ((!(flags & CBF_NOACTORS) && (mobj->BlockingMobj)) || (!(flags & CBF_NOLINES) && mobj->BlockingLine != NULL) || ((flags & CBF_DROPOFF) && !checker)) {