diff --git a/src/doomstat.h b/src/doomstat.h
index 3772456dfdff33f64877f7c65c31fd689155dc8b..a0cc83c1a10d445be22f86eec173a3b49e750fa0 100644
--- a/src/doomstat.h
+++ b/src/doomstat.h
@@ -391,7 +391,16 @@ enum {
 	TEAM_NONE,
 	TEAM_RED,
 	TEAM_BLUE,
-	MAXTEAMS = 4
+	TEAM_PLAYING = 1,
+	MAXTEAMS = 16
+};
+
+enum {
+	TEAM_ICON,
+	TEAM_ICON_FLAG,
+	TEAM_ICON_GOT_FLAG,
+	TEAM_ICON_MISSING_FLAG,
+	TEAM_ICON_MAX
 };
 
 typedef struct
@@ -403,6 +412,7 @@ typedef struct
 	UINT16 color;
 	UINT16 weapon_color;
 	UINT16 missile_color;
+	char *icons[TEAM_ICON_MAX];
 } team_t;
 
 extern team_t teams[MAXTEAMS];
@@ -485,6 +495,8 @@ typedef struct
 	INT16 rankings_type;
 	INT32 pointlimit;
 	INT32 timelimit;
+	UINT8 numteams;
+	UINT8 teams[MAXTEAMS];
 } gametype_t;
 
 extern gametype_t gametypes[NUMGAMETYPES];
diff --git a/src/g_game.c b/src/g_game.c
index 5e3f9ec9409b89602c58cd1b2e7b69741a303647..5bf91c1b92f9d1bf843acce8525b1a17452d4c7e 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -3459,7 +3459,9 @@ gametype_t gametypes[NUMGAMETYPES] = {
 		.rankings_type = RANKINGS_DEFAULT,
 		// default settings for match: timelimit 10 mins, no pointlimit
 		.timelimit = 10,
-		.pointlimit = 0
+		.pointlimit = 0,
+		.numteams = 2,
+		.teams = { TEAM_RED, TEAM_BLUE }
 	},
 	// GT_TAG
 	{
@@ -3491,7 +3493,9 @@ gametype_t gametypes[NUMGAMETYPES] = {
 		.rankings_type = RANKINGS_DEFAULT,
 		// default settings for CTF: no timelimit, pointlimit 5
 		.timelimit = 0,
-		.pointlimit = 5
+		.pointlimit = 5,
+		.numteams = 2,
+		.teams = { TEAM_RED, TEAM_BLUE }
 	},
 };
 
@@ -3526,9 +3530,17 @@ static void G_InitTeams(void)
 
 	teams[TEAM_RED].name = Z_StrDup("Red");
 	teams[TEAM_RED].flag_name = Z_StrDup("Red Flag");
+	teams[TEAM_RED].icons[TEAM_ICON] = Z_StrDup("RMATCICO");
+	teams[TEAM_RED].icons[TEAM_ICON_FLAG] = Z_StrDup("RFLAGICO");
+	teams[TEAM_RED].icons[TEAM_ICON_GOT_FLAG] = Z_StrDup("GOTRFLAG");
+	teams[TEAM_RED].icons[TEAM_ICON_MISSING_FLAG] = Z_StrDup("NONICON2");
 
 	teams[TEAM_BLUE].name = Z_StrDup("Blue");
 	teams[TEAM_BLUE].flag_name = Z_StrDup("Blue Flag");
+	teams[TEAM_BLUE].icons[TEAM_ICON] = Z_StrDup("BMATCICO");
+	teams[TEAM_BLUE].icons[TEAM_ICON_FLAG] = Z_StrDup("BFLAGICO");
+	teams[TEAM_BLUE].icons[TEAM_ICON_GOT_FLAG] = Z_StrDup("GOTBFLAG");
+	teams[TEAM_BLUE].icons[TEAM_ICON_MISSING_FLAG] = Z_StrDup("NONICON");
 
 	G_UpdateTeamSelection();
 }
@@ -3546,19 +3558,27 @@ void G_InitGametypes(void)
 
 void G_UpdateTeamSelection(void)
 {
-	UINT8 i;
+	UINT8 i = 0;
 
-	dummyteam_cons_t[0].value = 0;
-	dummyteam_cons_t[0].strvalue = "Spectator";
+	if (G_GametypeHasSpectators())
+	{
+		dummyteam_cons_t[0].value = 0;
+		dummyteam_cons_t[0].strvalue = "Spectator";
+		i++;
+	}
 
-	for (i = 1; i <= teamsingame; i++)
+	for (UINT8 j = 1; j < teamsingame; j++, i++)
 	{
-		dummyteam_cons_t[i].value = i;
-		dummyteam_cons_t[i].strvalue = teams[i].name;
+		UINT8 team = G_GetTeam(j);
+		dummyteam_cons_t[i].value = team;
+		dummyteam_cons_t[i].strvalue = teams[team].name;
 	}
 
 	dummyteam_cons_t[i].value = 0;
 	dummyteam_cons_t[i].strvalue = NULL;
+
+	cv_dummyteam.defaultvalue = dummyteam_cons_t[0].strvalue;
+	cv_dummyteam.value = 0;
 }
 
 //
@@ -3568,6 +3588,13 @@ void G_SetGametype(INT16 gtype)
 {
 	gametype = gtype;
 	gametyperules = gametypes[gametype].rules;
+
+	if (G_GametypeHasTeams())
+		teamsingame = gametypes[gametype].numteams + 1;
+	else
+		teamsingame = 3;
+
+	G_UpdateTeamSelection();
 }
 
 //
@@ -3855,6 +3882,49 @@ UINT32 G_TOLFlag(INT32 pgametype)
 	return gametypes[pgametype].typeoflevel;
 }
 
