diff --git a/src/d_clisrv.c b/src/d_clisrv.c
index 3878d879560d0a0991a0191cfdabd9c6188c8658..bb0978cdb2ba2eeeefe5fef1529eaaac633ec97c 100644
--- a/src/d_clisrv.c
+++ b/src/d_clisrv.c
@@ -2253,7 +2253,8 @@ static void Command_connect(void)
 		CONS_Printf(M_GetText(
 			"Connect <serveraddress> (port): connect to a server\n"
 			"Connect ANY: connect to the first lan server found\n"
-			"Connect SELF: connect to your own server.\n"));
+			//"Connect SELF: connect to your own server.\n"
+			));
 		return;
 	}
 
@@ -2267,7 +2268,7 @@ static void Command_connect(void)
 	// we don't request a restart unless the filelist differs
 
 	server = false;
-
+/*
 	if (!stricmp(COM_Argv(1), "self"))
 	{
 		servernode = 0;
@@ -2276,6 +2277,7 @@ static void Command_connect(void)
 		//SV_SpawnServer();
 	}
 	else
+*/
 	{
 		// used in menu to connect to a server in the list
 		if (netgame && !stricmp(COM_Argv(1), "node"))
@@ -2299,10 +2301,13 @@ static void Command_connect(void)
 
 			if (!stricmp(COM_Argv(1), "any"))
 				servernode = BROADCASTADDR;
-			else if (I_NetMakeNodewPort && COM_Argc() >= 3)
-				servernode = I_NetMakeNodewPort(COM_Argv(1), COM_Argv(2));
 			else if (I_NetMakeNodewPort)
-				servernode = I_NetMakeNode(COM_Argv(1));
+			{
+				if (COM_Argc() >= 3) // address AND port
+					servernode = I_NetMakeNodewPort(COM_Argv(1), COM_Argv(2));
+				else // address only, or address:port
+					servernode = I_NetMakeNode(COM_Argv(1));
+			}
 			else
 			{
 				CONS_Alert(CONS_ERROR, M_GetText("There is no server identification with this network driver\n"));
diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c
index d74cd0587778e9181e63d75d6de7ce01ce0eafb9..5ecde8a0b28047713d1817d52d158237e8a5fbd1 100644
--- a/src/hardware/hw_main.c
+++ b/src/hardware/hw_main.c
@@ -4753,8 +4753,6 @@ static polyplaneinfo_t *polyplaneinfo = NULL;
 #ifndef SORTING
 size_t numfloors = 0;
 #else
-//static floorinfo_t *floorinfo = NULL;
-//static size_t numfloors = 0;
 //Hurdler: 3D water sutffs
 typedef struct gr_drawnode_s
 {
diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h
index b0a14d3b58640b3d43ec10e91cb5de75b1f70a93..cb49f817ce1cf1f3e294755eebde0c19e9d08b74 100644
--- a/src/hardware/hw_main.h
+++ b/src/hardware/hw_main.h
@@ -46,8 +46,7 @@ void HWR_SetViewSize(void);
 void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option);
 void HWR_DrawFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t scale, INT32 option, const UINT8 *colormap);
 void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t scale, INT32 option, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h);
-void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, INT32 option, fixed_t scale, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h);
-void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap);
+void HWR_MakePatch(const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap);
 void HWR_CreatePlanePolygons(INT32 bspnum);
 void HWR_CreateStaticLightmaps(INT32 bspnum);
 void HWR_PrepLevelCache(size_t pnumtextures);
@@ -104,13 +103,4 @@ extern float gr_viewwindowx, gr_basewindowcentery;
 extern fixed_t *hwbbox;
 extern FTransform atransform;
 
-typedef struct
-{
-	wallVert3D    floorVerts[4];
-	FSurfaceInfo  Surf;
-	INT32           texnum;
-	INT32           blend;
-	INT32           drawcount;
-} floorinfo_t;
-
 #endif
diff --git a/src/p_inter.c b/src/p_inter.c
index d2101ca575ae358648a1ed863f642dce57b2d0d2..783f3229cb9096f37ade40e8c4fbbbafb26b6d76 100644
--- a/src/p_inter.c
+++ b/src/p_inter.c
@@ -1532,30 +1532,10 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
 			P_SetMobjState(special, special->info->deathstate);
 			return;
 		case MT_SPECIALSPIKEBALL:
-			if (!(!useNightsSS && G_IsSpecialStage(gamemap))) // Only for old special stages
-			{
-				P_DamageMobj(toucher, special, special, 1, 0);
-				return;
-			}
-
-			if (player->powers[pw_invulnerability] || player->powers[pw_flashing]
-			|| player->powers[pw_super])
-				return;
-			if (player->powers[pw_shield] || player->bot)  //If One-Hit Shield
-			{
-				P_RemoveShield(player);
-				S_StartSound(toucher, sfx_shldls); // Ba-Dum! Shield loss.
-			}
+			if (!useNightsSS && G_IsSpecialStage(gamemap)) // Only for old special stages
+				P_SpecialStageDamage(player, special, NULL);
 			else
-			{
-				P_PlayRinglossSound(toucher);
-				if (player->rings >= 10)
-					player->rings -= 10;
-				else
-					player->rings = 0;
-			}
-
-			P_DoPlayerPain(player, special, NULL);
+				P_DamageMobj(toucher, special, special, 1, 0);
 			return;
 		case MT_EGGMOBILE2_POGO:
 			// sanity checks
