diff --git a/src/d_player.h b/src/d_player.h
index 755926480ae9c2b2b90383659ec079230e48a881..6df6689c5fcf4f1085511218d7f19047cd8a7c0f 100644
--- a/src/d_player.h
+++ b/src/d_player.h
@@ -245,7 +245,8 @@ typedef enum
 	CR_MINECART,
 	CR_ROLLOUT,
 	CR_PTERABYTE,
-	CR_DUSTDEVIL
+	CR_DUSTDEVIL,
+	CR_FAN
 } carrytype_t; // pw_carry
 
 // Player powers. (don't edit this comment)
diff --git a/src/deh_tables.c b/src/deh_tables.c
index e45d552c9e601461e5c29025d9e7cb662ce966c0..11d8b1a0147aebf3e1dfb3cb5251324ebd76d6e9 100644
--- a/src/deh_tables.c
+++ b/src/deh_tables.c
@@ -5119,6 +5119,7 @@ struct int_const_s const INT_CONST[] = {
 	{"CR_ROLLOUT",CR_ROLLOUT},
 	{"CR_PTERABYTE",CR_PTERABYTE},
 	{"CR_DUSTDEVIL",CR_DUSTDEVIL},
+	{"CR_FAN",CR_FAN},
 
 	// Ring weapons (ringweapons_t)
 	// Useful for A_GiveWeapon
diff --git a/src/p_map.c b/src/p_map.c
index 1a8494deafadbeb6ffb7d76069b9fd1c9526a280..2bb02503f464fde0b166e6940e9c40ad166a171c 100644
--- a/src/p_map.c
+++ b/src/p_map.c
@@ -505,11 +505,12 @@ static void P_DoFanAndGasJet(mobj_t *spring, mobj_t *object)
 			if (flipval*object->momz > FixedMul(speed, spring->scale))
 				object->momz = flipval*FixedMul(speed, spring->scale);
 
-			if (p && !p->powers[pw_tailsfly]) // doesn't reset anim for Tails' flight
+			if (p && !p->powers[pw_tailsfly] && !p->powers[pw_carry]) // doesn't reset anim for Tails' flight
 			{
 				P_ResetPlayer(p);
-				if (p->panim != PA_FALL)
-					P_SetPlayerMobjState(object, S_PLAY_FALL);
+				P_SetPlayerMobjState(object, S_PLAY_FALL);
+				P_SetTarget(&object->tracer, spring);
+				p->powers[pw_carry] = CR_FAN;
 			}
 			break;
 		case MT_STEAM: // Steam
diff --git a/src/p_spec.c b/src/p_spec.c
index 259b15e0b431019e2257b518cdde5448d26d6e63..3207ddb95b5d8c724a87a678e812c5e9f7cc4a93 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -4965,9 +4965,13 @@ static void P_EvaluateSpecialFlags(player_t *player, sector_t *sector, sector_t
 		if (player->mo->momz > mobjinfo[MT_FAN].mass)
 			player->mo->momz = mobjinfo[MT_FAN].mass;
 
-		P_ResetPlayer(player);
-		if (player->panim != PA_FALL)
+		if (!player->powers[pw_carry])
+		{
+			P_ResetPlayer(player);
 			P_SetPlayerMobjState(player->mo, S_PLAY_FALL);
+			P_SetTarget(&player->mo->tracer, player->mo);
+			player->powers[pw_carry] = CR_FAN;
+		}
 	}
 	if (sector->specialflags & SSF_SUPERTRANSFORM)
 	{
diff --git a/src/p_user.c b/src/p_user.c
index fa42568cad316519ea09fdab2da736b09a7291d8..e48cb47eae6b0fcbc6b5bf8ece8e56e8ed705da4 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -1966,22 +1966,22 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj)
 
 	ghost->angle = (mobj->player ? mobj->player->drawangle : mobj->angle);
 	ghost->rollangle = mobj->rollangle;
-	
+
 	ghost->sprite = mobj->sprite;
 	ghost->sprite2 = mobj->sprite2;
 	ghost->frame = mobj->frame;
 	ghost->tics = -1;
 	ghost->frame &= ~FF_TRANSMASK;
 	ghost->frame |= tr_trans50<<FF_TRANSSHIFT;
-	
+
 	ghost->renderflags = mobj->renderflags;
 	ghost->blendmode = mobj->blendmode;
-	
+
 	ghost->spritexscale = mobj->spritexscale;
 	ghost->spriteyscale = mobj->spriteyscale;
 	ghost->spritexoffset = mobj->spritexoffset;
 	ghost->spriteyoffset = mobj->spriteyoffset;
-	
+
 	ghost->fuse = ghost->info->damage;
 	ghost->skin = mobj->skin;
 
@@ -12589,6 +12589,29 @@ void P_PlayerAfterThink(player_t *player)
 
 				break;
 			}
+			case CR_FAN:
+			{
+				fixed_t zdist;
+				mobj_t *mo = player->mo, *fan = player->mo->tracer;
+
+				if (!(player->pflags & PF_JUMPSTASIS))
+					player->pflags |= PF_JUMPSTASIS;
+
+				if (fan->eflags & MFE_VERTICALFLIP)
+					zdist = (mo->z + mo->height) - (fan->z + fan->height);
+				else
+					zdist = mo->z - fan->z;
+
+				if ((fan->type != MT_FAN && !P_PlayerTouchingSectorSpecialFlag(player, SSF_FAN))
+				|| (fan->type == MT_FAN && (abs(mo->x - fan->x) > fan->radius || abs(mo->y - fan->y) > fan->radius || zdist > (fan->health << FRACBITS))))
+				{
+					P_SetTarget(&player->mo->tracer, NULL);
+					player->pflags &= ~PF_JUMPSTASIS;
+					player->powers[pw_carry] = CR_NONE;
+					break;
+				}
+				break;
+			}
 			case CR_ROLLOUT:
 			{
 				mobj_t *mo = player->mo, *rock = player->mo->tracer;