diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 3a6e61e549..f88ba0b43d 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -257,10 +257,12 @@ launch.unable = [scarlet]Unable to LAUNCH.[] Enemies. launch.confirm = This will launch all resources in your core.\nYou will not be able to return to this base. uncover = Uncover configure = Configure Loadout -configure.locked = [LIGHT_GRAY]Configure loadout at wave {0}. +configure.locked = [LIGHT_GRAY]Unlock configuring loadout:\nWave {0}. zone.unlocked = [LIGHT_GRAY]{0} unlocked. -zone.complete = Zone conditions met. +zone.complete = Wave {0} reached:\nNew zone requirements met. +zone.config.complete = Wave {0} reached:\nLoadout config unlocked. zone.resources = Resources Detected: +add = Add... connectfail = [crimson]Failed to connect to server:\n\n[accent]{0} error.unreachable = Server unreachable.\nIs the address spelled correctly? diff --git a/core/src/io/anuke/mindustry/content/Zones.java b/core/src/io/anuke/mindustry/content/Zones.java index a29c219aa8..d59fcf43ea 100644 --- a/core/src/io/anuke/mindustry/content/Zones.java +++ b/core/src/io/anuke/mindustry/content/Zones.java @@ -19,8 +19,8 @@ public class Zones implements ContentList{ public void load(){ groundZero = new Zone("groundZero", new MapGenerator("groundZero", 1)){{ - deployCost = ItemStack.with(); - startingItems = ItemStack.with(Items.copper, 50); + baseLaunchCost = ItemStack.with(Items.copper, -50); + startingItems = ItemStack.list(Items.copper, 50); alwaysUnlocked = true; conditionWave = 10; launchPeriod = 5; @@ -63,8 +63,7 @@ public class Zones implements ContentList{ }}; craters = new Zone("craters", new MapGenerator("craters", 1).dist(0)){{ - deployCost = ItemStack.with(Items.copper, 200); - startingItems = ItemStack.with(Items.copper, 200); + startingItems = ItemStack.list(Items.copper, 200); conditionWave = 10; itemRequirements = ItemStack.with(Items.copper, 2000); zoneRequirements = new Zone[]{groundZero}; @@ -114,8 +113,8 @@ public class Zones implements ContentList{ frozenForest = new Zone("frozenForest", new MapGenerator("frozenForest", 2) .decor(new Decoration(Blocks.snow, Blocks.sporeCluster, 0.02)) .core(Blocks.coreFoundation)){{ - deployCost = ItemStack.with(Items.copper, 500); - startingItems = ItemStack.with(Items.copper, 400); + baseLaunchCost = ItemStack.with(Items.copper, 100); + startingItems = ItemStack.list(Items.copper, 400); conditionWave = 10; zoneRequirements = new Zone[]{craters}; itemRequirements = ItemStack.with(Items.copper, 4000, Items.lead, 2000); @@ -175,8 +174,8 @@ public class Zones implements ContentList{ ruinousShores = new Zone("ruinousShores", new MapGenerator("ruinousShores", 1) .core(Blocks.coreFoundation)){{ - deployCost = ItemStack.with(Items.copper, 600, Items.graphite, 50); - startingItems = ItemStack.with(Items.copper, 400); + baseLaunchCost = ItemStack.with(Items.copper, 200, Items.graphite, 50); + startingItems = ItemStack.list(Items.copper, 400); conditionWave = 20; launchPeriod = 20; zoneRequirements = new Zone[]{frozenForest}; @@ -249,7 +248,7 @@ public class Zones implements ContentList{ /* crags = new Zone("crags", new MapGenerator("groundZero", 1)){{ //TODO implement - deployCost = ItemStack.with(Items.copper, 300); + baseLaunchCost = ItemStack.with(Items.copper, 300); startingItems = ItemStack.with(Items.copper, 200); conditionWave = 15; zoneRequirements = new Zone[]{frozenForest}; @@ -265,8 +264,8 @@ public class Zones implements ContentList{ .dist(2.5f, true) .decor(new Decoration(Blocks.stainedStone, Blocks.stainedBoulder, 0.01)) .core(Blocks.coreFoundation)){{ - deployCost = ItemStack.with(Items.copper, 500, Items.lead, 300, Items.silicon, 100); - startingItems = ItemStack.with(Items.copper, 400, Items.lead, 100); + baseLaunchCost = ItemStack.with(Items.copper, 100, Items.lead, 200, Items.silicon, 100); + startingItems = ItemStack.list(Items.copper, 400, Items.lead, 100); conditionWave = 10; launchPeriod = 10; zoneRequirements = new Zone[]{frozenForest}; @@ -341,8 +340,8 @@ public class Zones implements ContentList{ new Decoration(Blocks.snow, Blocks.sporeCluster, 0.01), new Decoration(Blocks.metalFloor, Blocks.metalFloorDamaged, 0.02) ).drops(ItemStack.with(Items.copper, 2000, Items.lead, 1500, Items.silicon, 1000, Items.graphite, 2000, Items.pyratite, 2000, Items.titanium, 2000, Items.metaglass, 1000, Items.coal, 2000))){{ - deployCost = ItemStack.with(Items.copper, 2500, Items.lead, 1000, Items.silicon, 300); - startingItems = ItemStack.with(Items.copper, 2000, Items.lead, 500, Items.silicon, 200); + baseLaunchCost = ItemStack.with(Items.copper, 500, Items.lead, 500, Items.silicon, 100); + startingItems = ItemStack.list(Items.copper, 2000, Items.lead, 500, Items.silicon, 200); itemRequirements = ItemStack.with(Items.silicon, 8000, Items.titanium, 6000, Items.graphite, 4000); conditionWave = 20; zoneRequirements = new Zone[]{stainedMountains}; @@ -419,8 +418,8 @@ public class Zones implements ContentList{ desolateRift = new Zone("desolateRift", new MapGenerator("desolateRift") .core(Blocks.coreNucleus).dist(2f)){{ - deployCost = ItemStack.with(Items.copper, 2000); - startingItems = ItemStack.with(Items.copper, 1500); + baseLaunchCost = ItemStack.with(Items.copper, 500); + startingItems = ItemStack.list(Items.copper, 1500); itemRequirements = ItemStack.with(Items.copper, 8000, Items.metaglass, 2000, Items.graphite, 3000); conditionWave = 10; launchPeriod = 20; @@ -430,7 +429,7 @@ public class Zones implements ContentList{ rules = () -> new Rules(){{ waves = true; waveTimer = true; - waveSpacing = 60 * 60 * 2; + waveSpacing = 60 * 60 * 1.5f; spawns = Array.with( new SpawnGroup(UnitTypes.crawler){{ unitScaling = 1; @@ -490,7 +489,7 @@ public class Zones implements ContentList{ /* arcticDesert = new Zone("arcticDesert", new MapGenerator("groundZero", 1)){{ //TODO implement - deployCost = ItemStack.with(Items.copper, 300); + baseLaunchCost = ItemStack.with(Items.copper, 300); startingItems = ItemStack.with(Items.copper, 200); conditionWave = 15; zoneRequirements = new Zone[]{frozenForest}; @@ -503,7 +502,7 @@ public class Zones implements ContentList{ }}; dryWastes = new Zone("dryWastes", new MapGenerator("groundZero", 1)){{ //TODO implement - deployCost = ItemStack.with(Items.copper, 300); + baseLaunchCost = ItemStack.with(Items.copper, 300); startingItems = ItemStack.with(Items.copper, 200); conditionWave = 15; zoneRequirements = new Zone[]{frozenForest}; @@ -520,8 +519,8 @@ public class Zones implements ContentList{ .drops(ItemStack.with(Items.copper, 2000, Items.lead, 1500, Items.silicon, 1000, Items.graphite, 1000, Items.thorium, 200, Items.titanium, 2000, Items.metaglass, 1000)) .decor(new Decoration(Blocks.snow, Blocks.sporeCluster, 0.01)) .core(Blocks.coreNucleus)){{ - deployCost = ItemStack.with(Items.copper, 3000, Items.lead, 2000, Items.silicon, 1000, Items.metaglass, 500); - startingItems = ItemStack.with(Items.copper, 2500, Items.lead, 1500, Items.silicon, 800, Items.metaglass, 400); + baseLaunchCost = ItemStack.with(Items.copper, 500, Items.lead, 500, Items.silicon, 200, Items.metaglass, 100); + startingItems = ItemStack.list(Items.copper, 2500, Items.lead, 1500, Items.silicon, 800, Items.metaglass, 400); itemRequirements = ItemStack.with(Items.copper, 10000, Items.titanium, 8000, Items.metaglass, 6000, Items.plastanium, 2000); conditionWave = 30; launchPeriod = 15; @@ -606,7 +605,7 @@ public class Zones implements ContentList{ /* moltenFault = new Zone("moltenFault", new MapGenerator("groundZero", 1)){{ //TODO implement - deployCost = ItemStack.with(Items.copper, 300); + baseLaunchCost = ItemStack.with(Items.copper, 300); startingItems = ItemStack.with(Items.copper, 200); conditionWave = 15; zoneRequirements = new Zone[]{frozenForest}; diff --git a/core/src/io/anuke/mindustry/core/Control.java b/core/src/io/anuke/mindustry/core/Control.java index b1f7c806a1..ddcd40d6d0 100644 --- a/core/src/io/anuke/mindustry/core/Control.java +++ b/core/src/io/anuke/mindustry/core/Control.java @@ -169,7 +169,11 @@ public class Control implements ApplicationListener{ }); Events.on(ZoneCompleteEvent.class, e -> { - ui.hudfrag.showToast(Core.bundle.get("zone.complete")); + ui.hudfrag.showToast(Core.bundle.format("zone.complete", e.zone.conditionWave)); + }); + + Events.on(ZoneConfigureCompleteEvent.class, e -> { + ui.hudfrag.showToast(Core.bundle.format("zone.config.complete", e.zone.configureWave)); }); } diff --git a/core/src/io/anuke/mindustry/core/Logic.java b/core/src/io/anuke/mindustry/core/Logic.java index 43efd6e347..77f0f21cfa 100644 --- a/core/src/io/anuke/mindustry/core/Logic.java +++ b/core/src/io/anuke/mindustry/core/Logic.java @@ -34,7 +34,7 @@ public class Logic implements ApplicationListener{ public Logic(){ Events.on(WaveEvent.class, event -> { if(world.isZone()){ - data.updateWaveScore(world.getZone(), state.wave); + world.getZone().updateWave(state.wave); } }); } diff --git a/core/src/io/anuke/mindustry/core/World.java b/core/src/io/anuke/mindustry/core/World.java index 48572dc653..412cd43c3f 100644 --- a/core/src/io/anuke/mindustry/core/World.java +++ b/core/src/io/anuke/mindustry/core/World.java @@ -210,7 +210,7 @@ public class World implements ApplicationListener{ state.rules.zone = zone.id; loadGenerator(zone.generator); for(Tile core : state.teams.get(defaultTeam).cores){ - for(ItemStack stack : zone.startingItems){ + for(ItemStack stack : zone.getStartingItems()){ core.entity.items.add(stack.item, stack.amount); } } diff --git a/core/src/io/anuke/mindustry/game/EventType.java b/core/src/io/anuke/mindustry/game/EventType.java index 40754f6604..c5dc0ba433 100644 --- a/core/src/io/anuke/mindustry/game/EventType.java +++ b/core/src/io/anuke/mindustry/game/EventType.java @@ -18,6 +18,15 @@ public class EventType{ } } + /**Called when a zone's requirements are met.*/ + public static class ZoneConfigureCompleteEvent implements Event{ + public final Zone zone; + + public ZoneConfigureCompleteEvent(Zone zone){ + this.zone = zone; + } + } + /**Called when the game is first loaded.*/ public static class GameLoadEvent implements Event{ diff --git a/core/src/io/anuke/mindustry/game/GlobalData.java b/core/src/io/anuke/mindustry/game/GlobalData.java index c6cf8739d7..f1d7b00c78 100644 --- a/core/src/io/anuke/mindustry/game/GlobalData.java +++ b/core/src/io/anuke/mindustry/game/GlobalData.java @@ -8,13 +8,12 @@ import io.anuke.arc.collection.ObjectSet; import io.anuke.mindustry.Vars; import io.anuke.mindustry.content.Items; import io.anuke.mindustry.game.EventType.UnlockEvent; -import io.anuke.mindustry.game.EventType.ZoneCompleteEvent; import io.anuke.mindustry.type.ContentType; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.ItemStack; -import io.anuke.mindustry.type.Zone; -import static io.anuke.mindustry.Vars.*; +import static io.anuke.mindustry.Vars.content; +import static io.anuke.mindustry.Vars.state; /**Stores player unlocks. Clientside only.*/ public class GlobalData{ @@ -25,25 +24,19 @@ public class GlobalData{ public GlobalData(){ Core.settings.setSerializer(ContentType.class, (stream, t) -> stream.writeInt(t.ordinal()), stream -> ContentType.values()[stream.readInt()]); Core.settings.setSerializer(Item.class, (stream, t) -> stream.writeUTF(t.name), stream -> content.getByName(ContentType.item, stream.readUTF())); + + Core.settings.setSerializer(ItemStack.class, (stream, t) -> { + stream.writeUTF(t.item.name); + stream.writeInt(t.amount); + }, stream -> { + String name = stream.readUTF(); + int amount = stream.readInt(); + return new ItemStack(content.getByName(ContentType.item, name), amount); + }); } - public void updateWaveScore(Zone zone, int wave){ - int value = Core.settings.getInt(zone.name + "-wave", 0); - if(value < wave){ - Core.settings.put(zone.name + "-wave", wave); - modified = true; - if(wave == zone.conditionWave + 1){ - Events.fire(new ZoneCompleteEvent(zone)); - } - } - } - - public int getWaveScore(Zone zone){ - return Core.settings.getInt(zone.name + "-wave", 0); - } - - public boolean isCompleted(Zone zone){ - return getWaveScore(zone) >= zone.conditionWave; + public void modified(){ + modified = true; } public int getItem(Item item){ diff --git a/core/src/io/anuke/mindustry/game/Saves.java b/core/src/io/anuke/mindustry/game/Saves.java index 5555684cef..0142f194f7 100644 --- a/core/src/io/anuke/mindustry/game/Saves.java +++ b/core/src/io/anuke/mindustry/game/Saves.java @@ -197,7 +197,7 @@ public class Saves{ } public boolean isHidden(){ - return false; + return getZone() != null; } public String getPlayTime(){ diff --git a/core/src/io/anuke/mindustry/input/InputHandler.java b/core/src/io/anuke/mindustry/input/InputHandler.java index 0ca11d526a..71a0001de8 100644 --- a/core/src/io/anuke/mindustry/input/InputHandler.java +++ b/core/src/io/anuke/mindustry/input/InputHandler.java @@ -287,7 +287,7 @@ public abstract class InputHandler implements InputProcessor{ } public void tryDropItems(Tile tile, float x, float y){ - if(!droppingItem || player.item().amount <= 0 || canTapPlayer(x, y)){ + if(!droppingItem || player.item().amount <= 0 || canTapPlayer(x, y) || state.isPaused()){ droppingItem = false; return; } diff --git a/core/src/io/anuke/mindustry/type/ItemStack.java b/core/src/io/anuke/mindustry/type/ItemStack.java index 5b77275b36..47cfc87868 100644 --- a/core/src/io/anuke/mindustry/type/ItemStack.java +++ b/core/src/io/anuke/mindustry/type/ItemStack.java @@ -1,6 +1,8 @@ package io.anuke.mindustry.type; -public class ItemStack{ +import io.anuke.arc.collection.Array; + +public class ItemStack implements Comparable{ public Item item; public int amount; @@ -21,6 +23,19 @@ public class ItemStack{ return stacks; } + public static Array list(Object... items){ + Array stacks = new Array<>(items.length/2); + for(int i = 0; i < items.length; i+= 2){ + stacks.add(new ItemStack((Item)items[i], (Integer)items[i + 1])); + } + return stacks; + } + + @Override + public int compareTo(ItemStack itemStack){ + return item.compareTo(itemStack.item); + } + @Override public String toString(){ return "ItemStack{" + diff --git a/core/src/io/anuke/mindustry/type/Zone.java b/core/src/io/anuke/mindustry/type/Zone.java index 2df1c992ec..0b40c5cccc 100644 --- a/core/src/io/anuke/mindustry/type/Zone.java +++ b/core/src/io/anuke/mindustry/type/Zone.java @@ -1,9 +1,13 @@ package io.anuke.mindustry.type; import io.anuke.arc.Core; +import io.anuke.arc.Events; +import io.anuke.arc.collection.Array; import io.anuke.arc.function.Supplier; import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.scene.ui.layout.Table; +import io.anuke.mindustry.game.EventType.ZoneCompleteEvent; +import io.anuke.mindustry.game.EventType.ZoneConfigureCompleteEvent; import io.anuke.mindustry.game.Rules; import io.anuke.mindustry.game.UnlockableContent; import io.anuke.mindustry.maps.generators.MapGenerator; @@ -14,8 +18,6 @@ import static io.anuke.mindustry.Vars.state; public class Zone extends UnlockableContent{ public final MapGenerator generator; - public ItemStack[] deployCost = {}; - public ItemStack[] startingItems = {}; public Block[] blockRequirements = {}; public ItemStack[] itemRequirements = {}; public Zone[] zoneRequirements = {}; @@ -26,23 +28,93 @@ public class Zone extends UnlockableContent{ public int configureWave = 50; public int launchPeriod = 10; + protected ItemStack[] baseLaunchCost = {}; + protected Array startingItems = new Array<>(); + protected ItemStack[] launchCost = null; + public Zone(String name, MapGenerator generator){ super(name); this.generator = generator; } + public ItemStack[] getLaunchCost(){ + if(launchCost == null){ + updateLaunchCost(); + } + return launchCost; + } + + public Array getStartingItems(){ + return startingItems; + } + + public void updateWave(int wave){ + int value = Core.settings.getInt(name + "-wave", 0); + if(value < wave){ + Core.settings.put(name + "-wave", wave); + data.modified(); + + if(wave == conditionWave + 1){ + Events.fire(new ZoneCompleteEvent(this)); + } + + if(wave == configureWave + 1){ + Events.fire(new ZoneConfigureCompleteEvent(this)); + } + } + } + + public int bestWave(){ + return Core.settings.getInt(name + "-wave", 0); + } + + public boolean isCompleted(){ + return bestWave() >= conditionWave; + } + + public void updateLaunchCost(){ + Array stacks = new Array<>(); + + //TODO optimize + for(ItemStack stack : baseLaunchCost){ + ItemStack out = new ItemStack(stack.item, stack.amount); + for(ItemStack other : startingItems){ + if(other.item == out.item){ + out.amount += other.amount; + } + } + stacks.add(out); + } + + for(ItemStack other : startingItems){ + if(stacks.find(s -> s.item == other.item) == null){ + stacks.add(other); + } + } + + stacks.sort(); + launchCost = stacks.toArray(ItemStack.class); + Core.settings.putObject(name + "-starting-items", startingItems); + data.modified(); + } + /**Whether this zone has met its condition; if true, the player can leave.*/ public boolean metCondition(){ return state.wave >= conditionWave; } public boolean canConfigure(){ - return data.getWaveScore(this) >= configureWave; + return bestWave() >= configureWave; } @Override public void init(){ generator.init(); + + Array arr = Core.settings.getObject(name + "-starting-items", Array.class, () -> null); + if(arr != null){ + startingItems = arr; + } } @Override diff --git a/core/src/io/anuke/mindustry/ui/MultiReqImage.java b/core/src/io/anuke/mindustry/ui/MultiReqImage.java new file mode 100644 index 0000000000..41c9ef2e44 --- /dev/null +++ b/core/src/io/anuke/mindustry/ui/MultiReqImage.java @@ -0,0 +1,31 @@ +package io.anuke.mindustry.ui; + +import io.anuke.arc.collection.Array; +import io.anuke.arc.scene.ui.layout.Stack; +import io.anuke.arc.util.Time; + +public class MultiReqImage extends Stack{ + private Array displays = new Array<>(); + private float time; + + public void add(ReqImage display){ + displays.add(display); + super.add(display); + } + + @Override + public void act(float delta){ + super.act(delta); + + time += Time.delta() / 60f; + + displays.each(req -> req.visible(false)); + + ReqImage valid = displays.find(ReqImage::valid); + if(valid != null){ + valid.visible(true); + }else{ + displays.get((int)(time) % displays.size).visible(true); + } + } +} diff --git a/core/src/io/anuke/mindustry/ui/ReqImage.java b/core/src/io/anuke/mindustry/ui/ReqImage.java index 570330102e..315ce91211 100644 --- a/core/src/io/anuke/mindustry/ui/ReqImage.java +++ b/core/src/io/anuke/mindustry/ui/ReqImage.java @@ -11,8 +11,10 @@ import io.anuke.arc.scene.ui.layout.Unit; import io.anuke.mindustry.graphics.Pal; public class ReqImage extends Stack{ + private final BooleanProvider valid; public ReqImage(Element image, BooleanProvider valid){ + this.valid = valid; add(image); add(new Element(){ { @@ -33,4 +35,8 @@ public class ReqImage extends Stack{ public ReqImage(TextureRegion region, BooleanProvider valid){ this(new Image(region), valid); } + + public boolean valid(){ + return valid.get(); + } } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/ZoneInfoDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/ZoneInfoDialog.java index dc13b15bcf..63c3e80a1f 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/ZoneInfoDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/ZoneInfoDialog.java @@ -3,9 +3,12 @@ package io.anuke.mindustry.ui.dialogs; import io.anuke.arc.Core; import io.anuke.arc.graphics.Color; import io.anuke.arc.scene.ui.Button; +import io.anuke.arc.scene.ui.TextButton; +import io.anuke.arc.scene.ui.layout.Table; import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.ItemStack; +import io.anuke.mindustry.type.ItemType; import io.anuke.mindustry.type.Zone; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Block.Icon; @@ -34,6 +37,18 @@ public class ZoneInfoDialog extends FloatingDialog{ private void setup(Zone zone){ cont.clear(); + Table iteminfo = new Table(); + Runnable rebuildItems = () -> { + iteminfo.clear(); + ItemStack[] stacks = zone.unlocked() ? zone.getLaunchCost() : zone.itemRequirements; + for(ItemStack stack : stacks){ + iteminfo.addImage(stack.item.icon(Item.Icon.medium)).size(8*3).padRight(1); + iteminfo.add(stack.amount + "").color(Color.LIGHT_GRAY).padRight(5); + } + }; + + rebuildItems.run(); + cont.table(cont -> { if(zone.locked()){ cont.addImage("icon-zone-locked"); @@ -51,8 +66,8 @@ public class ZoneInfoDialog extends FloatingDialog{ for(Zone other : zone.zoneRequirements){ r.addImage("icon-zone").padRight(4); r.add(other.localizedName()).color(Color.LIGHT_GRAY); - r.addImage(data.isCompleted(other) ? "icon-check-2" : "icon-cancel-2") - .color(data.isCompleted(other) ? Color.LIGHT_GRAY : Color.SCARLET).padLeft(3); + r.addImage(other.isCompleted() ? "icon-check-2" : "icon-cancel-2") + .color(other.isCompleted() ? Color.LIGHT_GRAY : Color.SCARLET).padLeft(3); r.row(); } }); @@ -92,32 +107,74 @@ public class ZoneInfoDialog extends FloatingDialog{ } }); - if(data.getWaveScore(zone) > 0){ + if(zone.bestWave() > 0){ cont.row(); - cont.add(Core.bundle.format("bestwave", data.getWaveScore(zone))); + cont.add(Core.bundle.format("bestwave", zone.bestWave())); } - cont.row(); - cont.table("button-disabled", t -> { - t.left(); - t.add(!zone.canConfigure() ? Core.bundle.format("configure.locked", zone.configureWave) : "$configure"); - t.row(); - t.table(load -> { - load.left(); - for(ItemStack stack : zone.startingItems){ - load.addImage(stack.item.icon(Item.Icon.medium)).size(8 * 3).padRight(4); - load.label(() -> stack.amount + ""); + Table load = new Table(); + //thanks java, absolutely brilliant syntax here + Runnable[] rebuildLoadout = {null}; + rebuildLoadout[0] = () -> { + load.clear(); + float bsize = 40f; + int step = 100; + + load.left(); + for(ItemStack stack : zone.getStartingItems()){ + load.addButton("-", () -> { + stack.amount = Math.max(stack.amount - step, 0); + zone.updateLaunchCost(); + rebuildItems.run(); + }).size(bsize).pad(2); + load.addButton("+", () -> { + stack.amount = Math.min(stack.amount + step, zone.generator.coreBlock.itemCapacity); + zone.updateLaunchCost(); + rebuildItems.run(); + }).size(bsize).pad(2); + + load.addImage(stack.item.icon(Item.Icon.medium)).size(8 * 3).padRight(4); + load.label(() -> stack.amount + "").left(); + + load.row(); + } + + load.addButton("$add", () -> { + FloatingDialog dialog = new FloatingDialog(""); + dialog.setFillParent(false); + for(Item item : content.items().select(item -> data.getItem(item) > 0 && item.type == ItemType.material && zone.getStartingItems().find(stack -> stack.item == item) == null)){ + TextButton button = dialog.cont.addButton("", () -> { + zone.getStartingItems().add(new ItemStack(item, 0)); + zone.updateLaunchCost(); + rebuildLoadout[0].run(); + dialog.hide(); + }).size(300f, 35f).pad(1).get(); + button.clearChildren(); + button.left(); + button.addImage(item.icon(Item.Icon.medium)).size(8*3).pad(4); + button.add(item.localizedName); + dialog.cont.row(); } - }).growX().left(); - }).growX().left(); + dialog.show(); + }).colspan(4).size(100f, bsize).left(); + }; + + rebuildLoadout[0].run(); + + cont.row(); + cont.table(zone.canConfigure() ? "button" : "button-disabled", t -> { + t.left(); + t.add(!zone.canConfigure() ? Core.bundle.format("configure.locked", zone.configureWave) : "$configure").growX().wrap(); + if(zone.canConfigure()){ + t.row(); + t.add(load).pad(2).growX().left(); + } + }).width(300f).pad(4).left(); } }); cont.row(); - //cont.addButton(!zone.canConfigure() ? Core.bundle.format("configure.locked", zone.configureWave) : "$configure", () -> { }).disabled(b -> !zone.canConfigure()).size(300f, 70f).padTop(5).get(); - //cont.row(); - Button button = cont.addButton(zone.locked() ? "$uncover" : "$launch", () -> { if(!data.isUnlocked(zone)){ data.removeItems(zone.itemRequirements); @@ -126,20 +183,14 @@ public class ZoneInfoDialog extends FloatingDialog{ setup(zone); }else{ ui.deploy.hide(); - data.removeItems(zone.deployCost); + data.removeItems(zone.getLaunchCost()); hide(); world.playZone(zone); } - }).size(300f, 70f).padTop(5).disabled(b -> zone.locked() ? !canUnlock(zone) : !data.hasItems(zone.deployCost)).get(); + }).size(300f, 70f).padTop(5).disabled(b -> zone.locked() ? !canUnlock(zone) : !data.hasItems(zone.getLaunchCost())).get(); button.row(); - button.table(r -> { - ItemStack[] stacks = zone.unlocked() ? zone.deployCost : zone.itemRequirements; - for(ItemStack stack : stacks){ - r.addImage(stack.item.icon(Item.Icon.medium)).size(8*3).padRight(1); - r.add(stack.amount + "").color(Color.LIGHT_GRAY).padRight(5); - } - }); + button.add(iteminfo); } private boolean canUnlock(Zone zone){ @@ -148,7 +199,7 @@ public class ZoneInfoDialog extends FloatingDialog{ } for(Zone other : zone.zoneRequirements){ - if(!data.isCompleted(other)){ + if(!other.isCompleted()){ return false; } } diff --git a/core/src/io/anuke/mindustry/ui/fragments/BlockInventoryFragment.java b/core/src/io/anuke/mindustry/ui/fragments/BlockInventoryFragment.java index 7a920db03e..039d5f1152 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/BlockInventoryFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/BlockInventoryFragment.java @@ -131,7 +131,7 @@ public class BlockInventoryFragment extends Fragment{ container.add(i); - BooleanProvider canPick = () -> player.acceptsItem(item); + BooleanProvider canPick = () -> player.acceptsItem(item) && !state.isPaused(); HandCursorListener l = new HandCursorListener(); l.setEnabled(canPick); diff --git a/core/src/io/anuke/mindustry/world/blocks/power/BurnerGenerator.java b/core/src/io/anuke/mindustry/world/blocks/power/BurnerGenerator.java index 6568242ddb..dba75d1e0c 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/BurnerGenerator.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/BurnerGenerator.java @@ -6,7 +6,7 @@ import io.anuke.mindustry.type.Liquid; public class BurnerGenerator extends ItemLiquidGenerator{ public BurnerGenerator(String name){ - super(true, true, name); + super(true, false, name); } @Override diff --git a/core/src/io/anuke/mindustry/world/consumers/ConsumeItemFilter.java b/core/src/io/anuke/mindustry/world/consumers/ConsumeItemFilter.java index 592bb07a9f..597a4a7b77 100644 --- a/core/src/io/anuke/mindustry/world/consumers/ConsumeItemFilter.java +++ b/core/src/io/anuke/mindustry/world/consumers/ConsumeItemFilter.java @@ -1,17 +1,21 @@ package io.anuke.mindustry.world.consumers; import io.anuke.arc.collection.Array; +import io.anuke.arc.function.Predicate; +import io.anuke.arc.scene.ui.layout.Table; import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Item.Icon; +import io.anuke.mindustry.ui.ItemImage; +import io.anuke.mindustry.ui.MultiReqImage; +import io.anuke.mindustry.ui.ReqImage; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.meta.BlockStat; import io.anuke.mindustry.world.meta.BlockStats; import io.anuke.mindustry.world.meta.values.ItemFilterValue; -import io.anuke.arc.function.Predicate; -import io.anuke.arc.scene.ui.layout.Table; -import static io.anuke.mindustry.Vars.*; + +import static io.anuke.mindustry.Vars.content; public class ConsumeItemFilter extends Consume{ private final Predicate filter; @@ -23,14 +27,10 @@ public class ConsumeItemFilter extends Consume{ @Override public void build(Tile tile, Table table){ Array list = content.items().select(filter); + MultiReqImage image = new MultiReqImage(); + list.each(item -> image.add(new ReqImage(new ItemImage(item.icon(Icon.large), 1), () -> tile.entity != null && tile.entity.items != null && tile.entity.items.has(item)))); - for(int i = 0; i < list.size; i++){ - Item item = list.get(i); - table.addImage(item.icon(Icon.large)).size(8 * 4).padRight(2).padLeft(2); - if(i != list.size - 1){ - table.add("/"); - } - } + table.add(image).size(8*4); } @Override diff --git a/core/src/io/anuke/mindustry/world/consumers/ConsumeLiquidFilter.java b/core/src/io/anuke/mindustry/world/consumers/ConsumeLiquidFilter.java index 13b2d655ad..bb3accfefe 100644 --- a/core/src/io/anuke/mindustry/world/consumers/ConsumeLiquidFilter.java +++ b/core/src/io/anuke/mindustry/world/consumers/ConsumeLiquidFilter.java @@ -5,6 +5,7 @@ import io.anuke.arc.function.Predicate; import io.anuke.arc.scene.ui.layout.Table; import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.type.Liquid; +import io.anuke.mindustry.ui.MultiReqImage; import io.anuke.mindustry.ui.ReqImage; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; @@ -33,15 +34,10 @@ public class ConsumeLiquidFilter extends Consume{ @Override public void build(Tile tile, Table table){ Array list = content.liquids().select(l -> !l.isHidden() && filter.test(l)); + MultiReqImage image = new MultiReqImage(); + list.each(liquid -> image.add(new ReqImage(liquid.getContentIcon(), () -> tile.entity != null && tile.entity.liquids != null && tile.entity.liquids.get(liquid) >= use(tile.block(), tile.entity)))); - for(int i = 0; i < list.size; i++){ - Liquid liquid = list.get(i); - - table.add(new ReqImage(liquid.getContentIcon(), () -> valid(tile.block(), tile.entity))).size(8*4).pad(2); - if(i != list.size - 1){ - table.add("/"); - } - } + table.add(image).size(8*4); } @Override diff --git a/core/src/io/anuke/mindustry/world/meta/values/ItemFilterValue.java b/core/src/io/anuke/mindustry/world/meta/values/ItemFilterValue.java index 4aa7d9aef8..8bb1ecb6a0 100644 --- a/core/src/io/anuke/mindustry/world/meta/values/ItemFilterValue.java +++ b/core/src/io/anuke/mindustry/world/meta/values/ItemFilterValue.java @@ -1,11 +1,11 @@ package io.anuke.mindustry.world.meta.values; import io.anuke.arc.collection.Array; +import io.anuke.arc.function.Predicate; +import io.anuke.arc.scene.ui.layout.Table; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.ui.ItemDisplay; import io.anuke.mindustry.world.meta.StatValue; -import io.anuke.arc.function.Predicate; -import io.anuke.arc.scene.ui.layout.Table; import static io.anuke.mindustry.Vars.content; @@ -18,11 +18,7 @@ public class ItemFilterValue implements StatValue{ @Override public void display(Table table){ - Array list = new Array<>(); - - for(Item item : content.items()){ - if(filter.test(item)) list.add(item); - } + Array list = content.items().select(filter); for(int i = 0; i < list.size; i++){ Item item = list.get(i);