diff --git a/core/assets/baseparts/1591368658042.msch b/core/assets/baseparts/1591368658042.msch
deleted file mode 100644
index d1e42464a1..0000000000
--- a/core/assets/baseparts/1591368658042.msch
+++ /dev/null
@@ -1,4 +0,0 @@
-mschxœ%‹Ñ
-Ã E¯Z»BÊ>Ä—ý‘³2[‹Õ•ýýr)!9	çL
-Ãî·õñå8bu—ÏÙe_?fíóšÎVÓ»·R1…²ãO¶9µ¸¹³ô"–c�}ó-·Ö”3€E
-†07,¡y+�‡aJ‹ÝHgèË×�71@sXF�©oHàIc
\ No newline at end of file
diff --git a/core/assets/baseparts/1591368730003.msch b/core/assets/baseparts/1591368730003.msch
deleted file mode 100644
index f7974af4e2..0000000000
--- a/core/assets/baseparts/1591368730003.msch
+++ /dev/null
@@ -1,2 +0,0 @@
-mschxœ%LÑ
-Ã <›*…AÇ>Ä·ý�kC+ØV¢²ßŸYIrwÜ%Á„É`<ÃÁ0o‡×råÌâ¿!%Ÿ‚lŒq1á+¾\MÆ3ŸÜŽPãâW‰©§k,Uâ§ÕK0oòÞ÷}.ÀÜƒ‚¹aèe”Fµµ€%êÊuKAwB*þ™½?X=V"5�~ÿ[Öì
\ No newline at end of file
diff --git a/core/assets/baseparts/1591368779629.msch b/core/assets/baseparts/1591368779629.msch
deleted file mode 100644
index 2254a17355..0000000000
Binary files a/core/assets/baseparts/1591368779629.msch and /dev/null differ
diff --git a/core/assets/baseparts/1591385128968.msch b/core/assets/baseparts/1591385128968.msch
new file mode 100644
index 0000000000..d6ae616c4f
--- /dev/null
+++ b/core/assets/baseparts/1591385128968.msch
@@ -0,0 +1 @@
+mschxœ-Ïknƒ0à±�]Ò$mZ”ªgàP!’Á/©·ï.S~ðY»;Æ	ßÅ‡>>ãü¸üŒÝ:Ä¥o›ÇÔ§„²ÍãÖýæ	~ŽiË(×1åøè&TýÒ
Íœ×©•[\Ó ÁþX}X³ŸŒbˆ%ŽÄ“@^HIä¨G;ŽvZ”+¯è¨VùÒ_ûÎÚpƒÕæ»×AF6ÉçB¨´à¼ì¼ëºRê;9‘Wr&r%oä�ÜÈù$µ¤”ëìQEoUk¢ã"-Hî?¤±|
\ No newline at end of file
diff --git a/core/assets/baseparts/1591385266195.msch b/core/assets/baseparts/1591385266195.msch
new file mode 100644
index 0000000000..4611adddfa
--- /dev/null
+++ b/core/assets/baseparts/1591385266195.msch
@@ -0,0 +1 @@
+mschxœMÎa‚0àÇLDBÐsp¨)Å�ÀF&‰ñìˆ³sÑø£i³õË+NP	¤ÑAê¾ïsä£6rhnvÔ®�µ¡±åéJPg½,ä88šõÀŸv0ö³½“k�íùD¦c
¹ �)2¤‚›Àg„ä–í¤ù
Âo~õðkxEŒŠFESDS°É¾&ìû'¯J®eeUÕä/¤Š!u4u0@®}wO<
\ No newline at end of file
diff --git a/core/assets/baseparts/1591385293703.msch b/core/assets/baseparts/1591385293703.msch
new file mode 100644
index 0000000000..d48006b7be
--- /dev/null
+++ b/core/assets/baseparts/1591385293703.msch
@@ -0,0 +1,2 @@
+mschxœ%ŒA
+Ã0'VKÝB ~ˆeãKjçÐÇ—’J	HbwV,�0p«é�y”´/%ARŸymí“{¬mÉ„½­©Ç-Õ¼FU%O]<n@ðÞq‡ãâzez°Tµ¦\¹˜Í_er¾Mö6ZÉÏ™¬ûÐâe
\ No newline at end of file
diff --git a/core/assets/baseparts/1591385372367.msch b/core/assets/baseparts/1591385372367.msch
new file mode 100644
index 0000000000..a45bad9e2d
Binary files /dev/null and b/core/assets/baseparts/1591385372367.msch differ
diff --git a/core/assets/baseparts/1591385575600.msch b/core/assets/baseparts/1591385575600.msch
new file mode 100644
index 0000000000..a086e7d8a2
Binary files /dev/null and b/core/assets/baseparts/1591385575600.msch differ
diff --git a/core/assets/baseparts/1591385624323.msch b/core/assets/baseparts/1591385624323.msch
new file mode 100644
index 0000000000..acb5a9c4de
Binary files /dev/null and b/core/assets/baseparts/1591385624323.msch differ
diff --git a/core/assets/baseparts/1591385989609.msch b/core/assets/baseparts/1591385989609.msch
new file mode 100644
index 0000000000..ff5b9e014d
Binary files /dev/null and b/core/assets/baseparts/1591385989609.msch differ
diff --git a/core/src/mindustry/ai/BaseRegistry.java b/core/src/mindustry/ai/BaseRegistry.java
index 9ee27a3e8f..88ceb86635 100644
--- a/core/src/mindustry/ai/BaseRegistry.java
+++ b/core/src/mindustry/ai/BaseRegistry.java
@@ -4,6 +4,7 @@ import arc.*;
 import arc.struct.*;
 import arc.util.ArcAnnotate.*;
 import arc.util.*;
+import mindustry.ctype.*;
 import mindustry.game.*;
 import mindustry.game.Schematic.*;
 import mindustry.type.*;
@@ -20,16 +21,16 @@ import static mindustry.Vars.tilesize;
 public class BaseRegistry{
     public Array<BasePart> cores = new Array<>();
     public Array<BasePart> parts = new Array<>();
-    public ObjectMap<Item, Array<BasePart>> itemParts = new ObjectMap<>();
+    public ObjectMap<Content, Array<BasePart>> reqParts = new ObjectMap<>();
 
-    public Array<BasePart> forItem(Item item){
-        return itemParts.get(item, Array::new);
+    public Array<BasePart> forResource(Content item){
+        return reqParts.get(item, Array::new);
     }
 
     public void load(){
         cores.clear();
         parts.clear();
-        itemParts.clear();
+        reqParts.clear();
 
         String[] names = Core.files.internal("basepartnames").readString().split("\n");
 
@@ -42,9 +43,6 @@ public class BaseRegistry{
                 int drills = 0;
 
                 for(Stile tile : schem.tiles){
-                    //make note of occupied positions
-                    tile.block.iterateTaken(tile.x, tile.y, part.occupied::set);
-
                     //keep track of core type
                     if(tile.block instanceof CoreBlock){
                         part.core = tile.block;
@@ -53,17 +51,17 @@ public class BaseRegistry{
                     //save the required resource based on item source - multiple sources are not allowed
                     if(tile.block instanceof ItemSource){
                         Item config = (Item)tile.config;
-                        if(config != null) part.requiredItem = config;
+                        if(config != null) part.required = config;
                     }
 
                     //same for liquids - this is not used yet
                     if(tile.block instanceof LiquidSource){
                         Liquid config = (Liquid)tile.config;
-                        if(config != null) part.requiredLiquid = config;
+                        if(config != null) part.required = config;
                     }
 
                     //calculate averages
-                    if(tile.block instanceof Drill){
+                    if(tile.block instanceof Drill || tile.block instanceof Pump){
                         Tmp.v1.add(tile.x*tilesize + tile.block.offset(), tile.y*tilesize + tile.block.offset());
                         drills ++;
                     }
@@ -74,7 +72,7 @@ public class BaseRegistry{
 
                 if(part.core != null){
                     cores.add(part);
-                }else if(part.requiredItem == null){
+                }else if(part.required == null){
                     parts.add(part);
                 }
 
@@ -87,9 +85,8 @@ public class BaseRegistry{
                     part.centerY = part.schematic.height/2;
                 }
 
-                if(part.requiredItem != null){
-                    itemParts.get(part.requiredItem, Array::new).add(part);
-                }
+                if(part.required != null) reqParts.get(part.required, Array::new).add(part);
+
             }catch(IOException e){
                 throw new RuntimeException(e);
             }
@@ -97,18 +94,16 @@ public class BaseRegistry{
 
         cores.sort(Structs.comps(Structs.comparingFloat(b -> b.core.health), Structs.comparingFloat(b -> b.tier)));
         parts.sort();
-        itemParts.each((key, arr) -> arr.sort());
+        reqParts.each((key, arr) -> arr.sort());
     }
 
     public static class BasePart implements Comparable<BasePart>{
         public final Schematic schematic;
-        public final GridBits occupied;
 
         //offsets for drills
         public int centerX, centerY;
 
-        public @Nullable Liquid requiredLiquid;
-        public @Nullable Item requiredItem;
+        public @Nullable Content required;
         public @Nullable Block core;
 
         //total build cost
@@ -116,7 +111,6 @@ public class BaseRegistry{
 
         public BasePart(Schematic schematic){
             this.schematic = schematic;
-            this.occupied = new GridBits(schematic.width, schematic.height);
         }
 
         @Override
diff --git a/core/src/mindustry/maps/generators/BaseGenerator.java b/core/src/mindustry/maps/generators/BaseGenerator.java
index 1fd5754aa7..78f3639ea4 100644
--- a/core/src/mindustry/maps/generators/BaseGenerator.java
+++ b/core/src/mindustry/maps/generators/BaseGenerator.java
@@ -36,6 +36,7 @@ public class BaseGenerator{
         this.tiles = tiles;
         this.team = team;
         this.cores = cores;
+        Mathf.random.setSeed(sector.id);
 
         for(Block block : content.blocks()){
             if(block instanceof OreBlock && block.asFloor().itemDrop != null){
@@ -43,20 +44,22 @@ public class BaseGenerator{
             }
         }
 
+        float costBudget = 1000;
+
         Array<Block> wallsSmall = content.blocks().select(b -> b instanceof Wall && b.size == 1);
         Array<Block> wallsLarge = content.blocks().select(b -> b instanceof Wall && b.size == 2);
 
         float bracket = 0.1f;
         int wallAngle = 70; //180 for full coverage
         double resourceChance = 0.4;
-        double nonResourceChance = 0.0007;
+        double nonResourceChance = 0.0005;
         BasePart coreschem = bases.cores.getFrac(bracket);
 
         Block wall = wallsSmall.getFrac(bracket), wallLarge = wallsLarge.getFrac(bracket);
 
         for(Tile tile : cores){
             tile.clearOverlay();
-            Schematics.placeLoadout(coreschem.schematic, tile.x, tile.y, team, coreschem.requiredItem == null ? Blocks.oreCopper : ores.get(coreschem.requiredItem));
+            Schematics.placeLoadout(coreschem.schematic, tile.x, tile.y, team, coreschem.required instanceof Item ? ores.get((Item)coreschem.required) : Blocks.oreCopper);
 
             //fill core with every type of item (even non-material)
             Tilec entity = tile.entity;
@@ -65,14 +68,16 @@ public class BaseGenerator{
             }
         }
 
-        //first pass: random item specific schematics
+        //random schematics
         pass(tile -> {
-            if(tile.overlay().itemDrop != null && Mathf.chance(resourceChance)){
-                Array<BasePart> parts = bases.forItem(tile.overlay().itemDrop);
+            if(!tile.block().alwaysReplace) return;
+
+            if((tile.drop() != null || (tile.floor().liquidDrop != null && Mathf.chance(nonResourceChance * 2))) && Mathf.chance(resourceChance)){
+                Array<BasePart> parts = bases.forResource(tile.drop() != null ? tile.drop() : tile.floor().liquidDrop);
                 if(!parts.isEmpty()){
                     tryPlace(parts.random(), tile.x, tile.y);
                 }
-            }else if(tile.overlay().itemDrop == null && Mathf.chance(nonResourceChance)){
+            }else if(Mathf.chance(nonResourceChance)){
                 tryPlace(bases.parts.random(), tile.x, tile.y);
             }
         });
@@ -142,33 +147,35 @@ public class BaseGenerator{
         int rotation = Mathf.range(2);
         axis.set((int)(part.schematic.width / 2f), (int)(part.schematic.height / 2f));
         Schematic result = rotate(part.schematic, rotation);
+        int rotdeg = rotation*90;
 
-        rotator.set(part.centerX, part.centerY).rotateAround(axis, rotation * 90);
+        rotator.set(part.centerX, part.centerY).rotateAround(axis, rotdeg);
+        //bottom left schematic corner
         int cx = x - (int)rotator.x;
         int cy = y - (int)rotator.y;
 
-        for(int rx = cx; rx <= cx + result.width; rx++){
-            for(int ry = cy; ry <= cy + result.height; ry++){
-                Tile tile = tiles.get(rx, ry);
-                int ox = rx - cx, oy = ry - cy;
-                rotator.set(ox, oy).rotateAround(axis, rotation * 90);
-                ox = (int)rotator.x;
-                oy = (int)rotator.y;
-
-                if(tile == null || ((!tile.block().alwaysReplace || world.getDarkness(rx, ry) > 0) && part.occupied.get(ox, oy))){
-                    return false;
-                }
+        for(Stile tile : result.tiles){
+            int realX = tile.x + cx, realY = tile.y + cy;
+            if(isTaken(tile.block, realX, realY)){
+                return false;
             }
         }
 
-        if(part.requiredItem != null){
+        if(part.required instanceof Item){
             for(Stile tile : result.tiles){
                 if(tile.block instanceof Drill){
-                    tile.block.iterateTaken(tile.x + cx, tile.y + cy, (ex, ey) -> {
-                        tiles.getn(ex, ey).setOverlay(ores.get(part.requiredItem));
 
-                        //random ores nearby to make it look more natural
-                        tiles.getc(ex + Mathf.range(1), ey + Mathf.range(1)).setOverlay(ores.get(part.requiredItem));
+                    tile.block.iterateTaken(tile.x + cx, tile.y + cy, (ex, ey) -> {
+
+                        if(!tiles.getn(ex, ey).floor().isLiquid){
+                            tiles.getn(ex, ey).setOverlay(ores.get((Item)part.required));
+                        }
+
+                        Tile rand = tiles.getc(ex + Mathf.range(1), ey + Mathf.range(1));
+                        if(!rand.floor().isLiquid){
+                            //random ores nearby to make it look more natural
+                            rand.setOverlay(ores.get((Item)part.required));
+                        }
                     });
                 }
             }
@@ -179,10 +186,36 @@ public class BaseGenerator{
         return true;
     }
 
+    boolean isTaken(Block block, int x, int y){
+        if(block.isMultiblock()){
+            int offsetx = -(block.size - 1) / 2;
+            int offsety = -(block.size - 1) / 2;
+
+            for(int dx = 0; dx < block.size; dx++){
+                for(int dy = 0; dy < block.size; dy++){
+                    if(overlaps(dx + offsetx + x, dy + offsety + y)){
+                        return true;
+                    }
+                }
+            }
+
+        }else{
+            return overlaps(x, y);
+        }
+
+        return false;
+    }
+
+    boolean overlaps(int x, int y){
+        Tile tile = tiles.get(x, y);
+
+        return tile == null || !tile.block().alwaysReplace || world.getDarkness(x, y) > 0;
+    }
+
     Schematic rotate(Schematic input, int times){
         if(times == 0) return input;
 
-        boolean sign = times < 0;
+        boolean sign = times > 0;
         for(int i = 0; i < Math.abs(times); i++){
             input = rotated(input, sign);
         }