+UINT8 G_GetGametypeTeam(UINT8 gtype, UINT8 team)
+{
+	if (team == TEAM_NONE || team >= gametypes[gtype].numteams + 1)
+		return TEAM_NONE;
+
+	return gametypes[gtype].teams[team - 1] % MAXTEAMS;
+}
+
+UINT8 G_GetTeam(UINT8 team)
+{
+	return G_GetGametypeTeam(gametype, team);
+}
+
+UINT8 G_GetTeamFromTeamFlag(UINT32 flag)
+{
+	for (UINT16 i = 1; i < teamsingame; i++)
+	{
+		UINT32 otherflag = 1 << (i - 1);
+		if (flag == otherflag)
+			return i;
+	}
+
+	return TEAM_NONE;
+}
+
+UINT8 G_GetTeamListFromTeamFlags(UINT8 *teamlist, UINT32 flags)
+{
+	UINT8 count = 0;
+
+	for (UINT16 i = 1; i < teamsingame; i++)
+	{
+		UINT32 otherflag = 1 << (i - 1);
+		if ((flags & otherflag) != 0)
+		{
+			teamlist[count++] = i;
+			if (count == MAXTEAMS)
+				break;
+		}
+	}
+
+	return count;
+}
+
 const char *G_GetTeamName(UINT8 team)
 {
 	if (team >= numteams)
@@ -3895,6 +3965,22 @@ UINT16 G_GetTeamMissileColor(UINT8 team)
 	return teams[team].missile_color;
 }
 
