diff --git game/Player.cpp game/Player.cpp
index b82a3c6..79482fc 100644
--- game/Player.cpp
+++ game/Player.cpp
@@ -702,6 +702,7 @@ idPlayer::idPlayer() :
 
 	m_IdealCrouchState		= false;
 	m_CrouchIntent			= false;
+	m_CrouchToggleBypassed		= false;
 
 	m_LeanButtonTimeStamp	= 0;
 	m_InventoryOverlay		= -1;
@@ -5606,9 +5607,40 @@ void idPlayer::PerformImpulse( int impulse ) {
 
 		case IMPULSE_CROUCH:		// Crouch
 		{
-			if (!cv_tdm_crouch_toggle.GetBool())
+			// Daft Mugi: NOTE - The code paths for new and old toggle
+			// crouch were purposely separated for clarity and ease of
+			// comparison rather than reducing overall conditional logic.
+			if (cv_tdm_new_crouch_toggle.GetBool())
 			{
-				m_CrouchIntent = true;
+				if (cv_tdm_crouch_toggle.GetBool())
+				{
+					if (physicsObj.OnRope() || physicsObj.OnLadder())
+					{
+						// Climbing; use regular crouch behavior
+						m_CrouchToggleBypassed = true;
+						m_CrouchIntent = true;
+					}
+					else
+					{
+						// Not climbing; toggle crouch
+						if (entityNumber == gameLocal.localClientNum)
+						{
+							m_CrouchToggleBypassed = false;
+							m_CrouchIntent = !m_CrouchIntent;
+						}
+					}
+				}
+				else
+				{
+					m_CrouchIntent = true;
+				}
+			}
+			else	// Old toggle crouch path
+			{
+				if (!cv_tdm_crouch_toggle.GetBool())
+				{
+					m_CrouchIntent = true;
+				}
 			}
 			
 			m_ButtonStateTracker.StartTracking(impulse);
@@ -5933,16 +5965,37 @@ void idPlayer::PerformKeyRelease(int impulse, int holdTime)
 	switch (impulse)
 	{
 		case IMPULSE_CROUCH:		// TDM crouch
-			if (cv_tdm_crouch_toggle.GetBool())
+			// Daft Mugi: NOTE - The code paths for new and old toggle
+			// crouch were purposely separated for clarity and ease of
+			// comparison rather than reducing overall conditional logic.
+			if (cv_tdm_new_crouch_toggle.GetBool())
 			{
-				if ( entityNumber == gameLocal.localClientNum )
+				if (cv_tdm_crouch_toggle.GetBool())
 				{
-					m_CrouchIntent = !m_CrouchIntent;
+					if (physicsObj.OnRope() || physicsObj.OnLadder() || m_CrouchToggleBypassed)
+					{
+						// Climbing or initiated crouch while climbing; use regular crouch behavior
+						m_CrouchIntent = false;
+					}
 				}
-			}		
-			else
+				else
+				{
+					m_CrouchIntent = false;
+				}
+			}
+			else	// Old toggle crouch path
 			{
-				m_CrouchIntent = false;
+				if (cv_tdm_crouch_toggle.GetBool())
+				{
+					if ( entityNumber == gameLocal.localClientNum )
+					{
+						m_CrouchIntent = !m_CrouchIntent;
+					}
+				}
+				else
+				{
+					m_CrouchIntent = false;
+				}
 			}
 
 			// clear climb detach or slide intent when crouch is released
diff --git game/Player.h game/Player.h
index 370dbf8..21864ce 100644
--- game/Player.h
+++ game/Player.h
@@ -392,6 +392,10 @@ public:
 	// or toggle crouch is active
 	bool					m_CrouchIntent;
 
+	// Daft Mugi: For new toggle crouch, this is set to true when the
+	// player has pressed toggle crouch while on a rope or ladder/vine.
+	bool					m_CrouchToggleBypassed;
+
 	// STiFU: FrobHelper alpha calculation
 	CFrobHelper				m_FrobHelper;
 
diff --git game/gamesys/SysCvar.cpp game/gamesys/SysCvar.cpp
index 3beba14..4b23c30 100644
--- game/gamesys/SysCvar.cpp
+++ game/gamesys/SysCvar.cpp
@@ -237,6 +237,8 @@ idCVar cv_tdm_footfalls_movetype_specific( "tdm_footfall_sounds_movetype_specifi
 
 // Dark Mod crouching
 idCVar cv_tdm_crouch_toggle(			"tdm_toggle_crouch",			"1",			CVAR_GAME | CVAR_ARCHIVE | CVAR_BOOL, "Set to 1 to make crouching toggleable." );
+// Daft Mugi: New Toggle Crouch
+idCVar cv_tdm_new_crouch_toggle(			"tdm_new_toggle_crouch",			"1",			CVAR_GAME | CVAR_ARCHIVE | CVAR_BOOL, "Set to 1 to make toggle crouch on key press instead of key release." );
 idCVar cv_tdm_crouch_toggle_hold_time(	"tdm_crouch_toggle_hold_time",	"400",			CVAR_GAME | CVAR_ARCHIVE | CVAR_FLOAT, "The time in milliseconds to hold crouch while on a rope/ladder for starting to slide down." );
 idCVar cv_tdm_reattach_delay(			"tdm_reattach_delay",			"100",			CVAR_GAME | CVAR_ARCHIVE | CVAR_FLOAT, "Delay (in ms) for reattaching to ropes/ladders after detaching using crouch." );
 
diff --git game/gamesys/SysCvar.h game/gamesys/SysCvar.h
index 7d657e6..9040639 100644
--- game/gamesys/SysCvar.h
+++ game/gamesys/SysCvar.h
@@ -211,6 +211,7 @@ extern idCVar cv_savegame_compress;
 
 // angua: TDM toggle crouch
 extern idCVar cv_tdm_crouch_toggle;
+extern idCVar cv_tdm_new_crouch_toggle;
 extern idCVar cv_tdm_crouch_toggle_hold_time;
 extern idCVar cv_tdm_reattach_delay;
 
diff --git game/physics/Physics_Player.cpp game/physics/Physics_Player.cpp
index 6c54d3f..a28c89d 100644
--- game/physics/Physics_Player.cpp
+++ game/physics/Physics_Player.cpp
@@ -1532,6 +1532,15 @@ void idPhysics_Player::RopeMove( void )
 	wishspeed = wishvel.Normalize();
 	idPhysics_Player::Accelerate( wishvel, wishspeed, PM_ACCELERATE );
 
+	// Daft Mugi: Uncrouch if moving up a rope. (new toggle crouch)
+	if (cv_tdm_new_crouch_toggle.GetBool() && cv_tdm_crouch_toggle.GetBool())
+	{
+		// upscale: looking up?, wishspeed: moving?
+		if (upscale < 0 && wishspeed > 0) {
+			player->m_CrouchIntent = false;
+		}
+	}
+
 	// cap the climb velocity
 	upscale = current.velocity * -climbDir;
 	if ( upscale < -PM_ROPESPEED ) 
@@ -1662,6 +1671,7 @@ void idPhysics_Player::LadderMove( void )
 	float	upscale(0.0f), horizscale(0.0f), NormalDot(0.0f);
 	trace_t SurfTrace;
 	bool	bMoveAllowed( true );
+	idPlayer *player = static_cast<idPlayer *>(self);
 
 
 	// jump off the climbable surface if they jump, or fall off if they hit crouch
@@ -1870,6 +1880,15 @@ void idPhysics_Player::LadderMove( void )
 	wishspeed = wishvel.Normalize();
 	idPhysics_Player::Accelerate( wishvel, wishspeed, accel );
 
+	// Daft Mugi: Uncrouch if moving up a ladder or vine. (new toggle crouch)
+	if (cv_tdm_new_crouch_toggle.GetBool() && cv_tdm_crouch_toggle.GetBool())
+	{
+		// lenVert2: looking up?, wishspeed: moving?
+		if (lenVert2 > 0 && wishspeed > 0) {
+			player->m_CrouchIntent = false;
+		}
+	}
+
 	// don't apply friction on the wishdir direction
 	idPhysics_Player::Friction( wishdir );
 
@@ -2198,10 +2217,13 @@ void idPhysics_Player::CheckDuck( void ) {
 			}
 		}
 
-		// TODO_CROUCH: don't use crouch speed while climbing
 		if ( current.movementFlags & PMF_DUCKED ) 
 		{
-			playerSpeed = crouchSpeed;
+			// #5961 - Don't use crouch speed while climbing
+			if (!(OnRope() || OnLadder()))
+			{
+				playerSpeed = crouchSpeed;
+			}
 			maxZ = pm_crouchheight.GetFloat();
 		}
 		else 
