diff --git a/src/p_local.h b/src/p_local.h
index 6123e001e907d58929ef04539136ec6eea4afd91..70714ce3b4e0b9393667fbf6bd0d9c57e8e3f2b9 100644
--- a/src/p_local.h
+++ b/src/p_local.h
@@ -115,6 +115,8 @@ extern consvar_t cv_cam_speed, cv_cam_rotate, cv_cam_rotspeed, cv_cam_turnmultip
 extern consvar_t cv_cam2_dist, cv_cam2_still, cv_cam2_height;
 extern consvar_t cv_cam2_speed, cv_cam2_rotate, cv_cam2_rotspeed, cv_cam2_turnmultiplier, cv_cam2_orbit, cv_cam2_adjust;
 
+extern consvar_t cv_viewroll;
+
 extern consvar_t cv_cam_savedist[2][2], cv_cam_saveheight[2][2];
 void CV_UpdateCamDist(void);
 void CV_UpdateCam2Dist(void);
diff --git a/src/p_user.c b/src/p_user.c
index e1edeca8b2438affaf51ab0b9f2c00aa531fcaa3..67e63fa433e428f56ef9dbd5bf3835bb2fe2bd76 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -9849,6 +9849,8 @@ consvar_t cv_cam2_turnmultiplier = CVAR_INIT ("cam2_turnmultiplier", "0.75", NUL
 consvar_t cv_cam2_orbit = CVAR_INIT ("cam2_orbit", "Off", "If enabled, vertical camera movement will rotate around the player character rather than staying in place", CV_SAVE|CV_ALLOWLUA, CV_OnOff, NULL);
 consvar_t cv_cam2_adjust = CVAR_INIT ("cam2_adjust", "On", "Adjust camera angle relative to the slope the player is on", CV_SAVE|CV_ALLOWLUA, CV_OnOff, NULL);
 
+consvar_t cv_viewroll = CVAR_INIT ("viewroll", "Off", "Tilt camera on sloped surfaces", CV_SAVE, CV_OnOff, NULL);;
+
 // [standard vs simple][p1 or p2]
 consvar_t cv_cam_savedist[2][2] = {
 	{ // standard
@@ -11735,6 +11737,40 @@ void P_DoFollowMobj(player_t *player, mobj_t *followmobj)
 	}
 }
 
+
+
+static void
+DoABarrelRoll (player_t *player)
+{
+	angle_t slope;
+	angle_t delta;
+
+	if (player->mo->standingslope)
+	{
+		slope = player->mo->standingslope->zangle;
+	}
+	else
+	{
+		slope = 0;
+	}
+
+	
+	if (player->mo->standingslope && cv_viewroll.value && (abs((INT32)slope) > ANGLE_11hh))
+	{
+		delta = ( player->mo->angle - player->mo->standingslope->xydirection );
+		slope = -(FixedMul(FINESINE (delta>>ANGLETOFINESHIFT), slope));
+	}
+	else
+		slope = 0;
+
+	delta = (INT32)( slope - player->viewrollangle )/ 16;
+
+	if (delta)
+		player->viewrollangle += delta;
+	else
+		player->viewrollangle  = slope;
+}
+
 //
 // P_PlayerThink
 //
@@ -12664,6 +12700,7 @@ void P_PlayerThink(player_t *player)
 
 		I_Error("I'm done!\n");
 	}*/
+	DoABarrelRoll(player);
 }
 
 // Checks if the mobj is above lava. Used by Pterabyte.
diff --git a/src/r_main.c b/src/r_main.c
index 133c1862a3f4b628a9ef73799d48779cd6686792..7a3fe512ea1f89ce0779001105c64b44fb589370 100644
--- a/src/r_main.c
+++ b/src/r_main.c
@@ -1734,6 +1734,8 @@ void R_RegisterEngineStuff(void)
 	CV_RegisterVar(&cv_cam_saveheight[1][0]);
 	CV_RegisterVar(&cv_cam_saveheight[1][1]);
 
+	CV_RegisterVar(&cv_viewroll);
+
 	CV_RegisterVar(&cv_showhud);
 	CV_RegisterVar(&cv_translucenthud);