@@ -2979,7 +2959,17 @@ void P_RemoveShield(player_t *player)
 		else
 			player->powers[pw_shield] &= SH_STACK;
 	}
-	else if ((player->powers[pw_shield] & SH_NOSTACK) == SH_NONE)
+	else if (player->powers[pw_shield] & SH_NOSTACK)
+	{ // First layer shields
+		if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ARMAGEDDON) // Give them what's coming to them!
+		{
+			P_BlackOw(player); // BAM!
+			player->pflags |= PF_JUMPDOWN;
+		}
+		else
+			player->powers[pw_shield] &= SH_STACK;
+	}
+	else
 	{ // Second layer shields
 		if (((player->powers[pw_shield] & SH_STACK) == SH_FIREFLOWER) && !(player->powers[pw_super] || (mariomode && player->powers[pw_invulnerability])))
 		{
@@ -2988,13 +2978,6 @@ void P_RemoveShield(player_t *player)
 		}
 		player->powers[pw_shield] = SH_NONE;
 	}
-	else if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ARMAGEDDON) // Give them what's coming to them!
-	{
-		P_BlackOw(player); // BAM!
-		player->pflags |= PF_JUMPDOWN;
-	}
-	else
-		player->powers[pw_shield] = player->powers[pw_shield] & SH_STACK;
 }
 
 static void P_ShieldDamage(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype)
@@ -3064,6 +3047,38 @@ static void P_RingDamage(player_t *player, mobj_t *inflictor, mobj_t *source, IN
 		player->rings = 0;
 }
 
+//
+// P_SpecialStageDamage
+//
+// Do old special stage-style damaging
+// Removes 10 rings from the player, or knocks off their shield if they have one.
+// If they don't have anything, just knock the player back anyway (this doesn't kill them).
+//
+void P_SpecialStageDamage(player_t *player, mobj_t *inflictor, mobj_t *source)
+{
+	if (player->powers[pw_invulnerability] || player->powers[pw_flashing] || player->powers[pw_super])
+		return;
+
+	if (player->powers[pw_shield] || player->bot)  //If One-Hit Shield
+	{
+		P_RemoveShield(player);
+		S_StartSound(player->mo, sfx_shldls); // Ba-Dum! Shield loss.
+	}
+	else
+	{
+		P_PlayRinglossSound(player->mo);
+		if (player->rings >= 10)
+			player->rings -= 10;
+		else
+			player->rings = 0;
+	}
+
+	P_DoPlayerPain(player, inflictor, source);
+
+	if (gametype == GT_CTF && player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))
+		P_PlayerFlagBurst(player, false);
+}
+
 /** Damages an object, which may or may not be a player.
   * For melee attacks, source and inflictor are the same.
   *
diff --git a/src/p_local.h b/src/p_local.h
index b1bfc645641b39c04728d2bc45828a01214a6228..01d20b4ff2cd017de0d17431be96ba4e2016ab7c 100644
--- a/src/p_local.h
+++ b/src/p_local.h
@@ -417,6 +417,7 @@ void P_ForceFeed(const player_t *player, INT32 attack, INT32 fade, tic_t duratio
 void P_ForceConstant(const BasicFF_t *FFInfo);
 void P_RampConstant(const BasicFF_t *FFInfo, INT32 Start, INT32 End);
 void P_RemoveShield(player_t *player);
+void P_SpecialStageDamage(player_t *player, mobj_t *inflictor, mobj_t *source);
 boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype);
 void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damagetype);
 void P_PlayerRingBurst(player_t *player, INT32 num_rings); /// \todo better fit in p_user.c
diff --git a/src/p_spec.c b/src/p_spec.c
index 2cad4fc904dd8a8cae32edbabd8f2e08c957656d..8f85c713df888222fa9366977e296dff94457217 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -3525,31 +3525,14 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers
 				S_StartSound(player->mo, sfx_itemup);
 			}
 			break;
-		case 11: // Special Stage Damage - Kind of like a mini-P_DamageMobj()
-			if (player->powers[pw_invulnerability] || player->powers[pw_flashing] || player->powers[pw_super] || player->exiting || player->bot)
+		case 11: // Special Stage Damage
+			if (player->exiting || player->bot) // Don't do anything for bots or players who have just finished
 				break;
 
 			if (!(player->powers[pw_shield] || player->rings > 0)) // Don't do anything if no shield or rings anyway
 				break;
 
-			if (player->powers[pw_shield])
-			{
-				P_RemoveShield(player);
-				S_StartSound(player->mo, sfx_shldls); // Ba-Dum! Shield loss.
-			}
-			else if (player->rings > 0)
-			{
-				P_PlayRinglossSound(player->mo);
-				if (player->rings >= 10)
-					player->rings -= 10;
-				else
-					player->rings = 0;
-			}
-
-			P_DoPlayerPain(player, NULL, NULL); // this does basically everything that was here before
-
-			if (gametype == GT_CTF && player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))
-				P_PlayerFlagBurst(player, false);
+			P_SpecialStageDamage(player, NULL, NULL);
 			break;
 		case 12: // Space Countdown
 			if (!(player->powers[pw_shield] & SH_PROTECTWATER) && !player->powers[pw_spacetime])