diff --git a/src/deh_soc.c b/src/deh_soc.c
index 81adbc9d211fa2dab90483f3b7cb40775a413af4..f2f3e04b8d90eb4c2c47fddaee30fb117a3433c3 100644
--- a/src/deh_soc.c
+++ b/src/deh_soc.c
@@ -3839,6 +3839,10 @@ void readmaincfg(MYFILE *f)
 			{
 				useContinues = (UINT8)(value || word2[0] == 'T' || word2[0] == 'Y');
 			}
+			else if (fastcmp(word, "SHAREEMBLEMS"))
+			{
+				shareEmblems = (UINT8)(value || word2[0] == 'T' || word2[0] == 'Y');
+			}
 
 			else if (fastcmp(word, "GAMEDATA"))
 			{
diff --git a/src/doomstat.h b/src/doomstat.h
index 5875bd01f8d4c146a89802ad035407045e42309e..a812cc304f6e0b19cab8f2fecf37868264ed9b16 100644
--- a/src/doomstat.h
+++ b/src/doomstat.h
@@ -543,9 +543,12 @@ extern UINT8 useBlackRock;
 
 extern UINT8 use1upSound;
 extern UINT8 maxXtraLife; // Max extra lives from rings
+
 extern UINT8 useContinues;
 #define continuesInSession (!multiplayer && (ultimatemode || (useContinues && !marathonmode) || (!modeattacking && !(cursaveslot > 0))))
 
+extern UINT8 shareEmblems;
+
 extern mobj_t *hunt1, *hunt2, *hunt3; // Emerald hunt locations
 
 // For racing
diff --git a/src/g_game.c b/src/g_game.c
index 854bf9bbb4e3a54e7a9c249fa31614de839083d8..066b43cad3ad276ae3e9e32a6e222fb3929e4a2d 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -215,6 +215,7 @@ UINT8 ammoremovaltics = 2*TICRATE;
 UINT8 use1upSound = 0;
 UINT8 maxXtraLife = 2; // Max extra lives from rings
 UINT8 useContinues = 0; // Set to 1 to enable continues outside of no-save scenarioes
+UINT8 shareEmblems = 0; // Set to 1 to share all picked up emblems in multiplayer
 
 UINT8 introtoplay;
 UINT8 creditscutscene;
diff --git a/src/p_inter.c b/src/p_inter.c
index f2d20912f0c45ecf9f9ae68a8376634fc7a1adfa..02ae222e3111dab9503f6a92bea4610cea4a7008 100644
--- a/src/p_inter.c
+++ b/src/p_inter.c
@@ -164,6 +164,62 @@ boolean P_CanPickupItem(player_t *player, boolean weapon)
 	return true;
 }
 
+boolean P_CanPickupEmblem(player_t *player, INT32 emblemID)
+{
+	emblem_t *emblem = NULL;
+
+	if (emblemID < 0 || emblemID >= numemblems)
+	{
+		// Invalid emblem ID, can't pickup.
+		return false;
+	}
+
+	emblem = &emblemlocations[emblemID];
+
+	if (demoplayback)
+	{
+		// Never collect emblems in replays.
+		return false;
+	}
+
+	if (player->bot && player->bot != BOT_MPAI)
+	{
+		// Your little lap-dog can't grab these for you.
+		return false;
+	}
+
+	if (emblem->type == ET_SKIN)
+	{
+		INT32 skinnum = M_EmblemSkinNum(emblem);
+
+		if (player->skin != skinnum)
+		{
+			// Incorrect skin to pick up this emblem.
+			return false;
+		}
+	}
+
+	return true;
+}
+
+boolean P_EmblemWasCollected(INT32 emblemID)
+{
+	if (emblemID < 0 || emblemID >= numemblems)
+	{
+		// Invalid emblem ID, can't pickup.
+		return true;
+	}
+
+	if (shareEmblems && !serverGamedata->collected[emblemID])
+	{
+		// It can be worth collecting again if we're sharing emblems
+		// and the server doesn't have it.
+		return false;
+	}
+
+	return clientGamedata->collected[emblemID];
+}
+
 //
 // P_DoNightsScore
 //
@@ -738,25 +794,41 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
 		// Secret emblem thingy
 		case MT_EMBLEM:
 			{
-				if (demoplayback || (player->bot && player->bot != BOT_MPAI) || special->health <= 0 || special->health > MAXEMBLEMS)
-					return;
+				mobj_t *spark = NULL;
+				boolean prevCollected;
 
-				if (emblemlocations[special->health-1].type == ET_SKIN)
+				if (!P_CanPickupEmblem(player, special->health - 1))
 				{
-					INT32 skinnum = M_EmblemSkinNum(&emblemlocations[special->health-1]);
+					return;
+				}
 
-					if (player->skin != skinnum)
-					{
-						return;
-					}
+				prevCollected = P_EmblemWasCollected(special->health - 1);
+
+				if (((player - players) == serverplayer) || shareEmblems)
+				{
+					serverGamedata->collected[special->health-1] = true;
+					M_SilentUpdateUnlockablesAndEmblems(serverGamedata);
 				}
 
-				clientGamedata->collected[special->health-1] = serverGamedata->collected[special->health-1] = true;
+				if (P_IsLocalPlayer(player) || shareEmblems)
+				{
+					clientGamedata->collected[special->health-1] = true;
+					M_UpdateUnlockablesAndExtraEmblems(clientGamedata);
+					G_SaveGameData(clientGamedata);
+				}
 
-				M_SilentUpdateUnlockablesAndEmblems(serverGamedata);
-				M_UpdateUnlockablesAndExtraEmblems(clientGamedata);
-				G_SaveGameData(clientGamedata);
-				break;
+				// This always spawns the object to prevent mobjnum issues,
+				// but makes the effect invisible to whoever it doesn't matter to.
+				spark = P_SpawnMobjFromMobj(special, 0, 0, 0, MT_SPARK);
+				if (prevCollected == false && P_EmblemWasCollected(special->health - 1) == true)
+				{
+					S_StartSound(special, special->info->deathsound);
+				}
+				else
+				{
+					spark->flags2 |= MF2_DONTDRAW;
+				}
+				return;
 			}
 
 		// CTF Flags
