diff --git a/core/src/main/assets/messages/levels/levels.properties b/core/src/main/assets/messages/levels/levels.properties
index 93d7edfb6..258c31dc5 100644
--- a/core/src/main/assets/messages/levels/levels.properties
+++ b/core/src/main/assets/messages/levels/levels.properties
@@ -65,9 +65,12 @@ levels.traps.flocktrap.desc=Perhaps a joke from some amateur mage, triggering th
 levels.traps.frosttrap.name=frost trap
 levels.traps.frosttrap.desc=When activated, chemicals in this trap will rapidly freeze the air in a wide range around its location.
 
-levels.traps.gatewaytrap.name=grim trap
+levels.traps.gatewaytrap.name=gateway trap
 levels.traps.gatewaytrap.desc=This special teleportation trap can activate an infinite numbers of times and always teleports to the same location.
 
+levels.traps.geysertrap.name=geyser trap
+levels.traps.geysertrap.desc=When triggered, this trap will cause a geyser of water to spew forth, knocking away all nearby characters and converting the surrounding terrain to water.
+
 levels.traps.grimtrap.name=grim trap
 levels.traps.grimtrap.ondeath=You were killed by the blast of a grim trap...
 levels.traps.grimtrap.desc=Extremely powerful destructive magic is stored within this trap, enough to instantly kill all but the healthiest of heroes. Triggering it will send a ranged blast of lethal magic towards the nearest character.\n\nThankfully the trigger mechanism isn't hidden.
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/effects/Splash.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/effects/Splash.java
index 23246a573..bd09069f2 100644
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/effects/Splash.java
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/effects/Splash.java
@@ -63,6 +63,21 @@ public class Splash {
 		FACTORY.cone = cone;
 		emitter.burst( FACTORY, n );
 	}
+
+	public static void at( PointF p, final float dir, final float cone, final int color, int n, float interval ) {
+
+		if (n <= 0) {
+			return;
+		}
+
+		Emitter emitter = GameScene.emitter();
+		emitter.pos( p );
+
+		FACTORY.color = color;
+		FACTORY.dir = dir;
+		FACTORY.cone = cone;
+		emitter.start( FACTORY, interval, n );
+	}
 	
 	private static final SplashFactory FACTORY = new SplashFactory();
 			
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/CavesLevel.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/CavesLevel.java
index 5cb0eb8d6..2dbe7fee9 100644
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/CavesLevel.java
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/CavesLevel.java
@@ -31,6 +31,8 @@ import com.shatteredpixel.shatteredpixeldungeon.levels.traps.BurningTrap;
 import com.shatteredpixel.shatteredpixeldungeon.levels.traps.ConfusionTrap;
 import com.shatteredpixel.shatteredpixeldungeon.levels.traps.CorrosionTrap;
 import com.shatteredpixel.shatteredpixeldungeon.levels.traps.FrostTrap;
+import com.shatteredpixel.shatteredpixeldungeon.levels.traps.GatewayTrap;
+import com.shatteredpixel.shatteredpixeldungeon.levels.traps.GeyserTrap;
 import com.shatteredpixel.shatteredpixeldungeon.levels.traps.GrippingTrap;
 import com.shatteredpixel.shatteredpixeldungeon.levels.traps.GuardianTrap;
 import com.shatteredpixel.shatteredpixeldungeon.levels.traps.PitfallTrap;
@@ -98,7 +100,7 @@ public class CavesLevel extends RegularLevel {
 		return new Class[]{
 				BurningTrap.class, PoisonDartTrap.class, FrostTrap.class, StormTrap.class, CorrosionTrap.class,
 				GrippingTrap.class, RockfallTrap.class,  GuardianTrap.class,
-				ConfusionTrap.class, SummoningTrap.class, WarpingTrap.class, PitfallTrap.class };
+				ConfusionTrap.class, SummoningTrap.class, WarpingTrap.class, PitfallTrap.class, GatewayTrap.class, GeyserTrap.class };
 	}
 
 	@Override
