diff --git a/src/b_bot.c b/src/b_bot.c
index dfb5ee1cf2f02d65b8bba6fd54290593391c2846..51dc4d2f21c9f4db04a4304c7604290b06e622a4 100644
--- a/src/b_bot.c
+++ b/src/b_bot.c
@@ -335,27 +335,6 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
 	jump_last = jump;
 	spin_last = spin;
 
-	// ********
-	// Thinkfly overlay
-	if (thinkfly)
-	{
-		if (!tails->hnext)
-		{
-			P_SetTarget(&tails->hnext, P_SpawnMobjFromMobj(tails, 0, 0, 0, MT_OVERLAY));
-			if (tails->hnext)
-			{
-				P_SetTarget(&tails->hnext->target, tails);
-				P_SetTarget(&tails->hnext->hprev, tails);
-				P_SetMobjState(tails->hnext, S_FLIGHTINDICATOR);
-			}
-		}
-	}
-	else if (tails->hnext && tails->hnext->type == MT_OVERLAY && tails->hnext->state == states+S_FLIGHTINDICATOR)
-	{
-		P_RemoveMobj(tails->hnext);
-		P_SetTarget(&tails->hnext, NULL);
-	}
-
 	// Turn the virtual keypresses into ticcmd_t.
 	B_KeysToTiccmd(tails, cmd, forward, backward, left, right, false, false, jump, spin);
 
@@ -565,3 +544,30 @@ void B_RespawnBot(INT32 playernum)
 	P_SetScale(tails, sonic->scale);
 	tails->destscale = sonic->destscale;
 }
+
+void B_HandleFlightIndicator(player_t *player)
+{
+	mobj_t *tails = player->mo;
+
+	if (!tails)
+		return;
+
+	if (thinkfly && player->bot == 1 && tails->health)
+	{
+		if (!tails->hnext)
+		{
+			P_SetTarget(&tails->hnext, P_SpawnMobjFromMobj(tails, 0, 0, 0, MT_OVERLAY));
+			if (tails->hnext)
+			{
+				P_SetTarget(&tails->hnext->target, tails);
+				P_SetTarget(&tails->hnext->hprev, tails);
+				P_SetMobjState(tails->hnext, S_FLIGHTINDICATOR);
+			}
+		}
+	}
+	else if (tails->hnext && tails->hnext->type == MT_OVERLAY && tails->hnext->state == states+S_FLIGHTINDICATOR)
+	{
+		P_RemoveMobj(tails->hnext);
+		P_SetTarget(&tails->hnext, NULL);
+	}
+}
diff --git a/src/b_bot.h b/src/b_bot.h
index b42577c5c94cbc0139b9f359886f7f32e8991f73..54ef300a342e15dc50008dec5a1abaa7b21be4ef 100644
--- a/src/b_bot.h
+++ b/src/b_bot.h
@@ -15,3 +15,4 @@ void B_KeysToTiccmd(mobj_t *mo, ticcmd_t *cmd, boolean forward, boolean backward
 boolean B_CheckRespawn(player_t *player);
 void B_MoveBlocked(player_t *player);
 void B_RespawnBot(INT32 playernum);
+void B_HandleFlightIndicator(player_t *player);
diff --git a/src/g_game.c b/src/g_game.c
index efb580f2196eda27e7b380ba8e6904137ed05db1..79ea2c70bbef5be74b13d252072d7be3ba28fabf 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -1718,6 +1718,7 @@ void G_BuildTiccmd2(ticcmd_t *cmd, INT32 realtics)
 			G_CopyTiccmd(cmd,  I_BaseTiccmd2(), 1); // empty, or external driver
 			B_BuildTiccmd(player, cmd);
 		}
+		B_HandleFlightIndicator(player);
 	}
 
 	if (cv_analog2.value) {
@@ -1854,8 +1855,7 @@ void G_DoLoadLevel(boolean resetplayer)
 		return;
 	}
 
-	if (!resetplayer)
-		P_FindEmerald();
+	P_FindEmerald();
 
 	displayplayer = consoleplayer; // view the guy you are playing
 	if (!splitscreen && !botingame)
