From b3f7a57518f7b698d48de17c1066cf2c86082d40 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 9 Mar 2016 11:44:01 +0100 Subject: [PATCH] - yet another case of adding a workaround to preserve a side effect in Doom's original movement code that's bound to be inadvertently exploited: When a spechit results in teleportation, P_TryMove never accounted for that, so that subsequent spechits either failed or succeeded, depending on where the teleport ends up. With portal-aware positions stored within the spechit this no longer worked, so some handling is needed to revert to the original behavior in case there's no portals to consider. The ideal solution would have been to stop checking spechits (or to block further teleports) once this happens but the likelihood of some old maps depending on this is high. --- src/p_map.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/p_map.cpp b/src/p_map.cpp index a277c7b77d..181e730b77 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -2405,11 +2405,18 @@ bool P_TryMove(AActor *thing, fixed_t x, fixed_t y, if (!(thing->flags & (MF_TELEPORT | MF_NOCLIP))) { spechit_t spec; + fixedvec3 lastpos = thing->Pos(); while (spechit.Pop(spec)) { line_t *ld = spec.line; // see if the line was crossed - side = P_PointOnLineSide(spec.refpos.x, spec.refpos.y, ld); + + // One more case of trying to preserve some side effects from the original: + // If the reference position is the same as the actor's position before checking the spechits, + // we use the thing's actual position, including all the side effects of the original. + // If some portal transition has to be considered here, we cannot do that and use the reference position stored with the spechit. + bool posisoriginal = (spec.refpos.x == lastpos.x && spec.refpos.y == lastpos.y); + side = posisoriginal? P_PointOnLineSide(thing->X(), thing->Y(), ld) : P_PointOnLineSide(spec.refpos.x, spec.refpos.y, ld); oldside = P_PointOnLineSide(spec.oldrefpos.x, spec.oldrefpos.y, ld); if (side != oldside && ld->special && !(thing->flags6 & MF6_NOTRIGGER)) {