@@ -106,7 +108,7 @@ public class CavesLevel extends RegularLevel {
 		return new float[]{
 				4, 4, 4, 4, 4,
 				2, 2, 2,
-				1, 1, 1, 1};
+				1, 1, 1, 1, 1, 1 };
 	}
 	
 	@Override
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/CityLevel.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/CityLevel.java
index 5e0b916df..e7970c506 100644
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/CityLevel.java
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/CityLevel.java
@@ -34,6 +34,8 @@ import com.shatteredpixel.shatteredpixeldungeon.levels.traps.DisintegrationTrap;
 import com.shatteredpixel.shatteredpixeldungeon.levels.traps.DistortionTrap;
 import com.shatteredpixel.shatteredpixeldungeon.levels.traps.FlashingTrap;
 import com.shatteredpixel.shatteredpixeldungeon.levels.traps.FrostTrap;
+import com.shatteredpixel.shatteredpixeldungeon.levels.traps.GatewayTrap;
+import com.shatteredpixel.shatteredpixeldungeon.levels.traps.GeyserTrap;
 import com.shatteredpixel.shatteredpixeldungeon.levels.traps.GuardianTrap;
 import com.shatteredpixel.shatteredpixeldungeon.levels.traps.PitfallTrap;
 import com.shatteredpixel.shatteredpixeldungeon.levels.traps.RockfallTrap;
@@ -93,7 +95,7 @@ public class CityLevel extends RegularLevel {
 		return new Class[]{
 				FrostTrap.class, StormTrap.class, CorrosionTrap.class, BlazingTrap.class, DisintegrationTrap.class,
 				RockfallTrap.class, FlashingTrap.class, GuardianTrap.class, WeakeningTrap.class,
-				DisarmingTrap.class, SummoningTrap.class, WarpingTrap.class, CursingTrap.class, PitfallTrap.class, DistortionTrap.class };
+				DisarmingTrap.class, SummoningTrap.class, WarpingTrap.class, CursingTrap.class, PitfallTrap.class, DistortionTrap.class, GatewayTrap.class, GeyserTrap.class };
 	}
 
 	@Override
@@ -101,7 +103,7 @@ public class CityLevel extends RegularLevel {
 		return new float[]{
 				4, 4, 4, 4, 4,
 				2, 2, 2, 2,
-				1, 1, 1, 1, 1, 1 };
+				1, 1, 1, 1, 1, 1, 1, 1 };
 	}
 	
 	@Override
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/HallsLevel.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/HallsLevel.java
index ad731f0b3..af4ba22fe 100644
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/HallsLevel.java
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/HallsLevel.java
@@ -36,6 +36,8 @@ import com.shatteredpixel.shatteredpixeldungeon.levels.traps.DisintegrationTrap;
 import com.shatteredpixel.shatteredpixeldungeon.levels.traps.DistortionTrap;
 import com.shatteredpixel.shatteredpixeldungeon.levels.traps.FlashingTrap;
 import com.shatteredpixel.shatteredpixeldungeon.levels.traps.FrostTrap;
+import com.shatteredpixel.shatteredpixeldungeon.levels.traps.GatewayTrap;
+import com.shatteredpixel.shatteredpixeldungeon.levels.traps.GeyserTrap;
 import com.shatteredpixel.shatteredpixeldungeon.levels.traps.GrimTrap;
 import com.shatteredpixel.shatteredpixeldungeon.levels.traps.GuardianTrap;
 import com.shatteredpixel.shatteredpixeldungeon.levels.traps.PitfallTrap;
@@ -118,7 +120,7 @@ public class HallsLevel extends RegularLevel {
 		return new Class[]{
 				FrostTrap.class, StormTrap.class, CorrosionTrap.class, BlazingTrap.class, DisintegrationTrap.class,
 				RockfallTrap.class, FlashingTrap.class, GuardianTrap.class, WeakeningTrap.class,
-				DisarmingTrap.class, SummoningTrap.class, WarpingTrap.class, CursingTrap.class, GrimTrap.class, PitfallTrap.class, DistortionTrap.class };
+				DisarmingTrap.class, SummoningTrap.class, WarpingTrap.class, CursingTrap.class, GrimTrap.class, PitfallTrap.class, DistortionTrap.class, GatewayTrap.class, GeyserTrap.class };
 	}
 
 	@Override