@@ -3398,7 +3398,7 @@ INT32 G_GetGametypeByName(const char *gametypestr)
 {
 	INT32 i;
 
-	for (i = 0; i < NUMGAMETYPES; i++)
+	for (i = 0; i < gametypecount; i++)
 		if (!stricmp(gametypestr, Gametype_Names[i]))
 			return i;
 
diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c
index 4df71d145903532f9336ab2b18c6e7ee5cd6d94b..8545a88b33e05e19bdb18fe23936fb2ed1c39195 100644
--- a/src/hardware/hw_light.c
+++ b/src/hardware/hw_light.c
@@ -374,7 +374,6 @@ light_t *t_lspr[NUMSPRITES] =
 	&lspr[NOLIGHT],     // SPR_ADST
 	&lspr[NOLIGHT],     // SPR_MCRT
 	&lspr[NOLIGHT],     // SPR_MCSP
-	&lspr[NOLIGHT],     // SPR_NON2
 	&lspr[NOLIGHT],     // SPR_SALD
 	&lspr[NOLIGHT],     // SPR_TRAE
 	&lspr[NOLIGHT],     // SPR_TRAI
diff --git a/src/p_inter.c b/src/p_inter.c
index d42bb51c099e754a0c7597db0f0e870ecf269d0d..dc52cd3c0309441bc7849a465eb5267d327015e9 100644
--- a/src/p_inter.c
+++ b/src/p_inter.c
@@ -1807,7 +1807,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
 			return;
 
 		case MT_MINECARTSPAWNER:
-			if (!player->bot && (special->fuse < TICRATE || player->powers[pw_carry] != CR_MINECART))
+			if (!player->bot && special->fuse <= TICRATE && player->powers[pw_carry] != CR_MINECART)
 			{
 				mobj_t *mcart = P_SpawnMobj(special->x, special->y, special->z, MT_MINECART);
 				P_SetTarget(&mcart->target, toucher);
@@ -2481,9 +2481,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
 
 					P_SetMobjState(scoremobj, scorestate);
 
-					// On ground? No chain starts.
-					if (source->player->powers[pw_invulnerability] || !P_IsObjectOnGround(source))
-						source->player->scoreadd = locscoreadd;
+					source->player->scoreadd = locscoreadd;
 				}
 			}
 
diff --git a/src/p_map.c b/src/p_map.c
index 25da9c58dd5f62fd957b1f055cca70a1d26c204f..cd4ac3ca837d45843f409639226323b962687587 100644
--- a/src/p_map.c
+++ b/src/p_map.c
@@ -829,13 +829,13 @@ static boolean PIT_CheckThing(mobj_t *thing)
 			for (iter = thing->subsector->sector->thinglist; iter; iter = iter->snext)
 				if (iter->type == thing->type && iter->health > 0 && iter->flags & MF_SOLID && (iter == thing || P_AproxDistance(P_AproxDistance(thing->x - iter->x, thing->y - iter->y), thing->z - iter->z) < 56*thing->scale))//FixedMul(56*FRACUNIT, thing->scale))
 					P_KillMobj(iter, tmthing, tmthing, 0);
+			return true;
 		}
 		else
 		{
-			thing->health = 0;
-			P_KillMobj(thing, tmthing, tmthing, 0);
+			if (P_DamageMobj(thing, tmthing, tmthing, 1, 0))
+				return true;
 		}
-		return true;
 	}
 
 	// vectorise metal - done in a special case as at this point neither has the right flags for touching
diff --git a/src/p_polyobj.c b/src/p_polyobj.c
index 4709e5e6fce4c8245b6da856426a0a9098ecb0c6..36a9ba61356a07aec6ab7e118890ec33183c39a7 100644
--- a/src/p_polyobj.c
+++ b/src/p_polyobj.c
@@ -1825,6 +1825,7 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
 	if (po->thinker == NULL)
 		po->thinker = &th->thinker;
 
+/*
 	// Find out target first.
 	// We redo this each tic to make savegame compatibility easier.
 	for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next)
@@ -1843,6 +1844,9 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
 			break;
 		}
 	}
+*/
+
+	target = th->target;
 
 	if (!target)
 	{
@@ -2025,6 +2029,8 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
 
 			target = waypoint;
 			th->pointnum = target->health;
+			// Set the mobj as your target! -- Monster Iestyn 27/12/19
+			P_SetTarget(&th->target, target);
 
 			// calculate MOMX/MOMY/MOMZ for next waypoint
 			// change slope
@@ -2651,6 +2657,9 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata)
 
 	// Set pointnum
 	th->pointnum = target->health;
+	th->target = NULL; // set to NULL first so the below doesn't go wrong
+	// Set the mobj as your target! -- Monster Iestyn 27/12/19
+	P_SetTarget(&th->target, target);
 
 	// We don't deal with the mirror crap here, we'll
 	// handle that in the T_Thinker function.
