diff --git a/src/d_chat.c b/src/d_chat.c
index 145c9f388c525523df0ed6185c20fa468ce6c371..dac174a61d122a80c3ad47e1fc791662602d4a34 100644
--- a/src/d_chat.c
+++ b/src/d_chat.c
@@ -52,19 +52,19 @@
 void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags)
 {
 	char buf[2 + HU_MAXMSGLEN + 1];
-	size_t numwords, ix;
 	char *msg = &buf[2];
+	size_t numwords, ix;
 	const size_t msgspace = sizeof buf - 2;
 
-	numwords = COM_Argc() - usedargs;
-	I_Assert(numwords > 0);
-
 	if (CHAT_MUTE) // TODO: Per Player mute.
 	{
 		HU_AddChatText(va("%s>ERROR: The chat is muted. You can't say anything.", "\x85"), false);
 		return;
 	}
 
+	numwords = COM_Argc() - usedargs;
+	I_Assert(numwords > 0);
+
 	// Only servers/admins can CSAY.
 	if(!server && !(IsPlayerAdmin(consoleplayer)))
 		flags &= ~HU_CSAY;
@@ -74,8 +74,6 @@ void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags)
 	if(dedicated && !(flags & HU_CSAY))
 		flags |= HU_SERVER_SAY;
 
-	buf[0] = target;
-	buf[1] = flags;
 	msg[0] = '\0';
 
 	for (ix = 0; ix < numwords; ix++)
@@ -85,51 +83,11 @@ void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags)
 		strlcat(msg, COM_Argv(ix + usedargs), msgspace);
 	}
 
-	if (strlen(msg) > 4 && strnicmp(msg, "/pm", 3) == 0) // used /pm
-	{
-		// what we're gonna do now is check if the player exists
-		// with that logic, characters 4 and 5 are our numbers:
-		const char *newmsg;
-		char playernum[3];
-		INT32 spc = 1; // used if playernum[1] is a space.
-
-		strncpy(playernum, msg+3, 3);
-		// check for undesirable characters in our "number"
-		if (((playernum[0] < '0') || (playernum[0] > '9')) || ((playernum[1] < '0') || (playernum[1] > '9')))
-		{
-			// check if playernum[1] is a space
-			if (playernum[1] == ' ')
-				spc = 0;
-			// let it slide
-			else
-			{
-				HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<playernum> \'.", false);
-				return;
-			}
-		}
-		// I'm very bad at C, I swear I am, additional checks eww!
-		if (spc != 0 && msg[5] != ' ')
-		{
-			HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<playernum> \'.", false);
-			return;
-		}
-
-		target = atoi(playernum); // turn that into a number
-		//CONS_Printf("%d\n", target);
-
-		// check for target player, if it doesn't exist then we can't send the message!
-		if (target < MAXPLAYERS && playeringame[target]) // player exists
-			target++; // even though playernums are from 0 to 31, target is 1 to 32, so up that by 1 to have it work!
-		else
-		{
-			HU_AddChatText(va("\x82NOTICE: \x80Player %d does not exist.", target), false); // same
-			return;
-		}
-		buf[0] = target;
-		newmsg = msg+5+spc;
-		strlcpy(msg, newmsg, HU_MAXMSGLEN + 1);
-	}
+	if (!FilterPM(msg, &target)) // check for /pm + a valid target
+		return;
 
+	buf[0] = target;
+	buf[1] = flags;
 	SendNetXCmd(XD_SAY, buf, strlen(msg) + 1 + msg-buf);
 }
 
@@ -429,4 +387,42 @@ void Got_Saycmd(UINT8 **p, INT32 playernum)
 #endif
 }
 
+boolean FilterPM(char *msg, SINT8 target)
+{
+	if (strlen(msg) > 4 && strnicmp(msg, "/pm", 3) == 0) // used /pm
+	{
+		const char *newmsg;
+		char playernum[3];
+
+		if (target == -1) // don't allow PMs in team chat, they would be broadcast to everyone anyway
+		{
+			HU_AddChatText(va("%sCannot send sayto in Say-Team.", "\x85"), false);
+			return false;
+		}
+
+		strncpy(playernum, msg+3, 3);
+		// check for undesirable characters in our "number"
+		if (!isdigit(playernum[0]) || (!isdigit(playernum[1]) && playernum[1] != ' '))
+		{
+			HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<playernum> \'.", false);
+			return false;
+		}
+
+		target = atoi(playernum); // turn that into a number
+
+		if (target < MAXPLAYERS && (playeringame[target] || target == 0)) // check if target player exists or is dedicated host
+			target++; // even though playernums are from 0 to 31, target is 1 to 32, so up that by 1 to have it work!
+		else
+		{
+			HU_AddChatText(va("\x82NOTICE: \x80Player %d does not exist.", target), false); // same
+			return false;
+		}
+
+		newmsg = msg + 5 + (playernum[1] == ' ' ? 0 : 1);
+		strlcpy(msg, newmsg, HU_MAXMSGLEN + 1);
+	}
+
+	return true;
+}
+
 #endif
\ No newline at end of file
diff --git a/src/d_chat.h b/src/d_chat.h
index 5c73181d94c3f89c3f767a7fe70ec9009a11c810..3c1ab430a358cc8de069c01b4b0a45a137c2ab09 100644
--- a/src/d_chat.h
+++ b/src/d_chat.h
@@ -26,6 +26,7 @@ void Command_Sayto_f(void);
 void Command_Sayteam_f(void);
 void Command_CSay_f(void);
 void Got_Saycmd(UINT8 **p, INT32 playernum);
+boolean FilterPM(char *msg, SINT8 target);
 #endif
 
 #endif