@@ -126,7 +128,7 @@ public class HallsLevel extends RegularLevel {
 		return new float[]{
 				4, 4, 4, 4, 4,
 				2, 2, 2, 2,
-				1, 1, 1, 1, 1, 1, 1 };
+				1, 1, 1, 1, 1, 1, 1, 1, 1 };
 	}
 	
 	@Override
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/PrisonLevel.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/PrisonLevel.java
index 794a8579d..1f9fa0cb4 100644
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/PrisonLevel.java
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/PrisonLevel.java
@@ -33,6 +33,8 @@ import com.shatteredpixel.shatteredpixeldungeon.levels.traps.BurningTrap;
 import com.shatteredpixel.shatteredpixeldungeon.levels.traps.ChillingTrap;
 import com.shatteredpixel.shatteredpixeldungeon.levels.traps.ConfusionTrap;
 import com.shatteredpixel.shatteredpixeldungeon.levels.traps.FlockTrap;
+import com.shatteredpixel.shatteredpixeldungeon.levels.traps.GatewayTrap;
+import com.shatteredpixel.shatteredpixeldungeon.levels.traps.GeyserTrap;
 import com.shatteredpixel.shatteredpixeldungeon.levels.traps.GrippingTrap;
 import com.shatteredpixel.shatteredpixeldungeon.levels.traps.OozeTrap;
 import com.shatteredpixel.shatteredpixeldungeon.levels.traps.PoisonDartTrap;
@@ -99,7 +101,7 @@ public class PrisonLevel extends RegularLevel {
 		return new Class[]{
 				ChillingTrap.class, ShockingTrap.class, ToxicTrap.class, BurningTrap.class, PoisonDartTrap.class,
 				AlarmTrap.class, OozeTrap.class, GrippingTrap.class,
-				ConfusionTrap.class, FlockTrap.class, SummoningTrap.class, TeleportationTrap.class, };
+				ConfusionTrap.class, FlockTrap.class, SummoningTrap.class, TeleportationTrap.class, GatewayTrap.class, GeyserTrap.class };
 	}
 
 	@Override
@@ -107,7 +109,7 @@ public class PrisonLevel extends RegularLevel {
 		return new float[]{
 				4, 4, 4, 4, 4,
 				2, 2, 2,
-				1, 1, 1, 1 };
+				1, 1, 1, 1, 1, 1 };
 	}
 
 	@Override
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/SewerLevel.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/SewerLevel.java
index d0d7cfde2..0151f2263 100644
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/SewerLevel.java
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/SewerLevel.java
@@ -31,6 +31,8 @@ import com.shatteredpixel.shatteredpixeldungeon.levels.traps.AlarmTrap;
 import com.shatteredpixel.shatteredpixeldungeon.levels.traps.ChillingTrap;
 import com.shatteredpixel.shatteredpixeldungeon.levels.traps.ConfusionTrap;
 import com.shatteredpixel.shatteredpixeldungeon.levels.traps.FlockTrap;
+import com.shatteredpixel.shatteredpixeldungeon.levels.traps.GatewayTrap;
+import com.shatteredpixel.shatteredpixeldungeon.levels.traps.GeyserTrap;
 import com.shatteredpixel.shatteredpixeldungeon.levels.traps.OozeTrap;
 import com.shatteredpixel.shatteredpixeldungeon.levels.traps.ShockingTrap;
 import com.shatteredpixel.shatteredpixeldungeon.levels.traps.SummoningTrap;
@@ -94,7 +96,7 @@ public class SewerLevel extends RegularLevel {
 				new Class<?>[]{
 						ChillingTrap.class, ShockingTrap.class, ToxicTrap.class, WornDartTrap.class,
 						AlarmTrap.class, OozeTrap.class,
-						ConfusionTrap.class, FlockTrap.class, SummoningTrap.class, TeleportationTrap.class };
+						ConfusionTrap.class, FlockTrap.class, SummoningTrap.class, TeleportationTrap.class, GatewayTrap.class };
 }
 
 	@Override
