diff --git a/src/netcode/d_net.c b/src/netcode/d_net.c
index 4860d8688b4a8b998b59523c6cf52502c69d10ca..9718c40b331a52ad04a60d53fd477b52126eff7d 100644
--- a/src/netcode/d_net.c
+++ b/src/netcode/d_net.c
@@ -200,10 +200,9 @@ FUNCMATH static INT32 cmpack(UINT8 a, UINT8 b)
 /** Sets freeack to a free acknum and copies the netbuffer in the ackpak table
   *
   * \param freeack  The address to store the free acknum at
-  * \param lowtimer ???
   * \return True if a free acknum was found
   */
-static boolean GetFreeAcknum(UINT8 *freeack, boolean lowtimer)
+static boolean GetFreeAcknum(UINT8 *freeack)
 {
 	node_t *node = &nodes[doomcom->remotenode];
 	INT32 numfreeslot = 0;
@@ -232,17 +231,8 @@ static boolean GetFreeAcknum(UINT8 *freeack, boolean lowtimer)
 				node->nextacknum++;
 			ackpak[i].destinationnode = (UINT8)(node - nodes);
 			ackpak[i].length = doomcom->datalength;
-			if (lowtimer)
-			{
-				// Lowtime means can't be sent now so try it as soon as possible
-				ackpak[i].senttime = 0;
-				ackpak[i].resentnum = 1;
-			}
-			else
-			{
-				ackpak[i].senttime = I_GetTime();
-				ackpak[i].resentnum = 0;
-			}
+			ackpak[i].senttime = I_GetTime();
+			ackpak[i].resentnum = 0;
 			M_Memcpy(ackpak[i].pak.raw, netbuffer, ackpak[i].length);
 
 			*freeack = ackpak[i].acknum;
@@ -259,38 +249,6 @@ static boolean GetFreeAcknum(UINT8 *freeack, boolean lowtimer)
 	return false;
 }
 
-/** Counts how many acks are free
-  *
-  * \param urgent True if the type of the packet meant to
-  *               use an ack is lower than PT_CANFAIL
-  *               If for some reason you don't want use it
-  *               for any packet type in particular,
-  *               just set to false
-  * \return The number of free acks
-  *
-  */
-INT32 Net_GetFreeAcks(boolean urgent)
-{
-	INT32 numfreeslot = 0;
-	INT32 n = 0; // Number of free acks found
-
-	for (INT32 i = 0; i < MAXACKPACKETS; i++)
-		if (!ackpak[i].acknum)
-		{
-			// For low priority packets, make sure to let freeslots so urgent packets can be sent
-			if (!urgent)
-			{
-				numfreeslot++;
-				if (numfreeslot <= URGENTFREESLOTNUM)
-					continue;
-			}
-
-			n++;
-		}
-
-	return n;
-}
-
 // Get a ack to send in the queue of this node
 static UINT8 GetAcktosend(INT32 node)
 {
@@ -319,7 +277,7 @@ static int Processackpak(void)
 		node->remotefirstack = netbuffer->ackreturn;
 		// Search the ackbuffer and free it
 		for (INT32 i = 0; i < MAXACKPACKETS; i++)
-			if (ackpak[i].acknum && ackpak[i].destinationnode == node - nodes
+			if (ackpak[i].acknum && ackpak[i].destinationnode == doomcom->remotenode
 				&& cmpack(ackpak[i].acknum, netbuffer->ackreturn) <= 0)
 			{
 				RemoveAck(i);
@@ -333,7 +291,15 @@ static int Processackpak(void)
 		getackpacket++;
 		if (cmpack(ack, node->firstacktosend) <= 0)
 		{
+			UINT8 newhead = (UINT8)((node->acktosend_head+1) % MAXACKTOSEND);
 			DEBFILE(va("Discard(1) ack %d (duplicated)\n", ack));
+			if (newhead != node->acktosend_tail)
+			{
+				// push the ack back onto the acktosend list to make sure it's responded to
+				node->acktosend[node->acktosend_head] = ack;
+				node->acktosend_head = newhead;
+			}
+
 			duppacket++;
 			goodpacket = 1; // Discard packet (duplicate)
 		}
@@ -991,7 +957,7 @@ boolean HSendPacket(INT32 node, boolean reliable, UINT8 acknum, size_t packetlen
 		netbuffer->ackreturn = 0;
 	if (reliable)
 	{
-		if (!GetFreeAcknum(&netbuffer->ack, false))
+		if (!GetFreeAcknum(&netbuffer->ack))
 			return false;
 	}
 	else
diff --git a/src/netcode/d_net.h b/src/netcode/d_net.h
index 2f83939f8c5324883eb11e90dbb4e2897a54254c..6b3ee5e6751bd6d19457ea704274b5de9247c483 100644
--- a/src/netcode/d_net.h
+++ b/src/netcode/d_net.h
@@ -60,7 +60,6 @@ extern netnode_t netnodes[MAXNETNODES];
 
 extern boolean serverrunning;
 
-INT32 Net_GetFreeAcks(boolean urgent);
 void Net_AckTicker(void);
 
 // If reliable return true if packet sent, 0 else