diff --git a/src/p_polyobj.h b/src/p_polyobj.h
index ffacf628b3cd4bfcac5d36fc5e91cee45a2ada2d..339390c0af8eaa9a3f2f3bbda918d3bcf577bba7 100644
--- a/src/p_polyobj.h
+++ b/src/p_polyobj.h
@@ -161,6 +161,8 @@ typedef struct polywaypoint_s
 	fixed_t diffx;
 	fixed_t diffy;
 	fixed_t diffz;
+
+	mobj_t *target; // next waypoint mobj
 } polywaypoint_t;
 
 typedef struct polyslidedoor_s
diff --git a/src/p_saveg.c b/src/p_saveg.c
index 4cfeab6f84aa28ab77e685c9a4545880af868138..2b6a474bf70999317e2567bf70cbfb0a39abce48 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -2055,6 +2055,7 @@ static void SavePolywaypointThinker(const thinker_t *th, UINT8 type)
 	WRITEFIXED(save_p, ht->diffx);
 	WRITEFIXED(save_p, ht->diffy);
 	WRITEFIXED(save_p, ht->diffz);
+	WRITEUINT32(save_p, SaveMobjnum(ht->target));
 }
 
 //
@@ -3244,6 +3245,7 @@ static inline thinker_t* LoadPolywaypointThinker(actionf_p1 thinker)
 	ht->diffx = READFIXED(save_p);
 	ht->diffy = READFIXED(save_p);
 	ht->diffz = READFIXED(save_p);
+	ht->target = LoadMobj(READUINT32(save_p));
 	return &ht->thinker;
 }
 
@@ -3538,6 +3540,7 @@ static void P_NetUnArchiveThinkers(void)
 
 				case tc_polywaypoint:
 					th = LoadPolywaypointThinker((actionf_p1)T_PolyObjWaypoint);
+					restoreNum = true;
 					break;
 
 				case tc_polyslidedoor:
@@ -3599,9 +3602,9 @@ static void P_NetUnArchiveThinkers(void)
 	if (restoreNum)
 	{
 		executor_t *delay = NULL;
+		polywaypoint_t *polywp = NULL;
 		UINT32 mobjnum;
-		for (currentthinker = thlist[THINK_MAIN].next; currentthinker != &thlist[THINK_MAIN];
-		currentthinker = currentthinker->next)
+		for (currentthinker = thlist[THINK_MAIN].next; currentthinker != &thlist[THINK_MAIN]; currentthinker = currentthinker->next)
 		{
 			if (currentthinker->function.acp1 != (actionf_p1)T_ExecutorDelay)
 				continue;
@@ -3610,6 +3613,15 @@ static void P_NetUnArchiveThinkers(void)
 				continue;
 			delay->caller = P_FindNewPosition(mobjnum);
 		}
+		for (currentthinker = thlist[THINK_POLYOBJ].next; currentthinker != &thlist[THINK_POLYOBJ]; currentthinker = currentthinker->next)
+		{
+			if (currentthinker->function.acp1 != (actionf_p1)T_PolyObjWaypoint)
+				continue;
+			polywp = (void *)currentthinker;
+			if (!(mobjnum = (UINT32)(size_t)polywp->target))
+				continue;
+			polywp->target = P_FindNewPosition(mobjnum);
+		}
 	}
 }
 
diff --git a/src/p_user.c b/src/p_user.c
index b26615b465ce2ba36427cc6744ca50a6b84fb855..f3e6d4c975e91ccfab719a935f64adebce317f9d 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -4631,6 +4631,12 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd)
 						S_StartSound(player->mo, sfx_spin);
 						break;
 					}
