diff --git a/docs/rh-log.txt b/docs/rh-log.txt index dc72ef882..39d052324 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,12 @@ +December 6, 2009 (Changes by Graf Zahl) +- added some code that prevents overlapping monsters from getting stuck in + each other. PIT_CheckThing will return true under the following contitions + now: + * It was called from P_Move + * The actor that is blocking the move already overlaps with the monster + that is being moved. + * the move will take the 2 actors further apart. + December 1, 2009 - Added another surface to receive a copy of the top back buffer immediately before it is presented. This effectively produces a copy of the front diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 919c11bec..4b80d5b68 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -507,6 +507,8 @@ bool P_Move (AActor *actor) } FCheckPosition tm; + tm.FromPMove = true; + try_ok = true; for(int i=1; i < steps; i++) { @@ -518,7 +520,7 @@ bool P_Move (AActor *actor) if (try_ok) try_ok = P_TryMove (actor, tryx, tryy, dropoff, false, tm); // [GrafZahl] Interpolating monster movement as it is done here just looks bad - // so make it switchable! + // so make it switchable if (nomonsterinterpolation) { actor->PrevX = actor->x; diff --git a/src/p_local.h b/src/p_local.h index 84a50bb5d..415ac46ca 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -346,6 +346,7 @@ struct FCheckPosition sector_t *ceilingsector; bool touchmidtex; bool floatok; + bool FromPMove; line_t *ceilingline; AActor *stepthing; // [RH] These are used by PIT_CheckThing and P_XYMovement to apply @@ -359,6 +360,7 @@ struct FCheckPosition DoRipping = rip; LastRipped = NULL; PushTime = 0; + FromPMove = false; } }; diff --git a/src/p_map.cpp b/src/p_map.cpp index 00db77bee..e401e84fb 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -831,13 +831,32 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm) } } } + + // Both things overlap in x or y direction + bool unblocking = false; + + if (tm.FromPMove) + { + fixed_t newdist = P_AproxDistance(thing->x - tm.x, thing->y - tm.y); + fixed_t olddist = P_AproxDistance(thing->x - tm.thing->x, thing->y - tm.thing->y); + + // Both actors already overlap. To prevent them from remaining stuck allow the move if it + // takes them further apart. + if (newdist > olddist) + { + // ... but not if they did not overlap in z-direction before but would after the move. + unblocking = !((tm.thing->x >= thing->x + thing->height && tm.x < thing->x + thing->height) || + (tm.thing->x + tm.thing->height <= thing->x && tm.x + tm.thing->height > thing->x)); + } + } + // [RH] If the other thing is a bridge, then treat the moving thing as if it had MF2_PASSMOBJ, so // you can use a scrolling floor to move scenery items underneath a bridge. if ((tm.thing->flags2 & MF2_PASSMOBJ || thing->flags4 & MF4_ACTLIKEBRIDGE) && !(i_compatflags & COMPATF_NO_PASSMOBJ)) { // check if a mobj passed over/under another object if (tm.thing->flags3 & thing->flags3 & MF3_DONTOVERLAP) { // Some things prefer not to overlap each other, if possible - return false; + return unblocking; } if ((tm.thing->z >= topz) || (tm.thing->z + tm.thing->height <= thing->z)) { @@ -1145,7 +1164,7 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm) // despite another solid thing being in the way. // killough 4/11/98: Treat no-clipping things as not blocking - return !solid; + return !solid || unblocking; // return !(thing->flags & MF_SOLID); // old code -- killough }