diff --git a/core/assets-raw/sprites/blocks/turrets/scatter.png b/core/assets-raw/sprites/blocks/turrets/scatter.png new file mode 100644 index 0000000000..f6e1d7ff61 Binary files /dev/null and b/core/assets-raw/sprites/blocks/turrets/scatter.png differ diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index adbbaca530..1abc9e52f0 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -211,6 +211,8 @@ editor.elevation = Elevation editor.errorload = Error loading file:\n[accent]{0} editor.errorsave = Error saving file:\n[accent]{0} editor.errorname = Map has no name defined. +editor.update = Update +editor.apply = Apply editor.generate = Generate editor.resize = Resize editor.loadmap = Load Map diff --git a/core/assets/sprites/sprites.png b/core/assets/sprites/sprites.png index 69773f70f8..f04b623bb2 100644 Binary files a/core/assets/sprites/sprites.png and b/core/assets/sprites/sprites.png differ diff --git a/core/assets/sprites/sprites2.png b/core/assets/sprites/sprites2.png index a56c8e71c6..5f90253ca5 100644 Binary files a/core/assets/sprites/sprites2.png and b/core/assets/sprites/sprites2.png differ diff --git a/core/src/io/anuke/mindustry/content/Blocks.java b/core/src/io/anuke/mindustry/content/Blocks.java index 6cd5effc59..ab2ba4c56e 100644 --- a/core/src/io/anuke/mindustry/content/Blocks.java +++ b/core/src/io/anuke/mindustry/content/Blocks.java @@ -1083,7 +1083,7 @@ public class Blocks implements ContentList{ inaccuracy = 18f; shootCone = 35f; - health = 220; + health = 220*size*size; }}; hail = new ArtilleryTurret("hail"){{ @@ -1301,7 +1301,7 @@ public class Blocks implements ContentList{ powerUsed = 0.5f; consumes.powerBuffered(1200f); range = 160f; - reload = 200f; + reload = 170f; firingMoveFract = 0.1f; shootDuration = 220f; diff --git a/core/src/io/anuke/mindustry/editor/EditorTile.java b/core/src/io/anuke/mindustry/editor/EditorTile.java index 52b3eef819..b35ae191f6 100644 --- a/core/src/io/anuke/mindustry/editor/EditorTile.java +++ b/core/src/io/anuke/mindustry/editor/EditorTile.java @@ -35,12 +35,12 @@ public class EditorTile extends Tile{ } Block previous = floor(); - Block ore = oreBlock(); + Block ore = ore(); if(previous == type && ore == Blocks.air) return; super.setFloor(type); //ore may get nullified so make sure to save editrs - if(oreBlock() != ore){ - op(TileOp.get(x, y, (byte)OpType.ore.ordinal(), ore.id, oreBlock().id)); + if(ore() != ore){ + op(TileOp.get(x, y, (byte)OpType.ore.ordinal(), ore.id, ore().id)); } if(previous != type){ op(TileOp.get(x, y, (byte)OpType.floor.ordinal(), previous.id, type.id)); diff --git a/core/src/io/anuke/mindustry/editor/EditorTool.java b/core/src/io/anuke/mindustry/editor/EditorTool.java index 10dde9bda9..63ae60c569 100644 --- a/core/src/io/anuke/mindustry/editor/EditorTool.java +++ b/core/src/io/anuke/mindustry/editor/EditorTool.java @@ -101,7 +101,7 @@ public enum EditorTool{ boolean synth = editor.drawBlock.synthetic(); Block draw = editor.drawBlock; - dest = draw instanceof OreBlock ? tile.oreBlock() : isfloor ? floor : block; + dest = draw instanceof OreBlock ? tile.ore() : isfloor ? floor : block; if(dest == draw || block == Blocks.part || block.isMultiblock()){ return; @@ -190,7 +190,7 @@ public enum EditorTool{ boolean eq(int px, int py){ Tile tile = data.tile(px, py); - return (data.drawBlock instanceof OreBlock ? tile.oreBlock() : isfloor ? tile.floor() : tile.block()) == dest && !(data.drawBlock instanceof OreBlock && tile.floor().isLiquid); + return (data.drawBlock instanceof OreBlock ? tile.ore() : isfloor ? tile.floor() : tile.block()) == dest && !(data.drawBlock instanceof OreBlock && tile.floor().isLiquid); } }, zoom; diff --git a/core/src/io/anuke/mindustry/editor/MapEditor.java b/core/src/io/anuke/mindustry/editor/MapEditor.java index 5ab952ac37..c0bf7e8d41 100644 --- a/core/src/io/anuke/mindustry/editor/MapEditor.java +++ b/core/src/io/anuke/mindustry/editor/MapEditor.java @@ -224,6 +224,9 @@ public class MapEditor{ if(drawBlock.synthetic()){ tile.setTeam(drawTeam); } + if(drawBlock.rotate){ + tile.setRotation((byte)rotation); + } } } } diff --git a/core/src/io/anuke/mindustry/editor/MapEditorDialog.java b/core/src/io/anuke/mindustry/editor/MapEditorDialog.java index 240b293ce2..966f979a92 100644 --- a/core/src/io/anuke/mindustry/editor/MapEditorDialog.java +++ b/core/src/io/anuke/mindustry/editor/MapEditorDialog.java @@ -37,6 +37,7 @@ public class MapEditorDialog extends Dialog implements Disposable{ private MapInfoDialog infoDialog; private MapLoadDialog loadDialog; private MapResizeDialog resizeDialog; + private MapGenerateDialog generateDialog; private ScrollPane pane; private FloatingDialog menu; private boolean saved = false; @@ -50,8 +51,8 @@ public class MapEditorDialog extends Dialog implements Disposable{ editor = new MapEditor(); view = new MapView(editor); - infoDialog = new MapInfoDialog(editor); + generateDialog = new MapGenerateDialog(editor); menu = new FloatingDialog("$menu"); menu.addCloseButton(); @@ -62,15 +63,20 @@ public class MapEditorDialog extends Dialog implements Disposable{ menu.cont.table(t -> { t.defaults().size(swidth, 60f).padBottom(5).padRight(5).padLeft(5); - t.addImageTextButton("$editor.savemap", "icon-floppy-16", isize, this::save).size(swidth * 2f + 10, 60f).colspan(2); - - t.row(); + t.addImageTextButton("$editor.savemap", "icon-floppy-16", isize, this::save); t.addImageTextButton("$editor.mapinfo", "icon-pencil", isize, () -> { infoDialog.show(); menu.hide(); }); + t.row(); + + t.addImageTextButton("$editor.generate", "icon-editor", isize, () -> { + generateDialog.show(); + menu.hide(); + }); + t.addImageTextButton("$editor.resize", "icon-resize", isize, () -> { resizeDialog.show(); menu.hide(); diff --git a/core/src/io/anuke/mindustry/editor/MapGenerateDialog.java b/core/src/io/anuke/mindustry/editor/MapGenerateDialog.java new file mode 100644 index 0000000000..1c4303bc6d --- /dev/null +++ b/core/src/io/anuke/mindustry/editor/MapGenerateDialog.java @@ -0,0 +1,167 @@ +package io.anuke.mindustry.editor; + +import io.anuke.arc.collection.Array; +import io.anuke.arc.graphics.Pixmap; +import io.anuke.arc.graphics.Pixmap.Format; +import io.anuke.arc.graphics.Texture; +import io.anuke.arc.scene.Element; +import io.anuke.arc.scene.ui.layout.Table; +import io.anuke.mindustry.editor.generation.FilterOption; +import io.anuke.mindustry.editor.generation.GenerateFilter; +import io.anuke.mindustry.editor.generation.GenerateFilter.GenerateInput; +import io.anuke.mindustry.editor.generation.NoiseFilter; +import io.anuke.mindustry.game.Team; +import io.anuke.mindustry.io.MapIO; +import io.anuke.mindustry.ui.BorderImage; +import io.anuke.mindustry.ui.dialogs.FloatingDialog; +import io.anuke.mindustry.world.DummyTile; +import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.blocks.Floor; + +public class MapGenerateDialog extends FloatingDialog{ + private final MapEditor editor; + private Pixmap pixmap; + private Texture texture; + private GenerateInput input = new GenerateInput(); + private Array filters = new Array<>(); + + public MapGenerateDialog(MapEditor editor){ + super("editor.generate"); + this.editor = editor; + + shown(this::setup); + addCloseButton(); + buttons.addButton("$editor.apply", () -> { + apply(); + hide(); + }).size(180f, 64f); + } + + void setup(){ + if(pixmap != null){ + pixmap.dispose(); + texture.dispose(); + pixmap = null; + texture = null; + } + + pixmap = new Pixmap(editor.width(), editor.height(), Format.RGBA8888); + texture = new Texture(pixmap); + + cont.clear(); + cont.table("flat", t -> { + t.margin(8f); + t.add(new BorderImage(texture)).size(500f).padRight(6); + t.table(right -> { + Table[] fs = {null}; + Runnable rebuild = () -> { + Table p = fs[0]; + p.clearChildren(); + + for(GenerateFilter filter : filters){ + p.table("button", f -> { + f.left(); + for(FilterOption option : filter.options){ + option.build(f); + f.row(); + } + for(Element e : f.getChildren()){ + e.changed(this::update); + } + }).pad(3).width(280f); + p.row(); + } + }; + + right.pane(p -> { + p.top(); + fs[0] = p; + }).fill().width(300f).growY().get().setScrollingDisabled(true, false); + right.row(); + right.addButton("$add", () -> { + filters.add(new NoiseFilter()); + rebuild.run(); + }).fillX().height(50f); + }).grow(); + + t.row(); + t.addButton("$editor.update", () -> { + input.randomize(); + update(); + }).size(300f, 66f).colspan(2).pad(6); + }); + + update(); + } + + void apply(){ + Tile[][] writeTiles = new Tile[editor.width()][editor.height()]; + + for(int x = 0; x < editor.width(); x++){ + for(int y = 0; y < editor.height(); y++){ + writeTiles[x][y] = new DummyTile(x, y); + } + } + + for(GenerateFilter filter : filters){ + for(int x = 0; x < editor.width(); x++){ + for(int y = 0; y < editor.height(); y++){ + Tile tile = editor.tile(x, y); + Tile write = writeTiles[x][y]; + input.begin(editor, x, y, tile.floor(), tile.block(), tile.ore()); + filter.apply(input); + write.setRotation(tile.getRotation()); + write.setOre(input.ore); + write.setFloor((Floor)input.floor); + write.setBlock(input.block); + write.setTeam(tile.getTeam()); + } + } + + editor.load(() -> { + for(int x = 0; x < editor.width(); x++){ + for(int y = 0; y < editor.height(); y++){ + Tile tile = editor.tile(x, y); + Tile write = writeTiles[x][y]; + + tile.setRotation(write.getRotation()); + tile.setOre(write.ore()); + tile.setFloor(write.floor()); + tile.setBlock(write.block()); + tile.setTeam(write.getTeam()); + } + } + }); + } + + editor.renderer().updateAll(); + editor.clearOp(); + } + + void update(){ + + boolean modified = false; + for(GenerateFilter filter : filters){ + modified = true; + for(int x = 0; x < editor.width(); x++){ + for(int y = 0; y < editor.height(); y++){ + Tile tile = editor.tile(x, y); + input.begin(editor, x, y, tile.floor(), tile.block(), tile.ore()); + filter.apply(input); + pixmap.drawPixel(x, pixmap.getHeight() - 1 - y, MapIO.colorFor(input.floor, input.block, input.ore, Team.none)); + } + } + } + + if(!modified){ + for(int x = 0; x < editor.width(); x++){ + for(int y = 0; y < editor.height(); y++){ + Tile tile = editor.tile(x, y); + pixmap.drawPixel(x, pixmap.getHeight() - 1 - y, MapIO.colorFor(tile.floor(), tile.block(), tile.ore(), Team.none)); + } + } + } + + texture.draw(pixmap, 0, 0); + } +} diff --git a/core/src/io/anuke/mindustry/editor/MapRenderer.java b/core/src/io/anuke/mindustry/editor/MapRenderer.java index d7fb5ab6c1..65aa4fa56a 100644 --- a/core/src/io/anuke/mindustry/editor/MapRenderer.java +++ b/core/src/io/anuke/mindustry/editor/MapRenderer.java @@ -139,8 +139,8 @@ public class MapRenderer implements Disposable{ region = !Core.atlas.isFound(wall.editorIcon()) ? Core.atlas.find("clear-editor") : wall.editorIcon(); offsetX = tilesize/2f - region.getWidth()/2f * Draw.scl; offsetY = tilesize/2f - region.getHeight()/2f * Draw.scl; - }else if(wall == Blocks.air && tile.oreBlock() != null){ - region = tile.oreBlock().editorVariantRegions()[Mathf.randomSeed(idxWall, 0, tile.oreBlock().editorVariantRegions().length-1)];; + }else if(wall == Blocks.air && tile.ore() != null){ + region = tile.ore().editorVariantRegions()[Mathf.randomSeed(idxWall, 0, tile.ore().editorVariantRegions().length-1)];; }else{ region = Core.atlas.find("clear-editor"); } diff --git a/core/src/io/anuke/mindustry/editor/WaveInfoDialog.java b/core/src/io/anuke/mindustry/editor/WaveInfoDialog.java index 877d92ef2b..dd6ae3ea6d 100644 --- a/core/src/io/anuke/mindustry/editor/WaveInfoDialog.java +++ b/core/src/io/anuke/mindustry/editor/WaveInfoDialog.java @@ -200,7 +200,7 @@ public class WaveInfoDialog extends FloatingDialog{ preview.clear(); preview.top(); - Array groups = (this.groups == null ? DefaultWaves.getDefaultSpawns() : this.groups); + Array groups = (this.groups == null ? DefaultWaves.get() : this.groups); for(int i = start; i < displayed + start; i ++){ int wave = i; diff --git a/core/src/io/anuke/mindustry/editor/generation/DistortFilter.java b/core/src/io/anuke/mindustry/editor/generation/DistortFilter.java new file mode 100644 index 0000000000..c029eec7d7 --- /dev/null +++ b/core/src/io/anuke/mindustry/editor/generation/DistortFilter.java @@ -0,0 +1,24 @@ +package io.anuke.mindustry.editor.generation; + +import io.anuke.mindustry.editor.generation.FilterOption.SliderOption; +import io.anuke.mindustry.world.Tile; + +public class DistortFilter extends GenerateFilter{ + float scl = 40, mag = 5; + + { + options( + new SliderOption("scale", () -> scl, f -> scl = f, 1f, 1000f), + new SliderOption("mag", () -> mag, f -> mag = f, 0.5f, 10f) + ); + } + + @Override + public void apply(){ + Tile tile = in.tile(in.x + noise(in.x, in.y, scl, mag)-mag/2f, in.y + noise(in.x, in.y+o, scl, mag)-mag/2f); + + in.floor = tile.floor(); + if(!tile.block().synthetic() && !in.block.synthetic()) in.block = tile.block(); + in.ore = tile.ore(); + } +} diff --git a/core/src/io/anuke/mindustry/editor/generation/FilterOption.java b/core/src/io/anuke/mindustry/editor/generation/FilterOption.java new file mode 100644 index 0000000000..81754438a4 --- /dev/null +++ b/core/src/io/anuke/mindustry/editor/generation/FilterOption.java @@ -0,0 +1,78 @@ +package io.anuke.mindustry.editor.generation; + +import io.anuke.arc.Core; +import io.anuke.arc.function.*; +import io.anuke.arc.scene.style.TextureRegionDrawable; +import io.anuke.arc.scene.ui.layout.Table; +import io.anuke.mindustry.Vars; +import io.anuke.mindustry.ui.dialogs.FloatingDialog; +import io.anuke.mindustry.world.Block; +import io.anuke.mindustry.world.Block.Icon; +import io.anuke.mindustry.world.blocks.Floor; +import io.anuke.mindustry.world.blocks.OreBlock; + +public abstract class FilterOption{ + public static final Predicate floorsOnly = b -> (b instanceof Floor && !(b instanceof OreBlock)) && Core.atlas.isFound(b.icon(Icon.full)); + public static final Predicate wallsOnly = b -> (!b.synthetic() && !(b instanceof Floor)) && Core.atlas.isFound(b.icon(Icon.full)); + + public abstract void build(Table table); + + static class SliderOption extends FilterOption{ + final String name; + final FloatProvider getter; + final FloatConsumer setter; + final float min, max; + + SliderOption(String name, FloatProvider getter, FloatConsumer setter, float min, float max){ + this.name = name; + this.getter = getter; + this.setter = setter; + this.min = min; + this.max = max; + } + + @Override + public void build(Table table){ + table.add(name); + table.row(); + table.addSlider(min, max, (max-min)/100f, setter).get().setValue(getter.get()); + } + } + + static class BlockOption extends FilterOption{ + final String name; + final Supplier supplier; + final Consumer consumer; + final Predicate filter; + + BlockOption(String name, Supplier supplier, Consumer consumer, Predicate filter){ + this.name = name; + this.supplier = supplier; + this.consumer = consumer; + this.filter = filter; + } + + @Override + public void build(Table table){ + table.add(name + ": "); + table.addButton(b -> { + b.addImage(supplier.get().icon(Icon.small)).update(i -> ((TextureRegionDrawable)i.getDrawable()).setRegion(supplier.get().icon(Icon.small))).size(8*3); + }, () -> { + FloatingDialog dialog = new FloatingDialog(""); + dialog.setFillParent(false); + int i = 0; + for(Block block : Vars.content.blocks()){ + if(!filter.test(block)) continue; + + dialog.cont.addImage(block.icon(Icon.medium)).size(8*4).pad(3).get().clicked(() -> { + consumer.accept(block); + dialog.hide(); + }); + if(++i % 10 == 0) dialog.cont.row(); + } + + dialog.show(); + }); + } + } +} diff --git a/core/src/io/anuke/mindustry/editor/generation/GenerateFilter.java b/core/src/io/anuke/mindustry/editor/generation/GenerateFilter.java new file mode 100644 index 0000000000..fd3e107b6b --- /dev/null +++ b/core/src/io/anuke/mindustry/editor/generation/GenerateFilter.java @@ -0,0 +1,63 @@ +package io.anuke.mindustry.editor.generation; + +import io.anuke.arc.math.Mathf; +import io.anuke.arc.util.noise.Simplex; +import io.anuke.mindustry.editor.MapEditor; +import io.anuke.mindustry.world.Block; +import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.blocks.Floor; + +public abstract class GenerateFilter{ + protected float o = (float)(Math.random()*10000000.0); + protected GenerateInput in; + + public FilterOption[] options; + + protected abstract void apply(); + + protected float noise(float x, float y, float scl, float mag){ + return (float)in.noise.octaveNoise2D(1f, 0f, 1f/scl, x + o, y + o)*mag; + } + + protected float noise(float x, float y, float scl, float mag, float octaves, float persistence){ + return (float)in.noise.octaveNoise2D(octaves, persistence, 1f/scl, x + o, y + o)*mag; + } + + public void options(FilterOption... options){ + this.options = options; + } + + public final void apply(GenerateInput in){ + this.in = in; + apply(); + } + + public static class GenerateInput{ + public Floor srcfloor; + public Block srcblock; + public Block srcore; + public int x, y; + + public MapEditor editor; + public Block floor, block, ore; + + Simplex noise = new Simplex(); + + public void begin(MapEditor editor, int x, int y, Block floor, Block block, Block ore){ + this.editor = editor; + this.floor = this.srcfloor = (Floor)floor; + this.block = this.srcblock = block; + this.ore = srcore = ore; + this.x = x; + this.y = y; + } + + public void randomize(){ + noise.setSeed(Mathf.random(99999999)); + } + + Tile tile(double x, double y){ + return editor.tile((int)Mathf.clamp(x, 0, editor.width() - 1), (int)Mathf.clamp(y, 0, editor.height() - 1)); + } + } +} diff --git a/core/src/io/anuke/mindustry/editor/generation/NoiseFilter.java b/core/src/io/anuke/mindustry/editor/generation/NoiseFilter.java new file mode 100644 index 0000000000..da9ace148f --- /dev/null +++ b/core/src/io/anuke/mindustry/editor/generation/NoiseFilter.java @@ -0,0 +1,35 @@ +package io.anuke.mindustry.editor.generation; + +import io.anuke.mindustry.content.Blocks; +import io.anuke.mindustry.editor.generation.FilterOption.BlockOption; +import io.anuke.mindustry.editor.generation.FilterOption.SliderOption; +import io.anuke.mindustry.world.Block; + +import static io.anuke.mindustry.editor.generation.FilterOption.floorsOnly; +import static io.anuke.mindustry.editor.generation.FilterOption.wallsOnly; + +public class NoiseFilter extends GenerateFilter{ + float scl = 40, threshold = 0.5f, octaves = 3f, falloff = 0.5f; + Block floor = Blocks.stone, block = Blocks.rocks; + + { + options( + new SliderOption("scale", () -> scl, f -> scl = f, 1f, 100f), + new SliderOption("threshold", () -> threshold, f -> threshold = f, 0f, 1f), + new SliderOption("octaves", () -> octaves, f -> octaves = f, 1f, 20f), + new SliderOption("falloff", () -> falloff, f -> falloff = f, 0f, 1f), + new BlockOption("floor", () -> floor, b -> floor = b, floorsOnly), + new BlockOption("wall", () -> block, b -> block = b, wallsOnly) + ); + } + + @Override + public void apply(){ + float noise = noise(in.x, in.y, scl, 1f, octaves, falloff); + + if(noise > threshold){ + in.floor = floor; + if(wallsOnly.test(in.srcblock)) in.block = block; + } + } +} diff --git a/core/src/io/anuke/mindustry/game/DefaultWaves.java b/core/src/io/anuke/mindustry/game/DefaultWaves.java index dda11e2c48..8880c2996d 100644 --- a/core/src/io/anuke/mindustry/game/DefaultWaves.java +++ b/core/src/io/anuke/mindustry/game/DefaultWaves.java @@ -9,159 +9,158 @@ import io.anuke.mindustry.type.ItemStack; public class DefaultWaves{ private static Array spawns; - public static Array getDefaultSpawns(){ + public static Array get(){ if(spawns == null && UnitTypes.dagger != null){ spawns = Array.with( - new SpawnGroup(UnitTypes.dagger){{ - end = 8; - unitScaling = 2; - }}, + new SpawnGroup(UnitTypes.dagger){{ + end = 8; + unitScaling = 2; + }}, - new SpawnGroup(UnitTypes.wraith){{ - begin = 12; - end = 14; - unitScaling = 2; - }}, + new SpawnGroup(UnitTypes.wraith){{ + begin = 12; + end = 14; + unitScaling = 2; + }}, - new SpawnGroup(UnitTypes.dagger){{ - begin = 11; - unitScaling = 2; - spacing = 2; - max = 4; - }}, + new SpawnGroup(UnitTypes.dagger){{ + begin = 11; + unitScaling = 2; + spacing = 2; + max = 4; + }}, - new SpawnGroup(UnitTypes.titan){{ - begin = 9; - spacing = 3; - unitScaling = 2; + new SpawnGroup(UnitTypes.titan){{ + begin = 9; + spacing = 3; + unitScaling = 2; - end = 30; - }}, + end = 30; + }}, - new SpawnGroup(UnitTypes.dagger){{ - begin = 10; - unitScaling = 2; - unitAmount = 1; - spacing = 2; - end = 30; - }}, + new SpawnGroup(UnitTypes.dagger){{ + begin = 8; + unitScaling = 1; + unitAmount = 1; + spacing = 2; + end = 30; + }}, - new SpawnGroup(UnitTypes.titan){{ - begin = 28; - spacing = 3; - unitScaling = 1; - end = 40; - }}, + new SpawnGroup(UnitTypes.titan){{ + begin = 28; + spacing = 3; + unitScaling = 1; + end = 40; + }}, - new SpawnGroup(UnitTypes.titan){{ - begin = 45; - spacing = 3; - unitScaling = 2; - effect = StatusEffects.overdrive; - }}, + new SpawnGroup(UnitTypes.titan){{ + begin = 45; + spacing = 3; + unitScaling = 2; + effect = StatusEffects.overdrive; + }}, - new SpawnGroup(UnitTypes.titan){{ - begin = 120; - spacing = 2; - unitScaling = 3; - unitAmount = 5; - effect = StatusEffects.overdrive; - }}, + new SpawnGroup(UnitTypes.titan){{ + begin = 120; + spacing = 2; + unitScaling = 3; + unitAmount = 5; + effect = StatusEffects.overdrive; + }}, - new SpawnGroup(UnitTypes.wraith){{ - begin = 16; - unitScaling = 2; - spacing = 2; + new SpawnGroup(UnitTypes.wraith){{ + begin = 16; + unitScaling = 1; + spacing = 2; - end = 39; - max = 7; - }}, + max = 7; + }}, - new SpawnGroup(UnitTypes.dagger){{ - begin = 82; - spacing = 3; - unitAmount = 4; - unitScaling = 3; - effect = StatusEffects.overdrive; - }}, + new SpawnGroup(UnitTypes.dagger){{ + begin = 82; + spacing = 3; + unitAmount = 4; + unitScaling = 3; + effect = StatusEffects.overdrive; + }}, - new SpawnGroup(UnitTypes.dagger){{ - begin = 41; - spacing = 5; - unitAmount = 1; - unitScaling = 3; - effect = StatusEffects.shielded; - max = 10; - }}, + new SpawnGroup(UnitTypes.dagger){{ + begin = 41; + spacing = 5; + unitAmount = 1; + unitScaling = 3; + effect = StatusEffects.shielded; + max = 10; + }}, - new SpawnGroup(UnitTypes.fortress){{ - begin = 40; - spacing = 5; - unitAmount = 2; - unitScaling = 3; - max = 10; - }}, + new SpawnGroup(UnitTypes.fortress){{ + begin = 40; + spacing = 5; + unitAmount = 2; + unitScaling = 3; + max = 10; + }}, - new SpawnGroup(UnitTypes.dagger){{ - begin = 35; - spacing = 3; - unitAmount = 4; - effect = StatusEffects.overdrive; - items = new ItemStack(Items.blastCompound, 60); - end = 60; - }}, + new SpawnGroup(UnitTypes.dagger){{ + begin = 35; + spacing = 3; + unitAmount = 4; + effect = StatusEffects.overdrive; + items = new ItemStack(Items.blastCompound, 60); + end = 60; + }}, - new SpawnGroup(UnitTypes.dagger){{ - begin = 42; - spacing = 3; - unitAmount = 4; - effect = StatusEffects.overdrive; - items = new ItemStack(Items.pyratite, 100); - end = 130; - }}, + new SpawnGroup(UnitTypes.dagger){{ + begin = 42; + spacing = 3; + unitAmount = 4; + effect = StatusEffects.overdrive; + items = new ItemStack(Items.pyratite, 100); + end = 130; + }}, - new SpawnGroup(UnitTypes.ghoul){{ - begin = 40; - unitAmount = 2; - spacing = 2; - unitScaling = 3; - max = 8; - }}, + new SpawnGroup(UnitTypes.ghoul){{ + begin = 40; + unitAmount = 2; + spacing = 2; + unitScaling = 3; + max = 8; + }}, - new SpawnGroup(UnitTypes.wraith){{ - begin = 50; - unitAmount = 4; - unitScaling = 3; - spacing = 5; - effect = StatusEffects.overdrive; - max = 8; - }}, + new SpawnGroup(UnitTypes.wraith){{ + begin = 50; + unitAmount = 4; + unitScaling = 3; + spacing = 5; + effect = StatusEffects.overdrive; + max = 8; + }}, - new SpawnGroup(UnitTypes.revenant){{ - begin = 50; - unitAmount = 2; - unitScaling = 3; - spacing = 5; - max = 8; - }}, + new SpawnGroup(UnitTypes.revenant){{ + begin = 50; + unitAmount = 2; + unitScaling = 3; + spacing = 5; + max = 8; + }}, - new SpawnGroup(UnitTypes.ghoul){{ - begin = 53; - unitAmount = 2; - unitScaling = 3; - spacing = 4; - max = 8; - end = 74; - }}, + new SpawnGroup(UnitTypes.ghoul){{ + begin = 53; + unitAmount = 2; + unitScaling = 3; + spacing = 4; + max = 8; + end = 74; + }}, - new SpawnGroup(UnitTypes.ghoul){{ - begin = 53; - unitAmount = 2; - unitScaling = 3; - spacing = 4; - max = 8; - end = 74; - }} + new SpawnGroup(UnitTypes.ghoul){{ + begin = 53; + unitAmount = 2; + unitScaling = 3; + spacing = 4; + max = 8; + end = 74; + }} ); } return spawns == null ? new Array<>() : spawns; diff --git a/core/src/io/anuke/mindustry/game/RulePreset.java b/core/src/io/anuke/mindustry/game/RulePreset.java index 174f9e0df9..2fb2fbe504 100644 --- a/core/src/io/anuke/mindustry/game/RulePreset.java +++ b/core/src/io/anuke/mindustry/game/RulePreset.java @@ -9,13 +9,13 @@ public enum RulePreset{ waveTimer = true; waves = true; unitDrops = true; - spawns = DefaultWaves.getDefaultSpawns(); + spawns = DefaultWaves.get(); }}), sandbox(() -> new Rules(){{ infiniteResources = true; waves = true; waveTimer = false; - spawns = DefaultWaves.getDefaultSpawns(); + spawns = DefaultWaves.get(); }}), attack(() -> new Rules(){{ enemyCheat = true; diff --git a/core/src/io/anuke/mindustry/game/Rules.java b/core/src/io/anuke/mindustry/game/Rules.java index a23b15321d..cf31cce7e0 100644 --- a/core/src/io/anuke/mindustry/game/Rules.java +++ b/core/src/io/anuke/mindustry/game/Rules.java @@ -28,5 +28,5 @@ public class Rules{ /**Zone ID, -1 for invalid zone.*/ public byte zone = -1; /**Spawn layout. Since only zones modify this, it should be assigned on save load.*/ - public transient Array spawns = DefaultWaves.getDefaultSpawns(); + public transient Array spawns = DefaultWaves.get(); } diff --git a/core/src/io/anuke/mindustry/graphics/MinimapRenderer.java b/core/src/io/anuke/mindustry/graphics/MinimapRenderer.java index 0a8d68a176..7eac43461c 100644 --- a/core/src/io/anuke/mindustry/graphics/MinimapRenderer.java +++ b/core/src/io/anuke/mindustry/graphics/MinimapRenderer.java @@ -137,7 +137,7 @@ public class MinimapRenderer implements Disposable{ private int colorFor(Tile tile){ tile = tile.target(); - return MapIO.colorFor(tile.floor(), tile.block(), tile.oreBlock(), tile.getTeam()); + return MapIO.colorFor(tile.floor(), tile.block(), tile.ore(), tile.getTeam()); } @Override diff --git a/core/src/io/anuke/mindustry/io/MapIO.java b/core/src/io/anuke/mindustry/io/MapIO.java index 3e77af227e..6db9e18a2f 100644 --- a/core/src/io/anuke/mindustry/io/MapIO.java +++ b/core/src/io/anuke/mindustry/io/MapIO.java @@ -105,7 +105,7 @@ public class MapIO{ for(int x = 0; x < pixmap.getWidth(); x++){ for(int y = 0; y < pixmap.getHeight(); y++){ Tile tile = tiles[x][y]; - pixmap.drawPixel(x, pixmap.getHeight() - 1 - y, colorFor(tile.floor(), tile.block(), tile.oreBlock(), tile.getTeam())); + pixmap.drawPixel(x, pixmap.getHeight() - 1 - y, colorFor(tile.floor(), tile.block(), tile.ore(), tile.getTeam())); } } return pixmap; diff --git a/core/src/io/anuke/mindustry/maps/Map.java b/core/src/io/anuke/mindustry/maps/Map.java index b4604b442d..b97f30a91e 100644 --- a/core/src/io/anuke/mindustry/maps/Map.java +++ b/core/src/io/anuke/mindustry/maps/Map.java @@ -13,7 +13,7 @@ import io.anuke.mindustry.io.MapIO; import static io.anuke.mindustry.Vars.world; -public class Map{ +public class Map implements Comparable{ /** Whether this is a custom map.*/ public final boolean custom; /** Metadata. Author description, display name, etc.*/ @@ -54,10 +54,10 @@ public class Map{ }catch(Exception e){ Log.err("Malformed waves: {0}", tags.get("waves")); e.printStackTrace(); - return DefaultWaves.getDefaultSpawns(); + return DefaultWaves.get(); } }else{ - return DefaultWaves.getDefaultSpawns(); + return DefaultWaves.get(); } } @@ -90,6 +90,16 @@ public class Map{ return tags.containsKey(name); } + @Override + public int compareTo(Map map){ + int type = -Boolean.compare(custom, map.custom); + if(type != 0){ + return type; + }else{ + return name().compareTo(map.name()); + } + } + @Override public String toString(){ return "Map{" + diff --git a/core/src/io/anuke/mindustry/maps/Maps.java b/core/src/io/anuke/mindustry/maps/Maps.java index 960538a8f7..ff5fc523cb 100644 --- a/core/src/io/anuke/mindustry/maps/Maps.java +++ b/core/src/io/anuke/mindustry/maps/Maps.java @@ -113,6 +113,7 @@ public class Maps implements Disposable{ map.texture = new Texture(MapIO.generatePreview(data)); } maps.add(map); + maps.sort(); }catch(IOException e){ throw new RuntimeException(e); } @@ -181,6 +182,7 @@ public class Maps implements Disposable{ } maps.add(map); + maps.sort(); } private void loadCustomMaps(){ diff --git a/core/src/io/anuke/mindustry/ui/fragments/PlacementFragment.java b/core/src/io/anuke/mindustry/ui/fragments/PlacementFragment.java index 0ff7a440c4..2a05fe64f0 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/PlacementFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/PlacementFragment.java @@ -340,6 +340,6 @@ public class PlacementFragment extends Fragment{ /** Returns the block currently being hovered over in the world. */ Block tileDisplayBlock(){ - return hoverTile == null ? null : hoverTile.block().synthetic() ? hoverTile.block() : hoverTile.oreBlock() != Blocks.air ? hoverTile.oreBlock() : null; + return hoverTile == null ? null : hoverTile.block().synthetic() ? hoverTile.block() : hoverTile.ore() != Blocks.air ? hoverTile.ore() : null; } } \ No newline at end of file diff --git a/core/src/io/anuke/mindustry/world/DummyTile.java b/core/src/io/anuke/mindustry/world/DummyTile.java new file mode 100644 index 0000000000..147bc96de9 --- /dev/null +++ b/core/src/io/anuke/mindustry/world/DummyTile.java @@ -0,0 +1,25 @@ +package io.anuke.mindustry.world; + +import io.anuke.mindustry.game.Team; + +public class DummyTile extends Tile{ + + public DummyTile(int x, int y){ + super(x, y); + } + + @Override + public Team getTeam(){ + return Team.all[getTeamID()]; + } + + @Override + protected void changed(){ + //nothing matters + } + + @Override + protected void preChanged(){ + //it really doesn't + } +} diff --git a/core/src/io/anuke/mindustry/world/Tile.java b/core/src/io/anuke/mindustry/world/Tile.java index 3bfe361a43..bb3d9dacfa 100644 --- a/core/src/io/anuke/mindustry/world/Tile.java +++ b/core/src/io/anuke/mindustry/world/Tile.java @@ -345,7 +345,7 @@ public class Tile implements Position, TargetTrait{ this.ore = 0; } - public Floor oreBlock(){ + public Floor ore(){ return (Floor)content.block(ore); } diff --git a/core/src/io/anuke/mindustry/world/blocks/BlockPart.java b/core/src/io/anuke/mindustry/world/blocks/BlockPart.java index 50ae9a08db..8328d05c6f 100644 --- a/core/src/io/anuke/mindustry/world/blocks/BlockPart.java +++ b/core/src/io/anuke/mindustry/world/blocks/BlockPart.java @@ -18,6 +18,11 @@ public class BlockPart extends Block{ hasPower = hasItems = hasLiquids = true; } + @Override + public boolean synthetic(){ + return true; + } + @Override public boolean isHidden(){ return true; diff --git a/core/src/io/anuke/mindustry/world/blocks/Floor.java b/core/src/io/anuke/mindustry/world/blocks/Floor.java index 58564e9ebc..0487c66e85 100644 --- a/core/src/io/anuke/mindustry/world/blocks/Floor.java +++ b/core/src/io/anuke/mindustry/world/blocks/Floor.java @@ -109,7 +109,7 @@ public class Floor extends Block{ Mathf.random.setSeed(tile.pos()); Draw.rect(variantRegions[Mathf.randomSeed(tile.pos(), 0, Math.max(0, variantRegions.length - 1))], tile.worldx(), tile.worldy()); - Floor floor = tile.oreBlock(); + Floor floor = tile.ore(); if(floor != Blocks.air && floor != this){ //ore should never have itself on top, but it's possible, so prevent a crash in that case floor.draw(tile); }