diff --git a/regamedll/dlls/player.cpp b/regamedll/dlls/player.cpp
index d12768c1..06c55089 100644
--- a/regamedll/dlls/player.cpp
+++ b/regamedll/dlls/player.cpp
@@ -6351,6 +6351,44 @@ CBaseEntity *CBasePlayer::GiveNamedItemEx(const char *pszName)
 	return pEntity;
 }
 
+// Creates a copy of the specified entity (pEntitySource) and gives it to the player
+// The cloned entity inherits base properties (entvars) of the original entity
+// Returns Pointer to the cloned entity, or NULL if the entity cannot be created
+CBaseEntity *CBasePlayer::GiveCopyItem(CBaseEntity *pEntitySource)
+{
+	edict_t *pEdict = CREATE_NAMED_ENTITY(pEntitySource->pev->classname);
+	if (FNullEnt(pEdict))
+	{
+		ALERT(at_console, "NULL Ent in GiveCloneItem classname `%s`!\n", STRING(pEntitySource->pev->classname));
+		return nullptr;
+	}
+
+	// copy entity properties
+	Q_memcpy(&pEdict->v, pEntitySource->pev, sizeof(pEdict->v));
+
+	pEdict->v.pContainingEntity = pEdict;
+	pEdict->v.origin = pev->origin;
+	pEdict->v.spawnflags |= SF_NORESPAWN;
+	pEdict->v.owner = NULL; // will re-link owner after touching
+	pEdict->v.chain = ENT(pEntitySource->pev); // refer to source copy entity
+
+	DispatchSpawn(pEdict);
+	DispatchTouch(pEdict, ENT(pev));
+	pEdict->v.chain = NULL;
+
+	CBaseEntity *pEntity = GET_PRIVATE<CBaseEntity>(pEdict);
+
+	// not allow the item to fall to the ground.
+	if (FNullEnt(pEdict->v.owner) || pEdict->v.owner != edict())
+	{
+		pEdict->v.flags |= FL_KILLME;
+		UTIL_Remove(pEntity);
+		return nullptr;
+	}
+
+	return pEntity;
+}
+
 CBaseEntity *FindEntityForward(CBaseEntity *pEntity)
 {
 	TraceResult tr;
diff --git a/regamedll/dlls/player.h b/regamedll/dlls/player.h
index 4595bf22..8908e44c 100644
--- a/regamedll/dlls/player.h
+++ b/regamedll/dlls/player.h
@@ -536,6 +536,7 @@ public:
 	void ItemPostFrame();
 	CBaseEntity *GiveNamedItem(const char *pszName);
 	CBaseEntity *GiveNamedItemEx(const char *pszName);
+	CBaseEntity *GiveCopyItem(CBaseEntity *pEntityBase);
 	void EnableControl(BOOL fControl);
 	bool HintMessage(const char *pMessage, BOOL bDisplayIfPlayerDead = FALSE, BOOL bOverride = FALSE);
 	bool HintMessageEx(const char *pMessage, float duration = 6.0f, bool bDisplayIfPlayerDead = false, bool bOverride = false);
diff --git a/regamedll/dlls/weapons.cpp b/regamedll/dlls/weapons.cpp
index e6524a96..2c035c74 100644
--- a/regamedll/dlls/weapons.cpp
+++ b/regamedll/dlls/weapons.cpp
@@ -1852,39 +1852,72 @@ bool CWeaponBox::GiveAmmoToPlayer(CBasePlayer *pPlayer, CBasePlayerWeapon *pWeap
 		return false; // can't pickup more, these ammo are full in backpack
 
 	// If already have a weapon in backpack, just refill ammo for it
-	if (iCurrentAmmo > 0)
+	int iAmmoIndex = GetAmmoIndex(pszAmmo);
+	if (iAmmoIndex > 0)
 	{
-		int iAmmoIndex = GetAmmoIndex(pszAmmo);
-		if (iAmmoIndex > 0)
+		// How many weapon ammo can pick up?
+		int iAmmoPickup = min(m_rgAmmo[iAmmoIndex], iMaxAmmo - iCurrentAmmo);
+		if (iAmmoPickup > 0)
 		{
-			// how many gren ammo can pick up?
-			int iAmmoPickup = min(m_rgAmmo[iAmmoIndex], iMaxAmmo - iCurrentAmmo);
-			if (iAmmoPickup > 0)
+			if (iCurrentAmmo == 0 && !(pPlayer->pev->weapons & (1<<pWeapon->m_iId)) && (pWeapon->iFlags() & ITEM_FLAG_EXHAUSTIBLE))
 			{
-				if (!FStringNull(m_rgiszAmmo[iAmmoIndex]) &&
-					pPlayer->GiveAmmo(iAmmoPickup, STRING(m_rgiszAmmo[iAmmoIndex]), iMaxAmmo) != -1)
+				if (m_rgAmmo[iAmmoIndex] > iMaxAmmo)
 				{
-					m_rgAmmo[iAmmoIndex] -= iAmmoPickup;
+					// If ammo capacity of the dropped weapon exceeds the player's backpack capacity,
+					// make a copy of dropped weapon and give it to the player
+					CBasePlayerItem *copyItem = (CBasePlayerItem *)pPlayer->GiveCopyItem(pWeapon);
+					if (copyItem)
+					{
+						// The cloned weapon must inherit properties from a dropped weapon, such as Item Info
+#ifdef REGAMEDLL_API
+						ItemInfo info;
+						if (pWeapon->CSPlayerItem()->GetItemInfo(&info))
+							copyItem->CSPlayerItem()->SetItemInfo(&info);
+#endif
+						m_rgAmmo[iAmmoIndex]--;
+						iAmmoPickup--;
+					}
+				}
+				else
+				{
+					// If no weapon in backpack, then issue weapon
+					if (pPlayer->AddPlayerItem(pWeapon))
+					{
+						pWeapon->AttachToPlayer(pPlayer);
+						if (pGivenItem) *pGivenItem = pWeapon;
+					}
 
-					if (m_rgAmmo[iAmmoIndex] < 0)
-						m_rgAmmo[iAmmoIndex] = 0;
-
-					EMIT_SOUND(pPlayer->edict(), CHAN_ITEM, "items/9mmclip1.wav", VOL_NORM, ATTN_NORM);
+					// unlink this weapon from the box
+					return true;
 				}
 			}
 
-			// ammo exhausted, remove this weapon
-			if (m_rgAmmo[iAmmoIndex] <= 0)
+			Assert(iAmmoPickup != 0);
+			Assert(m_rgAmmo[iAmmoIndex] != 0);
+
+			if (!FStringNull(m_rgiszAmmo[iAmmoIndex]) &&
+				pPlayer->GiveAmmo(iAmmoPickup, STRING(m_rgiszAmmo[iAmmoIndex]), iMaxAmmo) != -1)
 			{
-				pWeapon->Kill();
+				m_rgAmmo[iAmmoIndex] -= iAmmoPickup;
 
-				// unlink this weapon from the box
-				return true;
+				if (m_rgAmmo[iAmmoIndex] < 0)
+					m_rgAmmo[iAmmoIndex] = 0;
+
+				EMIT_SOUND(pPlayer->edict(), CHAN_ITEM, "items/9mmclip1.wav", VOL_NORM, ATTN_NORM);
 			}
-
-			// ammo has not been exhausted yet, keep this weapon in weaponbox
-			return false;
 		}
+
+		// ammo exhausted, remove this weapon
+		if (m_rgAmmo[iAmmoIndex] <= 0)
+		{
+			pWeapon->Kill();
+
+			// unlink this weapon from the box
+			return true;
+		}
+
+		// ammo has not been exhausted yet, keep this weapon in weaponbox
+		return false;
 	}
 
 	// If no weapon in backpack, then issue weapon
@@ -2045,9 +2078,20 @@ void CWeaponBox::Touch(CBaseEntity *pOther)
 #ifdef REGAMEDLL_FIXES
 					CBasePlayerItem *pNext = m_rgpPlayerItems[i]->m_pNext;
 
+					// Determine the max ammo capacity for the picked-up grenade
+					int iMaxPickupAmmo = pGrenade->iMaxAmmo1();
+
+					// If the player already has the same weapon in inventory,
+					// prioritize the max ammo capacity value over the one from the dropped weapon
+					// When the pickup occurs, ammo will be granted up to
+					// the max ammo capacity of the weapon currently held by the player
+					CBasePlayerItem *pInventoryItem = (CBasePlayerItem *)pPlayer->GetItemById((WeaponIdType)pGrenade->m_iId);
+					if (pInventoryItem && !Q_stricmp(pInventoryItem->pszAmmo1(), pGrenade->pszAmmo1()))
+						iMaxPickupAmmo = pInventoryItem->iMaxAmmo1();
+
 					// Pickup grenade item or refill ammo
 					if (GiveAmmoToPlayer(pPlayer, pGrenade,
-						playerGrenades, pGrenade->pszAmmo1(), pGrenade->iMaxAmmo1(), &givenItem))
+						playerGrenades, pGrenade->pszAmmo1(), iMaxPickupAmmo, &givenItem))
 					{
 						// unlink this weapon from the box
 						m_rgpPlayerItems[i] = pItem = pNext;