diff --git a/src/p_local.h b/src/p_local.h
index cc060e4eee3c9b45f5b0da4e1c9c43a61f5c8ccf..3c84d6fe2f2ddaded0260623b3a402969a8fe11c 100644
--- a/src/p_local.h
+++ b/src/p_local.h
@@ -510,6 +510,8 @@ void P_ClearStarPost(INT32 postnum);
 void P_ResetStarposts(void);
 
 boolean P_CanPickupItem(player_t *player, boolean weapon);
+boolean P_CanPickupEmblem(player_t *player, INT32 emblemID);
+boolean P_EmblemWasCollected(INT32 emblemID);
 void P_DoNightsScore(player_t *player);
 void P_DoMatchSuper(player_t *player);
 
diff --git a/src/p_mobj.c b/src/p_mobj.c
index 6563e6f0a7ae7efe414d04aa344b0d479e19a51f..f198a1a69a56678e4605b36b091ab8dd3e5577e7 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -9716,6 +9716,11 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
 			A_AttractChase(mobj);
 		break;
 	case MT_EMBLEM:
+		if (P_EmblemWasCollected(mobj->health - 1) || !P_CanPickupEmblem(&players[consoleplayer], mobj->health - 1))
+			mobj->frame |= (tr_trans50 << FF_TRANSSHIFT);
+		else
+			mobj->frame &= ~FF_TRANSMASK;
+
 		if (mobj->flags2 & MF2_NIGHTSPULL)
 			P_NightsItemChase(mobj);
 		break;
@@ -12146,7 +12151,6 @@ static boolean P_SetupEmblem(mapthing_t *mthing, mobj_t *mobj)
 	INT32 j;
 	emblem_t* emblem = M_GetLevelEmblems(gamemap);
 	skincolornum_t emcolor;
-	boolean validEmblem = true;
 
 	while (emblem)
 	{
@@ -12171,47 +12175,19 @@ static boolean P_SetupEmblem(mapthing_t *mthing, mobj_t *mobj)
 	emcolor = M_GetEmblemColor(&emblemlocations[j]); // workaround for compiler complaint about bad function casting
 	mobj->color = (UINT16)emcolor;
 
-	validEmblem = true;
+	mobj->frame &= ~FF_TRANSMASK;
 
-	if (!netgame)
+	if (emblemlocations[j].type == ET_GLOBAL)
 	{
-		validEmblem = !serverGamedata->collected[j];
-
-		if (emblemlocations[j].type == ET_SKIN && !multiplayer)
+		mobj->reactiontime = emblemlocations[j].var;
+		if (emblemlocations[j].var & GE_NIGHTSITEM)
 		{
-			INT32 skinnum = M_EmblemSkinNum(&emblemlocations[j]);
-
-			if (players[0].skin != skinnum)
-			{
-				validEmblem = false;
-			}
+			mobj->flags |= MF_NIGHTSITEM;
+			mobj->flags &= ~MF_SPECIAL;
+			mobj->flags2 |= MF2_DONTDRAW;
 		}
 	}
 
-	if (validEmblem == false)
-	{
-		P_UnsetThingPosition(mobj);
-		mobj->flags |= MF_NOCLIP;
-		mobj->flags &= ~MF_SPECIAL;
-		mobj->flags |= MF_NOBLOCKMAP;
-		mobj->frame |= (tr_trans50 << FF_TRANSSHIFT);
-		P_SetThingPosition(mobj);
-	}
-	else
-	{
-		mobj->frame &= ~FF_TRANSMASK;
-
-		if (emblemlocations[j].type == ET_GLOBAL)
-		{
-			mobj->reactiontime = emblemlocations[j].var;
-			if (emblemlocations[j].var & GE_NIGHTSITEM)
-			{
-				mobj->flags |= MF_NIGHTSITEM;
-				mobj->flags &= ~MF_SPECIAL;
-				mobj->flags2 |= MF2_DONTDRAW;
-			}
-		}
-	}
 	return true;
 }
 
diff --git a/src/p_setup.c b/src/p_setup.c
index 70a2c0a8bd0c92d08b6b875836eab1df2aca7036..74645e8771c8055a8719de438cee252b05ba7364 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -876,7 +876,7 @@ static void P_SpawnMapThings(boolean spawnemblems)
 	size_t i;
 	mapthing_t *mt;
 
-        // Spawn axis points first so they are at the front of the list for fast searching.
+	// Spawn axis points first so they are at the front of the list for fast searching.
 	for (i = 0, mt = mapthings; i < nummapthings; i++, mt++)
 	{
 		switch (mt->type)
diff --git a/src/st_stuff.c b/src/st_stuff.c
index 1f0ca277f5d403353690a995d455af5bc22d86f1..986b712194b4c77aab6d2ef560cfc12d75c76c6e 100644
--- a/src/st_stuff.c
+++ b/src/st_stuff.c
@@ -2563,9 +2563,8 @@ static void ST_doItemFinderIconsAndSound(void)
 
 		emblems[stemblems++] = i;
 
-		if (!(clientGamedata->collected[i] && serverGamedata->collected[i]))
+		if (!P_EmblemWasCollected(i))
 		{
-			// It can be worth collecting again if the server doesn't have it.
 			++stunfound;
 		}