+					if (player->dashspeed < player->mindash)
+						player->dashspeed = player->mindash;
+
+					if (player->dashspeed > player->maxdash)
+						player->dashspeed = player->maxdash;
+					
 					if (player->dashspeed < player->maxdash && player->mindash != player->maxdash)
 					{
 #define chargecalculation (6*(player->dashspeed - player->mindash))/(player->maxdash - player->mindash)
@@ -7780,6 +7786,7 @@ void P_ElementalFire(player_t *player, boolean cropcircle)
 			flame->fuse = TICRATE*7; // takes about an extra second to hit the ground
 			flame->destscale = player->mo->scale;
 			P_SetScale(flame, player->mo->scale);
+			flame->flags2 = (flame->flags2 & ~MF2_OBJECTFLIP)|(player->mo->flags2 & MF2_OBJECTFLIP);
 			flame->eflags = (flame->eflags & ~MFE_VERTICALFLIP)|(player->mo->eflags & MFE_VERTICALFLIP);
 			P_InstaThrust(flame, flame->angle, FixedMul(3*FRACUNIT, flame->scale));
 			P_SetObjectMomZ(flame, 3*FRACUNIT, false);
@@ -11244,7 +11251,10 @@ static void P_DoMetalJetFume(player_t *player, mobj_t *fume)
 		if (panim == PA_WALK)
 		{
 			if (stat != fume->info->spawnstate)
+			{
+				fume->threshold = 0;
 				P_SetMobjState(fume, fume->info->spawnstate);
+			}
 			return;
 		}
 	}
@@ -11275,6 +11285,12 @@ static void P_DoMetalJetFume(player_t *player, mobj_t *fume)
 		if (underwater)
 		{
 			fume->frame = (fume->frame & FF_FRAMEMASK) | FF_ANIMATE | (P_RandomRange(0, 9) * FF_TRANS10);
+			fume->threshold = 1;
+		}
+		else if (fume->threshold)
+		{
+			fume->frame = (fume->frame & FF_FRAMEMASK) | fume->state->frame;
+			fume->threshold = 0;
 		}
 	}
 
diff --git a/src/r_defs.h b/src/r_defs.h
index 5de9dd15a04bd5345b94cc2193928abb2e992136..96ef953ceb54bee4f5a548241df0ec1c26c191fd 100644
--- a/src/r_defs.h
+++ b/src/r_defs.h
@@ -729,9 +729,11 @@ typedef struct
 {
 	patch_t *patch[8][ROTANGLES];
 	boolean cached[8];
+#ifdef HWRENDER
 	aatree_t *hardware_patch[8];
+#endif/*HWRENDER*/
 } rotsprite_t;
-#endif
+#endif/*ROTSPRITE*/
 
 typedef enum
 {
diff --git a/src/r_things.c b/src/r_things.c
index 342a45e057da6109468a5ea7aed22f5a32a5db2a..b9871c06bf155e478b2dd804eeb5e5a7089e784d 100644
--- a/src/r_things.c
+++ b/src/r_things.c
@@ -125,9 +125,11 @@ static void R_InstallSpriteLump(UINT16 wad,            // graphics patch
 		sprtemp[frame].rotsprite.cached[r] = false;
 		for (ang = 0; ang < ROTANGLES; ang++)
 			sprtemp[frame].rotsprite.patch[r][ang] = NULL;
+#ifdef HWRENDER
 		sprtemp[frame].rotsprite.hardware_patch[r] = M_AATreeAlloc(AATREE_ZUSER);
+#endif/*HWRENDER*/
 	}
-#endif
+#endif/*ROTSPRITE*/
 
 	if (rotation == 0)
 	{
diff --git a/src/s_sound.c b/src/s_sound.c
index a494990407693568ed6ddda9ad042784dd3d8c66..0235d8376ce791b7859ab8997153709a2b336848 100644
--- a/src/s_sound.c
+++ b/src/s_sound.c
@@ -61,7 +61,9 @@ static void GameMIDIMusic_OnChange(void);
 static void GameSounds_OnChange(void);
 static void GameDigiMusic_OnChange(void);
 
+#ifdef HAVE_OPENMPT
 static void ModFilter_OnChange(void);
+#endif
 
 static lumpnum_t S_GetMusicLumpNum(const char *mname);
 
diff --git a/src/sdl/sdl_sound.c b/src/sdl/sdl_sound.c
index 33b366bf60320270eb77df832e12257cc3f6b020..b8991293c344b65a8bc63ca356512896e3ffede6 100644
--- a/src/sdl/sdl_sound.c
+++ b/src/sdl/sdl_sound.c
@@ -1432,6 +1432,8 @@ static void I_ResumeGME(void)
 
 boolean I_LoadSong(char *data, size_t len)
 {
+	(void)data;
+	(void)len;
 	return false;
 }
 
@@ -1493,6 +1495,7 @@ boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms
 	(void)target_volume;
 	(void)source_volume;
 	(void)ms;
+	(void)callback;
 	return false;
 }
 
@@ -1500,6 +1503,7 @@ boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void))
 {
 	(void)target_volume;
 	(void)ms;
+	(void)callback;
 	return false;
 }