diff --git a/docs/rh-log.txt b/docs/rh-log.txt
index a5bee140a..5d758f967 100644
--- a/docs/rh-log.txt
+++ b/docs/rh-log.txt
@@ -1,4 +1,7 @@
 September 24, 2009
+- Changed P_XYMovement() to not call P_SlideMove() if the act of being
+  blocked changed the actor's velocity. I'm not entirely happy with this,
+  but it gets push-activated force fields to work.
 - Fixed: FMultiPatchTexture::CopyTrueColorPixels() should clear the buffer
   first before drawing into it if the copy op passed to it is OP_OVERWRITE.
   FTexture::FillBuffer() sets this to erase whatever texture might have been
diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp
index 17333f7d7..14585e016 100644
--- a/src/p_lnspec.cpp
+++ b/src/p_lnspec.cpp
@@ -2796,7 +2796,9 @@ FUNC(LS_ForceField)
 	if (it != NULL)
 	{
 		P_DamageMobj (it, NULL, NULL, 16, NAME_None);
-		P_ThrustMobj (it, it->angle + ANGLE_180, 0x7D000);
+		angle_t an = (it->angle + ANGLE_180) >> ANGLETOFINESHIFT;
+		it->velx = FixedMul(0x7D000, finecosine[an]);
+		it->vely = FixedMul(0x7D000, finesine[an]);
 	}
 	return true;
 }
diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp
index b070adef1..8449924ef 100644
--- a/src/p_mobj.cpp
+++ b/src/p_mobj.cpp
@@ -1736,6 +1736,8 @@ fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
 */
 		// [RH] If walking on a slope, stay on the slope
 		// killough 3/15/98: Allow objects to drop off
+		fixed_t startvelx = mo->velx, startvely = mo->vely;
+
 		if (!P_TryMove (mo, ptryx, ptryy, true, walkplane, tm))
 		{
 			// blocked move
@@ -1759,35 +1761,44 @@ fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
 					{
 						mo->velz = WATER_JUMP_SPEED;
 					}
-					if (player && (i_compatflags & COMPATF_WALLRUN))
+					// If the blocked move executed any push specials that changed the
+					// actor's velocity, do not attempt to slide.
+					if (mo->velx == startvelx && mo->vely == startvely)
 					{
-					// [RH] Here is the key to wall running: The move is clipped using its full speed.
-					// If the move is done a second time (because it was too fast for one move), it
-					// is still clipped against the wall at its full speed, so you effectively
-					// execute two moves in one tic.
-						P_SlideMove (mo, mo->velx, mo->vely, 1);
+						if (player && (i_compatflags & COMPATF_WALLRUN))
+						{
+						// [RH] Here is the key to wall running: The move is clipped using its full speed.
+						// If the move is done a second time (because it was too fast for one move), it
+						// is still clipped against the wall at its full speed, so you effectively
+						// execute two moves in one tic.
+							P_SlideMove (mo, mo->velx, mo->vely, 1);
+						}
+						else
+						{
+							P_SlideMove (mo, onestepx, onestepy, totalsteps);
+						}
+						if ((mo->velx | mo->vely) == 0)
+						{
+							steps = 0;
+						}
+						else
+						{
+							if (!player || !(i_compatflags & COMPATF_WALLRUN))
+							{
+								xmove = mo->velx;
+								ymove = mo->vely;
+								onestepx = xmove / steps;
+								onestepy = ymove / steps;
+								P_CheckSlopeWalk (mo, xmove, ymove);
+							}
+							startx = mo->x - Scale (xmove, step, steps);
+							starty = mo->y - Scale (ymove, step, steps);
+						}
 					}
 					else
-					{
-						P_SlideMove (mo, onestepx, onestepy, totalsteps);
-					}
-					if ((mo->velx | mo->vely) == 0)
 					{
 						steps = 0;
 					}
-					else
-					{
-						if (!player || !(i_compatflags & COMPATF_WALLRUN))
-						{
-							xmove = mo->velx;
-							ymove = mo->vely;
-							onestepx = xmove / steps;
-							onestepy = ymove / steps;
-							P_CheckSlopeWalk (mo, xmove, ymove);
-						}
-						startx = mo->x - Scale (xmove, step, steps);
-						starty = mo->y - Scale (ymove, step, steps);
-					}
 				}
 				else
 				{ // slide against another actor