diff --git a/src/p_sight.c b/src/p_sight.c
index bd6ab4d730f308973b011af421f147384ecbd648..132f993cfe1a1a95e4f083438fcd79eec2a4533b 100644
--- a/src/p_sight.c
+++ b/src/p_sight.c
@@ -103,12 +103,20 @@ static fixed_t P_InterceptVector2(divline_t *v2, divline_t *v1)
 static boolean P_CrossSubsecPolyObj(polyobj_t *po, register los_t *los)
 {
 	size_t i;
+	sector_t *polysec;
+
+	if (!(po->flags & POF_RENDERALL))
+		return true; // the polyobject isn't visible, so we can ignore it
+
+	polysec = po->lines[0]->backsector;
 
 	for (i = 0; i < po->numLines; ++i)
 	{
 		line_t *line = po->lines[i];
 		divline_t divl;
 		const vertex_t *v1,*v2;
+		fixed_t frac;
+		fixed_t topslope, bottomslope;
 
 		// already checked other side?
 		if (line->validcount == validcount)
@@ -140,7 +148,22 @@ static boolean P_CrossSubsecPolyObj(polyobj_t *po, register los_t *los)
 			continue;
 
 		// stop because it is not two sided
-		return false;
+		//if (!(po->flags & POF_TESTHEIGHT))
+			//return false;
+
+		frac = P_InterceptVector2(&los->strace, &divl);
+
+		// get slopes of top and bottom of this polyobject line
+		topslope = FixedDiv(polysec->ceilingheight - los->sightzstart , frac);
+		bottomslope = FixedDiv(polysec->floorheight - los->sightzstart , frac);
+
+		if (topslope >= los->topslope && bottomslope <= los->bottomslope)
+			return false; // view completely blocked
+
+		// TODO: figure out if it's worth considering partially blocked cases or not?
+		// maybe to adjust los's top/bottom slopes if needed
+		//if (los->topslope <= los->bottomslope)
+			//return false;
 	}
 
 	return true;
diff --git a/src/r_data.c b/src/r_data.c
index 4df5209a5a90b9fa4dd234083e00a5040000c602..d29c625e702cea9a7cd5553ecbe379a688e88416 100644
--- a/src/r_data.c
+++ b/src/r_data.c
@@ -635,42 +635,24 @@ void R_LoadTextures(void)
 			}
 			else
 			{
-				UINT16 patchcount = 1;
 				//CONS_Printf("\n\"%s\" is a single patch, dimensions %d x %d",W_CheckNameForNumPwad((UINT16)w,texstart+j),patchlump->width, patchlump->height);
-				if (SHORT(patchlump->width) == 64
-				&& SHORT(patchlump->height) == 64)
-				{ // 64x64 patch
-					const column_t *column;
-					for (k = 0; k < SHORT(patchlump->width); k++)
-					{ // Find use of transparency.
-						column = (const column_t *)((const UINT8 *)patchlump + LONG(patchlump->columnofs[k]));
-						if (column->length != SHORT(patchlump->height))
-							break;
-					}
-					if (k == SHORT(patchlump->width))
-						patchcount = 2; // No transparency? 64x128 texture.
-				}
-				texture = textures[i] = Z_Calloc(sizeof(texture_t) + (sizeof(texpatch_t) * patchcount), PU_STATIC, NULL);
+				texture = textures[i] = Z_Calloc(sizeof(texture_t) + sizeof(texpatch_t), PU_STATIC, NULL);
 
 				// Set texture properties.
 				M_Memcpy(texture->name, W_CheckNameForNumPwad((UINT16)w, texstart + j), sizeof(texture->name));
 				texture->width = SHORT(patchlump->width);
-				texture->height = SHORT(patchlump->height)*patchcount;
-				texture->patchcount = patchcount;
+				texture->height = SHORT(patchlump->height);
+				texture->patchcount = 1;
 				texture->holes = false;
 				texture->flip = 0;
 
 				// Allocate information for the texture's patches.
-				for (k = 0; k < patchcount; k++)
-				{
-					patch = &texture->patches[k];
+				patch = &texture->patches[0];
 
-					patch->originx = 0;
-					patch->originy = (INT16)(k*patchlump->height);
-					patch->wad = (UINT16)w;
-					patch->lump = texstart + j;
-					patch->flip = 0;
-				}
+				patch->originx = patch->originy = 0;
+				patch->wad = (UINT16)w;
+				patch->lump = texstart + j;
+				patch->flip = 0;
 
 				Z_Unlock(patchlump);
 
diff --git a/src/st_stuff.c b/src/st_stuff.c
index 89902fdb9c6225fc3a7c32690b16fa4c3c59e201..26f70dd970e2058df84566d1168d8c58595e6908 100644
--- a/src/st_stuff.c
+++ b/src/st_stuff.c
@@ -78,12 +78,6 @@ static patch_t *race3;
 static patch_t *racego;
 static patch_t *ttlnum;
 static patch_t *nightslink;
-static patch_t *count5;
-static patch_t *count4;
-static patch_t *count3;
-static patch_t *count2;
-static patch_t *count1;
-static patch_t *count0;
 static patch_t *curweapon;
 static patch_t *normring;
 static patch_t *bouncering;
@@ -272,12 +266,6 @@ void ST_LoadGraphics(void)
 	race3 = W_CachePatchName("RACE3", PU_HUDGFX);
 	racego = W_CachePatchName("RACEGO", PU_HUDGFX);
 	nightslink = W_CachePatchName("NGHTLINK", PU_HUDGFX);
-	count5 = W_CachePatchName("DRWNF0", PU_HUDGFX);
-	count4 = W_CachePatchName("DRWNE0", PU_HUDGFX);
-	count3 = W_CachePatchName("DRWND0", PU_HUDGFX);
-	count2 = W_CachePatchName("DRWNC0", PU_HUDGFX);
-	count1 = W_CachePatchName("DRWNB0", PU_HUDGFX);
-	count0 = W_CachePatchName("DRWNA0", PU_HUDGFX);
 
 	for (i = 0; i < 6; ++i)
 	{
@@ -862,50 +850,48 @@ static void ST_drawFirstPersonHUD(void)
 
 	p = NULL;
 
-	// Display the countdown drown numbers!
-	if ((player->powers[pw_underwater] <= 11*TICRATE + 1
-		&& player->powers[pw_underwater] >= 10*TICRATE + 1)
-		|| (player->powers[pw_spacetime] <= 11*TICRATE + 1
-		&& player->powers[pw_spacetime] >= 10*TICRATE + 1))
-	{
-		p = count5;
-	}
-	else if ((player->powers[pw_underwater] <= 9*TICRATE + 1
-		&& player->powers[pw_underwater] >= 8*TICRATE + 1)
-		|| (player->powers[pw_spacetime] <= 9*TICRATE + 1
-		&& player->powers[pw_spacetime] >= 8*TICRATE + 1))
-	{
-		p = count4;
-	}
-	else if ((player->powers[pw_underwater] <= 7*TICRATE + 1
-		&& player->powers[pw_underwater] >= 6*TICRATE + 1)
-		|| (player->powers[pw_spacetime] <= 7*TICRATE + 1
-		&& player->powers[pw_spacetime] >= 6*TICRATE + 1))
-	{
-		p = count3;
-	}
-	else if ((player->powers[pw_underwater] <= 5*TICRATE + 1
-		&& player->powers[pw_underwater] >= 4*TICRATE + 1)
-		|| (player->powers[pw_spacetime] <= 5*TICRATE + 1
-		&& player->powers[pw_spacetime] >= 4*TICRATE + 1))
 	{
-		p = count2;
-	}
-	else if ((player->powers[pw_underwater] <= 3*TICRATE + 1
-		&& player->powers[pw_underwater] >= 2*TICRATE + 1)
-		|| (player->powers[pw_spacetime] <= 3*TICRATE + 1
-		&& player->powers[pw_spacetime] >= 2*TICRATE + 1))
-	{
-		p = count1;
-	}
-	else if ((player->powers[pw_underwater] <= 1*TICRATE + 1
-		&& player->powers[pw_underwater] > 1)
-		|| (player->powers[pw_spacetime] <= 1*TICRATE + 1
-		&& player->powers[pw_spacetime] > 1))
-	{
-		p = count0;
+		UINT32 airtime;
+		UINT32 frame = 0;
+		spriteframe_t *sprframe;
+		// If both air timers are active, use the air timer with the least time left
+		if (player->powers[pw_underwater] && player->powers[pw_spacetime])
+			airtime = min(player->powers[pw_underwater], player->powers[pw_spacetime]);
+		else // Use whichever one is active otherwise
+			airtime = (player->powers[pw_spacetime]) ? player->powers[pw_spacetime] : player->powers[pw_underwater];
+
+		if (!airtime)
+			return; // No air timers are active, nothing would be drawn anyway
+
+		airtime--; // The original code was all n*TICRATE + 1, so let's remove 1 tic for simplicity
+
+		if (airtime > 11*TICRATE)
+			return; // Not time to draw any drown numbers yet
+		// Choose which frame to use based on time left
+		if (airtime <= 11*TICRATE && airtime >= 10*TICRATE)
+			frame = 5;
+		else if (airtime <= 9*TICRATE && airtime >= 8*TICRATE)
+			frame = 4;
+		else if (airtime <= 7*TICRATE && airtime >= 6*TICRATE)
+			frame = 3;
+		else if (airtime <= 5*TICRATE && airtime >= 4*TICRATE)
+			frame = 2;
+		else if (airtime <= 3*TICRATE && airtime >= 2*TICRATE)
+			frame = 1;
+		else if (airtime <= 1*TICRATE && airtime > 0)
+			frame = 0;
+		else
+			return; // Don't draw anything between numbers
+
+		if (player->charflags & SF_MACHINE)
+			frame += 6;  // Robots use different drown numbers
+
+		// Get the front angle patch for the frame
+		sprframe = &sprites[SPR_DRWN].spriteframes[frame];
+		p = W_CachePatchNum(sprframe->lumppat[0], PU_CACHE);
 	}
 
+	// Display the countdown drown numbers!
 	if (p)
 		V_DrawScaledPatch(SCX((BASEVIDWIDTH/2) - (SHORT(p->width)/2) + SHORT(p->leftoffset)), SCY(60 - SHORT(p->topoffset)),
 			V_NOSCALESTART|V_OFFSET|V_TRANSLUCENT, p);