@@ -104,7 +106,7 @@ public class SewerLevel extends RegularLevel {
 				new float[]{
 						4, 4, 4, 4,
 						2, 2,
-						1, 1, 1, 1};
+						1, 1, 1, 1, 1};
 	}
 	
 	@Override
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/traps/GeyserTrap.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/traps/GeyserTrap.java
new file mode 100644
index 000000000..e2382d3d8
--- /dev/null
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/traps/GeyserTrap.java
@@ -0,0 +1,77 @@
+package com.shatteredpixel.shatteredpixeldungeon.levels.traps;
+
+import com.shatteredpixel.shatteredpixeldungeon.Assets;
+import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
+import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
+import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
+import com.shatteredpixel.shatteredpixeldungeon.effects.Splash;
+import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfBlastWave;
+import com.shatteredpixel.shatteredpixeldungeon.mechanics.Ballistica;
+import com.shatteredpixel.shatteredpixeldungeon.tiles.DungeonTilemap;
+import com.shatteredpixel.shatteredpixeldungeon.utils.BArray;
+import com.watabou.noosa.audio.Sample;
+import com.watabou.utils.PathFinder;
+import com.watabou.utils.PointF;
+import com.watabou.utils.Random;
+
+import java.util.ArrayList;
+
+public class GeyserTrap extends Trap {
+
+	{
+		color = TEAL;
+		shape = DIAMOND;
+	}
+
+	@Override
+	public void activate() {
+		Splash.at( DungeonTilemap.tileCenterToWorld( pos ), -PointF.PI/2, PointF.PI/2, 0x5bc1e3, 100, 0.01f);
+		Sample.INSTANCE.play(Assets.Sounds.GAS, 1f, 0.75f);
+
+		PathFinder.buildDistanceMap( pos, BArray.not( Dungeon.level.solid, null ), 2 );
+		for (int i = 0; i < PathFinder.distance.length; i++) {
+			if (PathFinder.distance[i] < Integer.MAX_VALUE) {
+				Dungeon.level.setCellToWater(true, i);
+			}
+		}
+
+		for (int i : PathFinder.NEIGHBOURS8){
+			Char ch = Actor.findChar(pos + i);
+			if (ch != null){
+				//trace a ballistica to our target (which will also extend past them)
+				Ballistica trajectory = new Ballistica(pos, ch.pos, Ballistica.STOP_TARGET);
+				//trim it to just be the part that goes past them
+				trajectory = new Ballistica(trajectory.collisionPos, trajectory.path.get(trajectory.path.size()-1), Ballistica.PROJECTILE);
+				//knock them back along that ballistica
+				WandOfBlastWave.throwChar(ch, trajectory, 2, true);
+			}
+		}
+
+		Char ch = Actor.findChar(pos);
+		if (ch != null){
+			int targetpos = -1;
+			if (ch == Dungeon.hero){
+				//if it is the hero, random direction that isn't into a hazard
+				ArrayList<Integer> candidates = new ArrayList<>();
+				for (int i : PathFinder.NEIGHBOURS8){
+					//add as a candidate if both cells on the trajectory are safe
+					if (!Dungeon.level.avoid[pos + i] && !Dungeon.level.avoid[pos + i + i]){
+						candidates.add(pos + i + i);
+					}
+				}
+				if (!candidates.isEmpty()){
+					targetpos = Random.element(candidates);
+				}
+			} else {
+				//random direction if it isn't the hero
+				targetpos = pos + 2*PathFinder.NEIGHBOURS8[Random.Int(8)];
+			}
+			if (targetpos != -1){
+				//trace a ballistica in the direction of our target
+				Ballistica trajectory = new Ballistica(pos, targetpos, Ballistica.STOP_SOLID);
+				//knock them back along that ballistica
+				WandOfBlastWave.throwChar(ch, trajectory, 2, true);
+			}
+		}
+	}
+}