diff --git a/src/p_enemy.c b/src/p_enemy.c
index 29fcf50c2d0fdd432f448fc5a7e088ef11899a79..7091af5429e834c098ba7d81ace6961cc238e37f 100644
--- a/src/p_enemy.c
+++ b/src/p_enemy.c
@@ -5582,7 +5582,7 @@ void A_MinusDigging(mobj_t *actor)
 
 		minus = actor;
 
-		P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_MinusCarry);
+		P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_MinusCarry, minus);
 	}
 	else
 	{
@@ -13726,7 +13726,7 @@ void A_DustDevilThink(mobj_t *actor)
 
 	dustdevil = actor;
 
-	P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_DustDevilLaunch);
+	P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_DustDevilLaunch, dustdevil);
 
 	//Whirlwind sound effect.
 	if (leveltime % 70 == 0)
@@ -13842,7 +13842,7 @@ void A_TNTExplode(mobj_t *actor)
 
 	barrel = actor;
 
-	P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_TNTExplode);
+	P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_TNTExplode, barrel);
 
 	// cause a quake -- P_StartQuake does not exist yet
 	epicenter.x = actor->x;
diff --git a/src/p_map.c b/src/p_map.c
index fce17f8c4bb2357eb9d789a46261119e67f9e946..337344b2fec2c966d0774513c02d9397b2974382 100644
--- a/src/p_map.c
+++ b/src/p_map.c
@@ -2262,7 +2262,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
 		for (bx = xl; bx <= xh; bx++)
 			for (by = yl; by <= yh; by++)
 			{
-				if (!P_BlockThingsIterator(bx, by, PIT_CheckThing))
+				if (!P_BlockThingsIterator(bx, by, PIT_CheckThing, tmthing))
 					blockval = false;
 				else
 					tmhitthing = tmfloorthing;
@@ -2876,7 +2876,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
 		standx = x;
 		standy = y;
 
-		P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_PushableMoved);
+		P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_PushableMoved, stand);
 	}
 
 	// Link the thing into its new position
@@ -4223,7 +4223,7 @@ void P_RadiusAttack(mobj_t *spot, mobj_t *source, fixed_t damagedist, UINT8 dama
 	bombdamagetype = damagetype;
 	bombsightcheck = sightcheck;
 
-	P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_RadiusAttack);
+	P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_RadiusAttack, bombspot);
 }
 
 //
diff --git a/src/p_maputl.c b/src/p_maputl.c
index 5398fd7a4c584022e8f33bb49312a176207e74b8..3e30c5d6e3f45fdb08018fbe0ef7c3b8d414f982 100644
--- a/src/p_maputl.c
+++ b/src/p_maputl.c
@@ -1050,9 +1050,13 @@ boolean P_BlockLinesIterator(INT32 x, INT32 y, boolean (*func)(line_t *))
 //
 // P_BlockThingsIterator
 //
-boolean P_BlockThingsIterator(INT32 x, INT32 y, boolean (*func)(mobj_t *))
+boolean P_BlockThingsIterator(INT32 x, INT32 y, boolean (*func)(mobj_t *), mobj_t *thing)
 {
 	blocknode_t *block, *next = NULL;
+	
+	boolean checkthing = false;
+	if (thing)
+			checkthing = true;
 
 	if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight)
 		return true;
@@ -1065,20 +1069,20 @@ boolean P_BlockThingsIterator(INT32 x, INT32 y, boolean (*func)(mobj_t *))
 		if (!func(block->mobj))
 			return false;
 
-		if (P_MobjWasRemoved(tmthing)) // func just popped our tmthing, cannot continue.
+		if (checkthing && P_MobjWasRemoved(thing)) // func just popped our tmthing, cannot continue.
 			return true;
 	}
 
 	return true;
 }
 
-boolean P_DoBlockThingsIterate(int x1, int y1, int x2, int y2, boolean (*func)(mobj_t *))
+boolean P_DoBlockThingsIterate(int x1, int y1, int x2, int y2, boolean (*func)(mobj_t *), mobj_t *thing)
 {
 	boolean status = true;
 
 	for (INT32 bx = x1; bx <= x2; bx++)
 		for (INT32 by = y1; by <= y2; by++)
-			if (!P_BlockThingsIterator(bx, by, func))
+			if (!P_BlockThingsIterator(bx, by, func, thing))
 				status = false;
 
 	return status;
@@ -1451,7 +1455,7 @@ boolean P_PathTraverse(fixed_t px1, fixed_t py1, fixed_t px2, fixed_t py2,
 	INT32 flags, traverser_t trav)
 {
 	fixed_t xt1, yt1, xt2, yt2;
-	fixed_t xstep, ystep, partial, xintercept, yintercept;
+	fixed_t xstep, ystep, partialx, partialy, xintercept, yintercept;
 	INT32 mapx, mapy, mapxstep, mapystep, count;
 
 	earlyout = flags & PT_EARLYOUT;
@@ -1469,57 +1473,83 @@ boolean P_PathTraverse(fixed_t px1, fixed_t py1, fixed_t px2, fixed_t py2,
 	trace.y = py1;
 	trace.dx = px2 - px1;
 	trace.dy = py2 - py1;
-
-	px1 -= bmaporgx;
-	py1 -= bmaporgy;
-	xt1 = (unsigned)px1>>MAPBLOCKSHIFT;
-	yt1 = (unsigned)py1>>MAPBLOCKSHIFT;
-
-	px2 -= bmaporgx;
-	py2 -= bmaporgy;
-	xt2 = (unsigned)px2>>MAPBLOCKSHIFT;
-	yt2 = (unsigned)py2>>MAPBLOCKSHIFT;
+	
+	xt1 = px1>>MAPBLOCKSHIFT;
+	yt1 = py2>>MAPBLOCKSHIFT;
+	px1 = (unsigned)(px1 - bmaporgx);
+	py1 = (unsigned)(py1 - bmaporgy);
+	
+	xt2 = px2>>MAPBLOCKSHIFT;
+	yt2 = py2>>MAPBLOCKSHIFT;
+	px2 = (unsigned)(px2 - bmaporgx);
+	py2 = (unsigned)(py2 - bmaporgy);
 
 	if (xt2 > xt1)
 	{
 		mapxstep = 1;
-		partial = FRACUNIT - ((px1>>MAPBTOFRAC) & FRACMASK);
+		partialx = FRACUNIT - (((unsigned)px1>>MAPBTOFRAC) & FRACMASK);
 		ystep = FixedDiv(py2 - py1, abs(px2 - px1));
 	}
 	else if (xt2 < xt1)
 	{
 		mapxstep = -1;
-		partial = (px1>>MAPBTOFRAC) & FRACMASK;
+		partialx = ((unsigned)px1>>MAPBTOFRAC) & FRACMASK;
 		ystep = FixedDiv(py2 - py1, abs(px2 - px1));
 	}
 	else
 	{
 		mapxstep = 0;
-		partial = FRACUNIT;
+		partialx = FRACUNIT;
 		ystep = 256*FRACUNIT;
 	}
 
-	yintercept = (py1>>MAPBTOFRAC) + FixedMul(partial, ystep);
+	yintercept = ((unsigned)py1>>MAPBTOFRAC) + FixedMul(partialx, ystep);
 
 	if (yt2 > yt1)
 	{
 		mapystep = 1;
-		partial = FRACUNIT - ((py1>>MAPBTOFRAC) & FRACMASK);
+		partialy = FRACUNIT - (((unsigned)py1>>MAPBTOFRAC) & FRACMASK);
 		xstep = FixedDiv(px2 - px1, abs(py2 - py1));
 	}
 	else if (yt2 < yt1)
 	{
 		mapystep = -1;
-		partial = (py1>>MAPBTOFRAC) & FRACMASK;
+		partialy = ((unsigned)py1>>MAPBTOFRAC) & FRACMASK;
 		xstep = FixedDiv(px2 - px1, abs(py2 - py1));
 	}
 	else
 	{
 		mapystep = 0;
-		partial = FRACUNIT;
+		partialy = FRACUNIT;
 		xstep = 256*FRACUNIT;
 	}
-	xintercept = (px1>>MAPBTOFRAC) + FixedMul(partial, xstep);
+	xintercept = ((unsigned)px1>>MAPBTOFRAC) + FixedMul(partialy, xstep);
+	
+	// [RH] Fix for traces that pass only through blockmap corners. In that case,
+	// xintercept and yintercept can both be set ahead of mapx and mapy, so the
+	// for loop would never advance anywhere.
+	
+	if (abs(xstep) == 1 && abs(ystep) == 1)
+	{
+		if (ystep < 0)
+		{
+			partialx = FRACUNIT - partialx;
+		}
+		if (xstep < 0)
+		{
+			partialy = FRACUNIT - partialy;
+		}
+		if (partialx == partialy)
+		{
+			xintercept = xt1;
+			yintercept = yt1;
+		}
+	}
+	
+	xt1 = (unsigned)px1>>MAPBLOCKSHIFT;
+	yt1 = (unsigned)py1>>MAPBLOCKSHIFT;
+	xt2 = (unsigned)px2>>MAPBLOCKSHIFT;
+	yt2 = (unsigned)py2>>MAPBLOCKSHIFT;
 
 	// Step through map blocks.
 	// Count is present to prevent a round off error
@@ -1534,21 +1564,64 @@ boolean P_PathTraverse(fixed_t px1, fixed_t py1, fixed_t px2, fixed_t py2,
 				return false; // early out
 
 		if (flags & PT_ADDTHINGS)
-			if (!P_BlockThingsIterator(mapx, mapy, PIT_AddThingIntercepts))
+			if (!P_BlockThingsIterator(mapx, mapy, PIT_AddThingIntercepts, NULL))
 				return false; // early out
 
-		if (mapx == xt2 && mapy == yt2)
+		// both coordinates reached the end, so end the traversing.
+		if ((mapxstep | mapystep) == 0)
 			break;
 
-		if ((yintercept >> FRACBITS) == mapy)
+		// [RH] Handle corner cases properly instead of pretending they don't exist.
+		switch ((((yintercept >> FRACBITS) == mapy) << 1) | ((xintercept >> FRACBITS) == mapx))
 		{
-			yintercept += ystep;
-			mapx += mapxstep;
-		}
-		else if ((xintercept >> FRACBITS) == mapx)
-		{
-			xintercept += xstep;
-			mapy += mapystep;
+			case 0: // neither xintercept nor yintercept match!
+				count = 64; // Stop traversing, because somebody screwed up.
+				break;
+			
+			case 1: // xintercept matches
+				xintercept += xstep;
+				mapy += mapystep;
+				if (mapy == yt2)
+					mapystep = 0;
+				break;
+			
+			case 2: // yintercept matches
+				yintercept += ystep;
+				mapx += mapxstep;
+				if (mapx == xt2)
+					mapxstep = 0;
+				break;
+			
+			case 3: // xintercept and yintercept both match
+				// The trace is exiting a block through its corner. Not only does the block
+				// being entered need to be checked (which will happen when this loop
+				// continues), but the other two blocks adjacent to the corner also need to
+				// be checked.
+				if (flags & PT_ADDLINES)
+				{
+					if (!P_BlockLinesIterator(mapx + mapxstep, mapy, PIT_AddLineIntercepts))
+						return false; // early out
+					if (!P_BlockLinesIterator(mapx, mapy + mapystep, PIT_AddLineIntercepts))
+						return false; // early out
+				}
+				
+				if (flags & PT_ADDTHINGS)
+				{
+					if (!P_BlockThingsIterator(mapx + mapxstep, mapy, PIT_AddThingIntercepts, NULL))
+						return false; // early out
+					if (!P_BlockThingsIterator(mapx, mapy + mapystep, PIT_AddThingIntercepts, NULL))
+						return false; // early out
+				}
+				
+				xintercept += xstep;
+				yintercept += ystep;
+				mapx += mapxstep;
+				mapy += mapystep;
+				if (mapx == xt2)
+					mapxstep = 0;
+				if (mapy == yt2)
+					mapystep = 0;
+				break;
 		}
 	}
 	// Go through the sorted list
diff --git a/src/p_maputl.h b/src/p_maputl.h
index 67f7fd086a3c4ec11109ead24048ad118256c2d1..11cc90c59099c6a0c28cfa7db171c126993512f2 100644
--- a/src/p_maputl.h
+++ b/src/p_maputl.h
@@ -61,7 +61,7 @@ extern ffloor_t *openfloorrover, *openceilingrover;
 void P_LineOpening(line_t *plinedef, mobj_t *mobj);
 
 boolean P_BlockLinesIterator(INT32 x, INT32 y, boolean(*func)(line_t *));
-boolean P_BlockThingsIterator(INT32 x, INT32 y, boolean(*func)(mobj_t *));
+boolean P_BlockThingsIterator(INT32 x, INT32 y, boolean(*func)(mobj_t *), mobj_t *thing);
 
 void P_ClearBlockNodes(void);
 
@@ -94,7 +94,7 @@ typedef struct bthingit_s
 bthingit_t *P_NewBlockThingsIterator(int x1, int y1, int x2, int y2);
 mobj_t *P_BlockThingsIteratorNext(bthingit_t *it, boolean centeronly);
 void P_FreeBlockThingsIterator(bthingit_t *it);
-boolean P_DoBlockThingsIterate(int x1, int y1, int x2, int y2, boolean (*func)(mobj_t *));
+boolean P_DoBlockThingsIterate(int x1, int y1, int x2, int y2, boolean (*func)(mobj_t *), mobj_t *thing);
 
 #define PT_ADDLINES     1
 #define PT_ADDTHINGS    2
diff --git a/src/p_mobj.c b/src/p_mobj.c
index 9257177cd8d3e1b02e8b3ba664883f7881eb9025..6a116a04488bfcb5244957dc2cb5174436433cb3 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -9334,7 +9334,7 @@ static void P_PointPushThink(mobj_t *mobj)
 	yl = (unsigned)(mobj->y - radius - bmaporgy)>>MAPBLOCKSHIFT;
 	yh = (unsigned)(mobj->y + radius - bmaporgy)>>MAPBLOCKSHIFT;
 
-	P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_PushThing);
+	P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_PushThing, pushmobj);
 }
 
 static boolean P_MobjRegularThink(mobj_t *mobj)
diff --git a/src/p_user.c b/src/p_user.c
index b5423e13d2e5525001b8eaa7ec59f66b2d5037aa..25c68e5752afc82b28655f02d58b670706a4ac75 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -4125,7 +4125,7 @@ static void P_DoTeeter(player_t *player)
 			teeteryl = teeteryh = player->mo->y;
 			couldteeter = false;
 			solidteeter = teeter;
-			if (!P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_CheckSolidsTeeter))
+			if (!P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_CheckSolidsTeeter, tmthing))
 				goto teeterdone; // we've found something that stops us teetering at all
 teeterdone:
 			teeter = solidteeter;