diff --git a/src/info.c b/src/info.c
index 5d82fe06e3b04e82d315e3ee551eec5da0f516dd..3b99615d35799a1deed62e4f34c8ae93fb6c2a97 100644
--- a/src/info.c
+++ b/src/info.c
@@ -12860,10 +12860,10 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_None,       // seesound
-		8,              // reactiontime
+		8,              // reactiontime (sets number of frames the rock cycles through)
 		sfx_None,       // attacksound
 		S_NULL,         // painstate
-		0,              // painchance
+		12*TICRATE,     // painchance (sets how long an unridden rock should last before disappearing - set to 0 to disable)
 		sfx_None,       // painsound
 		S_NULL,         // meleestate
 		S_NULL,         // missilestate
diff --git a/src/p_enemy.c b/src/p_enemy.c
index 6fdb68ac4165c551b8a11d64d9ca068508ac3c87..20b9f9b03f93011345a4684ec00a106f7d753c3f 100644
--- a/src/p_enemy.c
+++ b/src/p_enemy.c
@@ -13935,7 +13935,7 @@ void A_RolloutSpawn(mobj_t *actor)
 		|| P_AproxDistance(actor->x - actor->target->x, actor->y - actor->target->y) > locvar1)
 	{
 		actor->target = P_SpawnMobj(actor->x, actor->y, actor->z, locvar2);
-		actor->target->flags2 |= (actor->flags2 & (MF2_AMBUSH | MF2_OBJECTFLIP));
+		actor->target->flags2 |= (actor->flags2 & (MF2_AMBUSH | MF2_OBJECTFLIP)) | MF2_SLIDEPUSH;
 		actor->target->eflags |= (actor->eflags & MFE_VERTICALFLIP);
 	}
 }
@@ -13957,41 +13957,45 @@ void A_RolloutRock(mobj_t *actor)
 		return;
 #endif
 
-	UINT8 maxframes = actor->info->reactiontime;
+	UINT8 maxframes = actor->info->reactiontime; // number of frames the mobj cycles through
 	fixed_t pi = (22*FRACUNIT/7);
-	fixed_t circumference = FixedMul(2 * pi, actor->radius);
+	fixed_t circumference = FixedMul(2 * pi, actor->radius); // used to calculate when to change frame
 	fixed_t speed = P_AproxDistance(actor->momx, actor->momy), topspeed = FixedMul(actor->info->speed, actor->scale);
 	boolean inwater = actor->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER);
 
-	actor->friction = FRACUNIT;
+	actor->friction = FRACUNIT; // turns out riding on solids sucks, so let's just make it easier on ourselves
 
-	if (inwater && !(actor->flags2 & MF2_AMBUSH))
+	if (inwater && !(actor->flags2 & MF2_AMBUSH)) // buoyancy in water (or lava)
 	{
 		actor->momz = FixedMul(actor->momz, locvar2);
 		actor->momz += P_MobjFlip(actor) * FixedMul(locvar2, actor->scale);
 	}
 
-	if (speed > topspeed)
+	if (speed > topspeed) // cap speed
 	{
 		actor->momx = FixedMul(FixedDiv(actor->momx, speed), topspeed);
 		actor->momy = FixedMul(FixedDiv(actor->momy, speed), topspeed);
 	}
+	
+	if (P_IsObjectOnGround(actor) || inwater) // apply drag to speed (compensates for lack of friction but also works in liquids)
+	{
+		actor->momx = FixedMul(actor->momx, locvar1);
+		actor->momy = FixedMul(actor->momy, locvar1);
+	}
 
-	actor->momx = FixedMul(actor->momx, locvar1);
-	actor->momy = FixedMul(actor->momy, locvar1);
-
-	speed = P_AproxDistance(actor->momx, actor->momy);
+	speed = P_AproxDistance(actor->momx, actor->momy); // recalculate speed for visual rolling
 
-	if (speed < actor->scale >> 1)
+	if (speed < actor->scale >> 1) // stop moving if speed is insignificant
 	{
 		actor->momx = 0;
 		actor->momy = 0;
 	}
 	else if (speed > actor->scale)
 	{
-		actor->angle = R_PointToAngle2(0, 0, actor->momx, actor->momy);
+		actor->movecount = 1; // rock has moved; fuse should be set so we don't have a trillion rocks lying around
+		actor->angle = R_PointToAngle2(0, 0, actor->momx, actor->momy); // set rock's angle to movement direction
 		actor->movefactor += speed;
-		if (actor->movefactor > circumference / maxframes)
+		if (actor->movefactor > circumference / maxframes) // if distance moved is enough to change frame, change it!
 		{
 			actor->reactiontime++;
 			actor->reactiontime %= maxframes;
@@ -13999,5 +14003,14 @@ void A_RolloutRock(mobj_t *actor)
 		}
 	}
 
-	actor->frame = actor->reactiontime % maxframes;
+	actor->frame = actor->reactiontime % maxframes; // set frame
+	
+	if (!(actor->flags & MF_PUSHABLE)) // if being ridden, don't disappear
+		actor->fuse = 0;
+	else if (!actor->fuse && actor->movecount == 1) // otherwise if rock has moved, set its fuse
+		actor->fuse = actor->info->painchance;
+	
+	if (actor->fuse && actor->fuse < 2*TICRATE)
+		actor->flags2 ^= MF2_DONTDRAW;
+		
 }
diff --git a/src/p_map.c b/src/p_map.c
index b62e33372f7afa8ca8a939420dee0ac01bc0abbd..e470de240e6152285f3b1ef13adf70e379f56a33 100644
--- a/src/p_map.c
+++ b/src/p_map.c
@@ -978,6 +978,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
 				|| (tmthing->eflags & MFE_VERTICALFLIP && abs(tmthing->z + tmthing->height - thing->z) < (thing->height>>2))))
 		{
 			thing->flags &= ~MF_PUSHABLE; // prevent riding player from applying pushable movement logic
+			thing->flags2 &= ~MF2_DONTDRAW; // don't leave the rock invisible if it was flashing prior to boarding
 			P_SetTarget(&thing->tracer, tmthing);
 			P_ResetPlayer(tmthing->player);
 			P_SetPlayerMobjState(tmthing, S_PLAY_WALK);