\ No newline at end of file
diff --git a/src/hu_chat.c b/src/hu_chat.c
index d32a0b89f0e76cbc5d9d47b4876f67197cb1ea36..6fdf1b40bce525bfc8d1bb3ac23264b1383f1e9b 100644
--- a/src/hu_chat.c
+++ b/src/hu_chat.c
@@ -15,6 +15,7 @@
 #include "byteptr.h"
 #include "hu_chat.h"
 #include "hu_stuff.h"
+#include "d_chat.h"
 
 #include "console.h"
 #include "d_clisrv.h"
@@ -389,30 +390,21 @@ void HU_DrawChat(void)
 		}
 #endif
 
-		for(i=0; i<MAXPLAYERS; i++)
+		for(i = 0; i < MAXPLAYERS; i++)
 		{
-			// filter: (code needs optimization pls help I'm bad with C)
 			if (w_chat[3])
 			{
 				char playernum[3];
 				UINT32 n;
-				// right, that's half important: (w_chat[4] may be a space since /pm0 msg is perfectly acceptable!)
-				if ( ( ((w_chat[3] != 0) && ((w_chat[3] < '0') || (w_chat[3] > '9'))) || ((w_chat[4] != 0) && (((w_chat[4] < '0') || (w_chat[4] > '9'))))) && (w_chat[4] != ' '))
+				if ((w_chat[3] != 0 && !isdigit(w_chat[3])) || (w_chat[4] != 0  && w_chat[4] != ' ' && !isdigit(w_chat[4])))
 					break;
 
 				strncpy(playernum, w_chat+3, 3);
-				n = atoi(playernum); // turn that into a number
-				// special cases:
-				if ((n == 0) && !(w_chat[4] == '0') && (!(i<10)))
+				n = atoi(playernum);
+				if (n < 10 && ((i >= 10 && n != i/10) || (i < 10 && n != i)))
 					continue;
-				else if ((n == 1) && !(w_chat[3] == '0') && (!((i == 1) || ((i >= 10) && (i <= 19)))))
+				else if (n >= 10 && n != i)
 					continue;
-				else if ((n == 2) && !(w_chat[3] == '0') && (!((i == 2) || ((i >= 20) && (i <= 29)))))
-					continue; 
-				else if ((n == 3) && !(w_chat[3] == '0') && (!((i == 3) || ((i >= 30) && (i <= 31)))))
-					continue; 
-				else	// general case.
-					if (i != n) continue;
 			}
 
 			if (playeringame[i] || i == 0) // dedicated server host is not in-game but still valid
@@ -492,7 +484,13 @@ void HU_sendChatMessage(void)
 	char buf[2 + HU_MAXMSGLEN + 1];
 	char *msg = &buf[2];
 	size_t ci;
-	INT32 target = 0;
+	SINT8 target = teamtalk ? -1 : 0;
+
+	if (CHAT_MUTE) // TODO: Per Player mute.
+	{
+		HU_AddChatText(va("%s>ERROR: The chat is muted. You can't say anything.", "\x85"), false);
+		return;
+	}
 
 	// if our message was nothing but spaces, don't send it.
 	if (HU_chatboxContainsOnlySpaces())
@@ -510,68 +508,12 @@ void HU_sendChatMessage(void)
 	memset(w_chat, '\0', sizeof(w_chat));
 	c_input = 0;
 
-	// last minute mute check
-	if (CHAT_MUTE)
-	{
-		HU_AddChatText(va("%s>ERROR: The chat is muted. You can't say anything.", "\x85"), false);
+	if (!FilterPM(msg, &target)) // check for /pm + a valid target
 		return;
-	}
-
-	if (strlen(msg) > 4 && strnicmp(msg, "/pm", 3) == 0) // used /pm
-	{
-		INT32 spc = 1; // used if playernum[1] is a space.
-		char playernum[3];
-		const char *newmsg;
 
-		// what we're gonna do now is check if the player exists
-		// with that logic, characters 4 and 5 are our numbers:
-
-		// teamtalk can't send PMs, just don't send it, else everyone would be able to see it, and no one wants to see your sex RP sicko.
-		if (teamtalk)
-		{
-			HU_AddChatText(va("%sCannot send sayto in Say-Team.", "\x85"), false);
-			return;
-		}
-
-		strncpy(playernum, msg+3, 3);
-		// check for undesirable characters in our "number"
-		if (!(isdigit(playernum[0]) && isdigit(playernum[1])))
-		{
-			// check if playernum[1] is a space
-			if (playernum[1] == ' ')
-				spc = 0;
-				// let it slide
-			else
-			{
-				HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<player num> \'.", false);
-				return;
-			}
-		}
-		// I'm very bad at C, I swear I am, additional checks eww!
-		if (spc != 0 && msg[5] != ' ')
-		{
-			HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<player num> \'.", false);
-			return;
-		}
-
-		target = atoi(playernum); // turn that into a number
-
-		// check for target player, if it doesn't exist then we can't send the message!
-		if (target < MAXPLAYERS && (playeringame[target] || target == 0)) // player exists or is dedicated host
-			target++; // even though playernums are from 0 to 31, target is 1 to 32, so up that by 1 to have it work!
-		else
-		{
-			HU_AddChatText(va("\x82NOTICE: \x80Player %d does not exist.", target), false); // same
-			return;
-		}
-
-		// we need to get rid of the /pm<player num>
-		newmsg = msg+5+spc;
-		strlcpy(msg, newmsg, HU_MAXMSGLEN + 1);
-	}
 	if (ci > 2) // don't send target+flags+empty message.
 	{
-		buf[0] = teamtalk ? -1 : target; // target
+		buf[0] = target;
 		buf[1] = 0; // flags
 		SendNetXCmd(XD_SAY, buf, 2 + strlen(&buf[2]) + 1);
 	}