diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml
index c2fca9ee65..97ccaace35 100644
--- a/android/AndroidManifest.xml
+++ b/android/AndroidManifest.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="io.anuke.mindustry"
-    android:versionCode="15"
-    android:versionName="2.4" >
+    android:versionCode="16"
+    android:versionName="3.0b" >
 
     <uses-sdk android:minSdkVersion="9" android:targetSdkVersion="25" />
 
diff --git a/android/src/io/anuke/mindustry/AndroidLauncher.java b/android/src/io/anuke/mindustry/AndroidLauncher.java
index 56d9e94a47..5c457088f3 100644
--- a/android/src/io/anuke/mindustry/AndroidLauncher.java
+++ b/android/src/io/anuke/mindustry/AndroidLauncher.java
@@ -51,7 +51,7 @@ public class AndroidLauncher extends AndroidApplication {
 			Unit.dp.multiplier = 1f;
 		}
 		
-		Mindustry.args.add("-debug");
+		//Mindustry.args.add("-debug");
 		
 		initialize(new Mindustry(), config);
 	}
diff --git a/build.gradle b/build.gradle
index fec2213330..6e977b8ab4 100644
--- a/build.gradle
+++ b/build.gradle
@@ -79,7 +79,7 @@ project(":core") {
     apply plugin: "java"
 
     dependencies {
-       // compile 'com.github.Anuken:ucore:61c43bf'
+        compile 'com.github.Anuken:ucore:92dc170f0e'
         compile "com.badlogicgames.gdx:gdx:$gdxVersion"
         compile "com.badlogicgames.gdx:gdx-ai:1.8.1"
     }
diff --git a/core/assets/maps/maze.png b/core/assets/maps/maze.png
index ffab959f20..c71f782049 100644
Binary files a/core/assets/maps/maze.png and b/core/assets/maps/maze.png differ
diff --git a/core/assets/shaders/shield.fragment b/core/assets/shaders/shield.fragment
index eed64e553c..c028303bad 100644
--- a/core/assets/shaders/shield.fragment
+++ b/core/assets/shaders/shield.fragment
@@ -5,6 +5,7 @@ precision mediump int;
 
 #define MAX_HITS 64
 #define HIT_RADIUS 12.0
+#define ALPHA 0.18
 
 uniform sampler2D u_texture;
 
@@ -53,7 +54,7 @@ void main() {
 	            color *= 1.65;
 	        }
 	        
-	        color.a = 0.18;
+	        color.a = ALPHA;
 	        
 	        for(int i = 0; i < u_hitamount; i ++){
 	    		vec3 hit = u_hits[i];
@@ -62,7 +63,7 @@ void main() {
 	    	
 	    		if(abs(distance(vec2(hit.x, hit.y), coords - u_texsize/2.0) - rad) < 1.0){
 	    			color = mix(color, u_color* vec4(si, si, si, 1.0), (1.0 * fract));
-	    			color.a = 0.18 + 0.82 *fract;
+	    			color.a = ALPHA + 0.82 *fract;
 	    		}
 	    	}
 	    }
diff --git a/core/src/io/anuke/mindustry/Vars.java b/core/src/io/anuke/mindustry/Vars.java
index 3403d4d2cc..ad34385288 100644
--- a/core/src/io/anuke/mindustry/Vars.java
+++ b/core/src/io/anuke/mindustry/Vars.java
@@ -43,7 +43,7 @@ public class Vars{
 	//whether to draw chunk borders
 	public static boolean debugChunks = false;
 	//whether turrets have infinite ammo (only with debug)
-	public static boolean infiniteAmmo = true;
+	public static boolean infiniteAmmo = false;
 	//whether to show paths of enemies
 	public static boolean showPaths = true;
 	//number of save slots-- increasing may lead to layout issues
diff --git a/core/src/io/anuke/mindustry/core/Control.java b/core/src/io/anuke/mindustry/core/Control.java
index c9eaab991a..b452f33964 100644
--- a/core/src/io/anuke/mindustry/core/Control.java
+++ b/core/src/io/anuke/mindustry/core/Control.java
@@ -115,7 +115,7 @@ public class Control extends Module{
 		player = new Player();
 		
 		spawns = WaveCreator.getSpawns();
-		WaveCreator.testWaves(1, 30);
+		//WaveCreator.testWaves(1, 30);
 	}
 	
 	public void reset(){
diff --git a/core/src/io/anuke/mindustry/entities/BulletType.java b/core/src/io/anuke/mindustry/entities/BulletType.java
index 698b8f35d2..9e6f2f46eb 100644
--- a/core/src/io/anuke/mindustry/entities/BulletType.java
+++ b/core/src/io/anuke/mindustry/entities/BulletType.java
@@ -62,7 +62,7 @@ public abstract class BulletType  extends BaseBulletType<Bullet>{
 			}
 		}
 	},
-	emp = new BulletType(1.6f, 6){
+	emp = new BulletType(1.6f, 8){
 		{
 			lifetime = 50f;
 			hitsize = 6f;
@@ -89,7 +89,7 @@ public abstract class BulletType  extends BaseBulletType<Bullet>{
 		
 		public void removed(Bullet b){
 			Timers.run(5f, ()->{
-				new EMP(b.x, b.y, b.damage).add();
+				new EMP(b.x, b.y, b.getDamage()).add();
 			});
 			Effects.effect(Fx.empshockwave, b);
 			Effects.shake(3f, 3f, b);
@@ -132,7 +132,7 @@ public abstract class BulletType  extends BaseBulletType<Bullet>{
 			DamageArea.damage(!(b.owner instanceof Enemy), b.x, b.y, 25f, (int)(damage * 2f/3f));
 		}
 	},
-	titanshell = new BulletType(1.8f, 40){
+	titanshell = new BulletType(1.8f, 38){
 		{
 			lifetime = 70f;
 			hitsize = 15f;
@@ -160,7 +160,7 @@ public abstract class BulletType  extends BaseBulletType<Bullet>{
 			Effects.effect(Fx.shellsmoke, b);
 			Effects.effect(Fx.shockwaveSmall, b);
 			
-			DamageArea.damage(!(b.owner instanceof Enemy), b.x, b.y, 25f, (int)(damage * 2f/3f));
+			DamageArea.damage(!(b.owner instanceof Enemy), b.x, b.y, 50f, (int)(damage * 2f/3f));
 		}
 	},
 	yellowshell = new BulletType(1.2f, 20){
diff --git a/core/src/io/anuke/mindustry/entities/WaveCreator.java b/core/src/io/anuke/mindustry/entities/WaveCreator.java
index 9833ccaf9b..11a1f69390 100644
--- a/core/src/io/anuke/mindustry/entities/WaveCreator.java
+++ b/core/src/io/anuke/mindustry/entities/WaveCreator.java
@@ -91,7 +91,7 @@ public class WaveCreator{
 			//boss wave
 			new EnemySpawn(FortressEnemy.class){{
 				after = 16;
-				amount = 2;
+				amount = 1;
 				spacing = 5;
 				scaling = 1;
 			}},
@@ -149,8 +149,8 @@ public class WaveCreator{
 			}},
 			new EnemySpawn(FortressEnemy.class){{
 				after = 12;
-				spacing = 3;
-				scaling = 5;
+				spacing = 4;
+				scaling = 6;
 			}},
 			new EnemySpawn(HealerEnemy.class){{
 				scaling = 3;
diff --git a/core/src/io/anuke/mindustry/entities/effect/EMP.java b/core/src/io/anuke/mindustry/entities/effect/EMP.java
index a079c7d38d..b4b124e67c 100644
--- a/core/src/io/anuke/mindustry/entities/effect/EMP.java
+++ b/core/src/io/anuke/mindustry/entities/effect/EMP.java
@@ -50,14 +50,15 @@ public class EMP extends TimedEntity{
 			Tile tile = array.get(i);
 			targets.add(tile);
 			
-			if(tile.block() instanceof PowerAcceptor){
+			if(tile != null && tile.block() instanceof PowerAcceptor){
 				PowerAcceptor p = (PowerAcceptor)tile.block();
-				tile.entity.damage(damage*2); //extra damage
 				p.setPower(tile, 0f);
+				tile.entity.damage(damage*2); //extra damage
 			}
 			
-			Effects.effect(Fx.empspark, tile.entity);
-			tile.entity.damage(damage);
+			//entity may be null here, after the block is dead!
+			Effects.effect(Fx.empspark, tile.worldx(), tile.worldy());
+			if(tile.entity != null) tile.entity.damage(damage);
 		}
 	}
 	
diff --git a/core/src/io/anuke/mindustry/entities/effect/Shield.java b/core/src/io/anuke/mindustry/entities/effect/Shield.java
index b62bfbdd41..7a3775d5f1 100644
--- a/core/src/io/anuke/mindustry/entities/effect/Shield.java
+++ b/core/src/io/anuke/mindustry/entities/effect/Shield.java
@@ -18,6 +18,7 @@ import io.anuke.ucore.util.Mathf;
 public class Shield extends Entity{
 	public boolean active;
 	public boolean hitPlayers = false;
+	public float radius = 0f;
 	
 	private float uptime = 0f;
 	private final Tile tile;
@@ -84,8 +85,7 @@ public class Shield extends Entity{
 	}
 	
 	float drawRadius(){
-		ShieldBlock block = (ShieldBlock)tile.block();
-		return (block.shieldRadius*2 + Mathf.sin(Timers.time(), 25f, 2f)) * uptime;
+		return (radius*2 + Mathf.sin(Timers.time(), 25f, 2f));
 	}
 	
 	public void removeDelay(){
diff --git a/core/src/io/anuke/mindustry/entities/enemies/Enemy.java b/core/src/io/anuke/mindustry/entities/enemies/Enemy.java
index 710f9e9152..bb7b703b97 100644
--- a/core/src/io/anuke/mindustry/entities/enemies/Enemy.java
+++ b/core/src/io/anuke/mindustry/entities/enemies/Enemy.java
@@ -5,13 +5,10 @@ import com.badlogic.gdx.math.Vector2;
 import com.badlogic.gdx.utils.reflect.ClassReflection;
 
 import io.anuke.mindustry.Vars;
-import io.anuke.mindustry.entities.Bullet;
-import io.anuke.mindustry.entities.BulletType;
-import io.anuke.mindustry.entities.Player;
+import io.anuke.mindustry.entities.*;
 import io.anuke.mindustry.entities.effect.Fx;
 import io.anuke.mindustry.entities.effect.Shaders;
 import io.anuke.mindustry.world.Tile;
-import io.anuke.ucore.UCore;
 import io.anuke.ucore.core.*;
 import io.anuke.ucore.entities.*;
 import io.anuke.ucore.util.Angles;
@@ -103,6 +100,10 @@ public class Enemy extends DestructibleEntity{
 	}
 	
 	void updateTargeting(boolean nearCore){
+		if(target != null && target instanceof TileEntity && ((TileEntity)target).dead){
+			target = null;
+		}
+		
 		if(Timers.get(this, "target", 15) && !nearCore){
 			target = Vars.world.findTileTarget(x, y, null, range, false);
 
@@ -110,10 +111,8 @@ public class Enemy extends DestructibleEntity{
 			if(target == null){
 				target = Entities.getClosest(Entities.defaultGroup(), x, y, range, e -> e instanceof Player);
 			}
-		}
-		
-		if(target instanceof Enemy){
-			UCore.log(target);
+		}else if(nearCore){
+			target = Vars.control.getCore().entity;
 		}
 
 		if(target != null && bullet != null){
diff --git a/core/src/io/anuke/mindustry/input/AndroidInput.java b/core/src/io/anuke/mindustry/input/AndroidInput.java
index 9659f8e3ab..d11401a025 100644
--- a/core/src/io/anuke/mindustry/input/AndroidInput.java
+++ b/core/src/io/anuke/mindustry/input/AndroidInput.java
@@ -3,6 +3,7 @@ package io.anuke.mindustry.input;
 import static io.anuke.mindustry.Vars.*;
 
 import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.Input.Buttons;
 import com.badlogic.gdx.Input.Keys;
 import com.badlogic.gdx.InputAdapter;
 import com.badlogic.gdx.math.Vector2;
@@ -10,7 +11,9 @@ import com.badlogic.gdx.math.Vector2;
 import io.anuke.mindustry.Vars;
 import io.anuke.mindustry.resource.ItemStack;
 import io.anuke.mindustry.world.Tile;
+import io.anuke.mindustry.world.blocks.types.Configurable;
 import io.anuke.ucore.core.Graphics;
+import io.anuke.ucore.core.Inputs;
 import io.anuke.ucore.core.Timers;
 import io.anuke.ucore.scene.ui.layout.Unit;
 import io.anuke.ucore.util.Mathf;
@@ -82,6 +85,18 @@ public class AndroidInput extends InputAdapter{
 	}
 	
 	public static void doInput(){
+		Tile cursor = selected();
+		
+		//TODO test
+		if(Inputs.buttonUp(Buttons.LEFT) && cursor != null){
+			Tile linked = cursor.isLinked() ? cursor.getLinked() : cursor;
+			if(linked != null && linked.block() instanceof Configurable){
+				Vars.ui.showConfig(linked);
+			}else if(!Vars.ui.hasConfigMouse()){
+				Vars.ui.hideConfig();
+			}
+		}
+		
 		if(Gdx.input.isTouched(0) 
 				&& Mathf.near2d(lmousex, lmousey, Gdx.input.getX(0), Gdx.input.getY(0), Unit.dp.inPixels(50)) 
 				&& !ui.hasMouse() /*&& (player.recipe == null || mode == PlaceMode.touch)*/){
diff --git a/core/src/io/anuke/mindustry/resource/Recipe.java b/core/src/io/anuke/mindustry/resource/Recipe.java
index 22ccc746a5..6419b26a20 100644
--- a/core/src/io/anuke/mindustry/resource/Recipe.java
+++ b/core/src/io/anuke/mindustry/resource/Recipe.java
@@ -52,7 +52,7 @@ public enum Recipe{
 	titaniumpurifier(crafting, ProductionBlocks.titaniumpurifier, stack(Item.steel, 30), stack(Item.iron, 30)),
 	oilrefinery(crafting, ProductionBlocks.oilrefinery, stack(Item.steel, 15), stack(Item.iron, 15)),
 	stoneformer(crafting, ProductionBlocks.stoneformer, stack(Item.steel, 10), stack(Item.iron, 10)),
-	lavasmelter(crafting, ProductionBlocks.lavasmelter, stack(Item.steel, 20), stack(Item.iron, 20), stack(Item.titanium, 10)),
+	lavasmelter(crafting, ProductionBlocks.lavasmelter, stack(Item.steel, 30), stack(Item.titanium, 15)),
 	
 	stonedrill(production, ProductionBlocks.stonedrill, stack(Item.stone, 12)),
 	irondrill(production, ProductionBlocks.irondrill, stack(Item.stone, 25)),
diff --git a/core/src/io/anuke/mindustry/ui/fragments/BlocksFragment.java b/core/src/io/anuke/mindustry/ui/fragments/BlocksFragment.java
index 053ac5bc2f..d27b15fe24 100644
--- a/core/src/io/anuke/mindustry/ui/fragments/BlocksFragment.java
+++ b/core/src/io/anuke/mindustry/ui/fragments/BlocksFragment.java
@@ -14,6 +14,7 @@ import io.anuke.mindustry.resource.Recipe;
 import io.anuke.mindustry.resource.Section;
 import io.anuke.mindustry.ui.FloatingDialog;
 import io.anuke.ucore.core.Draw;
+import io.anuke.ucore.graphics.Hue;
 import io.anuke.ucore.scene.builders.table;
 import io.anuke.ucore.scene.event.Touchable;
 import io.anuke.ucore.scene.ui.*;
@@ -105,7 +106,7 @@ public class BlocksFragment implements Fragment{
 							//image.setDisabled(!has);
 							image.setChecked(player.recipe == r);
 							image.setTouchable(canPlace ? Touchable.enabled : Touchable.disabled);
-							image.getImage().setColor(has ? Color.WHITE : Color.DARK_GRAY);
+							image.getImage().setColor(has ? Color.WHITE : Hue.lightness(0.33f));
 						});
 						
 						if(i % rows == rows-1)
@@ -195,7 +196,7 @@ public class BlocksFragment implements Fragment{
 				}).size(110, 50).pad(10f).units(Unit.dp);
 				
 				d.show();
-			}).expandX().padLeft(4).top().right().size(36f, 40f).units(Unit.dp);
+			}).expandX().padLeft(4).top().right().size(42f, 46f).padTop(-2).units(Unit.dp);
 		}
 		
 		
diff --git a/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java b/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java
index 34cf66d8f5..9b93767d85 100644
--- a/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java
+++ b/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java
@@ -22,6 +22,7 @@ import io.anuke.ucore.scene.actions.Actions;
 import io.anuke.ucore.scene.builders.imagebutton;
 import io.anuke.ucore.scene.builders.label;
 import io.anuke.ucore.scene.builders.table;
+import io.anuke.ucore.scene.event.Touchable;
 import io.anuke.ucore.scene.ui.Image;
 import io.anuke.ucore.scene.ui.Label;
 import io.anuke.ucore.scene.ui.layout.Cell;
@@ -42,7 +43,7 @@ public class HudFragment implements Fragment{
 			
 			new table(){{
 				left();
-				defaults().size(66).units(Unit.dp).left();
+				defaults().size(68).units(Unit.dp).left();
 				float isize = Unit.dp.inPixels(40);
 				
 				new imagebutton("icon-menu", isize, ()->{
@@ -64,6 +65,12 @@ public class HudFragment implements Fragment{
 			
 			row();
 			
+			new table(){{
+				addWaveTable();
+			}}.fillX().end();
+			
+			row();
+			
 			itemtable = new table("button").end().top().left().fillX().size(-1).get();
 			itemtable.setVisible(()-> control.getMode() != GameMode.sandbox);
 			itemcell = get().getCell(itemtable);
@@ -95,29 +102,16 @@ public class HudFragment implements Fragment{
 
 		//wave table...
 		new table(){{
-			atop();
-			aright();
 			
-			float uheight = 72f;
+			if(!Vars.android){
+				atop();
+				aright();
+			}else{
+				abottom();
+				aleft();
+			}
 			
-			new imagebutton("icon-play", Unit.dp.inPixels(30f), ()->{
-				Vars.control.runWave();
-			}).size(uheight).uniformY().units(Unit.dp)
-				.visible(()-> Vars.control.getMode() == GameMode.sandbox && Vars.control.getEnemiesRemaining() <= 0);
-
-			new table("button"){{
-
-				new label(()->"[orange]Wave " + control.getWave()).scale(fontscale*2f).left();
-
-				row();
-
-				new label(()-> control.getEnemiesRemaining() > 0 ?
-						control.getEnemiesRemaining() + " Enemies remaining" : 
-							(control.getTutorial().active() || Vars.control.getMode() == GameMode.sandbox) ? "waiting..." : "New wave in " + (int) (control.getWaveCountdown() / 60f))
-				.minWidth(150);
-
-				get().pad(Unit.dp.inPixels(12));
-			}}.height(uheight).units(Unit.dp);
+			//addWaveTable();
 
 			visible(()->!GameState.is(State.menu));
 		}}.end();
@@ -166,6 +160,46 @@ public class HudFragment implements Fragment{
 		}
 	}
 	
+	private void addWaveTable(){
+		float uheight = 66f;
+		
+		new table("button"){{
+			aleft();
+			new table(){{
+				aleft();
+
+				new label(()->"[orange]Wave " + control.getWave()).scale(fontscale*1.5f).left();
+
+				row();
+			
+				new label(()-> control.getEnemiesRemaining() > 0 ?
+					control.getEnemiesRemaining() + " enemies" : 
+						(control.getTutorial().active() || Vars.control.getMode() == GameMode.sandbox) ? "waiting..." : "Wave in " + (int) (control.getWaveCountdown() / 60f))
+				.minWidth(140).left();
+
+				get().pad(Unit.dp.inPixels(12));
+			}}.left().padLeft(-6).end();
+			
+			playButton(uheight);
+			//get().padTop(Unit.dp.inPixels(1));
+			//get().padBottom(Unit.dp.inPixels(1));
+		}}.height(uheight).units(Unit.dp).fillX().expandX().end();
+		
+	}
+	
+	private void playButton(float uheight){
+		new imagebutton("icon-play", Unit.dp.inPixels(30f), ()->{
+			Vars.control.runWave();
+		}).height(uheight).fillX().padTop(-8f).padBottom(-12f).padRight(-18f).padLeft(-10f).width(40f).units(Unit.dp).update(l->{
+			boolean vis = Vars.control.getMode() == GameMode.sandbox && Vars.control.getEnemiesRemaining() <= 0;
+			boolean paused = GameState.is(State.paused) || !vis;
+			
+			l.setVisible(vis);
+			l.getStyle().imageUp = Core.skin.getDrawable(vis ? "icon-play" : "clear");
+			l.setTouchable(!paused ? Touchable.enabled : Touchable.disabled);
+		});
+	}
+	
 	public void updateItems(){
 		
 		itemtable.clear();
diff --git a/core/src/io/anuke/mindustry/world/World.java b/core/src/io/anuke/mindustry/world/World.java
index 0c85042c11..ba31bbf780 100644
--- a/core/src/io/anuke/mindustry/world/World.java
+++ b/core/src/io/anuke/mindustry/world/World.java
@@ -278,7 +278,7 @@ public class World extends Module{
 			}
 		}
 		
-		if(Tmp.r2.overlaps(player.hitbox.getRect(player.x, player.y))){
+		if(!Vars.android && Tmp.r2.overlaps(player.hitbox.getRect(player.x, player.y))){
 			return false;
 		}
 		
diff --git a/core/src/io/anuke/mindustry/world/blocks/DistributionBlocks.java b/core/src/io/anuke/mindustry/world/blocks/DistributionBlocks.java
index 29d130b0c1..59818120dc 100644
--- a/core/src/io/anuke/mindustry/world/blocks/DistributionBlocks.java
+++ b/core/src/io/anuke/mindustry/world/blocks/DistributionBlocks.java
@@ -15,6 +15,7 @@ public class DistributionBlocks{
 	}},
 	
 	pulseconduit = new LiquidBlock("pulseconduit"){{
+		formalName = "pulse conduit";
 		fullDescription = "Advanced liquid transport block. Transports liquids faster and stores more than standard conduits.";
 		liquidCapacity = 16f;
 		flowfactor = 4.9f;
@@ -29,7 +30,6 @@ public class DistributionBlocks{
 	}},
 	
 	conveyor = new Conveyor("conveyor"){{
-		description = "Moves items.";
 		fullDescription = "Basic item transport block. Moves items forward and automatically deposits them into turrets or crafters. "
 				+ "Rotatable. Can be used as a bridge over liquids for enemies and players.";
 	}},
@@ -37,16 +37,13 @@ public class DistributionBlocks{
 	steelconveyor = new Conveyor("steelconveyor"){{
 		health = 55;
 		speed = 0.04f;
-		description = "Moves items faster.";
 		formalName = "steel conveyor";
 		fullDescription = "Advanced item transport block. Moves items faster than standard conveyors.";
 	}},
 	
-	//TODO
 	pulseconveyor = new Conveyor("poweredconveyor"){{
 		health = 75;
 		speed = 0.09f;
-		description = "Moves items even faster.";
 		formalName = "pulse conveyor";
 		fullDescription = "The ultimate item transport block. Moves items faster than steel conveyors.";
 	}},
@@ -71,7 +68,6 @@ public class DistributionBlocks{
 	}},
 	liquidjunction = new LiquidJunction("liquidjunction"){{
 		formalName = "liquid junction";
-		description = "Serves as a liquid junction.";
 		fullDescription = "Acts as a bridge for two crossing conduits. Useful in situations with "
 				+ "two different conduits carrying different liquids to different locations.";
 	}},
@@ -88,7 +84,7 @@ public class DistributionBlocks{
 	}},
 	powerlaser = new PowerLaser("powerlaser"){{
 		formalName = "power laser";
-		description = "Transmits power with a laser.";
+		description = "Transmits power.";
 		fullDescription = "Creates a laser that transmits power to the block in front of it. Does not generate any power itself. "
 				+ "Best used with generators or other lasers.";
 	}},
@@ -103,16 +99,16 @@ public class DistributionBlocks{
 		formalName = "laser corner";
 		description = "Splits input power into 2 lasers.";
 		fullDescription = "Laser that distributes power to two directions at once. "
-				+ "Useful in situations where it is required to power multiple blocks from one generator, and a normal router is imprecise.";
+				+ "Useful in situations where it is required to power multiple blocks from one generator, and a router is imprecise.";
 	}},
 	teleporter = new Teleporter("teleporter"){{
-		description = "[interact]Tap block to config[]\nTeleports items to others of the same color.";
+		description = "[interact]Tap block to config[]";
 		fullDescription = "Advanced item transport block. Teleporters input items to other teleporters of the same color."
 				+ " Does nothing if no teleporters of the same color exist. If multiple teleporters exist of the same color, a random one is selected."
 				+ " Tap and click the arrows to change color.";
 	}},
 	sorter = new Sorter("sorter"){{
-		description = "[interact]Tap block to config[]\nSorts input items by type.";
+		description = "[interact]Tap block to config[]";
 		fullDescription = "Sorts item by material type. Material to accept is indicated by the color in the block. "
 				+ "All items that match the sort material are outputted forward, everything else is outputted to the left and right.";
 	}};
diff --git a/core/src/io/anuke/mindustry/world/blocks/ProductionBlocks.java b/core/src/io/anuke/mindustry/world/blocks/ProductionBlocks.java
index 1d120eb1eb..dc13a2b1d4 100644
--- a/core/src/io/anuke/mindustry/world/blocks/ProductionBlocks.java
+++ b/core/src/io/anuke/mindustry/world/blocks/ProductionBlocks.java
@@ -78,7 +78,7 @@ public class ProductionBlocks{
 			liquidAmount = 18.99f;
 			output = Item.coal;
 			health = 50;
-			purifyTime = 60;
+			purifyTime = 50;
 			description = "Converts stone + water to coal.";
 			fullDescription = "A basic extractor block. Outputs coal when supplied with large amounts of water and stone.";
 		}
@@ -92,7 +92,7 @@ public class ProductionBlocks{
 			inputLiquid = Liquid.water;
 			liquidAmount = 40f;
 			liquidCapacity = 41f;
-			purifyTime = 80;
+			purifyTime = 60;
 			output = Item.titanium;
 			health = 70;
 			description = "Converts iron + water to titanium.";
@@ -106,7 +106,7 @@ public class ProductionBlocks{
 			inputLiquid = Liquid.oil;
 			liquidAmount = 45f;
 			liquidCapacity = 46f;
-			purifyTime = 70;
+			purifyTime = 60;
 			output = Item.coal;
 			health = 80;
 			craftEffect = Fx.purifyoil;
@@ -266,7 +266,7 @@ public class ProductionBlocks{
 			height = 3;
 			health = 600;
 			breaktime *= 2.3f;
-			description = "Generates power from uranium + water.";
+			//description = "Advanced generator.";
 			fullDescription = "The ultimate power generator. Highly volatile. Generates power from uranium. Requires constant cooling in the form of water. "
 					+ "Will explode violently if insufficient amounts of coolant are supplied. ";
 		}
diff --git a/core/src/io/anuke/mindustry/world/blocks/types/LiquidBlock.java b/core/src/io/anuke/mindustry/world/blocks/types/LiquidBlock.java
index 75d958b932..346abac2b9 100644
--- a/core/src/io/anuke/mindustry/world/blocks/types/LiquidBlock.java
+++ b/core/src/io/anuke/mindustry/world/blocks/types/LiquidBlock.java
@@ -20,7 +20,6 @@ public class LiquidBlock extends Block implements LiquidAcceptor{
 	
 	public LiquidBlock(String name) {
 		super(name);
-		description = "Transports liquids.";
 		rotate = true;
 		update = true;
 	}
diff --git a/core/src/io/anuke/mindustry/world/blocks/types/defense/PowerTurret.java b/core/src/io/anuke/mindustry/world/blocks/types/defense/PowerTurret.java
index 72c578a3ea..bed70e2aba 100644
--- a/core/src/io/anuke/mindustry/world/blocks/types/defense/PowerTurret.java
+++ b/core/src/io/anuke/mindustry/world/blocks/types/defense/PowerTurret.java
@@ -26,6 +26,11 @@ public class PowerTurret extends Turret implements PowerAcceptor{
 		ammo = null;
 	}
 	
+	@Override
+	public void postInit(){
+		description = "[turretinfo]Uses power.";
+	}
+	
 	@Override
 	public void getStats(Array<String> list){
 		super.getStats(list);
@@ -33,12 +38,6 @@ public class PowerTurret extends Turret implements PowerAcceptor{
 		list.add("[powerinfo]Power/shot: " + Strings.toFixed(powerUsed, 1));
 	}
 	
-	@Override
-	public void postInit(){
-		super.postInit();
-		description += "\n[powerinfo]Power/shot: " + Strings.toFixed(powerUsed, 1);
-	}
-	
 	@Override
 	public void drawPixelOverlay(Tile tile){
 		Vector2 offset = getPlaceOffset();
diff --git a/core/src/io/anuke/mindustry/world/blocks/types/defense/RepairTurret.java b/core/src/io/anuke/mindustry/world/blocks/types/defense/RepairTurret.java
index c696738a36..e6d4102ff7 100644
--- a/core/src/io/anuke/mindustry/world/blocks/types/defense/RepairTurret.java
+++ b/core/src/io/anuke/mindustry/world/blocks/types/defense/RepairTurret.java
@@ -31,7 +31,7 @@ public class RepairTurret extends PowerTurret{
 	
 	@Override
 	public void postInit(){
-		description = "[turretinfo]Range: " + (int)range + "\nPower/unit: "+powerUsed+"\n[description]Heals nearby tiles.";
+		description = "[powerinfo]Uses power[white]\nRepairs nearby blocks.";
 	}
 	
 	@Override
diff --git a/core/src/io/anuke/mindustry/world/blocks/types/defense/ShieldBlock.java b/core/src/io/anuke/mindustry/world/blocks/types/defense/ShieldBlock.java
index 3a08c576fd..75033ab71e 100644
--- a/core/src/io/anuke/mindustry/world/blocks/types/defense/ShieldBlock.java
+++ b/core/src/io/anuke/mindustry/world/blocks/types/defense/ShieldBlock.java
@@ -11,16 +11,20 @@ import io.anuke.mindustry.world.blocks.types.PowerBlock;
 import io.anuke.ucore.core.Effects;
 import io.anuke.ucore.core.Timers;
 import io.anuke.ucore.entities.BulletEntity;
+import io.anuke.ucore.util.Mathf;
 import io.anuke.ucore.util.Strings;
 
 public class ShieldBlock extends PowerBlock{
 	public float shieldRadius = 40f;
-	public float powerDrain = 0.006f;
+	public float powerDrain = 0.005f;
 	public float powerPerDamage = 0.1f;
+	public float maxRadius = 40f;
+	public float radiusPowerScale = 7.5f;
 	
 	public ShieldBlock(String name) {
 		super(name);
 		voltage = powerDrain;
+		health = 100;
 	}
 	
 	@Override
@@ -42,7 +46,7 @@ public class ShieldBlock extends PowerBlock{
 		}
 
 		if(entity.power > powerPerDamage){
-			if(!entity.shield.active && entity.power > powerPerDamage * 8f){
+			if(!entity.shield.active){
 				entity.shield.add();
 			}
 
@@ -52,6 +56,8 @@ public class ShieldBlock extends PowerBlock{
 				entity.shield.removeDelay();
 			}
 		}
+		
+		entity.shield.radius = Mathf.lerp(entity.shield.radius, Math.min(entity.power * radiusPowerScale, maxRadius), Timers.delta() * 0.05f);
 
 	}
 
diff --git a/core/src/io/anuke/mindustry/world/blocks/types/defense/Turret.java b/core/src/io/anuke/mindustry/world/blocks/types/defense/Turret.java
index e63681da52..63fa33a35e 100644
--- a/core/src/io/anuke/mindustry/world/blocks/types/defense/Turret.java
+++ b/core/src/io/anuke/mindustry/world/blocks/types/defense/Turret.java
@@ -66,8 +66,8 @@ public class Turret extends Block{
 	
 	@Override
 	public void postInit(){
-		description = "[turretinfo]" + (ammo==null ? "" : "Ammo: " + ammo +"\n")
-				+ "Range: " + (int)range;
+		if(ammo != null)
+			description = "[turretinfo]Ammo: " + ammo;
 	}
 	
 	@Override
diff --git a/core/src/io/anuke/mindustry/world/blocks/types/distribution/Junction.java b/core/src/io/anuke/mindustry/world/blocks/types/distribution/Junction.java
index 88edb0f11e..97a2b24ddb 100644
--- a/core/src/io/anuke/mindustry/world/blocks/types/distribution/Junction.java
+++ b/core/src/io/anuke/mindustry/world/blocks/types/distribution/Junction.java
@@ -33,6 +33,7 @@ public class Junction extends Block{
 	@Override
 	public boolean acceptItem(Item item, Tile dest, Tile source){
 		int dir = source.relativeTo(dest.x, dest.y);
+		if(dir == -1) return false;
 		Tile to = dest.getNearby()[dir];
 		return to != null && to.block().acceptItem(item, to, dest);
 	}
diff --git a/core/src/io/anuke/mindustry/world/blocks/types/distribution/PowerBooster.java b/core/src/io/anuke/mindustry/world/blocks/types/distribution/PowerBooster.java
index 3fe032b493..5e2f665640 100644
--- a/core/src/io/anuke/mindustry/world/blocks/types/distribution/PowerBooster.java
+++ b/core/src/io/anuke/mindustry/world/blocks/types/distribution/PowerBooster.java
@@ -18,6 +18,7 @@ public class PowerBooster extends Generator{
 		super(name);
 		explosive = false;
 		hasLasers = false;
+		powerSpeed = 0.4f;
 	}
 	
 	@Override
@@ -69,7 +70,6 @@ public class PowerBooster extends Generator{
 			int acceptors = 0;
 			float flow = 0f;
 
-			//TODO have two phases, where it checks nearby blocks first, then distributes it evenly
 			for(int i = 0; i < 2; i++){
 				for(int x = -powerRange; x <= powerRange; x++){
 					for(int y = -powerRange; y <= powerRange; y++){
diff --git a/core/src/io/anuke/mindustry/world/blocks/types/production/Generator.java b/core/src/io/anuke/mindustry/world/blocks/types/production/Generator.java
index 6544cab0f8..94b2cef3d8 100644
--- a/core/src/io/anuke/mindustry/world/blocks/types/production/Generator.java
+++ b/core/src/io/anuke/mindustry/world/blocks/types/production/Generator.java
@@ -24,7 +24,7 @@ public class Generator extends PowerBlock{
 
 	public int laserRange = 6;
 	public int laserDirections = 4;
-	public float powerSpeed = 0.06f;
+	public float powerSpeed = 0.1f;
 	public boolean explosive = true;
 	public boolean hasLasers = true;
 	public boolean outputOnly = false;
@@ -196,22 +196,17 @@ public class Generator extends PowerBlock{
 			int relrot = (rotation + 2) % 4;
 			if(other.hasLasers){
 				for(int i = 0; i < other.laserDirections; i ++){
-					if(target.getRotation() + i - other.laserDirections/2 == (target.getRotation() + 2) % 4){
+					if(Mathf.mod(target.getRotation() + i - other.laserDirections/2, 4) == relrot){
 						return true;
 					}
 				}
 			}
-			if(other.hasLasers && Math.abs(target.getRotation() - relrot) <= other.laserDirections / 2){
-				return true;
-			}
 		}
 		return false;
 	}
 
 	protected Tile laserTarget(Tile tile, int rotation){
-		if(rotation < 0)
-			rotation += 4;
-		rotation %= 4;
+		rotation = Mathf.mod(rotation, 4);
 		GridPoint2 point = Geometry.getD4Points()[rotation];
 
 		int i = 0;
diff --git a/desktop/mindustry-saves/2.mins b/desktop/mindustry-saves/2.mins
index 651006157e..3ee6521fdc 100644
Binary files a/desktop/mindustry-saves/2.mins and b/desktop/mindustry-saves/2.mins differ
diff --git a/desktop/mindustry-saves/7.mins b/desktop/mindustry-saves/7.mins
index e9cf74f853..e9bd698ec7 100644
Binary files a/desktop/mindustry-saves/7.mins and b/desktop/mindustry-saves/7.mins differ
diff --git a/html/webapp/html/logo.png b/html/webapp/html/logo.png
index d8c6598408..be1282d3c5 100644
Binary files a/html/webapp/html/logo.png and b/html/webapp/html/logo.png differ
diff --git a/html/webapp/styles.css b/html/webapp/styles.css
index edaf3900b7..3ac665b88a 100644
--- a/html/webapp/styles.css
+++ b/html/webapp/styles.css
@@ -10,3 +10,10 @@ body {
     margin: 0px;
     padding: 0px;
 }
+
+.gdx-meter.red > span {
+	background-color: #e44d3c !important;
+	background-image: -moz-linear-gradient(top, #f4ba6e, #d29d58) !important;
+	background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, #f4ba6e),color-stop(1, #d29d58)) !important;
+	background-image: -webkit-linear-gradient(#f4ba6e, #d29d58) !important;
+}