+const char *G_GetTeamIcon(UINT8 team, UINT8 icon_type)
+{
+	if (team >= numteams || icon_type >= TEAM_ICON_MAX || !teams[team].icons[icon_type])
+		return NULL;
+
+	return teams[team].icons[icon_type];
+}
+
+boolean G_HasTeamIcon(UINT8 team, UINT8 icon_type)
+{
+	if (team >= numteams || icon_type >= TEAM_ICON_MAX || !teams[team].icons[icon_type])
+		return false;
+
+	return true;
+}
+
 /** Select a random map with the given typeoflevel flags.
   * If no map has those flags, this arbitrarily gives you map 1.
   * \param tolflags The typeoflevel flags to insist on. Other bits may
diff --git a/src/g_game.h b/src/g_game.h
index 6906ae44be557346c43500e26f02e5b5bf5a6af3..0f5533f892e7f743ac89fec126dc03e4ab24913f 100644
--- a/src/g_game.h
+++ b/src/g_game.h
@@ -223,11 +223,17 @@ void G_UseContinue(void);
 void G_AfterIntermission(void);
 void G_EndGame(void); // moved from y_inter.c/h and renamed
 
+UINT8 G_GetGametypeTeam(UINT8 gtype, UINT8 team);
+UINT8 G_GetTeam(UINT8 team);
+UINT8 G_GetTeamFromTeamFlag(UINT32 flag);
+UINT8 G_GetTeamListFromTeamFlags(UINT8 *teamlist, UINT32 flags);
 const char *G_GetTeamName(UINT8 team);
 const char *G_GetTeamFlagName(UINT8 team);
 UINT16 G_GetTeamColor(UINT8 team);
 UINT16 G_GetTeamWeaponColor(UINT8 team);
 UINT16 G_GetTeamMissileColor(UINT8 team);
+const char *G_GetTeamIcon(UINT8 team, UINT8 icon_type);
+boolean G_HasTeamIcon(UINT8 team, UINT8 icon_type);
 
 void G_Ticker(boolean run);
 boolean G_Responder(event_t *ev);
diff --git a/src/hu_stuff.c b/src/hu_stuff.c
index 96417512878822fcb8609567b87a29b26f52fa93..8649cc5507103c0a8919a2ff62488f78963bb7ec 100644
--- a/src/hu_stuff.c
+++ b/src/hu_stuff.c
@@ -85,10 +85,7 @@ static boolean headsupactive = false;
 boolean hu_showscores; // draw rankings
 static char hu_tick;
 
-patch_t *rflagico;
-patch_t *bflagico;
-patch_t *rmatcico;
-patch_t *bmatcico;
+patch_t *teamicons[MAXTEAMS][TEAM_ICON_MAX];
 patch_t *tagico;
 patch_t *tallminus;
 patch_t *tallinfin;
@@ -2324,23 +2321,21 @@ static void HU_Draw32TeamTabRankings(playersort_t *tab, INT32 whiteplayer)
 
 		if (gametyperules & GTR_TEAMFLAGS)
 		{
-			if (players[tab[i].num].gotflag & GF_REDFLAG) // Red
-				V_DrawFixedPatch((x-10)*FRACUNIT, (y)*FRACUNIT, FRACUNIT/4, 0, rflagico, 0);
-			else if (players[tab[i].num].gotflag & GF_BLUEFLAG) // Blue
-				V_DrawFixedPatch((x-10)*FRACUNIT, (y)*FRACUNIT, FRACUNIT/4, 0, bflagico, 0);
+			UINT8 teamlist[MAXTEAMS];
+			UINT8 teamcount = G_GetTeamListFromTeamFlags(teamlist, players[tab[i].num].gotflag);
+			if (teamcount > 0)
+				V_DrawFixedPatch((x-10)*FRACUNIT, (y)*FRACUNIT, FRACUNIT/4, 0, ST_GetTeamIconImage(teamlist[0], TEAM_ICON_FLAG), 0);
 		}
 
 		// Draw emeralds
 		if (players[tab[i].num].powers[pw_invulnerability] && (players[tab[i].num].powers[pw_invulnerability] == players[tab[i].num].powers[pw_sneakers]) && ((leveltime/7) & 1))
 		{
 			HU_Draw32Emeralds(x+60, y+2, 255);
-			//HU_DrawEmeralds(x-12,y+2,255);
 		}
 		else if (!players[tab[i].num].powers[pw_super]
 			|| ((leveltime/7) & 1))
 		{
 			HU_Draw32Emeralds(x+60, y+2, tab[i].emeralds);
-			//HU_DrawEmeralds(x-12,y+2,tab[i].emeralds);
 		}
 
 		if (supercheck)
@@ -2453,10 +2448,10 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer)
 
 		if (gametyperules & GTR_TEAMFLAGS)
 		{
-			if (players[tab[i].num].gotflag & GF_REDFLAG) // Red
-				V_DrawSmallScaledPatch(x-28, y-4, 0, rflagico);
-			else if (players[tab[i].num].gotflag & GF_BLUEFLAG) // Blue
-				V_DrawSmallScaledPatch(x-28, y-4, 0, bflagico);
+			UINT8 teamlist[MAXTEAMS];
+			UINT8 teamcount = G_GetTeamListFromTeamFlags(teamlist, players[tab[i].num].gotflag);
+			if (teamcount > 0)
+				V_DrawSmallScaledPatch(x-28, y-4, 0, ST_GetTeamIconImage(teamlist[0], TEAM_ICON_FLAG));
 		}
 
 		// Draw emeralds
@@ -2486,8 +2481,6 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer)
 		{
 			if (tab[i].num != serverplayer)
 				HU_drawPing(x+ 113, y, players[tab[i].num].quittime ? UINT32_MAX : playerpingtable[tab[i].num], false, 0);
-			//else
-			//	V_DrawSmallString(x+ 94, y+4, V_YELLOWMAP, "SERVER");
 		}
 	}
 }
diff --git a/src/hu_stuff.h b/src/hu_stuff.h
index e10b45164458ca33c95021823439780f187fb7db..f7d1aa1c6525dca4add3585cd3f31860190eb40a 100644
--- a/src/hu_stuff.h
+++ b/src/hu_stuff.h
@@ -14,6 +14,7 @@
 #ifndef __HU_STUFF_H__
 #define __HU_STUFF_H__
 
+#include "doomstat.h"
 #include "d_event.h"
 #include "w_wad.h"
 #include "r_defs.h"
@@ -88,10 +89,7 @@ extern patch_t *ntb_font[NT_FONTSIZE];
 extern patch_t *nto_font[NT_FONTSIZE];
 extern patch_t *ttlnum[10];
 extern patch_t *emeraldpics[3][8];
-extern patch_t *rflagico;
-extern patch_t *bflagico;
-extern patch_t *rmatcico;
-extern patch_t *bmatcico;
+extern patch_t *teamicons[MAXTEAMS][TEAM_ICON_MAX];
 extern patch_t *tagico;
 extern patch_t *tallminus;
 extern patch_t *tallinfin;
diff --git a/src/m_menu.c b/src/m_menu.c
index 853cb1f258dc990d361bb2e6d234e3ce5ae7b5e2..26366adb7db6923e6e421874094c89e7b915295d 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -467,7 +467,8 @@ static CV_PossibleValue_t dummymares_cons_t[] = {
 
 CV_PossibleValue_t dummyteam_cons_t[MAXTEAMS + 1];
 
-static consvar_t cv_dummyteam = CVAR_INIT ("dummyteam", "Spectator", CV_HIDEN, dummyteam_cons_t, NULL);
+consvar_t cv_dummyteam = CVAR_INIT ("dummyteam", "Spectator", CV_HIDEN, dummyteam_cons_t, NULL);
+
 static consvar_t cv_dummyscramble = CVAR_INIT ("dummyscramble", "Random", CV_HIDEN, dummyscramble_cons_t, NULL);
 static consvar_t cv_dummyrings = CVAR_INIT ("dummyrings", "0", CV_HIDEN, ringlimit_cons_t,	NULL);
 static consvar_t cv_dummylives = CVAR_INIT ("dummylives", "0", CV_HIDEN, liveslimit_cons_t, NULL);
diff --git a/src/m_menu.h b/src/m_menu.h
index c28467b78a354874a5ecc9f222af0d9078106792..0769454442d2c2f85e457011a7ea12ed8e4b2b62 100644
--- a/src/m_menu.h
+++ b/src/m_menu.h
@@ -437,6 +437,7 @@ extern consvar_t cv_showfocuslost;
 extern consvar_t cv_newgametype, cv_nextmap, cv_chooseskin, cv_serversort;
 extern CV_PossibleValue_t gametype_cons_t[];
 extern CV_PossibleValue_t dummyteam_cons_t[];
+extern consvar_t cv_dummyteam;
 
 extern INT16 startmap;
 extern INT32 ultimate_selectable;
diff --git a/src/netcode/d_netcmd.c b/src/netcode/d_netcmd.c
index 92161216cdf18cdc7821577e3d1e7a9b7d7d233f..e9ec1dbd887af30af4bc252d984c832d8d1d59d8 100644
--- a/src/netcode/d_netcmd.c
+++ b/src/netcode/d_netcmd.c
@@ -2269,9 +2269,9 @@ static void Got_Clearscores(UINT8 **cp, INT32 playernum)
 
 static UINT8 GetTeamByName(const char *name)
 {
-	for (UINT8 i = TEAM_RED; i < teamsingame; i++)
+	for (UINT8 i = 1; i < teamsingame; i++)
 	{
-		if (!stricmp(name, G_GetTeamName(i)))
+		if (!stricmp(name, G_GetTeamName(G_GetTeam(i))))
 			return i;
 	}
 	return MAXTEAMS;
@@ -2312,7 +2312,11 @@ static void Command_Teamchange_f(void)
 		{
 			UINT8 newteam = MAXTEAMS;
 			if (M_StringOnlyHasDigits(COM_Argv(1)))
+			{
 				newteam = atoi(COM_Argv(1));
+				if (newteam >= teamsingame)
+					newteam = MAXTEAMS;
+			}
 			else
 				newteam = GetTeamByName(COM_Argv(1));
 			if (newteam != MAXTEAMS)
@@ -2326,7 +2330,7 @@ static void Command_Teamchange_f(void)
 		if (!strcasecmp(COM_Argv(1), "spectator") || !strcasecmp(COM_Argv(1), "0"))
 			NetPacket.packet.newteam = 0;
 		else if (!strcasecmp(COM_Argv(1), "playing") || !strcasecmp(COM_Argv(1), "1"))
-			NetPacket.packet.newteam = MAXTEAMS;
+			NetPacket.packet.newteam = 3;
 		else
 			error = true;
 	}
@@ -2359,7 +2363,7 @@ static void Command_Teamchange_f(void)
 	else if (G_GametypeHasSpectators())
 	{
 		if ((players[consoleplayer].spectator && !NetPacket.packet.newteam) ||
-			(!players[consoleplayer].spectator && NetPacket.packet.newteam == MAXTEAMS))
+			(!players[consoleplayer].spectator && NetPacket.packet.newteam == 3))
 			error = true;
 	}
 #ifdef PARANOIA
@@ -2424,7 +2428,11 @@ static void Command_Teamchange2_f(void)
 		{
 			UINT8 newteam = MAXTEAMS;
 			if (M_StringOnlyHasDigits(COM_Argv(1)))
+			{
 				newteam = atoi(COM_Argv(1));
+				if (newteam >= teamsingame)
+					newteam = MAXTEAMS;
+			}
 			else
 				newteam = GetTeamByName(COM_Argv(1));
 			if (newteam != MAXTEAMS)
@@ -2438,7 +2446,7 @@ static void Command_Teamchange2_f(void)
 		if (!strcasecmp(COM_Argv(1), "spectator") || !strcasecmp(COM_Argv(1), "0"))
 			NetPacket.packet.newteam = 0;
 		else if (!strcasecmp(COM_Argv(1), "playing") || !strcasecmp(COM_Argv(1), "1"))
-			NetPacket.packet.newteam = MAXTEAMS;
+			NetPacket.packet.newteam = 3;
 		else
 			error = true;
 	}
@@ -2543,7 +2551,7 @@ static void Command_ServerTeamChange_f(void)
 		else if (!strcasecmp(COM_Argv(2), "notit") || !strcasecmp(COM_Argv(2), "2"))
 			NetPacket.packet.newteam = 2;
 		else if (!strcasecmp(COM_Argv(2), "playing") || !strcasecmp(COM_Argv(2), "3"))
-			NetPacket.packet.newteam = MAXTEAMS;
+			NetPacket.packet.newteam = 3;
 		else if (!strcasecmp(COM_Argv(2), "spectator") || !strcasecmp(COM_Argv(2), "0"))
 			NetPacket.packet.newteam = 0;
 		else
@@ -2557,7 +2565,11 @@ static void Command_ServerTeamChange_f(void)
 		{
 			UINT8 newteam = MAXTEAMS;
 			if (M_StringOnlyHasDigits(COM_Argv(1)))
+			{
 				newteam = atoi(COM_Argv(1));
+				if (newteam >= teamsingame)
+					newteam = MAXTEAMS;
+			}
 			else
 				newteam = GetTeamByName(COM_Argv(1));
 			if (newteam != MAXTEAMS)
@@ -2571,7 +2583,7 @@ static void Command_ServerTeamChange_f(void)
 		if (!strcasecmp(COM_Argv(2), "spectator") || !strcasecmp(COM_Argv(2), "0"))
 			NetPacket.packet.newteam = 0;
 		else if (!strcasecmp(COM_Argv(2), "playing") || !strcasecmp(COM_Argv(2), "1"))
-			NetPacket.packet.newteam = MAXTEAMS;
+			NetPacket.packet.newteam = 3;
 		else
 			error = true;
 	}
@@ -2682,7 +2694,7 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
 		if (((players[playernum].pflags & PF_TAGIT) && NetPacket.packet.newteam == 1) ||
 			(!(players[playernum].pflags & PF_TAGIT) && NetPacket.packet.newteam == 2) ||
 			(players[playernum].spectator && NetPacket.packet.newteam == 0) ||
-			(!players[playernum].spectator && NetPacket.packet.newteam == MAXTEAMS))
+			(!players[playernum].spectator && NetPacket.packet.newteam == 3))
 			return;
 	}
 	else if (G_GametypeHasTeams())
@@ -2694,7 +2706,7 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
 	else if (G_GametypeHasSpectators())
 	{
 		if ((players[playernum].spectator && !NetPacket.packet.newteam) ||
-			(!players[playernum].spectator && NetPacket.packet.newteam == MAXTEAMS))
+			(!players[playernum].spectator && NetPacket.packet.newteam == 3))
 			return;
 	}
 	else
@@ -2708,8 +2720,23 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
 		return;
 	}
 
-	// Don't switch team, just go away, please, go awaayyyy, aaauuauugghhhghgh
-	if (!LUA_HookTeamSwitch(&players[playernum], NetPacket.packet.newteam, players[playernum].spectator, NetPacket.packet.autobalance, NetPacket.packet.scrambled))
+	UINT8 ctfteam = NetPacket.packet.newteam;
+
+	if (G_GametypeHasTeams())
+	{
+		ctfteam = G_GetTeam(ctfteam);
+	}
+	else if (G_TagGametype() || G_GametypeHasSpectators())
+	{
+		if (ctfteam == 3)
+			ctfteam = TEAM_PLAYING;
+		else
+			ctfteam = 0;
+	}
+	else
+		ctfteam = 0;
+
+	if (!LUA_HookTeamSwitch(&players[playernum], ctfteam, players[playernum].spectator, NetPacket.packet.autobalance, NetPacket.packet.scrambled))
 		return;
 
 	//no status changes after hidetime
@@ -2757,7 +2784,7 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
 		break; //Otherwise, you don't need special permissions.
 	}
 
-	if (server && ((NetPacket.packet.newteam < 0 || NetPacket.packet.newteam > 3) || error))
+	if (server && ((NetPacket.packet.newteam < 0 || NetPacket.packet.newteam > MAXTEAMS) || error))
 	{
 		CONS_Alert(CONS_WARNING, M_GetText("Illegal team change received from player %s\n"), player_names[playernum]);
 		SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
@@ -2812,15 +2839,14 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
 	}
 	else if (G_GametypeHasTeams())
 	{
-		UINT8 team = NetPacket.packet.newteam % MAXTEAMS;
-		if (!team)
+		if (!ctfteam)
 		{
 			players[playernum].ctfteam = 0;
 			players[playernum].spectator = true;
 		}
 		else
 		{
-			players[playernum].ctfteam = team;
+			players[playernum].ctfteam = ctfteam;
 			players[playernum].spectator = false;
 		}
 	}
@@ -2833,20 +2859,23 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
 	}
 
 	if (NetPacket.packet.autobalance)
-		CONS_Printf(M_GetText("%s was autobalanced to %s%s%c.\n"), player_names[playernum], GetChatColorForSkincolor(G_GetTeamColor(NetPacket.packet.newteam)), G_GetTeamName(NetPacket.packet.newteam), '\x80');
+		CONS_Printf(M_GetText("%s was autobalanced to %s%s%c.\n"), player_names[playernum], GetChatColorForSkincolor(G_GetTeamColor(ctfteam)), G_GetTeamName(ctfteam), '\x80');
 	else if (NetPacket.packet.scrambled)
-		CONS_Printf(M_GetText("%s was scrambled to %s%s%c.\n"), player_names[playernum], GetChatColorForSkincolor(G_GetTeamColor(NetPacket.packet.newteam)), G_GetTeamName(NetPacket.packet.newteam), '\x80');
-	else if (NetPacket.packet.newteam == MAXTEAMS)
-		CONS_Printf(M_GetText("%s entered the game.\n"), player_names[playernum]);
-	else if (G_TagGametype() && NetPacket.packet.newteam != 0)
-	{
-		if (NetPacket.packet.newteam == 1)
-			CONS_Printf(M_GetText("%s is now IT!\n"), player_names[playernum]);
-		else if (NetPacket.packet.newteam == 2)
-			CONS_Printf(M_GetText("%s is no longer IT!\n"), player_names[playernum]);
-	}
-	else if (G_GametypeHasTeams() && NetPacket.packet.newteam != 0)
-		CONS_Printf(M_GetText("%s switched to %s%s%c.\n"), player_names[playernum], GetChatColorForSkincolor(G_GetTeamColor(NetPacket.packet.newteam)), G_GetTeamName(NetPacket.packet.newteam), '\x80');
+		CONS_Printf(M_GetText("%s was scrambled to %s%s%c.\n"), player_names[playernum], GetChatColorForSkincolor(G_GetTeamColor(ctfteam)), G_GetTeamName(ctfteam), '\x80');
+	else if (NetPacket.packet.newteam != 0)
+	{
+		if (G_TagGametype())
+		{
+			if (NetPacket.packet.newteam == 1)
+				CONS_Printf(M_GetText("%s is now IT!\n"), player_names[playernum]);
+			else if (NetPacket.packet.newteam == 2)
+				CONS_Printf(M_GetText("%s is no longer IT!\n"), player_names[playernum]);
+		}
+		else if (G_GametypeHasTeams())
+			CONS_Printf(M_GetText("%s switched to %s%s%c.\n"), player_names[playernum], GetChatColorForSkincolor(G_GetTeamColor(ctfteam)), G_GetTeamName(ctfteam), '\x80');
+		else
+			CONS_Printf(M_GetText("%s entered the game.\n"), player_names[playernum]);
+	}
 	else
 		CONS_Printf(M_GetText("%s became a spectator.\n"), player_names[playernum]);
 
@@ -4322,6 +4351,7 @@ retryscramble:
 	// Randomly place players on teams.
 	if (cv_teamscramble.value == 1)
 	{
+		// TODO
 		maxcomposition = playercount / 2;
 
 		// Now randomly assign players to teams.
@@ -4374,7 +4404,7 @@ retryscramble:
 		{
 			if (repick)
 			{
-				newteam = (INT16)((M_RandomByte() % 2) + TEAM_RED);
+				newteam = (INT16)((M_RandomByte() % 2) + 1);
 				repick = false;
 			}
 			else if (i != 2) // Mystic's secret sauce - ABBA is better than ABAB, so team B doesn't get worse players all around
diff --git a/src/p_tick.c b/src/p_tick.c
index a462c6dd48680acad8171bbfc817e81584d561ed..9a7b6513d88d33cd46230aafdfd389bff2424829 100644
--- a/src/p_tick.c
+++ b/src/p_tick.c
@@ -443,15 +443,17 @@ static void P_DoAutobalanceTeams(void)
 {
 	changeteam_union NetPacket;
 	UINT16 usvalue;
-	INT32 i=0;
-	INT32 red=0, blue=0;
-	INT32 redarray[MAXPLAYERS], bluearray[MAXPLAYERS];
-	INT32 redflagcarrier = 0, blueflagcarrier = 0;
-	INT32 totalred = 0, totalblue = 0;
+	INT32 i;
+	INT32 count[MAXTEAMS];
+	INT32 array[MAXTEAMS][MAXPLAYERS];
+	INT32 flagcarrier[MAXTEAMS];
+	INT32 total[MAXTEAMS];
 
 	NetPacket.value.l = NetPacket.value.b = 0;
-	memset(redarray, 0, sizeof(redarray));
-	memset(bluearray, 0, sizeof(bluearray));
+	memset(count, 0, sizeof(count));
+	memset(array, 0, sizeof(array));
+	memset(flagcarrier, 0, sizeof(flagcarrier));
+	memset(total, 0, sizeof(total));
 
 	// Only do it if we have enough room in the net buffer to send it.
 	// Otherwise, come back next time and try again.
@@ -464,39 +466,28 @@ static void P_DoAutobalanceTeams(void)
 	{
 		if (playeringame[i] && players[i].ctfteam)
 		{
-			if (players[i].ctfteam == TEAM_RED)
+			UINT8 team = players[i].ctfteam;
+			if (!players[i].gotflag)
 			{
-				if (!players[i].gotflag)
-				{
-					redarray[red] = i; //store the player's number.
-					red++;
-				}
-				else
-					redflagcarrier++;
+				array[team][count[team]] = i;
+				count[team]++;
 			}
 			else
-			{
-				if (!players[i].gotflag)
-				{
-					bluearray[blue] = i; //store the player's number.
-					blue++;
-				}
-				else
-					blueflagcarrier++;
-			}
+				flagcarrier[team]++;
 		}
 	}
 
-	totalred = red + redflagcarrier;
-	totalblue = blue + blueflagcarrier;
+	for (i = 0; i < teamsingame; i++)
+		total[i] = count[i] + flagcarrier[i];
 
-	if ((abs(totalred - totalblue) > max(1, (totalred + totalblue) / 8)))
+	// TODO
+	if ((abs(total[G_GetTeam(1)] - total[G_GetTeam(2)]) > max(1, (total[G_GetTeam(1)] + total[G_GetTeam(2)]) / 8)))
 	{
-		if (totalred > totalblue)
+		if (total[G_GetTeam(1)] > total[G_GetTeam(2)])
 		{
-			i = M_RandomKey(red);
-			NetPacket.packet.newteam = TEAM_BLUE;
-			NetPacket.packet.playernum = redarray[i];
+			i = M_RandomKey(count[G_GetTeam(1)]);
+			NetPacket.packet.newteam = 2;
+			NetPacket.packet.playernum = array[1][i];
 			NetPacket.packet.verification = true;
 			NetPacket.packet.autobalance = true;
 
@@ -505,9 +496,9 @@ static void P_DoAutobalanceTeams(void)
 		}
 		else
 		{
-			i = M_RandomKey(blue);
-			NetPacket.packet.newteam = TEAM_RED;
-			NetPacket.packet.playernum = bluearray[i];
+			i = M_RandomKey(count[G_GetTeam(2)]);
+			NetPacket.packet.newteam = 1;
+			NetPacket.packet.playernum = array[2][i];
 			NetPacket.packet.verification = true;
 			NetPacket.packet.autobalance = true;
 
diff --git a/src/p_user.c b/src/p_user.c
index 4757714002f72b0c0fd08c1c21ef0e387b0c4b42..52c005abdb11c50c39bd8ae1a7dd7a659fc979c9 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -3184,10 +3184,7 @@ static void P_DoPlayerHeadSigns(player_t *player)
 				sign->eflags |= MFE_VERTICALFLIP;
 			}
 
-			if (player->gotflag & GF_REDFLAG)
-				sign->frame = 1|FF_FULLBRIGHT;
-			else //if (player->gotflag & GF_BLUEFLAG)
-				sign->frame = 2|FF_FULLBRIGHT;
+			sign->frame = G_GetTeamFromTeamFlag(player->gotflag) | FF_FULLBRIGHT;
 		}
 	}
 
@@ -8683,7 +8680,7 @@ void P_MovePlayer(player_t *player)
 	// Toss a flag
 	if (G_GametypeHasTeams() && (cmd->buttons & BT_TOSSFLAG) && !(player->powers[pw_super]) && !(player->tossdelay))
 	{
-		if (!(player->gotflag & (GF_REDFLAG|GF_BLUEFLAG)))
+		if (!player->gotflag)
 			P_PlayerEmeraldBurst(player, true); // Toss emeralds
 		else
 			P_PlayerFlagBurst(player, true);
@@ -10502,7 +10499,44 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
 	}
 
 	return (x == thiscam->x && y == thiscam->y && z == thiscam->z && angle == thiscam->aiming);
+}
+
+static UINT8 P_GetWorstPerformingTeam(void)
+{
+	INT32 numplayers[MAXTEAMS];
+	INT32 leastscore = TEAM_NONE;
+	INT32 leastplayers = TEAM_NONE;
+
+	for (INT32 i = 0; i < MAXPLAYERS; i++)
+	{
+		if (playeringame[i])
+			numplayers[players[i].ctfteam]++;
+	}
+
+	for (INT32 i = 1; i < teamsingame; i++)
+	{
+		UINT8 team = G_GetTeam(i);
+		UINT8 compareto = leastscore == TEAM_NONE ? G_GetTeam(1) : leastscore;
+
+		if (teamscores[team] < teamscores[compareto])
+		{
+			leastscore = i;
+		}
 
+		compareto = leastplayers == TEAM_NONE ? G_GetTeam(1) : leastplayers;
+
+		if (numplayers[team] < numplayers[compareto])
+		{
+			leastplayers = i;
+		}
+	}
+
+	if (leastplayers != TEAM_NONE)
+		return leastplayers;
+	else if (leastscore != TEAM_NONE)
+		return leastscore;
+
+	return G_GetTeam(P_RandomRange(1, teamsingame - 1));
 }
 
 boolean P_SpectatorJoinGame(player_t *player)
@@ -10519,27 +10553,7 @@ boolean P_SpectatorJoinGame(player_t *player)
 	// Partial code reproduction from p_tick.c autobalance code.
 	else if (G_GametypeHasTeams())
 	{
-		INT32 changeto = 0;
-		INT32 z, numplayers[MAXTEAMS];
-
-		//find a team by num players, score, or random if all else fails.
-		for (z = 0; z < MAXPLAYERS; ++z)
-			if (playeringame[z])
-			{
-				numplayers[players[z].ctfteam]++;
-			}
-		// for z
-
-		if (numplayers[TEAM_BLUE] > numplayers[TEAM_RED])
-			changeto = TEAM_RED;
-		else if (numplayers[TEAM_RED] > numplayers[TEAM_BLUE])
-			changeto = TEAM_BLUE;
-		else if (teamscores[TEAM_BLUE] > teamscores[TEAM_RED])
-			changeto = TEAM_RED;
-		else if (teamscores[TEAM_RED] > teamscores[TEAM_BLUE])
-			changeto = TEAM_BLUE;
-		else
-			changeto = (P_RandomFixed() & 1) + TEAM_RED;
+		UINT8 changeto = P_GetWorstPerformingTeam();
 
 		if (!LUA_HookTeamSwitch(player, changeto, true, false, false))
 			return false;
@@ -10574,7 +10588,7 @@ boolean P_SpectatorJoinGame(player_t *player)
 		// respawn in place and sit there for the rest of the round.
 		if (!((gametyperules & GTR_HIDEFROZEN) && leveltime > (hidetime * TICRATE)))
 		{
-			if (!LUA_HookTeamSwitch(player, 3, true, false, false))
+			if (!LUA_HookTeamSwitch(player, TEAM_PLAYING, true, false, false))
 				return false;
 			if (player->mo)
 			{
diff --git a/src/st_stuff.c b/src/st_stuff.c
index 88f27d476572b6dc529d68abb86cfc434b962905..957e5ac3112a330fd2d35bae5620e08cdb9b447d 100644
--- a/src/st_stuff.c
+++ b/src/st_stuff.c
@@ -106,8 +106,6 @@ static patch_t *thundershield;
 static patch_t *invincibility;
 static patch_t *sneakers;
 static patch_t *gravboots;
-static patch_t *nonicon;
-static patch_t *nonicon2;
 static patch_t *nightopianhelper;
 static patch_t *linkfreeze;
 static patch_t *superparaloop;
@@ -131,8 +129,6 @@ static patch_t *capsulefill;
 patch_t *ngradeletters[7];
 static patch_t *minus5sec;
 static patch_t *minicaps;
-static patch_t *gotrflag;
-static patch_t *gotbflag;
 static patch_t *fnshico;
 
 static boolean facefreed[MAXPLAYERS];
@@ -318,11 +314,9 @@ void ST_LoadGraphics(void)
 	gravboots = W_CachePatchName("TVGVICON", PU_HUDGFX);
 
 	tagico = W_CachePatchName("TAGICO", PU_HUDGFX);
-	gotrflag = W_CachePatchName("GOTRFLAG", PU_HUDGFX);
-	gotbflag = W_CachePatchName("GOTBFLAG", PU_HUDGFX);
 	fnshico = W_CachePatchName("FNSHICO", PU_HUDGFX);
-	nonicon = W_CachePatchName("NONICON", PU_HUDGFX);
-	nonicon2 = W_CachePatchName("NONICON2", PU_HUDGFX);
+
+	ST_LoadTeamIcons();
 
 	// NiGHTS HUD things
 	nightopianhelper = W_CachePatchName("NHLPICON", PU_HUDGFX);
@@ -365,6 +359,28 @@ void ST_LoadGraphics(void)
 		ngradeletters[i] = W_CachePatchName(va("GRADE%d", i), PU_HUDGFX);
 }
 
+void ST_LoadTeamIcons(void)
+{
+	for (UINT8 i = 0; i < numteams; i++)
+	{
+		for (UINT8 j = 0; j < TEAM_ICON_MAX; j++)
+			teamicons[i][j] = W_CachePatchName(G_HasTeamIcon(i, j) ? G_GetTeamIcon(i, j) : "MISSING", PU_HUDGFX);
+	}
+}
+
+patch_t *ST_GetTeamIconImage(UINT8 team, UINT8 icon_type)
+{
+	if (team >= numteams || icon_type >= TEAM_ICON_MAX || !teamicons[team][icon_type])
+		return W_CachePatchName("MISSING", PU_PATCH);
+
+	return teamicons[team][icon_type];
+}
+
+patch_t *ST_GetCurrentTeamIconImage(UINT8 team, UINT8 icon_type)
+{
+	return ST_GetTeamIconImage(G_GetTeam(team), icon_type);
+}
+
 // made separate so that skins code can reload custom face graphics
 void ST_LoadFaceGraphics(INT32 skinnum)
 {
@@ -1578,11 +1594,12 @@ static void ST_drawPowerupHUD(void)
 // CTF flags
 // ---------
 
-	// YOU have a flag. Display a monitor-like icon for it.
+	// YOU have a flag. Display an icon for it.
 	if (stplyr->gotflag)
 	{
+		// TODO
 		flagoffs[q] = ICONSEP;
-		p = (stplyr->gotflag & GF_REDFLAG) ? gotrflag : gotbflag;
+		p = ST_GetCurrentTeamIconImage(G_GetTeamFromTeamFlag(stplyr->gotflag), TEAM_ICON_GOT_FLAG);
 		V_DrawSmallScaledPatch(offs, hudinfo[HUD_POWERUPS].y, V_PERPLAYER|hudinfo[HUD_POWERUPS].f|V_HUDTRANS, p);
 	}
 	else if (flagoffs[q])
@@ -2415,23 +2432,24 @@ static void ST_drawTeamHUD(void)
 	if (F_GetPromptHideHud(0)) // y base is 0
 		return;
 
-	rflagico = W_CachePatchName("RFLAGICO", PU_HUDGFX);
-	bflagico = W_CachePatchName("BFLAGICO", PU_HUDGFX);
-	rmatcico = W_CachePatchName("RMATCICO", PU_HUDGFX);
-	bmatcico = W_CachePatchName("BMATCICO", PU_HUDGFX);
-
 	if (LUA_HudEnabled(hud_teamscores))
 	{
+		patch_t *bmatcico = NULL;
+		patch_t *rmatcico = NULL;
+
 		if (gametyperules & GTR_TEAMFLAGS)
 		{
-			V_DrawSmallScaledPatch(BASEVIDWIDTH/2 - SEP - (bflagico->width / 4), 4, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, bflagico);
-			V_DrawSmallScaledPatch(BASEVIDWIDTH/2 + SEP - (rflagico->width / 4), 4, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, rflagico);
+			bmatcico = ST_GetCurrentTeamIconImage(1, TEAM_ICON_FLAG);
+			rmatcico = ST_GetCurrentTeamIconImage(2, TEAM_ICON_FLAG);
 		}
 		else
 		{
-			V_DrawSmallScaledPatch(BASEVIDWIDTH/2 - SEP - (bmatcico->width / 4), 4, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, bmatcico);
-			V_DrawSmallScaledPatch(BASEVIDWIDTH/2 + SEP - (rmatcico->width / 4), 4, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, rmatcico);
+			bmatcico = ST_GetCurrentTeamIconImage(1, TEAM_ICON);
+			rmatcico = ST_GetCurrentTeamIconImage(2, TEAM_ICON);
 		}
+
+		V_DrawSmallScaledPatch(BASEVIDWIDTH/2 - SEP - (bmatcico->width / 4), 4, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, bmatcico);
+		V_DrawSmallScaledPatch(BASEVIDWIDTH/2 + SEP - (rmatcico->width / 4), 4, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, rmatcico);
 	}
 
 	if (!(gametyperules & GTR_TEAMFLAGS))
@@ -2439,40 +2457,47 @@ static void ST_drawTeamHUD(void)
 	{
 		INT32 i;
 		UINT16 whichflag = 0;
+		UINT16 allflags = 0;
+
+		for (i = 1; i < teamsingame; i++)
+			allflags |= teams[G_GetTeam(i)].flag;
 
 		// Show which flags aren't at base.
 		for (i = 0; i < MAXPLAYERS; i++)
 		{
+			patch_t *rmissing = ST_GetCurrentTeamIconImage(1, TEAM_ICON_MISSING_FLAG);
+			patch_t *bmissing = ST_GetCurrentTeamIconImage(2, TEAM_ICON_MISSING_FLAG);
+
 			// Blue flag isn't at base
-			if (players[i].gotflag & GF_BLUEFLAG && LUA_HudEnabled(hud_teamscores))
-				V_DrawScaledPatch(BASEVIDWIDTH/2 - SEP - (nonicon->width / 2), 0, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, nonicon);
+			if (players[i].gotflag & teams[G_GetTeam(2)].flag && LUA_HudEnabled(hud_teamscores))
+				V_DrawScaledPatch(BASEVIDWIDTH/2 - SEP - (bmissing->width / 2), 0, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, bmissing);
 
 			// Red flag isn't at base
-			if (players[i].gotflag & GF_REDFLAG && LUA_HudEnabled(hud_teamscores))
-				V_DrawScaledPatch(BASEVIDWIDTH/2 + SEP - (nonicon2->width / 2), 0, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, nonicon2);
+			if (players[i].gotflag & teams[G_GetTeam(1)].flag && LUA_HudEnabled(hud_teamscores))
+				V_DrawScaledPatch(BASEVIDWIDTH/2 + SEP - (rmissing->width / 2), 0, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, rmissing);
 
 			whichflag |= players[i].gotflag;
 
-			if ((whichflag & (GF_REDFLAG|GF_BLUEFLAG)) == (GF_REDFLAG|GF_BLUEFLAG))
+			if (whichflag == allflags)
 				break; // both flags were found, let's stop early
 		}
 
 		// Display a countdown timer showing how much time left until the flag returns to base.
 		{
-			if (flagmobjs[TEAM_BLUE] && flagmobjs[TEAM_BLUE]->fuse > 1 && LUA_HudEnabled(hud_teamscores))
-				V_DrawCenteredString(BASEVIDWIDTH/2 - SEP, 8, V_YELLOWMAP|V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, va("%u", (flagmobjs[TEAM_BLUE]->fuse / TICRATE)));
+			if (flagmobjs[G_GetTeam(2)] && flagmobjs[G_GetTeam(2)]->fuse > 1 && LUA_HudEnabled(hud_teamscores))
+				V_DrawCenteredString(BASEVIDWIDTH/2 - SEP, 8, V_YELLOWMAP|V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, va("%u", (flagmobjs[G_GetTeam(2)]->fuse / TICRATE)));
 
-			if (flagmobjs[TEAM_RED] && flagmobjs[TEAM_RED]->fuse > 1 && LUA_HudEnabled(hud_teamscores))
-				V_DrawCenteredString(BASEVIDWIDTH/2 + SEP, 8, V_YELLOWMAP|V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, va("%u", (flagmobjs[TEAM_RED]->fuse / TICRATE)));
+			if (flagmobjs[G_GetTeam(1)] && flagmobjs[G_GetTeam(1)]->fuse > 1 && LUA_HudEnabled(hud_teamscores))
+				V_DrawCenteredString(BASEVIDWIDTH/2 + SEP, 8, V_YELLOWMAP|V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, va("%u", (flagmobjs[G_GetTeam(1)]->fuse / TICRATE)));
 		}
 	}
 
 num:
 	if (LUA_HudEnabled(hud_teamscores))
-		V_DrawCenteredString(BASEVIDWIDTH/2 - SEP, 16, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, va("%u", teamscores[TEAM_BLUE]));
-
-	if (LUA_HudEnabled(hud_teamscores))
-		V_DrawCenteredString(BASEVIDWIDTH/2 + SEP, 16, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, va("%u", teamscores[TEAM_RED]));
+	{
+		V_DrawCenteredString(BASEVIDWIDTH/2 - SEP, 16, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, va("%u", teamscores[G_GetTeam(2)]));
+		V_DrawCenteredString(BASEVIDWIDTH/2 + SEP, 16, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, va("%u", teamscores[G_GetTeam(1)]));
+	}
 
 #undef SEP
 }
diff --git a/src/st_stuff.h b/src/st_stuff.h
index 603be3c309c761b31fa269f2b0fbad795a489676..d8ffd1b4557c8acb5e584e1e6f9a3034365ea3fe 100644
--- a/src/st_stuff.h
+++ b/src/st_stuff.h
@@ -41,6 +41,8 @@ void ST_changeDemoView(void);
 void ST_UnloadGraphics(void);
 void ST_LoadGraphics(void);
 
+void ST_LoadTeamIcons(void);
+
 // face load graphics, called when skin changes
 void ST_LoadFaceGraphics(INT32 playernum);
 void ST_ReloadSkinFaceGraphics(void);
@@ -61,6 +63,9 @@ extern tic_t lt_exitticker, lt_endtime;
 // return if player a is in the same team as player b
 boolean ST_SameTeam(player_t *a, player_t *b);
 
+patch_t *ST_GetTeamIconImage(UINT8 team, UINT8 icon_type);
+patch_t *ST_GetCurrentTeamIconImage(UINT8 team, UINT8 icon_type);
+
 //--------------------
 // status bar overlay
 //--------------------
diff --git a/src/y_inter.c b/src/y_inter.c
index 444579bd926868913567d8a9586f7428fa1b871c..c992055a1d84c6878d33d569c69efbd001233605 100644
--- a/src/y_inter.c
+++ b/src/y_inter.c
@@ -271,16 +271,10 @@ void Y_LoadIntermissionData(void)
 		case int_ctf:
 		case int_teammatch:
 		{
-			if (!rflagico) //prevent a crash if we haven't cached our team graphics yet
-			{
-				rflagico = W_CachePatchName("RFLAGICO", PU_HUDGFX);
-				bflagico = W_CachePatchName("BFLAGICO", PU_HUDGFX);
-				rmatcico = W_CachePatchName("RMATCICO", PU_HUDGFX);
-				bmatcico = W_CachePatchName("BMATCICO", PU_HUDGFX);
-			}
+			ST_LoadTeamIcons();
 
-			data.match.redflag = (intertype == int_ctf) ? rflagico : rmatcico;
-			data.match.blueflag = (intertype == int_ctf) ? bflagico : bmatcico;
+			data.match.redflag = (intertype == int_ctf) ? ST_GetCurrentTeamIconImage(1, TEAM_ICON_FLAG) : ST_GetCurrentTeamIconImage(1, TEAM_ICON);
+			data.match.blueflag = (intertype == int_ctf) ? ST_GetCurrentTeamIconImage(2, TEAM_ICON_FLAG) : ST_GetCurrentTeamIconImage(2, TEAM_ICON);
 		}
 		/* FALLTHRU */
 		case int_match: